react、echarts和地图的结合

PS:使用的是React框架

要实现的效果如下:

image-20200828222623165.png
image-20200828222646486.png
  • 需要一张地图,对地图进行下钻操作,地图的区域需要颜色标记

  • 两种标记方式(气泡和圆点),且颜色需要不一样

  • 右边要有柱状图显示人数

开始之前我们需要准备一个获得地图json数据的网站

地图选择器: https://datav.aliyun.com/tools/atlas/

image-20200828222918544.png

需要哪部分的数据,点击这个按钮复制到你的编辑器上就可以了。

image-20200828223007494.png

准备工作做完,我们就开始进入正题了:首先我们要一个“地图画布”,有了画布才能折腾数据。


画一个地图

引入echarts和相关的json文件

import Echarts from 'echarts';
import jiangxi from '../../../config/mapJSON/jiangxi.json';
import jiujiang from '../../../config/mapJSON/jiujiang.json';

准备一个div存放地图,记得写div的高度和宽度。

<div id='map' style={{height: '100%', width: '100%'}}></div>

整体的框架(我们先把option放一放,先别急,现在你的页面一定是空的)

let myChart = Echarts.init(document.getElementById('map'))

let name = 'jiangxi' //地图名是jiangxi
let data = jiangxi  //地图的数据来自之前引入的json文件
Echarts.registerMap(name, data) //此步不可省略,要想展示一个地图,先需要注册,巨坑(官方根本无文档,全靠瞎猜)
let option = {} //此处先省略,不放入任何数据
myChart.setOption(option, true);

现在为option添砖加瓦,此时你的页面会有一个小地图了

let option = {
      backgroundColor: '#fff',
      title: {
        top: 20,
        text: '用户注册区域展示',
        subtext: '',
        x: 'center',
        textStyle: {
          color: '#000'
        }
      },
      geo: {
        type: 'map',
        map: name, //'jiangxi'
        roam: true,
        geoIndex: 1,
        zoom: 1.1,  //地图的比例
        label: {
          normal: {
            show: true,
            textStyle: {
              color: '#000000'  //字体颜色
            }
          },
          emphasis: {
            textStyle: {
              color: '#000000'  //选中后的字体颜色
            }
          }
        },
        itemStyle: {
          normal: {
            areaColor: '#EEEEEE',
            borderColor: '#8b8b8b',
          },
          emphasis: {
            areaColor: '#ffffff',
          }
        },
      },
    }
image-20200828225711380.png

现在想在地图上绑定我的数据,应该怎么做呢?

//获得数据这一步我就不写了,用下面的死数据
let cityData = [{name:'南昌市',value:47},{name:'九江市',value:22},{name:'新余市',value:4}]

//在geo多配置一行data数据
geo:{
    ...
    data:cityData
}


设置地图色块

此时虽然数据绑定成功了,但是地图上依旧什么色块都没有。我们继续下一步,设置option中的visualMap参数和series参数。

visualMap用来设置地图的色块,series参数用于标记地图。

visualMap: {
         show: true,
         //设置最大值和最小值
         min: 0,
         max: 50,
         //设置位置
         left: '4%',
         top: '40%',
         text: ['高', '低'], // 文本,默认为数值文本
         calculable: true,
         seriesIndex: [0], //作用在哪个series上
         inRange: {
           color: ['#ffcbc5', '#ffd661'] //粉黄
         }
       },
       
series:[
        {
          name: "市报名人数",
          type: "map",
          geoIndex: 0,
          data: cityData,
        },
      ]

设置圆点标记

下图是圆点需要的数组,为这个数组命名为areaData

image-20200828231834043.png

给series新增一个圆点标记

  {
          name: '区县报名人数',
          type: 'effectScatter',
          coordinateSystem: 'geo',
          showEffectOn: 'render',
          rippleEffect: {
            period: 15,
            scale: 4,
            brushType: 'fill'
          },
          hoverAnimation: true,
          itemStyle: {
            normal: {
              color: '#fffd21', //设置圆点的颜色
              shadowBlur: 10,
              shadowColor: '#333'
            }
          },
          symbolSize: function (params) {
            console.log('paramsparams', params[2])
            if (params[2] > 30)
              return params[2] / 5
            else
              return 3
          }, //圆点的大小可以自行设置,这里不赘述
          data: areaData,
},

设置气泡标记

气泡和圆点的原理是相同的,他们的数据要求是需要经纬度以及数据,你无法知道经纬度的时候可以从提前下载好的json数据中取。然后继续在series中添加气泡标记。

  let geoCoordMap = jiangxi.features.map(item => {
      return {
        name: item.properties.name,
        value: item.properties.center
      }
  });
  
 let convertData = function (data) {
      let res = [];
      for (let i = 0; i < data.length; i++) {
        if (geoCoordMap.filter(item => item.name === data[i].name).length)
          res.push({
            name: data[i].name,
            value: geoCoordMap.filter(item => item.name === data[i].name)[0].value.concat(data[i].value)
          })
      }
      return res;
}
{
          name: 'Top 5',
          type: 'scatter',
          coordinateSystem: 'geo',
          symbol: 'pin',
          symbolSize: 40,
          label: {
            normal: {
              show: true,
              textStyle: {
                color: '#fff',
                fontSize: 9,
                fontWeight: 'bold'
              },
              formatter(value) {
                return value.data.value[2]
              }
            }
          },
          itemStyle: {
            normal: {
              color: '#F62157', //标志颜色
            }
          },
              //使用之前的函数处理数据,为之前的cityData添加经纬度,当然也可以让初始数据像之前的areaData一样就有经纬度
          data: convertData(cityData), 
          showEffectOn: 'render',
          rippleEffect: {
            brushType: 'stroke'
          },
          hoverAnimation: true,
          zlevel: 1
},

