Echarts仿百度中国疫情地图实现(Vue)

  近期做了一些echarts图表的开发,都是基本的单轴和双轴的折线图、饼图、柱状图等,看到百度疫情实时地图,对中国地图和各个省份地图充满了好奇,想着通过echarts模仿实现百度疫情实时地图。
  整体代码在vue中实现,跟普通的html和js中实现并无太大差距,差距主要体现在vue的数据双向绑定上。

1.创建vue项目,配置路由相关等设置,创建展示的页面。

<template>
  <div class="home">
    
  </div>
</template>

<script>
  export default {
    name: 'ChinaMap'
  }
</script>

<style scoped>

</style>

2.vue中获取并引入 ECharts、引入Echarts中的中国地图

(1)在控制台中执行命令:npm install echarts --save,安装完成后vue项目中就获取到了echarts,在依赖文件夹node_modules中,即可找到获取到的echarts:

(2)项目中引入echart以及echarts提供的中国地图

<template>
  <div class="home">

  </div>
</template>

<script>
  import echarts from 'echarts'
  import china from 'echarts/map/js/china'
  export default {
    name: 'ChinaMap'
  }
</script>

<style scoped>

</style>

3.初始化地图

(1)代码中dataList数据为模拟的各个省市的疫情数据,
(2)id为"main"的div块为存放地图的容器(echarts的相关学习可以去官网查看)。

<template>
  <div class="home">
<!--    放地图的容器-->
    <div id='main' ref='chart' style='width: 100%;height:600px;'></div>
  </div>
</template>
<script>
  import echarts from 'echarts'
  import china from 'echarts/map/js/china'
  export default {
    name: 'ChinaMap',
    data() {
      return {
        // 地图上显示的疫情数据
        dataList : [
          { name: '南海诸岛', value: 0 },
          { 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: 2 },
          { 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 },
          { name: '西藏', value: 0 },
          { name: '四川', value: 44 },
          { name: '宁夏', value: 4 },
          { name: '海南', value: 22 },
          { name: '台湾', value: 3 },
          { name: '香港', value: 5 },
          { name: '澳门', value: 5 }
        ]
      }
    },
    methods: {
      initChart() {
        // 获取存放地图的dom元素
        let myChart = echarts.init(this.$refs.chart);
        // 指定图表的配置项和数据
        let option = {
          // 地图标题
          title: {
            text: '中国疫情地图',
            x: 'center'
          },
          // 放上鼠标后显示的新
          tooltip : {
            trigger: 'item',
            formatter: function(e, t, n) {
              return '地区:' + e.data.name + '<br/>确诊:' + e.data.value
            },
            textStyle:{
              align:'left'
            }
          },
          // 设置地图数据
          series: [
            {
              type: 'map',
              map: 'china',
              label: {
                show: true,
                color: 'black',
                fontsize: 12,
                formatter: res=> {
                  return  res.data.name
                }
              },
              itemStyle: {
                // borderColor: 'red',
                borderWidth: .5
              },
              // 选中时候显示内容
              emphasis: {
                label: {
                  color: 'black',
                  fontsize:15
                },
                itemStyle: {
                  // borderColor: '#00FFFF',
                  areaColor: '#ADFF2F'
                }
              },
              roam: true,
              data: this.dataList,
            }
          ]
        }
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option)
      }
    },
    mounted() {
      this.initChart()
    }
  }
</script>
<style scoped>
</style>

  现在地图已经初步的有了样子,如果对地图显示上有个性化的的设置,可以自己去官网查看相关属性配置。

4.利用visualMap属性实现根据疫情数据动态的设置地图中各省市的颜色

// 视觉映射组件,根据疫情数据的不同,地图显示不同的颜色
          visualMap: {
            type: 'piecewise',
            min: 0,
            max: 1000,
            left: 300,
            bottom: 40,
            showLabel: !0,
            text: ['高', '低'],
            pieces: [{
              gt: 100,
              label: '> 100 人',
              color: '#7f1100',
              symbol: 'roundRect'
            }, {
              gte: 10,
              lte: 100,
              label: '10 - 100 人',
              color: '#ff5428'
            }, {
              gte: 1,
              lt: 10,
              label: '1 - 9 人',
              color: '#ff8c71'
            }, {
              value: 0,
              color: '#ADFF2F',
              symbol: 'roundRect'
            }],
            show: !0
          }

  设置完这个属性,地图已经初步有了百度中国疫情的样子:

