1
头图

本文主要介绍了在vue3项目中使用echarts开发geo地图的详细配置。
本文包含了:地图注册,地图贴图,地图切换,散点图·热力图·路径图·柱形图

直接先上项目github链接,代码注释全面,地图组件可以直接拿来在业务里使用👇

项目仓库地址

项目在线预览地址👇:

https://vue3_echarts_geo_map-rfka0hh6-kikidoulovemeruriding.4everland.app

第1步,创建好一个vue3+typescript的项目,开始安装相关库

npm i echarts -S
npm i echarts-wordcloud -S

第2步,下载一份地图geo json数据,本文使用山东省的数据,其他地区的json数据可以从阿里的dataV下载:
https://datav.aliyun.com/portal/school/atlas/area_selector

第3步,新建GeoMap.vue,引入依赖、声明props、初始化echarts实例、抛出实例:

<template>
  <div
    :style="{ height: `${props.height}px` }"
    class="map-container"
    ref="map"
  ></div>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref, withDefaults, watch } from 'vue';
import * as echarts from 'echarts';
import ShandongGeoJson from '../assets/json/shandong.json?raw';

interface Props {
  // 地图的大小主要依赖DOM容器的高度
  height?: number;
  json: string;
  // 具体业务数据(散点图 热力图 柱形图等)
  series: any;
}
const props = withDefaults(defineProps<Props>(), {
  height: 400,
  json: ShandongGeoJson,
  series: null,
});

// echats挂载的DOM节点
const map = ref<HTMLElement>();
// echarts实例
const chartInstance = ref<echarts.ECharts>();
// 抛出echarts实例,方便父组件使用
defineExpose({
  chartInstance,
});

onMounted(() => {
    //初始化实例
  chartInstance.value = echarts.init(map.value);
}
onUnmounted(() => {
  // 释放echarts实例
  chartInstance.value?.dispose();
})
</script>

<style lang="less" scoped>
.map-container {
  width: 600px; // 为了演示效果,这里固定宽度, 通常给100%, 宽度由父级DOM决定
}
</style>

第4步,分别定义地图注册方法,贴图绘制方法,配置地图方法,并写好watch监听props.series和props.json执行方法:

<template>
  <div
    :style="{ height: `${props.height}px` }"
    class="map-container"
    ref="map"
  ></div>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref, withDefaults, watch } from 'vue';
import * as echarts from 'echarts';
import ShandongGeoJson from '../assets/json/shandong.json?raw';

interface Props {
  // 地图的大小主要依赖DOM容器的高度
  height?: number;
  json: string;
  // 具体业务数据(散点图 热力图 柱形图等)
  series: any;
}
const props = withDefaults(defineProps<Props>(), {
  height: 400,
  json: ShandongGeoJson,
  series: null,
});

// echats挂载的DOM节点
const map = ref<HTMLElement>();
// echarts实例
const chartInstance = ref<echarts.ECharts>();
// 抛出echarts实例,方便父组件使用
defineExpose({
  chartInstance,
});


// 注册地图
const registerMap = (value?: echarts.SeriesOption) => {
  echarts.registerMap('shandong', JSON.parse(props.json));
  if (chartInstance.value) {
    // 判断options是否为空,为空则执行初始渲染,不为空则执行更新
    const options = chartInstance.value.getOption();
    if (options) {
      options.series = value;
      chartInstance.value.setOption(options);
    } else {
      drawSticker(value);
    }
  } else {
    console.error('echarts实例未初始化,无法渲染地图');
  }
};

/**
 * 绘制地图
 * 绘制地图贴图要早于渲染地图,否则地图贴图会出现黑色贴图的情况
 *
 */
const drawSticker = (value?: echarts.SeriesOption) => {
  let sticker: HTMLCanvasElement;
  const width = map.value?.offsetWidth ?? 1000;
  const stickerDom = document.getElementById('sticker') as HTMLCanvasElement;
  if (!stickerDom) {
    sticker = document.createElement('canvas');
    sticker.id = 'sticker';
    map.value?.appendChild(sticker);
  } else {
    sticker = stickerDom;
  }
  // 贴图的大小,宽高一致,一般情况下小于props.height更为合适,根据实际情况调整
  sticker.width = props.height;
  sticker.height = props.height;
  const stickerCtx = sticker.getContext('2d');
  const image = new Image();
  image.src = new URL('../assets/image/sticker.jpg', import.meta.url).href;
  image.onload = () => {
    // 5个参数分别为:图片、x原点、y原点、宽度、高度
    stickerCtx?.drawImage(image, 0, 0, width, width);
    // 不显示贴图在文档流中
    sticker.style.display = 'none';
    generateMap(value);
  };
};

