教你从零开始画echarts地图

教你从零开始画echarts地图echarts 地图制作离线地图下载地址 https datav aliyun com tools atlas index htmlecharts 文档地址 https echarts apache org zh option html 基于 VUE 编写 其他框架请自行转换 大同小异基础配置先让地图内容出来 npm 安装步骤省略 请参考官方文档 创建的 div 必须设置宽度和高度 关于图表的宽高自适应 参考我的另一篇文章 template template

echarts地图制作

  • 离线地图下载地址https://datav.aliyun.com/tools/atlas/index.html
  • echarts文档地址https://echarts.apache.org/zh/option.html

基于VUE编写,其他框架请自行转换,大同小异

基础配置

先让地图内容出来,npm安装步骤省略,请参考官方文档,创建的div必须设置宽度和高度,关于图表的宽高自适应,参考我的另一篇文章

 
    

这是最基础的配置,外加了一些我自己写的样式,使地图美观一些,如果你完全的复制,并且china.json文件也引入了,那么你会看到如下的内容

请添加图片描述

这其中比较有意思的是,如果你注册地图时,还有option.geo.map的名字用的是china,南海诸岛会如上图以缩略图展示,但是以此之外来命名地图,则不会展示缩略图。

再次声明,如果二者名字不一致,将会导致异常,致使地图无法显示

数据渲染

实际开发中,往往需要将后台的数据渲染到地图里,我们在option里添加series属性,以下是我的两个示例,仅做参考:

series: [ { 
    type: "scatter", coordinateSystem: "geo", symbol: "pin", legendHoverLink: true, symbolSize: [60, 60], // 这里渲染标志里的内容以及样式 label: { 
    show: true, formatter(value) { 
    return value.data.value[2]; }, color: "#fff", }, // 标志的样式 itemStyle: { 
    normal: { 
    color: "rgba(255,0,0,.7)", shadowBlur: 2, shadowColor: "D8BC37", }, }, // 数据格式,其中name,value是必要的,value的前两个值是数据点的经纬度,其他的数据格式可以自定义 // 至于如何展示,完全是靠上面的formatter来自己定义的 data: [ { 
    name: "西藏", value: [91.23, 29.5, 2333] }, { 
    name: "黑龙江", value: [128.03, 47.01, 1007] }, ], showEffectOn: "render", rippleEffect: { 
    brushType: "stroke", }, hoverAnimation: true, zlevel: 1, }, // { 
    // type: "effectScatter", // coordinateSystem: "geo", // effectType: "ripple", // showEffectOn: "render", // rippleEffect: { 
    // period: 10, // scale: 10, // brushType: "fill", // }, // hoverAnimation: true, // itemStyle: { 
    // normal: { 
    // color: "rgba(255, 235, 59, .7)", // shadowBlur: 10, // shadowColor: "#333", // }, // }, // zlevel: 1, // data: [ // { name: "西藏", value: [91.23, 29.5, 2333] }, // { name: "黑龙江", value: [128.03, 47.01, 1007] }, // ], // }, ], 

两种渲染方式如下:

请添加图片描述

请添加图片描述

使用备注的部分时,需要在option.tooltip里添加formatter属性,我写的如下:

const option = { 
    // ... tooltip: { 
    // ... formatter(params) { 
    return `地区:${ 
     params.name}数值:${ 
     params.value[2]}`; } } } 

更多的方式还要自己多试验,这是个费时且需要耐心的活,你甚至可以将柱状图放上去。有更花里胡哨的效果,也请分享给我。

嵌入文字

使用option.graphic可以实现简单的水印效果

