vue + echarts实现中国地图三级下钻

5,580 阅读5分钟

前言

最近项目中用到了地图三级下钻功能,GitHub上找到了一个轮子 - echarts3-chinese-map-drill-down,启动项目看了一下Demo,动画衔接的很流畅,膜拜大佬🙌🙌🙌

我用 VScode 打开这个项目的时候,发现注册地图用的部分原始 JSON数据乱码了,但不影响项目运行。粗略看了一下源码,技术栈用的是jQuery + EChars,本着与时俱进的想法,打算用Vue + EChars写一个新轮子,哈哈哈哈,其实是我不太想在项目中用 JQuery 这种远古时代的 JavaScript 库,傲娇脸😕

此篇文章用于记录柏成从零开发一个地图三级下钻Demo的历程,最终效果如下:

地图三级下钻_4.7M.gif

初始化地图实例

初始化香港18区人口密度

由于之前没有接触过 ECharts 的地理坐标/地图,本着官网是第一手学习资料原则,柏成首先初始化了一个官网示例 - 香港18区人口密度,并根据 文档配置项手册 自定义了地图样式,注册地图用到了一个方法:registerMap

registerMap(mapName: string, geoJson: Object)

  • mapName

    地图名称,在 geo 组件或者 map 图表类型中设置的 map 对应的就是该值

  • geoJson

    GeoJson 格式的数据,具体格式见 geojson.org,ECharts 使用 geoJSON格式的数据作为地图的轮廓

香港18区人口密度.png

初始化中国地图

通过官网示例柏成了解了地图相关的属性及API,对 ECharts 地图有了一个大概认知,接下来我们初始化一个中国地图,此时我们需要中国地图的 geoJSON格式的数据,通过 ECharts 官网得知 地图下载

ECharts 之前提供下载的矢量地图数据来自第三方,由于部分数据不符合国家《测绘法》规定,目前暂时停止下载服务。

好家伙,看到官网通告我差点嗝屁了😱,最终在 github 上找到了 [中国省市区县geoJSON格式地图数据]🌟

中国地图_文本偏移.png

注册渲染地图之后发现文本标签位置并不理想,部分标签偏移到了地图之外,例如内蒙古,部分标签揉挤作一团,例如北京天津河北。此时我们需要修改 china.json 中原始 geoJSON数据,给每个省份的properties属性下新增cp属性,即文字居中位置,例如新疆维吾尔族自治区数据,详细 china.json 数据请移步 vue-map-drilling 查看

 {
      "type": "Feature",
      "properties": {
        "adcode": 650000,
        "name": "新疆",
        "cp": [86.9023, 41.148],
		...
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [79.039649, 34.33427],
              [78.958961, 34.386132],
              [78.878273, 34.391563],
			  ...
            ]
          ]
        ]
      }
    },
 }

噔噔噔噔😎,这样看着就舒服多了

中国地图_文本修正.png

自定义鼠标事件

自定义单击事件

查阅 ECharts 官方API文档 ECharts / API / 鼠标事件 得知左击事件为:myChart.on('click', (e) => {})我们需要在此处实现下钻进入下一级地图的逻辑

点击某个区域高亮,鼠标移出地图后高亮并没有消失,将 ECharts 版本降级为 v4 即可 npm i echarts@4 -S

bindClickChart () {
   this.myChart.on('click', e => {
      console.log(e)
   })
},

自定义右击事件

首先要阻止默认右击事件上下文菜单【图片另存为,复制图片 ... 】

然后再自定义右击事件,查阅 ECharts 官方API文档 ECharts / API / 鼠标事件 得知右击事件为:myChart.on('contextmenu', (e) => {})我们需要在此处实现返回上一级地图的逻辑

bindContextmenuChart () {
  	// 取消右击默认事件
    const container = document.getElementById('chart')
    container.oncontextmenu = e => e.preventDefault()

    // 绑定自定义右击事件
    this.myChart.on('contextmenu', e => {
        console.log(e)
    })
},

下钻思路

地图下钻用到了栈先入后出的思想

大体思路: 左击地图进入下一级时,获取注册渲染下一级地图所需的 geoJSON数据 和 seriesData数据,然后注册渲染下一级地图。并把当前地图数据入栈;右击返回地图上一级,数据出栈并注册渲染地图

如果按照此思路严格执行的话,会发现我们需要创建一个额外的变量去存储当前的地图数据,用以左击地图入栈使用

优化:始终保持栈中最顶层的数据即是当前渲染的地图数据。 只要地图渲染完毕,立即把当前地图数据入栈(若栈中无此地图数据),而不是左击地图时才进行入栈操作。当我们右击返回上一级时,需要先把最顶层数据pop出栈,然后再渲染栈顶地图数据

我们将地图数据入栈前,需要先判断下栈中是否已经存在此数据。若存在,则不入栈;若不存在,则入栈

下钻动效

开发前的预期效果: 当我重新注册并渲染地图时,想当然的认为 ECharts 会自动处理地图上下级关系,并注入切换动效,毕竟官网对 setOption() 是这样介绍的:

设置图表实例的配置项以及数据,万能接口,所有参数和数据的修改都可以通过 setOption 完成,ECharts 会合并新的参数和数据,然后刷新图表。如果开启动画的话,ECharts 找到两组数据之间的差异然后通过合适的动画去表现数据的变化。

当我使用 ECharts v4.9.0 实际操作时发现,地图层级之间毫无过渡动画,生硬至极,what❓,难道地图注册registerMap不兼容setOption动画❗,不应该吧❓,马上就薅成👨‍🦲时,我隐隐感觉可能是ECharts版本的锅

于是我更新了 Echarts 最新版本 v5 npm i echarts@latest -S,重启项目发现还是不行!重来,之后我又将 Echarts 降级到了v3版本npm i echarts@3 -S,大功告成👌

经亲自尝试,只要ECharts版本 <= v4.3.0,即自带下钻动效🌟🌟🌟

为什么版本更新会把地图下钻的动效给去掉呢?很是不能理解,也可能是我太菜了,没找到 Echarts 最新版本开启地图下钻动效的正确方式,如有大佬知道,请指点一二

源码

地图三级下钻demo代码:vue-map-drilling