const generateMap = (value?: echarts.SeriesOption) => {
  const echartsOptions = {
    // 一般背景一定设置为透明
    backgroundColor: 'transparent',
    /**
     * 这里的tooltip为《地图本身》鼠标移入显示的div,这里设置为false,不会影响散点图 热力图等series设置的tooltip
     */
    tooltip: {
      show: true,
    },
    grid: {
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
    },
    geo: [
      {
        map: 'shandong',
        roam: false,
        // 开启多选
        selectedMode: 'multiple',
        left: '18%',
        top: '18%',
        // 应用在第一层的tooltip
        tooltip: {
          show: true,
          // 使用自定义的tooltip样式,下面这四个属性要这么设置,避免影响到自己的样式
          backgroundColor: 'transparent',
          borderWidth: 0,
          padding: 0,
          extraCssText: 'box-shadow: none',
          // className: 'tooltip-style',
          // 自定义的tooltip样式,可以在《公共css文件》声明css类在此使用,当然也可以直接使用style行内样式
          formatter: (params: any) => {
            return `
            <div class="tooltip-style">
              <p>
                ${params?.name}  
              </p>
            </div>
        `;
          },
        },
        // 可以给某个地区单独设置样式
        regions: [
          {
            name: '青岛市', // 必须提供对应的name
            itemStyle: {},
          },
        ],
        label: {
          show: true,
          fontSize: 12,
          // fontFamily: 'YSXS',
        },
        itemStyle: {
          borderColor: 'red',
          borderWidth: 1,
          color: {
            image: document.getElementById('sticker'),
            repeat: 'no-repeat',
          },
        },
        z: 2,
      },
      {
        map: 'shandong', //注册地图的名字
        roam: false, //开启鼠标缩放和平移漫游。默认不开启
        left: '18.8%',
        top: '18.8%',
        label: {
          show: false
        },
        itemStyle: {
          shadowColor: '#000',
          shadowOffsetX: 6,
          shadowOffsetY: 6,
          shadowBlur: 3,
          color: 'darkgreen', // 背景
          borderWidth: 1, // 边框宽度
          borderColor: 'red', // 边框颜色
          fontSize: 0.1, //
        },
        z: 1,
      },
    ],
    visualMap: {
      type: 'continuous',
      map: 'shandong',
      show: false,
      top: 'top',
      min: 1,
      max: 1 * 100,
      // seriesIndex: 0,
      splitNumber: 5,
      inRange: {
        color: ['#d94e5d', '#eac736', '#50a3ba'].reverse(),
      },
      calculable: true,
    },
    series: [value],
  };
  chartInstance.value?.setOption(echartsOptions);
  // 重绘一次,不然省会城市会缺失,暂时没有发现BUG问题所在
  chartInstance.value?.resize();
};

