123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- 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} <br/>${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 (
- <div ref={this.chartRef} style={{ width: "100%", height: "100%" }} />
- );
- }
- }
- export default WorldMap2D;
|