vue cli中echarts实现中国地图

186 阅读7分钟

众所周知,用echarts上官网

Documentation - Apache ECharts​echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts

根据教程npm安装

npm install echarts --save

然后在需要使用的页面引入

import * as echarts from 'echarts'

下面重点来了,echarts官方建议使用百度地图的方式展示中国地图,但是好多项目场景都百度地图都不符合,只有通过JSON数据生成的地图可以符合。

(或者是可以通过贴图、图层方式实现地图的areaStyle , 但是官网一无例子 二无教程,还是我太菜了)

这里通过JSON数据生成地图,这种方式的重点是去找china.json , 可以通过github去搜索或者通过阿里云DataV

github方式请小伙伴们自行搜索,主要是最近tz又双叒叕过期了,难受啊

下面是DataV地址链接,可根据需要自行选择下载

阿里云 DataV - 数据可视化平台​datav.aliyun.com/portal/school/atlas/area_selector

如下图, 怒赞一波大厂(牛批!)

然后本地获取一下JSON数据,这里需要对echarts注册一下,附一下教程截图

这里的GeoJSON链接略坑,兴冲冲的点过去, 纳尼???

效果图如下,后面上一下主要代码

这里我觉得UI的visualMap位置设计的不好,要是我直接就放左下角了

主要代码如下(给新手们提醒一下axios也是需要npm安装+引入的呦)

    initMapChart() {
      // 这里提一下china.json是放在public下的city文件夹的, 所以这里可以直接/city/china.json
      // 此时部署到服务器根目录是没有问题的,如果部署到二级目录 比如/demo/下这里会报错
      // 比较简单的方式是直接在根目录拷贝一份city/china.json
      // 因为在项目中使用了process.env.NODE_ENV所以这里暂不做兼容判断 简单直接拷贝一份完事
      axios.get("/city/china.json").then((res) => {
        console.log(res);
        echarts.registerMap("china", { geoJSON: res.data });
        let myChart = echarts.init(document.getElementById("mapChart"));
        let arr = [
          {
            name: "北京市",
            value: 54,
          },
          {
            name: "天津市",
            value: 13,
          },
          {
            name: "上海市",
            value: 40,
          },
          {
            name: "重庆市",
            value: 75,
          },
          {
            name: "河北省",
            value: 13,
          },
          {
            name: "河南省",
            value: 83,
          },
          {
            name: "云南省",
            value: 11,
          },
          {
            name: "辽宁省",
            value: 19,
          },
          {
            name: "黑龙江省",
            value: 15,
          },
          {
            name: "湖南省",
            value: 69,
          },
          {
            name: "安徽省",
            value: 60,
          },
          {
            name: "山东省",
            value: 39,
          },
          {
            name: "新疆省",
            value: 4,
          },
          {
            name: "江苏省",
            value: 31,
          },
          {
            name: "浙江省",
            value: 104,
          },
          {
            name: "江西省",
            value: 36,
          },
          {
            name: "湖北省",
            value: 1052,
          },
          {
            name: "广西省",
            value: 33,
          },
          {
            name: "甘肃省",
            value: 7,
          },
          {
            name: "山西省",
            value: 9,
          },
          {
            name: "内蒙古省",
            value: 7,
          },
          {
            name: "陕西省",
            value: 22,
          },
          {
            name: "吉林省",
            value: 4,
          },
          {
            name: "福建省",
            value: 18,
          },
          {
            name: "贵州省",
            value: 5,
          },
          {
            name: "广东省",
            value: 98,
          },
          {
            name: "青海市",
            value: 1,
          },
        ];
        let option = {
          visualMap: {
            type: "piecewise",
            show: true,
            min: 0,
            max: 1000000,
            left: "28%",
            bottom: "25%",
            showLabel: true,
            // text: ["高", "低"],
            textStyle: {
              color: "#ffffff",
            },
            pieces: [
              // 图例颜色
              {
                min: 10000,
                max: 999999,
                label: ">10000",
                color: "#A9251B",
                symbol: "roundRect",
              },
              {
                min: 1000,
                max: 9999,
                label: "1000-9999",
                color: "#D5514D",
                symbol: "roundRect",
              },
              {
                min: 100,
                max: 999,
                label: "100-999",
                color: "#E57C6D",
                symbol: "roundRect",
              },
              {
                min: 10,
                max: 99,
                label: "10-99",
                color: "#F19D8A",
                symbol: "roundRect",
              },
              {
                min: 1,
                max: 9,
                label: "1-9",
                color: "#FBE6DC",
                symbol: "roundRect",
              },
              {
                value: 0,
                label: "0",
                color: "#ffffff",
                symbol:
                  "image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAeCAMAAAAB8C7XAAAAeFBMVEUAAADBIhzAIh+/ISDBHSHDHh6jMyHAISDAISC/ISDAIR/AISDAHiG/IR+6RjG+IiC/IiHAICC/IR/AISG+ISG+Ix+/ICDAIiC+IB/AIBzCHh68JRa/IiHAIB+/ISC9IiK/Hx+/IiC+IiK+Ih++ICDCJB/BJB+/ISDiIZL9AAAAJ3RSTlMALfv3HQwG0secl4NTQQPkvLWoo2xpZWFYJBkR693CkIx4WktHMjGv/nLNAAAAp0lEQVQoz4XNVwrEMAxFUcUlvfcyvWn/OxxBMASPxNyPBL9jMPwrNJ9gcwfTLfQt52ueRgqpeLQ0rJnGgP4BHtJNcqE7BNQJvRy0EgwSLBJAJUEnwSSBkQDO/l6XOyTe3lrYexxX1bzAte5TlWT9XFg4FNGs+xJ+SgnuwJQTGA42xYB7pGDhhjiw8ERMWbAKY2CLUYcsZIhvFgrEkYVQYw5s9QR8/tNf+EUpppEdkKMAAAAASUVORK5CYII=",
              },
            ],
          },
          geo: {
            map: "china",
            zoom: 1.7,
            top: "30%",
            label: {
              show: true,
              fontSize: "14",
              color: "#00D9A9",
            },
          },
          series: [
            {
              type: "map",
              geoIndex: 0,
              data: arr,
            },
          ],
        };
        myChart.setOption(option);
      });
    },

