React项目在map上叠加柱状图

1,410 阅读5分钟

​ 根据官网上的案例并结合echars-for-react研究了一下,话不多说,效果如下。

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/6/5/16b26a0119f221ea~tplv-t2oaga2asx-image.image

​ 下面简单说一下实现的过程和代码:

一、安装依赖 ​ 在react项目中使用,安装echarts-for-react和echarts;

yarn add echarts-for-react
//或者
npm install echarts-for-react

yarn add echarts
//或者
npm install echarts

​ 依赖安装成功,下面直接上代码;

import React, {Component} from 'react';
import 'echarts/lib/chart/map';
import 'echarts/map/js/china';//中国地图数据,生成中国地图
import echarts from 'echarts';
import ReactEcharts from 'echarts-for-react';
import {geoCoordMap} from './data';//全国省会坐标数据,在地图上标记各省会
import {rawData} from "./data";//生成柱状图数据
let divObj;//定义一个全局的变量,方便后面生成浮框
render() {
  const events={//echarts地图事件定义
    "click":this.handleClick
  }
  return (
    <div  	className="wrap" 
        	style={{width:"800px",height:"800px",border:"1px solid red",position:"relative",margin:"auto"}}>
          	<ReactEcharts onEvents={events}  option={this.getOption()} style={{height:"800px"}} ref={(event)this.echarts_react= event}}/>
    </div>
  );
}
//ref用来返回echarts对象,方便获取echarts实例对象的原生API

​ getOption方法,生成中国地图:

getOption=()=>{
        const option={
                animation: false,
                tooltip:{trigger:'axis'},
                geo:{
                  map:"china",
                  roam : false,
                  zoom : 1.2,
                  label:{
                    emphasis:{
                      show:false,
                      areaColor:"#eee"
                    }
                  },
                  itemStyle:{//地图区块颜色、
                    normal:{
                      areaColor: "#55c3fc",
                      borderColor : '#fff'
                    },
                    emphasis: {
                      areaColor:"#21aef8"
                    }
                  }
                }
        }
        return option;
}

​ renderEachProvince方法渲染省市名称及柱状图:

 renderEachProvince=()=> {//渲染每一个省的堤防和险工险段的柱状图
        let option = {
          xAxis:  [],
          yAxis:  [],
          grid:   [],
          series: []
        };
        let map_Obj= this.echarts_react.getEchartsInstance();//获取echarts实例化API
        
        this.echarts_react.echartsLib.util.each(rawData,(dataItem, idx)=> {//调用echars的each方法,循环柱状图数据;
                let  geoCoord =this.state.geoCoordMap[dataItem[0]];
                let  coord = map_Obj.convertToPixel('geo', geoCoord);
                idx += '';
                let  inflationData = [];
                for (let k = 1; k < 4; k++) {
                    inflationData.push(dataItem[k])
                }
                option.xAxis.push({
                    id: idx,
                    gridId: idx,
                    type: 'category',
                    name: dataItem[0],
                    nameLocation: 'middle',
                    nameGap: 3,
                    splitLine: {
                    show: false
                    },
                    axisTick: {
                    show: false
                    },
                    axisLabel: {
                    show: false
                    },
                    axisLine: {
                    onZero: false,
                    lineStyle: {
                        color: '#666'
                    }
                    },
                    data: ["数据A","数据B"],
                    z: 100
            
                });
                option.yAxis.push({
                    id: idx,
                    gridId: idx,
                    splitLine: {
                    show: false
                    },
                    axisTick: {
                    show: false
                    },
                    axisLabel: {
                    show: false
                    },
                    axisLine: {
                    show: false,
                    lineStyle: {
                        color: '#1C70B6'
                    }
                    },
                    z: 100
                });
                option.grid.push({
                    id: idx,
                    width: 18,
                    height: 24,
                    left: coord[0]-15,
                    top: coord[1]-15,
                    z: 100
                });
                option.series.push({
                    id: idx,
                    type: 'bar',
                    xAxisId: idx,
                    yAxisId: idx,
                    barGap: 0,
                    barCategoryGap: 0,
                    data:inflationData,
                    z: 100,
                    itemStyle: {
                    normal: {
                        color: function(params){
                        // 柱状图每根柱子颜色
                        let colorList = ['#F75D5D','#59ED4F'];
                        return colorList[params.dataIndex];
                        }
                    }
                    }
                  });
            });
        map_Obj.setOption(option)
      }
 componentDidMount() {
    setTimeout(this.renderEachProvince(), 0);//调用renderEachProvince方法
}

