头图

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

工作中经常使用到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的源码体积确实很大,所以我相信我同事是因为没有经受住这种诱惑)这本来没有什么问题,直到我在现有的项目基础上进行需求迭代

image.png

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

1. echarts4.x和echarts5.x的一个重要区别

我们以vue项目为demo,以前只需要在项目中安装 echarts(4.x版)

npm i echarts

在node_modules中会看到

image.png

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

image.png

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

2. 方法一:同时使用两个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中

image.png

直接贴上效果页面代码:

<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>

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

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

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

总结

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


【Tips】

  • 想要一起学习交流的朋友可以扫下方二维码进入社群来一起交流
  • 群内还有更多学习资料免费获得(群公告自取)



Dash
1 声望0 粉丝