|
@@ -3,24 +3,24 @@ 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); // 注册地图
|
|
|
+ echarts.registerMap("world", worldJson);
|
|
|
this.initChart();
|
|
|
window.addEventListener("resize", this.resizeChart);
|
|
|
+ this.startPulseAnimation();
|
|
|
}
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
- if (this.chartInstance) {
|
|
|
- this.chartInstance.dispose();
|
|
|
- }
|
|
|
+ if (this.chartInstance) this.chartInstance.dispose();
|
|
|
+ if (this.pulseTimer) clearInterval(this.pulseTimer);
|
|
|
window.removeEventListener("resize", this.resizeChart);
|
|
|
}
|
|
|
|
|
@@ -29,71 +29,72 @@ class WorldMap2D extends React.Component {
|
|
|
}
|
|
|
|
|
|
resizeChart = () => {
|
|
|
- if (this.chartInstance) {
|
|
|
- this.chartInstance.resize();
|
|
|
- }
|
|
|
+ if (this.chartInstance) this.chartInstance.resize();
|
|
|
};
|
|
|
|
|
|
initChart() {
|
|
|
if (!this.chartRef.current) return;
|
|
|
this.chartInstance = echarts.init(this.chartRef.current);
|
|
|
- // 顶部图标数据,计算 y 偏移(柱子高度的一半)
|
|
|
- const topIconData = this.props.data.map((d) => {
|
|
|
- return {
|
|
|
- name: d.name,
|
|
|
- value: [d.value[0], d.value[1], d.value[2]], // 位置
|
|
|
- symbolOffset: [0, -d.value[2] / 2 * 50 ], // Y轴偏移(柱子高度一半 + 额外10像素)
|
|
|
- };
|
|
|
- });
|
|
|
- const option = {
|
|
|
+
|
|
|
+ // 顶部图标数据
|
|
|
+ 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) => {
|
|
|
- return `${params.name} <br/>${params.value[2]}`;
|
|
|
- },
|
|
|
- textStyle: {
|
|
|
- fontSize: 30,
|
|
|
- fontWeight: "bold",
|
|
|
- },
|
|
|
+ // formatter: (params) => `${params.name} <br/>${params.value[2]}`,
|
|
|
+ textStyle: { fontSize: 30, fontWeight: "bold" },
|
|
|
},
|
|
|
geo: {
|
|
|
map: "world",
|
|
|
- roam: true, // 支持缩放拖拽
|
|
|
+ roam: true,
|
|
|
zoom: 1.1,
|
|
|
itemStyle: {
|
|
|
areaColor: "rgba(126, 206, 244, 0.1)",
|
|
|
borderColor: "#2EA7E0",
|
|
|
borderWidth: 2,
|
|
|
},
|
|
|
- label: {
|
|
|
- show: false, // ⚡ 确保不显示文字
|
|
|
- color: "#fff", // 如果 show: true 时设置文字颜色
|
|
|
- fontSize: 12
|
|
|
- },
|
|
|
+ label: { show: false },
|
|
|
emphasis: {
|
|
|
itemStyle: {
|
|
|
- areaColor: "rgba(41, 241, 250, 0.6)", // 悬浮时高亮色
|
|
|
+ areaColor: "rgba(41, 241, 250, 0.6)",
|
|
|
borderWidth: 1,
|
|
|
- borderColor: 'rgba(41, 241, 250, 1)',
|
|
|
- shadowColor: "rgba(41, 241, 250, 1)", // 阴影颜色
|
|
|
- // shadowColor: '#fff',
|
|
|
- shadowBlur: 2,
|
|
|
- shadowOffsetX: 10, // X 偏移
|
|
|
- shadowOffsetY: -10,
|
|
|
+ borderColor: "rgba(41, 241, 250, 1)",
|
|
|
+ shadowColor: "rgba(41, 241, 250, 1)",
|
|
|
+ shadowBlur: 2,
|
|
|
+ shadowOffsetX: 10,
|
|
|
+ shadowOffsetY: -10,
|
|
|
},
|
|
|
- label: {
|
|
|
- show: false // 悬浮时也不显示文字
|
|
|
- }
|
|
|
+ label: { show: false },
|
|
|
},
|
|
|
},
|
|
|
series: [
|
|
|
+ // 主柱子
|
|
|
{
|
|
|
type: "scatter",
|
|
|
coordinateSystem: "geo",
|
|
|
- symbol: "rect", // 用矩形柱代替点
|
|
|
- symbolSize: (val) => {
|
|
|
- const height = val[2] * 50;
|
|
|
- return [28, height];
|
|
|
- },
|
|
|
+ symbol: "rect",
|
|
|
+ symbolSize: (val) => [28, val[2] * 50],
|
|
|
itemStyle: {
|
|
|
color: {
|
|
|
type: "linear",
|
|
@@ -110,20 +111,66 @@ class WorldMap2D extends React.Component {
|
|
|
shadowBlur: 10,
|
|
|
borderRadius: [8, 8, 0, 0],
|
|
|
},
|
|
|
- encode: { tooltip: 2 }, // 提示框显示 value[2]
|
|
|
- data: this.props.data, // [lng, lat, value]
|
|
|
+ encode: { tooltip: 2 },
|
|
|
+ data: this.props.data,
|
|
|
},
|
|
|
+
|
|
|
+ // 顶部图标
|
|
|
{
|
|
|
type: "scatter",
|
|
|
coordinateSystem: "geo",
|
|
|
- symbol: `image://${topIcon}`, // 图片 URL
|
|
|
- symbolSize: [33, 33], // 图片大小
|
|
|
- data: topIconData,
|
|
|
+ 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,
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
+ }
|
|
|
|
|
|
- this.chartInstance.setOption(option);
|
|
|
+ // 启动依次扩散动画
|
|
|
+ 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() {
|