import React from "react"; import * as echarts from "echarts"; import worldJson from "../world.json"; import topIcon from "../../../../assets/bigscreen/map-bar-head.svg"; class WorldMap2D extends React.Component { constructor(props) { super(props); this.chartRef = React.createRef(); this.chartInstance = null; this.pulseTimer = null; } componentDidMount() { echarts.registerMap("world", worldJson); this.initChart(); window.addEventListener("resize", this.resizeChart); this.startPulseAnimation(); } componentWillUnmount() { if (this.chartInstance) this.chartInstance.dispose(); if (this.pulseTimer) clearInterval(this.pulseTimer); window.removeEventListener("resize", this.resizeChart); } componentDidUpdate() { this.initChart(); } resizeChart = () => { if (this.chartInstance) this.chartInstance.resize(); }; initChart() { if (!this.chartRef.current) return; this.chartInstance = echarts.init(this.chartRef.current); // 顶部图标数据 this.topIconData = this.props.data.map((d) => ({ name: d.name, value: [d.value[0], d.value[1], d.value[2]], symbolOffset: [0, (-d.value[2] / 2) * 50], })); // 底部光圈初始化 this.pulseData = this.props.data.map((d) => ({ name: d.name, value: [d.value[0], d.value[1], 0], })); // 初始图表 const option = this.getChartOption(); this.chartInstance.setOption(option); } // 获取图表配置 getChartOption(currentPulseIndex = -1) { // 当前显示光圈的柱子 const pulseSeriesData = currentPulseIndex >= 0 ? [this.pulseData[currentPulseIndex]] : []; return { tooltip: { // formatter: (params) => `${params.name}
${params.value[2]}`, textStyle: { fontSize: 30, fontWeight: "bold" }, }, geo: { map: "world", roam: true, zoom: 1.1, itemStyle: { areaColor: "rgba(126, 206, 244, 0.1)", borderColor: "#2EA7E0", borderWidth: 2, }, label: { show: false }, emphasis: { itemStyle: { areaColor: "rgba(41, 241, 250, 0.6)", borderWidth: 1, borderColor: "rgba(41, 241, 250, 1)", shadowColor: "rgba(41, 241, 250, 1)", shadowBlur: 2, shadowOffsetX: 10, shadowOffsetY: -10, }, label: { show: false }, }, }, series: [ // 主柱子 { type: "scatter", coordinateSystem: "geo", symbol: "rect", symbolSize: (val) => [28, val[2] * 50], itemStyle: { color: { type: "linear", x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: "#EC903A" }, { offset: 1, color: "rgba(18,92,178,0)" }, ], }, shadowColor: "#4fd2dd", shadowBlur: 10, borderRadius: [8, 8, 0, 0], }, encode: { tooltip: 2 }, data: this.props.data, }, // 顶部图标 { type: "scatter", coordinateSystem: "geo", symbol: `image://${topIcon}`, symbolSize: [33, 33], data: this.topIconData, }, // 底部光圈 { type: "effectScatter", coordinateSystem: "geo", rippleEffect: { period: 5, // 波纹扩散周期 scale: 800, // 扩散倍数 brushType: "stroke", // 只描边 }, symbol: "circle", symbolSize: 1, // 小中心点 itemStyle: { color: "rgba(76,216,255,0.8)", // 中心点颜色 shadowBlur: 0, // 去掉阴影 shadowColor: "transparent", }, data: pulseSeriesData, }, ], }; } // 启动依次扩散动画 startPulseAnimation() { const { data } = this.props; clearInterval(this.pulseTimer); this.currentIndex = 0; this.pulseTimer = setInterval(() => { if (!this.chartInstance) return; const pulseData = [data[this.currentIndex]]; // 当前光圈数据 // 更新 effectScatter this.chartInstance.setOption({ series: [{}, {}, { data: pulseData }], }); // 自动显示 tooltip this.chartInstance.dispatchAction({ type: "showTip", seriesIndex: 0, // 主柱子 series dataIndex: this.currentIndex, }); this.currentIndex = (this.currentIndex + 1) % data.length; }, 2000); } render() { return (
); } } export default WorldMap2D;