这里说一个坑了我1个多小时的坑,即渲染数据arr的每一项的name都要与china.json中的城市名称一致,否则无法渲染色块。

这里也有两种实现方式(细微区别) :

1、使用geo组件 ,需要在series中设置geoIndex (上面的代码就是这种方式)

2、使用series的type: 'map', 需要设置map: 'china' , 这里的china就是echarts.registerMap所注册的名字

剩下的大同小异,echarts项目做多了就会发现很多配置都有共通点。这里就不放代码了,放张图意思一下吧。

这个是在gallery里看来的湖北地图示例

where is gallery ? oh its here

最后总结一下: 官方文档才是第一权威,百度的好多是5年前的代码 早就过时了, CSDN ? 那是什么???我还是继续攒钱买新的tz google吧。


更新一下产品2.0,领导一句话: 要3D效果,要小红旗 对 就是CSDN上那个!

so 2.0更新内容,区域颜色径向渐变 + 地图堆叠实现2.5D立体效果 + scatter实现清零板块放置小红旗

效果图如下

下面是主要代码,有三点需要注意

1、这里是把series的map作为上层(它的zlevel为1,),geo渲染的map作为底层(它的zlevel为0)在底层地图上渲染阴影 实现2.5D ; 因为visualMap是需要渲染在series上的(这块不太确定,目前在官方没找到visualMap可以选择geo渲染), scatter的小红旗zlevel为3

2、目前发现在visualMap中的pieces中使用symbol时 series中的type: scatter中的symbol会失效, 而且pieces中设置symbol也会有问题这里不细说了 已去github提了issue 等待回复中

