Vue vue 遇到 echarts5.x,迁徙图怎么办?

daishenhao · 2021年12月31日 · 430 次阅读

工作中经常使用到 echarts,最近用到迁徙图的时候突然发现,自从 echarts 更新到 5.0 之后,迁徙图变得不可用了,echarts 官方在新版本中移除了行政区域的 map 数据,再想实现迁徙图怎么办,这里提供一种思路

故事前景:同事先写的代码直接在项目中安装了 echarts(@5.2.2)新版本提供了更为细致的模块化引用,例如:

// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。  
import * as echarts from 'echarts/core';  
// 引入柱状图图表,图表后缀都为 Chart  
import { BarChart } from 'echarts/charts';  
// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component  
import {  
  TitleComponent,  
  TooltipComponent,  
  GridComponent,  
  DatasetComponent,  
  DatasetComponentOption,  
  TransformComponent  
} from 'echarts/components';  

新的引入方式对 tree-shaking 更加友好,打包出来的代码体积小了很多(毕竟 echarts 的源码体积确实很大,所以我相信我同事是因为没有经受住这种诱惑)这本来没有什么问题,直到我在现有的项目基础上进行需求迭代

很多小伙伴都做过这样的需求,我们称之为迁徙图或者飞线图,当我一如既往地开开心心的写着代码并思考着晚上该的泡面是放一个卤鸡蛋还是一根火腿肠时,突然看到页面上的爆红,内心一顿疑惑,再当打开官方文档之时,直接痛苦面具了...一顿操作之后决定把踩过的这个坑分享一下

  1. echarts4.x 和 echarts5.x 的一个重要区别 我们以 vue 项目为 demo,以前只需要在项目中安装 echarts(4.x 版)

npm i echarts\

在 node_modules 中会看到

echarts 更新到 5.x 后,再在项目中安装 echarts

map 文件夹消失了,因为官方的 map 数据中行政区域划分和我国实际的行政区域划分相比出现偏差,所以在新版本中官方直接移除了 map 数据,这就让人很头大了。因为 echarts 没有 map 数据,也就是说我们现在没有办法直接拿到中国地图来使用,那么要怎么办呢

  1. 方法一:同时使用两个 echarts 版本

同时使用 echarts4.x 版本在当前项目中,可能有同学会问,既然 echarts 官方的 map 数据不准为什么要用,需要声明一下,不准确是出现在极少数的县区这种划分的,对于整个中国地图省级单位来说,echarts 是没有问题的,所以我们可以沿用 echarts4.x 中的 map,在 package.json 中手动加入一行依赖引入:

"dependencies": {  
    "echarts": "^4.8.0",  
    "echarts5": "npm:echarts@^5.2.2",  
  },  

再执行npm install 之后你会看到 node_modules 中

直接贴上效果页面代码:

<template>  
  <div class="min-body">  
    <div id="ChinaLineMap"></div>  
  </div>  
</template>