onMounted(() => {
    //初始化实例
  chartInstance.value = echarts.init(map.value);
// 监听两个数据
  watch(
    () => props.series,
    (newValue) => {
      registerMap(newValue);
    },
    {
      immediate: true,
    }
  );
  // 监听新的地图json数据,渲染地图
  watch(
    () => props.json,
    (newValue) => {
      registerMap(newValue);
    }
  );
}
onUnmounted(() => {
  // 释放echarts实例
  chartInstance.value?.dispose();
})
</script>

<style lang="less" scoped>
.map-container {
  width: 600px; // 为了演示效果,这里固定宽度, 通常给100%, 宽度由父级DOM决定
}
</style>

到这里地图组件已经封装好了,在父级组件开始使用。

第5步,在父级组件引入地图组件使用:

<template>
  <div
    id="main"
    class="main"
  >
    <div class="btn-list">
      <button @click="switchData(scatterSeries)">散点图</button>
      <button @click="switchData(heatmapSeries)">热力图</button>
      <button @click="switchData(lineseries)">路径图</button>
      <button @click="handleMockBarData">柱形图</button>
      <button @click="handleChangeMap">
        {{ currentJson === ShandongJson ? '切换到青岛市' : '切换到山东省' }}
      </button>
    </div>
    <div id="map-container">
      <GeoMap
        ref="map"
        :series="currentData"
        :height="600"
        :json="currentJson"
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
// 引入地图JSON用来切换地区
import ShandongJson from './assets/json/shandong.json?raw';
import QindaoJson from './assets/json/qingdao.json?raw';
import GeoMap from './components/GeoMap.vue';

// map子组件的模板引用,我们通过这里可以访问到子组件的echarts实例
const map = ref<any>(null);

// 演示不同数据类型的地图
const currentData = ref();
// 演示不同地区的地图
const currentJson = ref(ShandongJson);
const switchData = (data: any) => {
  currentData.value = data;
};

/**
 * 地图中心点, 通常地图json中有确定的中心点,实际应用中我们需要根据具体视图UI来自定义中心点
 * json数据里的center: [*****, *****]就是中心点的经纬度数组,可以取来改动和使用
 * 中心点主要在用在,给不含有经纬度的数据集,通过遍历赋值,添加上我们预设的中心点经纬度
 */
const regionCenterPoints = [
  {
    name: '青岛市',
    value: [120.355173, 36.082982],
  },
  {
    name: '烟台市',
    value: [121.391382, 37.539297],
  },
  {
    name: '济南市',
    value: [117.000923, 36.675807],
  },
];
console.log(regionCenterPoints);
// 父组件把处理好的series传给子组件, 这里展示几种业务常用的图表类型

/**
 * 1. 散点图
 * 数据格式: [{name: '数据名称', value: [经度, 纬度]}],name是可选项
 * 默认散点大小是一样大,即symbolSize为10,自行设置symbolSize可以控制点的大小
 * 散点的颜色,如果map子组件里声明了visualMap,将会使用visualMap inrange的第一个颜色,
 * 如果要更改,需要在data数据里传入itemStyle更改颜色
 * 其他散点图的参数参考 https://echarts.apache.org/zh/option.html#series-scatter
 */
const scatterSeries = ref<echarts.ScatterSeriesOption>({
  type: 'scatter',
  coordinateSystem: 'geo',
  z: 10,
  data: [
    {
      name: '青岛市',
      value: [120.355173, 36.082982],
      symbolSize: 30,
      itemStyle: {
        color: 'red',
      },
    },
    {
      name: '烟台市',
      value: [121.391382, 37.539297],
      symbolSize: 80,
    },
    {
      name: '济南市',
      value: [117.000923, 36.675807],
    },
  ],
  tooltip: {
    show: true,
    // echarts这个formatter函数参数的类型声明很多没有导出,直接用any
    formatter: (params: any) => {
      return `<div style="background: red">${params?.data.value[0]}</div>`;
    },
  },
});

/**
 * 2. 热力图
 * 数据格式:[[经度,纬度,热力值],...]
 * 使用热力图必须要在map子组件里定义visualMap,否则无法显示
 * 其他热力图的参数参考 https://echarts.apache.org/zh/option.html#series-heatmap
 *
 */
const heatmapSeries = ref<echarts.HeatmapSeriesOption>({
  type: 'heatmap',
  coordinateSystem: 'geo',
  data: [
    [120.355173, 36.082982, 100],
    [121.391382, 37.539297, 100],
    [119.121733, 36.146036, 100],
    [119.121733, 36.146037, 100],
    [119.121733, 36.146038, 100],
    [119.121733, 36.146039, 100],
    [119.121733, 36.146031, 100],
    [119.121733, 36.146032, 100],
    [119.121733, 36.146033, 100],
  ],
  z: 8,
  geoIndex: 0,
  blurSize: 20,
});

/**
 * 3. 路径图
 * 数据格式:[{coords: [[经度,纬度],[经度,纬度]], lineStyle: {}}] , coord是二维数组
 * coords数组第一项为起始点的经纬度,第二项为终点的经纬度,lineStyle是线的样式可选项
 * 其他路径图的参数参考 https://echarts.apache.org/zh/option.html#series-lines
 */
const lineseries = ref<echarts.LinesSeriesOption>({
  type: 'lines',
  coordinateSystem: 'geo',
  data: [
    {
      coords: [
        [120.355173, 36.082982],
        [121.391382, 37.539297],
      ],
      lineStyle: {
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          {
            offset: 0,
            color: '#3B80E2',
          },
          {
            offset: 1,
            color: '#49BEE5',
          },
        ]),
        width: 2,
      },
    },
    {
      coords: [
        [120.355173, 36.082982],
        [117.000923, 36.675807],
      ],
      lineStyle: {
        color: 'darkgreen',
        width: 2,
      },
    },
  ],
  lineStyle: {
    curveness: 0.3, // 线的曲度,默认为0直线,0-1的取值范围,值越大曲度越大,可以为负数即设置为反向弧度
  },
  effect: {
    show: true, // 是否显示特效
    period: 6, // 特效动画时间,单位s
    trailLength: 0.9, // 特效尾迹长度,取值0-1,值越大尾迹越长
    constantSpeed: 40, // 特效动画速度,值为像素点,越大越快
    color: 'lightblue', // 特效标记的颜色
    symbol: 'circle', // 特效标记的图形,可以使用图片等
    symbolSize: 10, // 特效标记的大小
  },
});
/**
 * 4. 柱形图
 * 柱形图稍微复杂一些,由于coordinateSystem无法设置geo,只能设置为直角坐标系
 * 所以在这里要做一下geo经纬度到二维坐标的转换才能使用
 * 处理好的数据并不是series数据,而是需要重新执行setOption
 * 其他柱形图的参数参考 https://echarts.apache.org/zh/option.html#series-bar
 * 通过该示例,其余大部分的二维坐标的图表都可以自行摸索实现
 */