现在的效果:

image-20200828233714352.png

设置右侧的柱状图

为option添加xAxis和yAxis(一定要有,否则在series中新增type为bar的标记时会报错)

柱状图中的数据需要特殊处理

let barData = cityData.map((item) => {
  return [item.value, item.name]
})
   //option中的grid表示bar的位置
    grid: {
              left: '70%',
              right: '10%',
              // top: '30%',
              // bottom:'40%'
    },

    xAxis: {
      type: 'value',
      // scale: true,
      position: 'top',
      min: 0,
      boundaryGap: false,
      splitLine: {
        show: false
      },
      axisLine: {
        show: false
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        margin: 1,
        textStyle: {
          color: '#aaa'
        }
      },
    },
    yAxis: {
      type: 'category',
      inverse: true, //改变数据顺序
      nameGap: 16,
      axisLine: {
        show: true,
        lineStyle: {
          color: '#ddd'
        }
      },
      axisTick: {
        show: false,
        lineStyle: {
          color: '#ddd'
        }
      },
      axisLabel: {
        interval: 0,
        show: true,
        textStyle: {
          color: '#000000'
        }
      },
    },

地图下钻操作※

你需要知道:

  • 点击地图怎么做到
  • 怎么通过点击地图进行下钻
  • 下钻后地图上的标记数据如何改变(气泡、圆点、柱状图)

你还记得我们给地图的命名吗——myChart,实现点击就要为它添加点击事件,打印看看这里的e是何方神圣。

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

想一想,我们需要根据点击城市名的不同下钻到不同的城市。那么需要的就是点击这块区域的name了。

image-20200829000036839.png

还记得我们是怎么使用地图的吗?注册地图时,有一个地图名和地图名对应的json,由于我们获得的name是中文,无法和json数据对应,选择switch语句进行调整地图名,下面的thisMap相当于最开始初始化地图时的name,thisData相当于最开始初始化地图时的data。

image-20200829000610811.png

//得到加载地图时的地图名
switch (e.name) {
        case  '九江市':
          thisMap = 'jiujiang';
          break
        case '南昌市':
          thisMap = 'nanchang';
          break
        case '抚州市':
          thisMap = 'fuzhou';
          break
        case '赣州市':
          thisMap = 'ganzhou';
          break
        case '吉安市':
          thisMap = 'jian';
          break
        case '景德镇市':
          thisMap = 'jingdezhen';
          break
        case '萍乡市':
          thisMap = 'pingxiang';
          break
        case '上饶市':
          thisMap = 'shangrao';
          break
        case '新余市':
          thisMap = 'xinyu';
          break
        case '宜春市':
          thisMap = 'yichun';
          break
        case '鹰潭市':
          thisMap = 'yingtan';
          break
      }
      //得到加载地图时的地图json
      let area = {
      '九江市': require('../../../config/mapJSON/jiujiang.json'),
      '南昌市': require('../../../config/mapJSON/nanchang.json'),
      '抚州市': require('../../../config/mapJSON/fuzhou.json'),
      '赣州市': require('../../../config/mapJSON/ganzhou.json'),
      '吉安市': require('../../../config/mapJSON/jian.json'),
      '景德镇市': require('../../../config/mapJSON/jingdezhen.json'),
      '萍乡市': require('../../../config/mapJSON/pingxiang.json'),
      '上饶市': require('../../../config/mapJSON/shangrao.json'),
      '新余市': require('../../../config/mapJSON/xinyu.json'),
      '宜春市': require('../../../config/mapJSON/yichun.json'),
      '鹰潭市': require('../../../config/mapJSON/yingtan.json')
    }
      
    thisData = area[e.name]

如何动态的把thisMap和thisData传递给Echarts,告诉Echarts我需要换一个地图进行注册呢?可以写一个函数loadMap(可以还有别的方法,不赘述)。先打个框架。

let loadMap = (name,data) =>{
 //现在是否是下钻状态=>通过name是否为'jiangxi'判断
 //如果是下钻:过滤areaData,barData中的其他区域数据,
 //如果不是下钻状态:之前在jiangxi时的数据全部存入state,现在取出并赋值还原。
    let option = {}
} 

总结

最后重新整理一下整体框架

showMap(cityData, areaData){
    //cityData,areaData 这里的数据需要你自己获得 
    let myChart = Echarts.init(document.getElementById('map'))
    
     //默认地图:江西省
    let thisMap = 'jiangxi'
    let thisData = jiangxi
    
    let loadMap = (name, data) => {
      //地图名转回中文,为了方便过滤数据
      if (name !== 'jiangxi') {
        let key = ''
        switch (name) {
          case 'jiujiang' :
            key = '九江市';
            break
          //... 不赘述
        }
        //在areaData中找到对应市的区和县
        let array = areaData.filter(item => item.city === key)
        let cd = array.map(item => {
          return {
            name: item.name,
            value: item.value[2]
          }
        })
        barData = array.map(item => {
          return [item.value[2], item.name]
        })
        areaData = []
        cityData = cd
      } else {
        areaData = this.state.areaData
        cityData = this.state.cityData
        barData = cityData.map((item) => {
          return [item.value, item.name]
        })
      }
      Echarts.registerMap(name, data) //注册地图

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