根据官网上的案例并结合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};