​ hanldeClick方法,点击柱状图,浮框显示柱状图:

handleClick=(obj)=>{//点击地图返回的对象,里面包含事件对象events
    if(obj.componentSubType === "bar"){//点击柱状图
      this.clickBar(obj)
    }
 }
clickBar=(obj)=>{//点击柱状图,生成浮框柱状图
    divObj=this.createNewBox(obj);//在<div className="wrap"></div>中动态创建一个div容器,用来放柱状图,并将点击对象传递过去,在createNewBox需要根据events事件对象获取点击位置,生成浮框
    let parentNode=document.getElementsByClassName("wrap")[0];
        parentNode.appendChild(divObj);
    this.createBar();//容器生成,生成柱状图
}
createNewBox=(obj)=>{//生成浮框容器
    let divX = this.getMousePos(obj.event)['x'];//获取点击处的横坐标
    let divY = this.getMousePos(obj.event)['y'];//获取点击处的纵坐标
    let isObj = document.getElementById("_bar");//判断是否进行过点击,生成过浮框;
    if(isObj!=null){//清除浮框
      isObj.parentNode.removeChild(isObj);

    }
    divObj = document.createElement('div');
    divObj.id="_bar";
    divObj.style.width="250px";
    divObj.style.height="180px";
    divObj.style.border="1px solid #f5f5f5";
    divObj.style.position="absolute";
    divObj.style.top=divY+"px";
    divObj.style.left=divX+"px";
    divObj.style.backgroundColor="#fff";
    return divObj;
}
getMousePos=(event)=>{//点击的时候获取鼠标横纵坐标的位置
     console.log(event,event.event)//获取相对窗口定位(client)对象时,用后面的对象(event.event)
    let e = event || window.event;
    let scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
    let scrollY = document.documentElement.scrollTop || document.body.scrollTop;
    let x =e.offsetX + scrollX;//根据父级定位方式不同获取offsetX或者clientX
    let y =e.offsetY + scrollY;//根据父级定位方式不同获取offsetY或者clientY
    return {'x': x,'y': y};
}
createBar=()=>{//生成浮框柱状图
    let barObj=echarts.init(document.getElementById("_bar"));
    let option={
          backgroundColor: 'rgba(255,255,255,.3)',
          legend: {
            data: ['数据A','数据B',]
          },
          xAxis: [
            {
              type: 'category',
              data: ['数据A','数据B']
            }
          ],
          yAxis: [
            {
              splitLine: {
                show: false
            },
            type: 'value'
            }
          ],
          series: [
            {
              type: 'bar',
              itemStyle: {
              normal: {
                color: function(params){
                let  colorList = ['#F75D5D','#59ED4F'];
                return colorList[params.dataIndex];
              },
              label: {
                show: true,
                position: 'top',
                textStyle: {
                  color: '#000'
                }
              }
            }
          },
          data: [10,20,30]
        }
      ]
    }
    barObj.setOption(option);
 } 
   render() {
        const events={
            "click":this.mouseEvent,
            "mouseover":this.mouseEvent,
            "geoRoam":this.handleRoam
        }
        return (
            <div  className="wrap" style={{width:"800px",height:"700px"}}>
                  <ReactEcharts  onEvents={events}  option={this.getOption()} style={{height:"700px"}} ref={(event) => { this.echarts_react= event}}/>
            </div>
        )
    }