const mockBarData = [
  {
    name: '青岛市',
    value: [120.355173, 36.082982],
    count: 100,
  },
  {
    name: '烟台市',
    value: [121.391382, 37.539297],
    count: 10,
  },
  {
    name: '济南市',
    value: [117.000923, 36.675807],
    count: 20,
  },
];

const barSeries = ref<any>({
  xAxis: [],
  yAxis: [],
  series: [],
  grid: [],
});
const handleMockBarData = () => {
  mockBarData.forEach((item: any, index: number) => {
    const geoCoords = item.value; // 获取经纬度
    // 转换后的二维坐标
    const coords: any = map.value?.chartInstance?.convertToPixel(
      'geo',
      geoCoords
    );
    index += 1;
    barSeries.value.xAxis.push({
      id: index, // 组件id,在配置中引用标识
      gridIndex: index, // x轴所在的grid的索引
      gridId: index,
      type: 'category', // 设置为主轴
      splitArea: {
        show: false,
      },
      splitLine: {
        // 是否显示坐标轴在 grid 区域中的分隔线
        show: false,
      },
      axisTick: {
        // 是否显示坐标轴刻度
        show: false,
      },
      axisLabel: {
        // 是否显示坐标轴刻度标签
        show: false,
      },

      axisLine: {
        // 是否显示坐标轴轴线
        show: false,
      },
      z: 100,
      // 通常设置一个比较大的数值 确保柱形图在最高层
    });
    // Y轴配置
    barSeries.value.yAxis.push({
      id: index, // 组件id,在配置中引用标识
      gridIndex: index, // x轴所在的grid的索引
      gridId: index,
      // 默认柱子的高度是相同的,如果要设置为不同,调整min 和 max
      // min: 0.1,
      // max: 60,
      // interval: 0.1,
      splitLine: {
        // 坐标轴在 grid 区域中的分隔线
        show: false,
      },
      axisTick: {
        // 坐标轴刻度
        show: false,
      },
      axisLabel: {
        // 坐标轴刻度标签
        show: false,
      },
      axisLine: {
        // 坐标轴轴线
        show: false,
      },
      splitArea: {
        show: false,
      },
      z: 100,
    });
    // 坐标系配置控制柱子的位置,需要根据实际UI视图来调整 left top
    barSeries.value.grid.push({
      gridIndex: index, // x轴所在的grid的索引
      gridId: index,
      id: index, // 组件id,在配置中引用标识
      width: 100, // 组件的宽度
      height: 100, // 组件的高度
      left: coords[0] - 50, // 离容器左侧的距离
      top: coords[1] - 105, // 离容器上侧的距离
      z: 100,
    });
    barSeries.value.series.push({
      labelLine: {
        show: false,
      },
      emphasis: {
        show: false,
        disabled: true,
      },
      z: 100,
      id: index, // 组件id,在配置中引用标识
      type: 'bar', // 柱状图
      xAxisId: index, // 使用的x轴的id
      yAxisId: index, // 使用的y轴的id
      barGap: 0, // 柱间距离
      barWidth: 8,
      barCategoryGap: 0, // 同一系列的柱间距离
      data: [item.count], // 柱子数据, 可以设置多个数据,显示多个柱子
      label: {
        show: false,
        itemStyle: {
          color: 'red',
        },
      },
      itemStyle: {
        // 柱子样式
        borderRadius: [4, 4, 0, 0],
        color: new echarts.graphic.LinearGradient(
          0,
          0,
          0,
          1,
          [
            {
              offset: 0,
              color: 'rgba(232, 137, 58, 1)',
            },
            {
              offset: 1,
              color: 'rgba(232, 137, 58, 0.2)',
            },
          ],
          false
        ),
      },
    });
  });
  // 执行setOption, 通常会和之前的图表合并,如果不想合并,传递第二个参数{replaceMerge: 'series'}
  map.value.chartInstance.setOption(barSeries.value, {
    replaceMerge: 'series',
  });
};