const option = { 
    // ... graphic:{ 
    // 水印类型 type: 'text', // 相对于容器的位置 left:'10%', top: '10%', // 样式设置 style: { 
    // 文本内容 text: "create by cRack_cLick", // 字体粗细、大小、字体 font: 'bolder 1.5rem "Microsoft YaHei", sans-serif', // 字体颜色 fill: "#fff" } } } 

效果如下:

请添加图片描述

利用graphictype=“group”,还可以组合出一些有意思的效果(抄官方文档的效果):

 graphic: { 
    type: "group", rotation: Math.PI / 4, bounding: "raw", left: 110, top: 110, z: 100, children: [ { 
    type: "rect", left: "center", top: "center", z: 100, shape: { 
    width: 400, height: 50, }, style: { 
    fill: "rgba(0,0,0,0.3)", }, }, { 
    type: "text", left: "center", top: "center", z: 100, style: { 
    fill: "#ddd", text: "create by cRack_cLick", font: 'bolder 1.5rem "Microsoft YaHei", sans-serif', }, }, ], }, 

请添加图片描述

地图下钻

往往还有一种需求,在我们点击一个省的时候,需要切换到这个省的详细地图,甚至还可以下钻到市、县等等。

为了试下点击下钻,我们需要先了解echarts中的点击事件,文档参考

以目前的功能来说,我们暂时不需要加入其它的业务逻辑以及省级的数据渲染,仅仅只做地图的切换,所以点击事件里我们需要实现获取点击的省份名称,然后根据省份名称,来选择地图的JSON文件,最后重新渲染echarts图表,下面是我的简单示例:

// 新增加北京的地图JSON文件 import beijing from "@/assets/mapJson/data-beijing.json"; // ... initCharts(){ 
    const charts = echarts.init(this.$refs["charts"]); // ... // 注意这里是echarts的实例对象,而不是echarts组件本身。 charts.on('click', ({ 
    name}) => { 
    if (name === "北京") { 
    // 修改option的配置,可以继续自定义 option.geo.zoom = 0.8 // 就像上面提到的,这里必须要和注册地图时的名字一致 option.geo.map = "beijing" // 注册地图 echarts.registerMap("beijing", beijing) // 重新渲染 charts.setOption(option, true) } }) } 

需要注意的是,在重新setOption的时候,我们加入了第二个参数,按照官方文档的说法:


参数:

调用方式:

chart.setOption(option, notMerge, lazyUpdate); 

或者

chart.setOption(option, { 
     notMerge: ..., lazyUpdate: ..., silent: ... }); 
  • option

    图表的配置项和数据。

  • notMerge

    可选,是否不跟之前设置的 option 进行合并,默认为 false,即合并。

  • lazyUpdate

    可选,在设置完 option 后是否不立即更新图表,默认为 false,即立即更新。

  • silent

    可选,阻止调用 setOption 时抛出事件,默认为 false,即抛出事件。


第二个从参数设置为true来让图表重新渲染,而不合并配置,当然,这一点具体需要看你显示开发的需求,我在这里仅是为了演示。绝不是偷懒

另外在echarts v3.x的版本里,切换地图默认是有过渡动画的,而v4.xv5.x的版本里则没有过渡动画,如果知道怎么加上的,可以私信我。

上面虽然可以实现地图切换,但很显然开发中这么写要被打死。下钻三十多个地图要写三十多个if,显然是一种不理智的开发方式。一种方式我们可以通过axios或者ajax异步请求,但是这样需要你在生产环境和运维协商好,否则会导致请求不到JSON文件。

下面是我在前端写的一个简单的工具方法,仅供参考:

import zhongguo from "@/assets/mapJson/data-city.json"; import neimenggu from "@/assets/mapJson/data-neimenggu.json"; import beijing from "@/assets/mapJson/data-beijing.json"; // ... const mapDict = { 
      "北京": "beijing", "内蒙古": "neimenggu", // ... } const mapData = { 
      beijing, neimenggu, // ... } export function getMap(mapName) { 
      const cityName = mapDict[mapName] if(cityName){ 
      return [cityName, mapData[cityName]] } return ['china', zhongguo] } 

需要建立两个字典,一个是汉字和拼音的对照映射,一个是拼音和JSON文件的映射,这个可灵活配置,并非唯一。

优化一下上面的的代码:

// 删除地图json文件的引用,修改为上面的工具方法 import { 
      getMap } from "./maputil"; methods: { 
      initCharts() { 
      const charts = echarts.init(this.$refs["charts"]); const option = { 
      // ... }; // 不传name默认会返回中国地图 const [mapName, mapJson] = getMap(); option.geo.map = mapName; // 地图注册,第一个参数的名字必须和option.geo.map一致 echarts.registerMap(mapName, mapJson); charts.setOption(option); charts.on("click", ({ 
       name }) => { 
      // 这里和上面一样,其实还可以再优化一下。为了方便阅读,这里不再封装。 const [mapName, mapJson] = getMap(name); option.geo.zoom = 0.8; option.geo.map = mapName; echarts.registerMap(mapName, mapJson); charts.setOption(option, true); }); } } 

效果如下:

请添加图片描述

结合水印制作级联效果

现在的地图可以下钻了,但是似乎操作起来还有些别扭。

我们现在想要的效果是:我们需要每下钻一层,水印部分就会加上当前地区的名称。点击水印地区的名称,就会跳转到当前地区的地图,我们要来改造一下echarts示例的click事件。

首先option.graphic的默认值修改为中国地图,这里为了方便阅读,仅使用text格式演示:

// ... graphic: [ { 
      type: "text", left: "10%", top: "10%", style: { 
      text: "中国", font: 'bolder 1.5rem "Microsoft YaHei", sans-serif', fill: "#fff", }, }, ], 

