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的高度和宽度。

整体的框架(我们先把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)
      }
    })
}

你可能感兴趣的:(react、echarts和地图的结合)