/**
 * 关于缩放和拖动的问题,echarts自带的roam问题很多:
 * 问题1:地图贴图之后,只有地图本身,表面没有图表的时候,只有在地图空白区域才可以拖动和缩放
 * 问题2:地图表面加入图表后,拖动和缩放只对第一层geo生效
 * 问题3:通过使用监听事件georoam,对除了第二层geo的地图进行拖动和缩放,会卡顿无比(GeoMap.vue)
 * 问题4:缩放和拖动对geo经纬转成二维坐标的图表不生效,例如上面的柱形图
 * 综上自己实现一个wheel监听,缩放父级dom元素,算是一个折中的解决方案
 */
let num = 1;
const handleMouseEvent = () => {
  const main = document.getElementById('main');
  const mapContainer = document.getElementById('map-container');

  main?.addEventListener('wheel', (event: WheelEvent) => {
    // 该缩放方案tooltip会出现移动位置的问题,所以直接把显示中的tooltip隐藏了
    map.value?.chartInstance?.dispatchAction({
      type: 'hideTip',
    });
    event.preventDefault();
    if (event.deltaY < 0) {
      num += 0.1;
      mapContainer!.style.transform = `scale(${num})`;
    } else {
      if (num < 0.11) {
        num = 0.1;
      } else {
        num -= 0.1;
      }
      mapContainer!.style.transform = `scale(${num})`;
    }
  });
};

// 切换地图JSON即可完成切换
const handleChangeMap = () => {
  currentJson.value =
    currentJson.value === ShandongJson ? QindaoJson : ShandongJson;
};
// 监听地图的点击事件
const handleClickMap = () => {
  map.value?.chartInstance?.on('click', (params: any) => {
    if (params.componentType === 'geo') {
      if (params.name === '青岛市') {
        currentJson.value = QindaoJson;
      }
    }
  });
};
// 监听地图的选中事件
const handleSelectMap = () => {
  map.value?.chartInstance?.on('geoselectchanged', (params: any) => {
    console.log(params.selected, 'selectchanged');
  });
};

onMounted(() => {
  handleMouseEvent();
  handleClickMap();
  handleSelectMap();
});
</script>

<style lang="less">
.tooltip-style {
  width: 100px;
  height: 33px;
  padding: 5px;
  border-radius: 8px;
  background: darkorange;
  color: #fff;
  line-height: 33px;
  p {
    margin: 0;
  }
}
.main {
  width: 1000px;
  height: 1000px;
  position: relative;
  .btn-list {
    width: 500px;
    display: flex;
    position: relative;
    z-index: 1000;
    justify-content: space-between;
  }
  #map-container {
    position: absolute;
    transition: all 0.1s linear;
  }
}
</style>

上面代码中已经列出了散点图 热力图 路径图 柱形图 还有地图点击事件和选中事件的回调函数示例。一切顺利的话,你应该已经看到地图了。
image.png

其他方面,关于echarts地图的缩放平移建议用监听鼠标事件通过css操作父级dom的方式实现(如上面代码),当然你也可以使用监听echarts缩放事件来实现:

  chartInstance.value?.on('georoam', (params: any) => {
    const options: any = chartInstance.value?.getOption();
    if (params?.zoom) {
      // 缩放
      options.geo.slice(1)?.forEach((item: any) => {
        item.zoom = options?.geo?.[0]['zoom'];
        item.center = options?.geo?.[0]['center'];
      })
    } else {
      // 移动
      options.geo.slice(1)?.forEach((item: any) => {
        item.center = options?.geo?.[0]['center'];
      })
    }
    chartInstance.value?.setOption(options, {
      replaceMerge: ['geo'],
    });
  })