首先增加监听事件geoRoam,然后增加方法:throttle

 throttle=(fn,delay,debounce)=>{//地图缩放
        let currCall,lastCall=0,lastExec=0,timer=null,diff,scope,args;
        delay=delay||0;
        function exec() {
          lastExec = (new Date()).getTime();
          timer = null;
          fn.apply(scope, args || []);
        }
        const  cb=function () {
          currCall = (new Date()).getTime();
          scope = this;
          args = arguments;
          diff = currCall - (debounce ? lastCall : lastExec) - delay;
          clearTimeout(timer);
          if (debounce) {
            timer = setTimeout(exec, delay);
          }else{
            if (diff >= 0) {
              exec();
            }
            else {
              timer = setTimeout(exec, -diff);
            }
            lastCall = currCall;
          }
          return cb;
        }
    
      }

最后在handleRoam方法中调用

 handleRoam=(obj)=>{//地图缩放功能
        this.throttle(this.renderEachProvince(), 0);
 }

以上就是实现地图上叠加柱状图的过程,目前还不是太完善,后期会慢慢的进行完善,欢迎大家指正,最后附上rawData和geoCoordMap;

const geoCoordMap = {//全国各省坐标数据
  '西藏' : [ 91.11, 30.97 ],
  '上海' : [ 121.48, 31.22 ],
  '福建' : [ 118.1, 27.46 ],
  '浙江' : [ 119.96, 29.86 ],
  '广东' : [ 113.23, 24.16 ],
  '山西' : [ 112.53, 38.87 ],
  '云南' : [ 101.73, 25.04 ],
  '辽宁' : [ 123.38, 42.8 ],
  '吉林' : [ 125.35, 44.88 ],
  '江西' : [ 115.89, 28.68 ],
  '海南' : [ 109.51, 20.25 ],
  '广西' : [ 108.74, 24.16 ],
  '内蒙古' : [ 111.65, 42.42 ],
  '四川' : [ 104.06, 31.67 ],
  '陕西' : [ 108.95, 35.27 ],
  '江苏' : [ 119.78, 33.04 ],
  '贵州' : [ 106.71, 27.57 ],
  '北京' : [ 116.46, 41.92 ],
  '新疆' : [ 86.68, 41.77 ],
  '山东' : [ 118, 36.65 ],
  '甘肃' : [ 103.73, 37.03 ],
  '天津' : [ 117.2, 40.13 ],
  '河南' : [ 113.65, 34.76 ],
  '黑龙江' : [ 127.63, 47.75 ],
  '河北' : [ 115.48, 40.03 ],
  '湖南' : [ 112, 28.21 ],
  '安徽' : [ 117.27, 32.86 ],
  '湖北' : [ 112.31, 31.52 ],
  '青海' : [ 97.31, 37.03 ],
  '重庆' : [ 107.31, 30.52 ],
  '宁夏' : [ 106.31, 38.52 ],
  '香港' : [ 114.31, 23.02 ],
  '澳门' : [ 114.01, 22.52 ],
  '台湾' : [ 120.81, 25.02 ]
};
const rawData=[
   ['西藏', 5, 10,{count:10}],
   ['上海', 6, 11],
   ['福建', 7, 12],
   ['浙江', 8, 13],
   ['广东', 9, 14],
   ['山西', 10,15],
   ['云南', 11,16],
   ['辽宁', 12,17],
   ['吉林', 13,18],
   ['江西', 14,19],
   ['海南', 15,20],
   ['广西', 16,21],
   ['内蒙古', 17,22],
   ['四川', 18, 23],
   ['陕西', 19, 24],
   ['江苏', 20, 25],
   ['贵州', 21, 26],
   ['北京', 22, 27],
   ['新疆', 23, 28],
   ['山东', 24, 29],
   ['甘肃', 25, 30],
   ['天津', 26, 31],
   ['河南', 27, 32],
   ['黑龙江',28,33],
   ['河北', 29, 34],
   ['湖南', 30, 35],
   ['安徽', 31, 36],
   ['湖北', 32, 37],
   ['青海', 33, 38],
   ['重庆', 34, 39],
   ['宁夏', 35, 40],
  ]
export {geoCoordMap,rawData};