5.确诊为0的省市插上小旗子的标注

  对比下百度做的疫情地图,清零的省地图上标注为小旗子,接下来实现这个功能:

百度的疫情地图

  小旗子这个样式百度了好久,看了好多案例,结果走错了路线,虽然也实现了该功能,但是特别繁琐,最后发现使用series-map中的markPoint属性可以轻松实现小旗子的功能:
  (1)繁琐的方法思路:在中国地图坐标系中引入散点图(series-scatter),然后找到各个省份的坐标,通过该坐标布置散点图,并通过series-scatter的symbol改变散点的样式,自定义图例,设置小旗子的标注。该方法比较麻烦,而且对地图缩放设置也比较复杂,不太推荐。
  (2)最终的思路:使用series-map中的markPoint属性可以轻松实现该功能,之后看api应该认真仔细,才能少走弯路。
  在地图的series中添加markPoint属性,并做如下设置:

          markPoint: { //标记点
            // symbol设置的为小旗子图片的base64吗
            symbol: 'image://data:image/png;base64,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',
            symbolSize: 14, //图形大小
            label: {
              normal: {
                formatter: function(params) {
                  console.log(params);
                  return params.name;
                },
                show: false,
              },
              emphasis: {
                show: false,
              }
            },
            data: this.markPointData
          }

  其中markPointData为需要标注小旗子的省份地图坐标数组,将清零之后的省份坐标放入markPointData中,该省份就会标注为小红旗。下面为操作的具体步骤:
  a.从echarts中导入各省的坐标数据mapJson,对数据进行修整后存入geoCoordMap中,数据类型为{'新疆': [X值, Y值],'北京': [X值, Y值]...};
  b.然后遍历存放疫情数据的变量dataList,当疫情数据value为0时,根据dataList的省份名称找出geoCoordMap对应的坐标,按markPointData的格式存放进去(南海诸岛有些特殊,详情看上方代码注释);
  c.此时关于疫情的的数据都准备好了,此时可以初始化地图了(将生命周期函数呢的初始化地图操作this.initChart()去掉,直接调用this.getMapJson())。

  import echarts from 'echarts'
  import china from 'echarts/map/js/china'
  import mapJson from 'echarts/map/json/china.json'
  export default {
    name: 'ChinaMap',
    data() {
      return {
        dataList:[...], //疫情数据(上面写了,这里省略掉了。。)
        markPointData: [ ],  // 当某个省清零后,为这个省标注小红旗,存放这个省坐标的数据
        geoCoordMap: { }, // 存放地图中各个省的坐标
      }
    }
  }
  methods:{
    getMapJson() {
      let mapXY = mapJson.features  // 获取地图中各省的坐标数据
      // 对获从echarts中获取的各个省的地图坐标进行修正
      mapXY.forEach(res=>{
        this.geoCoordMap[res.properties.name]=res.properties.cp
        //旗子的位置跟省的名字重合了,纵坐标上移1.25
        this.geoCoordMap[res.properties.name][1]=this.geoCoordMap[res.properties.name][1] + 1.25 
      })
      // 对疫情数据进行遍历,查找出疫情数据为0的省份,加入到markPointData
      this.dataList.forEach(res=>{
        if(res.value===0) {
          // echarts中未提供南海诸岛的坐标,此坐标为我自己根据坐标系推算的
          if(res.name=== '南海诸岛') {
            this.markPointData.push({
            name: '南海诸岛',
            coord: [130, 22],
            value: 0
            })
          } else {
            let tmp= {}
            tmp.name= res.name
            tmp.coord= this.geoCoordMap[res.name]
            tmp.value= res.value
            this.markPointData.push(tmp)
          }
        }
      })
       // 数据准备完毕后,初始化地图
      this.initChart()
    },
    mounted() {
      // this.initChart()
     this.getMapJson()
    }
  }

6.最终仿百度中国疫情地图就实现了

补充:关于visualMap中当数据为0时,小旗子的显示,只需要添加symbol属性设置为小旗子的base64码,并设置其大小即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355