3、出于业务考虑 这里再开头先销毁了一下echarts对象,当然也可以创建一个全局的echarts 然后只更新options 。 一切已实际业务为准

    initMapChart(mapData = []) {
      if (this.mapChart) {
        this.mapChart.dispose()
      }
      // 后面反应过来,这里的china.json 可以直接import引入,不需要和echarts官网例子一致, 使用也会更方便
      axios.get("/city/china.json").then((res) => {
        console.log(res);
        echarts.registerMap("china", { geoJSON: res.data });
        this.mapChart = echarts.init(document.getElementById("mapChart"));

        // 目标数据格式
        // let arr = [
        //   {
        //     name: "北京市",
        //     value: 54,
        //   }
        // ];
        
        // 找出数据中所有数据为0 的坐标 用于0数据小红旗的渲染
        let markPointData = [], brr = [];
        for (let i of mapData) {
          if (i.value == 0) {
            brr.push(i.name)
          }
        }
        for (let j of brr) {
          for(let k of res.data.features) {
            if (j == k.properties.name) {
              markPointData.push({
                name: j,
                value: k.properties.center
              })
            }
          }
        }
        console.log('markPointData:', markPointData)
        let option = {
          visualMap: {
            type: "piecewise",
            show: true,
            min: 0,
            max: 1000000,
            left: "27%",
            bottom: "25%",
            showLabel: true,
            itemWidth: 12,
            itemHeight: 12,
            zlevel: 2,
            // seriesIndex: 0,
            // text: ["高", "低"],
            textStyle: {
              // color: "#ffffff",
              color: "#06fcff"
            },
            pieces: [
              // 图例颜色
              {
                min: 10000,
                max: 999999,
                label: ">10000",
                color: "#A9251B",
                // symbol: "roundRect",
              },
              {
                min: 1000,
                max: 9999,
                label: "1000-9999",
                // symbol: "roundRect",
                color: '#D5514D',
              },
              {
                min: 100,
                max: 999,
                label: "100-999",
                // symbol: "roundRect",
                color: '#E57C6D',
              },
              {
                min: 10,
                max: 99,
                label: "10-99",
                // symbol: "roundRect",
                color: '#F19D8A',
              },
              {
                min: 1,
                max: 9,
                label: "1-9",
                // symbol: "roundRect",
                color: '#FBE6DC',
              },
              {
                value: 0,
                label: "0",
                // color: "#ffffff",
                color: { // 径向渐变
                  type: 'radial',
                  x: 0.5,
                  y: 0.5,
                  r: 0.5,
                  colorStops: [{
                      offset: 0, color: '#040E3B' // 0% 处的颜色
                  }, {
                      offset: 1, color: '#082750' // 100% 处的颜色
                  }],
                  global: false, // 缺省为 false
                },
                // symbol: "image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAeCAMAAAAB8C7XAAAAeFBMVEUAAADBIhzAIh+/ISDBHSHDHh6jMyHAISDAISC/ISDAIR/AISDAHiG/IR+6RjG+IiC/IiHAICC/IR/AISG+ISG+Ix+/ICDAIiC+IB/AIBzCHh68JRa/IiHAIB+/ISC9IiK/Hx+/IiC+IiK+Ih++ICDCJB/BJB+/ISDiIZL9AAAAJ3RSTlMALfv3HQwG0secl4NTQQPkvLWoo2xpZWFYJBkR693CkIx4WktHMjGv/nLNAAAAp0lEQVQoz4XNVwrEMAxFUcUlvfcyvWn/OxxBMASPxNyPBL9jMPwrNJ9gcwfTLfQt52ueRgqpeLQ0rJnGgP4BHtJNcqE7BNQJvRy0EgwSLBJAJUEnwSSBkQDO/l6XOyTe3lrYexxX1bzAte5TlWT9XFg4FNGs+xJ+SgnuwJQTGA42xYB7pGDhhjiw8ERMWbAKY2CLUYcsZIhvFgrEkYVQYw5s9QR8/tNf+EUpppEdkKMAAAAASUVORK5CYII=",
                // symbol: "roundRect",
              },
            ],
          },
          geo: {
            map: "china",
            zoom: 1.7,
            top: "30%",
            zlevel: 0,
            label: {
              show: false,
            },
            itemStyle: {
              areaColor: '#07183F',
              shadowColor: '#1863DE',
              shadowOffsetY: 15,
              shadowOffsetX: 2,
            },
          },
          series: [
            {
              type: "map",
              map: 'china',
              zoom: 1.7,
              top: "30%",
              zlevel: 1,
              label: {
                show: true,
                fontSize: "14",
                color: "#00D9A9",
              },
              itemStyle: {
                // areaColor: '#07183F',
                // areaColor: { // 单向渐变
                //   type: 'linear',
                //   x: 0,
                //   y: 0,
                //   x2: 0,
                //   y2: 1,
                //   colorStops: [{
                //       offset: 0, color: '#040E3B' // 0% 处的颜色
                //   }, {
                //       offset: 1, color: '#144975' // 100% 处的颜色
                //   }],
                //   global: false // 缺省为 false
                // },
                areaColor: { // 径向渐变
                  type: 'radial',
                  x: 0.5,
                  y: 0.5,
                  r: 0.5,
                  colorStops: [{
                      offset: 0, color: '#040E3B' // 0% 处的颜色
                  }, {
                      offset: 1, color: '#082750' // 100% 处的颜色
                  }],
                  global: false // 缺省为 false
                },
                borderWidth: 2,
                borderColor: '#3680A8',
                shadowColor: '#3680A8',
                // shadowOffsetY: 15,
                // shadowOffsetX: 0,
              },
              // geoIndex: 0,
              data: mapData,
            },
            {
              type: 'scatter',
              coordinateSystem: 'geo',
              symbol: 'image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAeCAMAAAAB8C7XAAAAeFBMVEUAAADBIhzAIh+/ISDBHSHDHh6jMyHAISDAISC/ISDAIR/AISDAHiG/IR+6RjG+IiC/IiHAICC/IR/AISG+ISG+Ix+/ICDAIiC+IB/AIBzCHh68JRa/IiHAIB+/ISC9IiK/Hx+/IiC+IiK+Ih++ICDCJB/BJB+/ISDiIZL9AAAAJ3RSTlMALfv3HQwG0secl4NTQQPkvLWoo2xpZWFYJBkR693CkIx4WktHMjGv/nLNAAAAp0lEQVQoz4XNVwrEMAxFUcUlvfcyvWn/OxxBMASPxNyPBL9jMPwrNJ9gcwfTLfQt52ueRgqpeLQ0rJnGgP4BHtJNcqE7BNQJvRy0EgwSLBJAJUEnwSSBkQDO/l6XOyTe3lrYexxX1bzAte5TlWT9XFg4FNGs+xJ+SgnuwJQTGA42xYB7pGDhhjiw8ERMWbAKY2CLUYcsZIhvFgrEkYVQYw5s9QR8/tNf+EUpppEdkKMAAAAASUVORK5CYII=',
              symbolSize: 12, //图形大小
              zlevel: 3,
              label: {
                show: false,
              },
              data: markPointData
            }
          ],
        };
        this.mapChart.setOption(option);
      });
    },