antd react echarts地图组件点击地市传参给父组件,点击同一个地市取消选中并传参给父组件触发查询地图组件:
import { useEffect, useState } from "react";
import * as echarts from "echarts";
import chinaJson from './chinaJson';
const MapIndex = ({
option,
onCityClick,
width = "100%",
height = "100%",
}) => {
const [selectedCity, setSelectedCity] = useState('');
let mapInstance;
const renderMap = () => {
// 销毁实例,销毁后实例无法再被使用
if (mapInstance) {
mapInstance.dispose();
}
let chartDom = document.getElementById("map");
mapInstance = echarts.init(chartDom);
// 注册地图到echarts中,这里的'china'要与地图数据的option中的series、geo中的map属性值对应
echarts.registerMap('china', chinaJson);
mapInstance.setOption(option);
document.getElementById("map").removeEventListener;
window.addEventListener("resize", () => {
mapInstance.resize();
});
// 在渲染点击事件之前先清除点击事件
mapInstance.off('click');
mapInstance.on("click", (params) => {
// params中包含了点击的地市信息
const { name } = params;
console.log(name, selectedCity);
if (name === selectedCity) {
// 点击的同一个城市
setSelectedCity('');
onCityClick(''); // 传参给父组件
} else {
setSelectedCity(name); // 点击其他地市则传递地市名称
onCityClick(name); // 传参给父组件
}
});
};
useEffect(() => {
renderMap();
}, [option, selectedCity]);
return <div id="map" style={{ width, height }} />;
};
export default MapIndex;
chinaJson文件从 DataV.GeoAtlas地理小工具系列获取:
组件使用:
import { useRef, useEffect } from "react";
import MapIndex from './MapIndex';
const Index = () => {
let option = {
tooltip: {},
visualMap: {
show: false, // 是否显示 visualMap-continuous 组件。如果设置为 false,不会显示,但是数据映射的功能还存在
type: "continuous", // 类型为连续型视觉映射
calculable: false, // 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)
inRange: {
color: ["#ffd258", "#ff9e45"],
},
},
// 地理坐标系组件
geo: {
map: 'china',
aspectScale: 0.75, //长宽比
zoom: 1.2,
roam: false, // 滚轮 放大缩小
emphasis: {
label: {
show: false,
},
},
itemStyle: {
areaColor: {
// 默认区块颜色
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#BFFFDD", // 0% 处的颜色
},
{
offset: 1,
color: "#FFFFFF", // 100% 处的颜色
},
],
},
shadowColor: "#FFFFFF", // 青色
shadowBlur: 0,
shadowOffsetX: 10,
shadowOffsetY: 10,
borderWidth: 0,
},
},
series: [
{
id: "map",
type: "map", // 图表类型
map: 'china', // 已注册的地图
aspectScale: 0.75, //长宽比
showLegendSymbol: false, // 存在legend时显示
roam: false,
label: {
show: true,
color: "#333",
fontWeight: 700,
textShadowBlur: 5,
textShadowOffsetX: 0,
textShadowOffsetY: 4,
},
emphasis: {
label: {
color: "#e8eefc",
}
},
select: {
// 选中状态下的多边形和标签样式
itemStyle: {
borderColor: "#67E51F",
borderWidth: 1,
areaColor: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#A3DF7F", // 0% 处的颜色
},
{
offset: 1,
color: "#017E0F", // 100% 处的颜色
},
],
},
},
label: {
color: "#e8efce",
},
},
itemStyle: {
// 地图区域的多边形 图形样式
borderColor: "#017E0F",
borderWidth: 0.4,
areaColor: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#BFDFDF", // 0% 处的颜色
},
{
offset: 1,
color: "#FFFFFF", // 100% 处的颜色
},
],
},
},
emphasis: {
itemStyle: {
areaColor: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#A3DF7F", // 0% 处的颜色
},
{
offset: 1,
color: "#017E0F", // 100% 处的颜色
},
],
},
borderColor: "#67E51F",
borderWidth: 1,
shadowColor: "rgba(103, 225, 245, 0.7)",
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 0,
}
},
zoom: 1.2,
animation: false,
data: [
{
value: 218,
name: "北京",
},
{
value: 122,
name: "广东",
},
],
},
], // 图表数据
};
// 点击地图获取地市名称
const handleCityClick = (cityName) => {
console.log(cityName);
};
<MapIndex option={option} onCityClick={handleCityClick} height="100%" width="100%" />;
}
export default Index;
使用上面的代码,遇到qiankun微应用挂载不同的子应用时,由于地图的width、height以及其父元素的宽高都是百分比,地图渲染会偏向一边,canvas的width会很大,解决该问题可以通过ResizeObserver监听父容器尺寸的变化,并在尺寸变化时调用ECharts的resize方法来重新计算图表的尺寸,地图组件代码如下:
import { useRef, useEffect, useState } from "react";
import * as echarts from "echarts";
import chinaJson from './chinaJson';
const MapIndex = ({
option,
onCityClick,
width = "100%",
height = "100%",
}) => {
const [selectedCity, setSelectedCity] = useState('');
const chartRef = useRef(null);
let myChart = null;
const renderMap = () => {
if (chartRef.current) {
// 初始化ECharts实例
myChart = echarts.init(chartRef.current);
// 注册地图到echarts中,这里的'china'要与地图数据的option中的series、geo中的map属性值对应
echarts.registerMap('china', chinaJson);
// 设置图表选项
myChart.setOption(option);
// 监听窗口大小变化
const resizeObserver = new ResizeObserver(() => {
if (myChart) {
myChart.resize();
}
});
resizeObserver.observe(chartRef.current.parentElement);
// 在渲染点击事件之前先清除点击事件
myChart.off('click');
myChart.on("click", (params) => {
// params中包含了点击的地市信息
const { name } = params;
if (name === selectedCity) {
// 点击的同一个城市 设置指定值
setSelectedCity('xxx');
onCityClick('xxx');
} else {
setSelectedCity(name); // 点击其他地市则传递地市名称
onCityClick(name);
}
});
// 清理函数
return () => {
if (myChart) {
myChart.dispose();
}
resizeObserver.disconnect();
};
}
};
useEffect(() => {
renderMap();
}, [option, selectedCity]);
return <div ref={chartRef} style={{ width, height }} />;
};
export default MapIndex;
组件的使用:
import MapIndex from './MapIndex';
const Index = () => {
let option = {
tooltip: {},
visualMap: {
show: false, // 是否显示 visualMap-continuous 组件。如果设置为 false,不会显示,但是数据映射的功能还存在
type: "continuous", // 类型为连续型视觉映射
calculable: false, // 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)
inRange: {
color: ["#ffd258", "#ff9e45"],
},
},
// 地理坐标系组件
geo: {
map: 'china',
aspectScale: 0.75, //长宽比
zoom: 1.2,
roam: false, // 滚轮 放大缩小
emphasis: {
label: {
show: false,
},
},
itemStyle: {
areaColor: {
// 默认区块颜色
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#BFFFDD", // 0% 处的颜色
},
{
offset: 1,
color: "#FFFFFF", // 100% 处的颜色
},
],
},
shadowColor: "#FFFFFF", // 青色
shadowBlur: 0,
shadowOffsetX: 10,
shadowOffsetY: 10,
borderWidth: 0,
},
},
series: [
{
id: "map",
type: "map", // 图表类型
map: 'china', // 已注册的地图
aspectScale: 0.75, //长宽比
showLegendSymbol: false, // 存在legend时显示
roam: false,
label: {
show: true,
color: "#333",
fontWeight: 700,
textShadowBlur: 5,
textShadowOffsetX: 0,
textShadowOffsetY: 4,
},
emphasis: {
label: {
color: "#e8eefc",
}
},
select: {
// 选中状态下的多边形和标签样式
itemStyle: {
borderColor: "#67E51F",
borderWidth: 1,
areaColor: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#A3DF7F", // 0% 处的颜色
},
{
offset: 1,
color: "#017E0F", // 100% 处的颜色
},
],
},
},
label: {
color: "#e8efce",
},
},
itemStyle: {
// 地图区域的多边形 图形样式
borderColor: "#017E0F",
borderWidth: 0.4,
areaColor: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "#BFDFDF", // 0% 处的颜色
},
{
offset: 1,
color: "#FFFFFF", // 100% 处的颜色
},
],
},
},
emphasis: {
itemStyle: {
areaColor: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#A3DF7F", // 0% 处的颜色
},
{
offset: 1,
color: "#017E0F", // 100% 处的颜色
},
],
},
borderColor: "#67E51F",
borderWidth: 1,
shadowColor: "rgba(103, 225, 245, 0.7)",
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 0,
}
},
zoom: 1.2,
animation: false,
data: [
{
value: 218,
name: "北京",
},
{
value: 122,
name: "广东",
},
],
},
], // 图表数据
};
// 点击地图获取地市名称
const handleCityClick = (cityName) => {
console.log(cityName);
};
<MapIndex option={option} onCityClick={handleCityClick} />;
}
export default Index;