Echarts+GL实现3D区域地图与纹理图片

3,762 阅读2分钟

效果截图

截图1.png

引入地图JSON文件

要生成区域地图,首先需要地图的GeoJSON文件,可以去阿里云提供的数据可视化平台获取

QQ截图20240508150141.png

在vue项目中引入JSON数据

import mapJson from '@/assets/json/hubei.json';

渲染区域地图并添加纹理图片

在vue项目中新建一个ChartMap.vue文件

<template>
  <div class="map-container">
    <!-- 地图部分 -->
    <div ref="map" id="chart-map" />
  </div>
</template>

<script>
import 'echarts-gl';
import * as echarts from 'echarts';
import mapJson from '@/assets/json/hubei.json';
import pointJson from '@/assets/json/point.json';
import lineJson from '@/assets/json/lineData.json';
import laboratoryPoint from '@/assets/json/laboratoryPoint.json';
import WLImg from '@/assets/images/WL.png';

export default {
  name: 'ChartMap',
  data() {
    return {
      chartMap: null,
      option: null
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.initMap();
    });
  },
  methods: {
    initMap() {
      this.chartMap = echarts.init(this.$refs.map);
      echarts.registerMap('homeMap', mapJson);

      let lineData = [];
      const { coordinates } = lineJson.features[0].geometry;
      for (let i = 0; i < coordinates.length; i++) {
        const nextIndex = i + 1;
        if (nextIndex < coordinates.length) {
          const coord1 = coordinates[i];
          const coord2 = coordinates[nextIndex];
          const coords = [coord1, coord2];
          lineData.push({
            coords
          });
        }
      }

      this.option = {
        geo3D: {
          map: 'homeMap',
          roam: true,
          regionHeight: 5,
          itemStyle: {
            borderWidth: 2,
            borderColor: '#fdb347'
          },
          viewControl: {
            panMouseButton: 'left',
            rotateMouseButton: 'right',
            rotateSensitivity: 1, // 旋转操作的灵敏度,值越大越灵敏
            panSensitivity: 1, // 平移操作的灵敏度,值越大越灵敏
            zoomSensitivity: 1, // 缩放操作的灵敏度,值越大越灵敏
            distance: 120,
            minAlpha: 5, // 上下旋转的最小 alpha 值。即视角能旋转到达最上面的角度。[ default: 5 ]
            maxAlpha: 90, // 上下旋转的最大 alpha 值。即视角能旋转到达最下面的角度。[ default: 90 ]
            minBeta: -360, // 左右旋转的最小 beta 值。即视角能旋转到达最左的角度。[ default: -80 ]
            maxBeta: 360 // 左右旋转的最大 beta 值。即视角能旋转到达最右的角度。[ default: 80 ]
          },
          emphasis: {
            label: {
              show: true,
              distance: 1,
              position: 'top',
              lineHeight: 20,
              padding: [8, 10],
              backgroundColor: 'rgba(0,0,0,0.7)',
              color: '#fff',
              fontSize: 15,
              borderWidth: 1.5,
              borderRadius: 5,
              borderColor: '#06b2f7'
            }
          },
          // 将echarts设置为纹理
          shading: 'realistic',
          realisticMaterial: {
            // 引入纹理贴图
            detailTexture: WLImg,
            textureTiling: 1
          },
          light: {
            //光照阴影
            main: {
              intensity: 1, //光照强度
              shadow: true, //是否显示阴影
              shadowQuality: 'medium', //阴影质量
              alpha: 20,
              beta: 10
            },
            ambient: {
              intensity: 0.7
            }
          }
        },
        series: [
          {
            type: 'scatter3D',
            coordinateSystem: 'geo3D',
            symbol: 'circle',
            symbolSize: 16,
            itemStyle: {
              color: '#2068de',
              borderWidth: 0.5,
              borderColor: '#fff'
            },
            data: pointJson
          },
          {
            type: 'scatter3D',
            coordinateSystem: 'geo3D',
            symbol: 'pin',
            symbolSize: 28,
            itemStyle: {
              color: 'red',
              borderWidth: 0.5,
              borderColor: '#fff'
            },
            label: {
              show: true,
              distance: 5,
              position: 'top',
              lineHeight: 20,
              padding: [8, 10],
              backgroundColor: 'rgba(0,0,0,0.7)',
              textStyle: {
                color: '#fff',
                fontSize: 15,
                borderWidth: 1.5,
                borderRadius: 5,
                borderColor: '#06b2f7'
              },
              formatter: params => {
                const { data } = params;
                return `${data.name}`;
              }
            },
            data: laboratoryPoint
          },
          {
            type: 'lines3D',
            polyline: true,
            coordinateSystem: 'geo3D',
            lineStyle: {
              color: '#349ef4',
              opacity: 1,
              width: 13
            },
            zlevel: 2,
            effect: {
              show: true,
              period: 2,
              trailWidth: 11,
              trailLength: 0.5,
              trailColor: '#47e3e5'
            },
            blendMode: 'source-over',
            data: lineData
          }
        ]
      };

      this.chartMap.setOption(this.option);
      window.addEventListener('resize', () => {
        this.chartMap.resize();
      });
    }
  },
  beforeDestroy() {
    if (!this.chartMap) {
      return;
    }
    this.chartMap.dispose();
    this.ChartMap = null;
  }
};
</script>

<style scoped lang="scss">
.map-container {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  #chart-map {
    width: calc(100vw - 40px);
    height: 100%;
  }
}
</style>

总结

使用EcahrtsGL实现只需要设置配置属性即可,十分的方便,如果,你需要实现科技感的边界效果,可以使用threeJS实现,还在研究学习中。

QQ截图20240508151347.png