点击前
点击后(山东省为例)
1. 安装echarts,echarts按需引入
npm install echarts --save
//引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口
import * as echarts from 'echarts/core';
2.引入echarts后,基于准备好的dom,初始化echarts实例。
const ChartMap = (props) =>{
const {id} = props;
const [name, setName] = useState('china');
const renderMap = (code, name) => {
const chartId = document.getElementById(id);
const myChart = echarts.getInstanceByDom(chartId as HTMLElement);
if (myChart) {
mapInstance = myChart;
} else {
mapInstance = echarts.init(chartId as HTMLElement);
}
};
const chinaMapConfig = (name, data) => {
// 地图配置
const option = {...}
mapInstance.clear();
mapInstance.setOption(option);
}
useEffect(() =>{
renderMap(name);
},[name])
return (
<div style={{ width: "100%", height: "70vh" }} id={id}></div>
);
};
export default ChartMap;
3. 使用echarts.registerMap 注册可用地图
import { MapChart } from 'echarts/charts';
//使用visiualMap来配置图表根据值的范围显示特定的颜色
import { VisualMapComponent } from 'echarts/components';
// 必须在使用 use 方法注册了 MapChart 后才能使用 registerMap 注册地图
echarts.registerMap(name, data); // name: 地图当前名称和地图的地理数据
4. 地图数据下载,推荐阿里云 DataV
我已经提前下载到本地,可以统一放在后端或者cdn上
import { mapJson } from './map';
import { ahuiJson } from './ahui';
// 上海, cp地理位置
export const mapJson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
id: 'shang_hai',
properties: {
name: '上海',
cp: [121.4648, 31.2891],
childNum: 19,
adcode: '310000',
},
geometry: {
type: 'Polygon',
coordinates: [
[
[120.9375, 31.0254],
[121.2012, 31.4648],
[121.377, 31.5088],
[121.1133, 31.7285],
[121.2012, 31.8604],
[121.9922, 31.5967],
[121.9043, 31.1572],
[121.9922, 30.8057],
[121.2891, 30.6738],
[120.9375, 31.0254],
],
],
},
}],
}
5. visualMap 视觉映射组件
visualMap
是视觉映射组件。可以定义为 分段型(visualMapPiecewise) 或 连续型(visualMapContinuous),通过 type
来区分。
visualMap: {
left: "left", // visualMap 组件离容器左侧的距离,值为`'left'`, `'center'`, `'right'`,组件会根据相应的位置自动对齐。
bottom: 0,
itemSymbol:"circle",
right: 10,
seriesIndex: [0],
itemWidth: 10, // 每个图元的宽度
itemGap: 4, // 每两个图元之间的间隔距离,单位为px
pieces: [
{gte: 8, lte: 9, label: '连续下降', color: '#FF4D4D', symbol: 'circle'},
{gte: 5, lte: 8, label: '本期下降', color: '#FF6F00', symbol: 'circle'},
{gte: 1, lte: 5, label: '本期上升', color: '#FFC666', symbol: 'circle'},
{gte: 0, lte: 1, label: '连续上升', color: '#13BF30', symbol: 'circle'},
{gte: -1, lte: 0, label: '价格预警', color:'', symbol: 'image://http://xxx.png'}
],
},
6. 利用echartsInstance.resize
改变图表尺寸
useEffect(() => {
window.addEventListener("resize", function () {
mapInstance.resize();
});
return () => {
mapInstance && mapInstance.dispose();
};
}, []);
7. 地图的后端数据
alwaysDown:true是显示炸弹图标
value: 是根据数据大小显示色值不同
const mapInfos1 = [
{
alwaysDown: false,
marketShareTrend: "8",
name: "上海",
provCode: "310000",
provName: "上海",
value: 1,
},
{
alwaysDown: true,
marketShareTrend: "8",
name: "安徽",
provCode: "340000",
provName: "安徽省",
value: 8,
}
]
const mapInfos2 = [
{
alwaysDown: false,
marketShareTrend: "2",
provCode: "340200",
provName: "芜湖市",
name: "芜湖市",
value: 3
},
{
alwaysDown: false,
marketShareTrend: "2",
name: "马鞍山市",
provCode: "340500",
provName: "马鞍山市",
value: 3
}
]
8. 图例禁止点击
const toEntriesObject = (data) => {
return data?.features?.map((v) => ({
name: v.properties.name,
adcode: v.properties.adcode,
}));
};
const handleClickMap = () => {
mapInstance?.on('click', (params) => {
clearTimeout(timeFn);
timeFn = setTimeout(function() {
const name = params.name; //地区name
const code = toEntriesObject(mapJson).find((el:any) => el.name === name)?.adcode;
if(!code) return
setName(name);
}, 250);
});
// 炸弹不点击
mapInstance?.on('datarangeselected',(e) => {
const selected = { 0: true, 1: true, 2: true, 3: true, 4: true };
if (JSON.stringify(selected) !== JSON.stringify(e.selected) && !Object.values(e.selected)[4]) { //* 判断是否为全部选中,全部选中则不用设置。如果不判断则会死循环
e.selected[4] = true
mapInstance.dispatchAction({ //* 调用action方法将图例重新设置为全部选中
type: 'selectDataRange',
selected: e.selected
})
}
})
}
9. 炸弹图标添加
geo: {
map: name,
zoom: 1.25,
roam: false,
},
series: [{
map: name,
type: "scatter",
coordinateSystem: "geo",
symbol: icon,
symbolSize: 16,
symbolOffset: [2, 8],
data:convertData(mapInfos, mapData),
tooltip:{
show: false
}
}]
10. 地图的完整配置
const option = {
backgroundColor: '#E1E6EB',
tooltip: {
trigger: "item",
showDelay: 0,
transitionDuration: 0.2,
},
visualMap: {
left: "left", // visualMap 组件离容器左侧的距离,值为`'left'`, `'center'`, `'right'`,组件会根据相应的位置自动对齐。
bottom: 0,
itemSymbol:"circle",
right: 10,
seriesIndex: [0],
itemWidth: 10, // 每个图元的宽度
itemGap: 4, // 每两个图元之间的间隔距离,单位为px
pieces: [
{gte: 8, lte: 9, label: '连续下降', color: '#FF4D4D', symbol: 'circle'},
{gte: 5, lte: 8, label: '本期下降', color: '#FF6F00', symbol: 'circle'},
{gte: 1, lte: 5, label: '本期上升', color: '#FFC666', symbol: 'circle'},
{gte: 0, lte: 1, label: '连续上升', color: '#13BF30', symbol: 'circle'},
{gte: -1, lte: 0, label: '价格预警', color:'', symbol: 'image://http://xxx.png'}
],
},
geo: {
map: name,
zoom: 1.25,
roam: false,
},
series: [{
name: 'MAP',
type: 'map',
zoom: 1.25,
mapType: name,
selectedMode: false,//是否允许选中多个区域
label: {
normal: {
show: true,
},
emphasis: {
show: true
}
},
itemStyle: {
normal: {
borderColor: "rgba(254, 254, 254, 1)",
borderWidth: 1,
label:{
color: '#48535A'
}
},
emphasis: {
areaColor: "#eee",
borderColor: "rgba(255,111,0,1)",
borderWidth: 1,
label:{
color: '#FF6F00'
}
},
},
data: mapInfos
},{
map: name,
type: "scatter",
coordinateSystem: "geo",
symbol: icon,
symbolSize: 16,
symbolOffset: [2, 8],
data:convertData(mapInfos, mapData),
tooltip:{
show: false
}
}]
};
注意:
- mapInfos1,mapInfos2中的name的值要和mapJson的name保持一致,这样数据才会展示出来
- mapJson的cp字段是为了调整文字展示的位置,防止重叠在一起
- serise内scatter的配置与option.geo共存,即在地理坐标系内添加组件,且option.geo.roam为false,否则出现如下情况