<script>  
import "echarts/map/js/china"; //引入中国地图  
export default {  
  name: "chinaLineMap",  
  data: function () {  
    return {};  
  },  
  mounted() {  
    this.loadChinaLineMap();  
  },  
  methods: {  
    //加载中国飞线地图  
    loadChinaLineMap() {  
      var newarray = \[\];  
      var echarts = require("echarts");  
      var myCharts = echarts.init(document.getElementById("ChinaLineMap"));  
      var geoCoordMap = {  
        黑龙江: \[127.9688, 45.368\],  
        内蒙古: \[110.3467, 41.4899\],  
        吉林: \[125.8154, 44.2584\],  
        北京: \[116.4551, 40.2539\],  
        辽宁: \[123.1238, 42.1216\],  
        河北: \[114.4995, 38.1006\],  
        天津: \[117.4219, 39.4189\],  
        山西: \[112.3352, 37.9413\],  
        陕西: \[109.1162, 34.2004\],  
        甘肃: \[103.5901, 36.3043\],  
        宁夏: \[106.3586, 38.1775\],  
        青海: \[101.4038, 36.8207\],  
        新疆: \[87.9236, 43.5883\],  
        西藏: \[91.11, 29.97\],  
        四川: \[103.9526, 30.7617\],  
        重庆: \[108.384366, 30.439702\],  
        山东: \[117.1582, 36.8701\],  
        河南: \[113.4668, 34.6234\],  
        江苏: \[118.8062, 31.9208\],  
        安徽: \[117.29, 32.0581\],  
        湖北: \[114.3896, 30.6628\],  
        浙江: \[119.5313, 29.8773\],  
        福建: \[119.4543, 25.9222\],  
        江西: \[116.0046, 28.6633\],  
        湖南: \[113.0823, 28.2568\],  
        贵州: \[106.6992, 26.7682\],  
        云南: \[102.9199, 25.4663\],  
        广东: \[113.12244, 23.009505\],  
        广西: \[108.479, 23.1152\],  
        海南: \[110.3893, 19.8516\],  
        上海: \[121.4648, 31.2891\],  
        台湾: \[124.343, 25.563\],  
      };  
      var geoCoordColor = \[  
        { name: "黑龙江", value: 1 }, // value值代表颜色  
        { name: "内蒙古", value: 2 },  
        { name: "吉林", value: 3 },  
        { name: "北京", value: 4 },  
        { name: "辽宁", value: 5 },  
        { name: "河北", value: 6 },  
        { name: "天津", value: 7 },  
        { name: "山西", value: 8 },  
        { name: "陕西", value: 9 },  
        { name: "甘肃", value: 10 },  
        { name: "宁夏", value: 11 },  
        { name: "青海", value: 12 },  
        { name: "新疆", value: 13 },  
        { name: "西藏", value: 14 },  
        { name: "四川", value: 15 },  
        { name: "重庆", value: 16 },  
        { name: "山东", value: 17 },  
        { name: "河南", value: 18 },  
        { name: "江苏", value: 19 },  
        { name: "安徽", value: 20 },  
        { name: "湖北", value: 21 },  
        { name: "浙江", value: 22 },  
        { name: "福建", value: 23 },  
        { name: "江西", value: 24 },  
        { name: "湖南", value: 25 },  
        { name: "贵州", value: 26 },  
        { name: "云南", value: 27 },  
        { name: "广东", value: 28 },  
        { name: "广西", value: 29 },  
        { name: "海南", value: 30 },  
        { name: "上海", value: 31 },  
        { name: "台湾", value: 31 },  
      \];  
      var convertData = function (data) {  
        var res = \[\];  
        for (var i = 0; i < data.length; i++) {  
          var dataItem = data\[i\];  
          var fromCoord = geoCoordMap\[dataItem\[0\].name\];  
          var toCoord = geoCoordMap\[dataItem\[1\].name\];  
          if (fromCoord && toCoord) {  
            res.push({  
              fromName: dataItem\[0\].name,  
              toName: dataItem\[1\].name,  
              coords: \[fromCoord, toCoord\],  
            });  
          }  
        }  
        return res;  
      };  
      //飞线数据  
      var chinaData = \[\];  
      //获取飞线数据  
      var res = \[  
        {  
          name: "安徽",  
          value: 6114,  
        },  
        {  
          name: "浙江",  
          value: 4341,  
        },  
        {  
          name: "上海",  
          value: 3600,  
        },  
        {  
          name: "四川",  
          value: 2980,  
        },  
        {  
          name: "河南",  
          value: 2504,  
        },  
        {  
          name: "山东",  
          value: 1590,  
        },  
        {  
          name: "湖南",  
          value: 1163,  
        },  
        {  
          name: "广东",  
          value: 1100,  
        },  
        {  
          name: "重庆",  
          value: 838,  
        },  
        {  
          name: "河北",  
          value: 534,  
        },  
        {  
          name: "北京",  
          value: 473,  
        },  
      \];  
      res.forEach(function (item) {  
        newarray.push(item.value);  
        var array = \[\];  
        var o = {};  
        var o1 = {};  
        o.name = item.name;  
        o1.name = "江西";  
        o.value = item.value;  
        array.push(o1);  
        array.push(o);

        chinaData.push(array);  
      });  
      console.log(chinaData, "--------");  
      var series = \[\];  
      \[\["江西", chinaData\]\].forEach(function (item) {  
        console.log(item\[1\]);  
        series.push(  
          {  
            name: item\[2\],  
            type: "lines",  
            zlevel: 2,  
            effect: {  
              show: true,  
              period: 4, //箭头指向速度,值越小速度越快  
              trailLength: 0.02, //特效尾迹长度\[0,1\]值越大,尾迹越长重  
              symbol: "arrow", //箭头图标  
              symbolSize: 3, //图标大小  
            },  
            lineStyle: {  
              normal: {  
                color: "#FCE931",  
                width: 0.1, //尾迹线条宽度  
                opacity: 0.5, //尾迹线条透明度  
                curveness: 0.3, //尾迹线条曲直度  
              },  
            },  
            data: convertData(item\[1\]),  
          },  
          {  
            //       name: item\[1\],  
            type: "effectScatter",  
            coordinateSystem: "geo",  
            zlevel: 3,  
            rippleEffect: {  
              brushType: "stroke",  
            },  
            symbolSize: function (val) {  
              console.log(val);  
              //return 3 + val\[2\] / 10;  
              return 20;  
            },  
            itemStyle: {  
              normal: {  
                color: "#FCE931",  
              },  
            },  
            data: item\[1\].map(function (dataItem) {  
              return {  
                name: dataItem\[0\].name,  
                value: geoCoordMap\[dataItem\[0\].name\].concat(33),  
              };  
            }),  
          },  
          {  
            name: "中国",  
            type: "map",  
            zlevel: 0,  
            mapType: "china",  
            zoom: 1.2,  
            selectedMode: "single",  
            itemStyle: {  
              normal: {  
                label: {  
                  color: "#fff",  
                  show: true,  
                },  
                borderWidth: 0.5,  
                borderColor: "#009fe0",  
                areaColor: "#009fe0",  
              },  
              emphasis: {  
                borderWidth: 0.5,  
                borderColor: "#00f4ff",  
                shadowColor: "#FCE931",  
                shadowBlur: 10,  
                areaColor: "#ffa800",  
              },  
            },  
            data: geoCoordColor.map(function (dataItem) {  
              return {  
                name: dataItem.name,  
                value: geoCoordMap\[dataItem.name\].concat(\[dataItem.value\]),  
              };  
            }),  
          }  
        );  
      });  
      var option = {  
        background: "none",  
        visualMap: {  
          type: "piecewise",  
          min: 0,  
          max: 33,  
          realtime: false,  
          calculable: true,  
          splitNumber: 21,  
          show: false,  
          inRange: {  
            color: \["#C40000", "#F03566", "#9B4E9A", "#105D98", "#EB7A20"\],  
          },  
        },  
        selectedMode: "multiple",  
        geo: {  
          map: "china",  
          label: {  
            emphasis: {  
              show: false,  
            },  
          },  
          zoom: 1.2,  
          roam: false,  
          itemStyle: {  
            normal: {  
              borderColor: "#3b56b5",  
              borderWidth: 2,  
              areaColor: "rgba(0,0,0,0)",  
              shadowColor: "#2485af",  
              shadowBlur: 20,  
            },  
            emphasis: {  
              areaColor: "green",  
            },  
          },  
        },  
        series: series,  
      };  
      myCharts.clear();  
      myCharts.setOption(option);  
    },  
  },  
};  
</script>