以数组的形势编写后,思路就明显了,只要在click事件的时候,将下钻地图的信息push进来,并且为了防止重合,稍微移动一下定位即可,我的示例如下:

charts.on("click", ({ 
       name }) => { 
      const [mapName, mapJson] = getMap(name); option.geo.zoom = 0.8; option.geo.map = mapName; // 为了重新定位,这里使用了length const idx = option.graphic.length + 1; option.graphic.push({ 
      type: "text", left: `${ 
       idx * 10}%`, top: "10%", style: { 
      text: name, font: 'bolder 1.5rem "Microsoft YaHei", sans-serif', fill: "#fff", }, }); echarts.registerMap(mapName, mapJson); charts.setOption(option, true); }); 

点击后效果如下:

请添加图片描述

现在还有问题,就是点击地区名字没有响应,所以我们还要为option.graphic子元素加上click事件

这个click事件功能也类似,获取地图名称,获取地图数据,重新渲染。但是这个click事件需要注意,比如我点击了北京,那么在数组里是需要将密云区的元素删除掉的,同理,点击中国,则后面的元素都要删除。在这里我就不把相同的部分抽离出来了:

// 防止graph里频繁添加click事件,在添加click事件之前先全部清空掉。 charts.off() charts.on("click", ({ 
      name}) => { 
      // 如果option.graphic里已经有了城市名称,则不进行任何操作,防止频繁点击 const index = option.graphic.findIndex(i => i.style.text === name); if (!name || index !== -1) return const [mapName, mapJson] = getMap(name); option.geo.zoom = 0.8; option.geo.map = mapName; // 为了重新定位,这里使用了length const idx = option.graphic.length + 1; option.graphic.push({ 
      type: "text", left: `${ 
       idx * 10}%`, top: "10%", style: { 
      text: name, font: 'bolder 1.5rem "Microsoft YaHei", sans-serif', fill: "#fff", }, onclick: () => { 
      // 利用函数的作用域,可以直接拿上面的name来用 const [grahpName, graphJson] = getMap(name); const index = option.graphic.findIndex(i => i.style.text === name); // 点击元素之后的所有元素全部删除 option.graphic.splice(index + 1); // 很多操作重复了,你可以将公共部分抽离出来 option.geo.map = mapName; echarts.registerMap(grahpName, graphJson); charts.setOption(option, true); }, }); echarts.registerMap(mapName, mapJson); charts.setOption(option, true); }); 

这里会有个坑,在给graph添加click事件后,点击时会同时触发我们上面charts.on的click事件,想了很久也没有找到好一点的方式来解决这个事件冲突,最后只好判断了一下name是否为空来暂时解决。如果有更好的办法,也请留言。最终效果如下:

请添加图片描述

至此绘制地图已经完毕,更多是依靠自己的业务需求来进行更灵活的配置和渲染,它的API没有什么太复杂的,只是我们缺少了一点耐心去实验。

visualMap

首先来看效果

请添加图片描述

增加visualMap来让地图的数据渲染更有层次感,实现起来也很简单,只需要在option里增加visualMap配置即可:

const option = { 
      // ... visualMap: { 
      // 是否展示左下角,即是是false,也仅是不显示,不影响数据的映射 show: true, // 上下端文字 text: ["高", "低"], // 最小值和最大值,必须指定 min: 0, max: 6000, // 位置 left: "10%", bottom: "10%", // 是否展示滑块 calculable: true, // 指定映射的数据,对应的是option.series,这里根据自己的实际需要进行配置 seriesIndex: [0], // 从下到上的颜色 inRange: { 
      color: ['#00467F', '#A5CC82'], }, //字体颜色 textStyle: { 
      color: "#fff", map: "china", }, } } 

如果你的代码是跟着我从上面一直写下来的,那么此时你应该发现只是定位的图标变了,相应的地图区域并未变色,所以我们还要把地图的数据映射上去,所以在option.series里再加一个元素,使其type=“map”,内容与geo一致即可,但是要多加data属性,渲染的数据和定位图标一致。并将seriesIndex的索引做好映射,即可实现。

const option = { 
      // ... visualMap: { 
      // 是否展示左下角,即是是false,也仅是不显示,不影响数据的映射 show: true, // 上下端文字 text: ["高", "低"], // 最小值和最大值,必须指定 min: 0, max: 6000, // 位置 left: "10%", bottom: "10%", // 是否展示滑块 calculable: true, // 指定映射的数据,对应的是option.series,这里根据自己的实际需要进行配置 seriesIndex: [0], // 从下到上的颜色 inRange: { 
      color: ['#00467F', '#A5CC82'], }, //字体颜色 textStyle: { 
      color: "#fff", map: "china", }, } } 