但是效果很卡顿...

关于设置地图最外层边框和地图内部边框不一样的颜色宽度,可以修改GeoMap.vue组件里的generateMap方法如下:

const generateMap = (value?: echarts.SeriesOption) => {
  const echartsOptions = {
    // 一般背景一定设置为透明
    backgroundColor: 'transparent',
    /**
     * 这里的tooltip为《地图本身》鼠标移入显示的div,这里设置为false,不会影响散点图 热力图等series设置的tooltip
     */
    tooltip: {
      show: true,
    },
    grid: {
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
    },
    geo: [
      {
        map: 'shandong',
        roam: false,
        selectedMode: 'multiple',
        left: '18%',
        top: '18%',
        // 应用在第一层的tooltip
        tooltip: {
          show: true,
          // 使用自定义的tooltip样式,下面这四个属性要这么设置,避免影响到自己的样式
          backgroundColor: 'transparent',
          borderWidth: 0,
          padding: 0,
          extraCssText: 'box-shadow: none',
          // className: 'tooltip-style',
          // 自定义的tooltip样式,可以在《公共css文件》声明css类在此使用,当然也可以直接使用style行内样式
          formatter: (params: any) => {
            return `
            <div class="tooltip-style">
              <p>
                ${params?.name}  
              </p>
            </div>
        `;
          },
        },
        // 可以给某个地区单独设置样式
        regions: [
          {
            name: '青岛市', // 必须提供对应的name
            itemStyle: {},
          },
        ],
        label: {
          show: true,
          fontSize: 12,
          // fontFamily: 'YSXS',
        },
        itemStyle: {
          borderColor: 'red',
          borderWidth: 1,
          color: {
            image: document.getElementById('sticker'),
            repeat: 'no-repeat',
          },
        },
        z: 2,
      },
      {
        map: 'shandong', //注册地图的名字
        roam: false, //开启鼠标缩放和平移漫游。默认不开启
        left: '18.8%',
        top: '18.8%',
        label: {
          show: false
        },
        itemStyle: {
          shadowColor: '#000',
          shadowOffsetX: 6,
          shadowOffsetY: 6,
          shadowBlur: 3,
          color: 'darkgreen', // 背景
          borderWidth: 1, // 边框宽度
          borderColor: 'red', // 边框颜色
          fontSize: 0.1, //
        },
        z: 1,
      },
    ],
    visualMap: {
      type: 'continuous',
      map: 'shandong',
      show: false,
      top: 'top',
      min: 1,
      max: 1 * 100,
      // seriesIndex: 0,
      splitNumber: 5,
      inRange: {
        color: ['#d94e5d', '#eac736', '#50a3ba'].reverse(),
      },
      calculable: true,
    },
    /**
     *  需要设置最外层和内部的边框不同颜色时,在series这里声明一层map,把第一层geo配置全部给到这里,
     *  纹理贴图需要设置到areaColor那里
     *  第一层的borderWidth 大于 这里的borderWidth 即可实现最外层和内部的边框样式不同的效果
     */
    series: [
      {
        type: 'map',
        map: 'shandong',
        itemStyle: {
          borderWidth: 1,
          areaColor: document.getElementById('sticker'),
        },
      }
    ]
  };
  chartInstance.value?.setOption(echartsOptions);
  // 重绘一次,不然省会城市会缺失,暂时没有发现BUG问题所在
  chartInstance.value?.resize();
};

关于地图的立体感, 这需要看你的UI设计稿的复杂度,不是很复杂的设置一层geo添加阴影即可,复杂的就在geo数组里多加几层,堆叠出想要的效果,配置的时候,z这个参数越大的越在上层。

代码注释里有很多细节说明,这里就不一一赘述了,各位clone一下代码跑起来看看,实践一下。有任何不懂得问题可以在评论区回复,我看到了一定会回复的。see you!


盛必击击而破之
8 声望1 粉丝

毕业于山东蓝翔高级技工学校,挖掘机专业,在校期间选修了第二专业美容美发。