<style scoped>  
#ChinaLineMap {  
  width: 100%;  
  height: calc(100% - 7vh);  
}  
.min-body {  
  width: 100%;  
  height: 100%;  
  overflow: hidden;  
  background: #010827;  
}  
.header {  
  position: relative;  
  height: 6vh;  
  background-color: #cccccc33;  
  background-size: 100% 100%;  
  user-select: none;  
}

.til {  
  width: 100%;  
  font-size: 2.2vw;  
  font-weight: bold;  
  text-align: center;  
  line-height: 6vh;  
  letter-spacing: 0.3vw;  
  color: #fff;  
  margin: 0;  
}

.til:before {  
  content: "";  
  display: inline-block;  
  width: 5vh;  
  height: 5vh;

  margin-right: 1vw;  
  vertical-align: middle;  
}  
.time-box {  
  font-size: 1.3vw;  
  letter-spacing: 0.2vw;  
  color: #00ffff;  
  font-weight: normal;  
  position: absolute;  
  top: 2.2vh;  
  right: 1vw;

  z-index: 100;  
}  
</style>  

如此你就能在页面上看到如上图一样的效果了

  1. 方法二:使用第三方 map 数据

网上看到很多帖子,例如:阿里的 DATAV.GeoAtlas可以下载完整的 map 数据,用下载的 json,但是这种方法目前只能实现地图的绘制,echarts5.x 中,原本初始化迁徙图的线条的方法也无法生效,所以,这种解决方案在我这个需求(迁徙图)上试过之后不生效,所以小伙伴们需要自行

总结 方法一其实就是沿用之前的方式,只不过需要注意如何让两个版本的 echarts 共存于一个项目,方法二是建立在 echarts5.x 版本上使用的,但是没有绘制飞线线条的方法(或者是我看漏了官方文档?)这个问题有更合适的解决方案的小伙伴可以一起留言讨论一下

想要一起学习交流的朋友可以扫下方二维码进入社群来一起交流


→ 加入群一起学习交流

→ 一起拓展行业人脉资源

→ 获得学习资料(不卖课、不关注、纯分享、进群群公告自取)

→ 学习资料戳蓝字:https://shimo.im/sheets/CtcH8...

→_扫码进群一起聊天

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号