如果你的代码是跟着我从上面一直写下来的,那么此时你应该发现只是定位的图标变了,相应的地图区域并未变色,所以我们还要把地图的数据映射上去,所以在option.series里再加一个元素,使其type=“map”,内容与geo一致即可,但是要多加data属性,渲染的数据和定位图标一致。并将seriesIndex的索引做好映射,即可实现。

如果出现了缩放重影,说明生成了两个地图组件,需要在新的series里加上geoIndex属性,值是geo里的索引,这样就只会共享一个组件,不会出现缩放重影的问题了

以下为源文档:

默认情况下,map series 会自己生成内部专用的 geo 组件。但是也可以用这个 geoIndex 指定一个 geo组件。这样的话,map 和 其他 series(例如散点图)就可以共享一个 geo组件了。并且,geo组件的颜色也可以被这个 map series 控制,从而用 visualMap来更改。

当设定了 geoIndex 后,series-map.map属性,以及 series-map.itemStyle 等样式配置不再起作用,而是采用 geo中的相应属性。


很多人找我要源码,博主的本意是希望大家可以自己实验,加深印象。就我个人来说,我拿到源码后就懒得去研究了,总觉得自己已经会了。但介于可能很多人还是刚刚接触,对很多内容并不熟悉,所以在这里贴一下源码,只不过因为时间久远,已经找不到写文章时的代码了,这里贴的是从项目里抽出来的代码,可能会有一些冗余,所以大家尽量参考文章来理解:源码地址

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/198235.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午3:30
下一篇 2026年3月26日 下午3:31


相关推荐

  • 低压差降压稳压电路设计

    低压差降压稳压电路设计TPS73xx系列(TPS7301,25,30,33,48,50等)是一款低压差串联型降压稳压芯片,可以提供500mA的稳压电流,在输出100mA电流的情况下,输入输出电压压差可以最多不超过35mV,这可以大大提高稳压电源的效率,或者提供大的电源稳压范围。除了主要提供电源稳压功能之外,芯片内部还集成了电压检测模块,可以输出低电平RESET信号,为供电的微控制器、处理器提供复位功能。TPS7…

    2022年6月20日
    31
  • 部署gpt-oss-20b:Docker镜像使用全流程指南

    部署gpt-oss-20b:Docker镜像使用全流程指南

    2026年3月15日
    2
  • 清晰的java代码初学者,一个不错的 java初学者手册

    清晰的java代码初学者,一个不错的 java初学者手册刚刚在网上看到有人在讨论java应注意的技巧已经整理好了本人太菜遇见这种菜鸟口粮自然不会放过不过也感觉其中有些不是特别的清楚不过作为参考至于是否准确工作中验证吧(1)使用Integer.valueOf()代替newInteger();(2)if(result.size()>0)returntrue;returnfalse;可以优化为returnres…

    2022年7月8日
    24
  • vmware找不到vmx文件_虚拟机重启后文件丢失

    vmware找不到vmx文件_虚拟机重启后文件丢失在使用Vmware的过程中,不小心删除了vmx文件,导致Vmware无法启动。经过上网搜查资料,找到解决办法。vmx只是一个对Vmware文件的简单描述性文件,并不包含任何实质性信息,信息主要包含在vmdk和vmxf文件中。对于Ubuntu虚拟机,用记事本创建空白文件,在其中输入下面内容并保存为ubuntu.vmx即可。(其中加粗的部分是需要修改的内容,包括vmdk文件的

    2025年6月12日
    10
  • 汇编语言伪指令详解(附实例)

    汇编语言伪指令详解(附实例)伪指令不是真正的指令 并没有与之对应的的机器码 不会被执行 伪指令所起的作用主要是对汇编过程进行控制 常见的伪指令如下所示 目录 1 ORG 汇编起始指令 2 END 汇编结束命令 3 EQU 赋值指令 4 DB 字节定义伪指令 5 DW 定义字命令 6 DS 定义存储空间指令 7 BIT 位地址符号命令功能 规定该伪指令下面的目标程序的起始地址格式 ORG16 位地址举例 ORG0080H 表示下面的程序从地址 0080H 开始

    2026年3月26日
    2
  • n8n vs dify vs Coze:三大AI工作流平台终极对决

    n8n vs dify vs Coze:三大AI工作流平台终极对决

    2026年3月15日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号