返回顶部

react+echarts实现地图飞线图

参考

1.datav 大屏特效使用 https://blog.csdn.net/qq_53479087/article/details/129411685

2.map china not exists. the geojson of the map must be provided. https://blog.csdn.net/qq_45043813/article/details/136999076

3.ECharts中Map(地图)样式配置、渐变色生成 https://cloud.tencent.com/developer/article/2402983

4.第三方示例平台:https://www.makeapie.cn/echarts

5.ehcarts配置项:https://echarts.apache.org/zh/option.html#title

 

效果

 有个问题:未设置飞线的接收点也会有飞线效果,比如新疆,后面看看怎么解决。

 

1.安装echarts和echarts-for-react

pnpm add echarts echarts-for-react

我的版本是:

"echarts": "^5.6.0"
"echarts-for-react": "^3.0.2"
 

2.地图组件

import { useEffect, useRef, useState } from 'react'
import * as echarts from 'echarts'
import ReactECharts from 'echarts-for-react'
import chinaJson from './china.json' // 直接导入 GeoJSON

export default function MapFlyLine() {
  const chartRef = useRef(null)
  const [echartsOption, setEchartsOption] = useState()

  // 接收点颜色
  const centerColor = '#FABD45'
  let centerCitys: any[] = []
  let aroundCitys: any[] = []
  let linesArr: any[] = []

  const result = [
    {
      name: '总部-北京',
      addressX: '116.4',
      addressY: '39.9',
      provinceName: '北京市',
      childVOS: [
        {
          name: '分部-上海市',
          addressX: '121.47',
          addressY: '31.23',
          showLine: true,
        },
        {
          name: '分部-新疆',
          addressX: '87.617733',
          addressY: '43.792818',
          showLine: false,
        },
        {
          name: '分部-青海',
          addressX: '101.778916',
          addressY: '36.623178',
          showLine: true,
        },
        {
          name: '分部-四川',
          addressX: '104.065735',
          addressY: '30.659462',
          showLine: true,
        },
        {
          name: '分部-湖南',
          addressX: '112.982279',
          addressY: '28.19409',
          showLine: true,
        },
        {
          name: '分部-西藏',
          addressX: '91.132212',
          addressY: '29.660361',
          showLine: false,
        },
        {
          name: '分部-广西',
          addressX: '108.320004',
          addressY: '22.82402',
          showLine: false,
        },
      ],
    },
  ]
  result.forEach((center, index) => {
    // 总部
    centerCitys.push({
      name: center.name,
      value: [center.addressX, center.addressY],
      provinceName: center.provinceName,
    })
    center.childVOS.forEach(child => {
      // 分部
      aroundCitys.push({
        name: child.name,
        value: [child.addressX, child.addressY],
        itemStyle: {
          color: centerColor,
        },
      })
      // 飞线
      linesArr.push({
        name: `${child.name}-${center.name}`,
        coords: [
          [center.addressX, center.addressY],
          [child.addressX, child.addressY],
        ],
        lineStyle: {
          normal: {
            width: 2,
            curveness: 0, // 边的曲度,支持从 0 到 1 的值,值越大曲度越大
            color: {
              type: 'linear', // 线性渐变
              x: 1,
              y: 0,
              x2: 0,
              y2: 1,
              colorStops: [
                {
                  offset: 0,
                  color: 'rgba(250, 189, 69, 1)', // 起始颜色
                },
                {
                  offset: 1,
                  color: ' rgba(250, 189, 69, 0)', // 终止颜色
                },
              ],
            },
            opacity: child.showLine ? 1 : 0,
          },
        },
      })
    })
  })

  const regions = chinaJson.features.map(item => {
    const { name } = item.properties

    return {
      name: name,
      itemStyle: {
        normal: {
          shadowColor: 'rgba(133, 26, 10, 1)', // 阴影颜色
          shadowBlur: 5, // 阴影模糊大小
          shadowOffsetX: 2, // 阴影水平偏移
          shadowOffsetY: 12, // 阴影垂直偏移
        },
      },
    }
  })

  const option: any = {
    // 地理坐标系组件,地图的配置是一层盖一层,从底层到顶层的配置依次为:geo => series => visualMap。geo隐藏掉只有series也是能正常显示整个地图的。
    geo: {
      map: 'china', // 使用 registerMap 注册的地图名称
      zlevel: 13, // 所有图形的 zlevel 值
      show: true,
      // layoutCenter: ['50%', '50%'], // 地图中心在屏幕中的位置
      roam: false, // 是否开启鼠标缩放和平移漫游,只开启单个时,设置'scale' 或者 'move'
      // layoutSize: '100%', // 地图的大小
      zoom: 1.2, // 当前视角的缩放比例
      // 图形上的文本标签
      label: {
        normal: {
          show: true, // 开启会显示省份名称
          textStyle: {
            fontSize: 12,
            color: 'rgba(253, 218, 190,0.45)',
          },
        },
      },
      // 在地图中对特定的区域配置样式(不包含南海诸岛缩略框)
      regions: regions,
      // 地图区域的多边形 图形未选中的样式(包含南海诸岛缩略框)
      itemStyle: {
        normal: {
          areaColor: '#9E1B12',
          borderColor: '#620E04',
          borderWidth: 1,
        },
      },
      // 鼠标移入高亮效果
      emphasis: {
        disabled: true,
      },
    },
    series: [
      // 发射点
      {
        type: 'effectScatter', // 带有涟漪特效动画的散点(气泡)图
        coordinateSystem: 'geo', // 该系列使用的坐标系
        zlevel: 15,
        symbol:
          'image://data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7', // 标记的图形
        symbolSize: 13, // 标记的大小
        // 涟漪特效相关配置
        rippleEffect: {
          period: 6, // 动画的周期,秒数
          num: 3, // 波纹的数量
          brushType: 'fill', // 波纹的绘制方式,可选 'stroke' 和 'fill'
          scale: 3, // 动画中波纹的最大缩放比例
        },
        data: centerCitys,
      },
      // 接收点
      {
        type: 'effectScatter',
        coordinateSystem: 'geo',
        zlevel: 15,
        symbolSize: 4,
        data: aroundCitys,
      },
      // 飞线
      {
        type: 'lines',
        coordinateSystem: 'geo',
        zlevel: 14,
        // 线特效的配置
        effect: {
          show: true,
          period: 2, // 控制流星的速度,数字越小越快
          trailLength: 0.2, // 控制流星尾巴的长度,范围为0-1
          symbol: 'pin', // 尾巴形状,也可以设置成其他符号
          symbolSize: 10, // 尾巴大小
        },
        data: linesArr,
      },
    ],
  }

  // 注册地图
  useEffect(() => {
    echarts.registerMap('china', chinaJson) // 'china' 是地图注册名称
    setEchartsOption(option) // 确保 registerMap 在 setEchartsOption 之前执行
  }, [])

  // 响应式重绘(窗口大小变化)
  useEffect(() => {
    const handleResize = () => {
      if (chartRef.current) {
        chartRef.current.getEchartsInstance().resize()
      }
    }

    window.addEventListener('resize', handleResize)

    return () => {
      window.removeEventListener('resize', handleResize)
    }
  }, [])

  if (echartsOption) {
    return <ReactECharts ref={chartRef} option={echartsOption} style={{ height: '70vh' }} />
  }
  return <></>
}

china.json文件可去DataV下载

https://datav.aliyun.com/portal/school/atlas/area_selector#&lat=30.332329214580188&lng=106.72278672066881&zoom=3.5

 

我的其他问题

1.使用DataV组件

import { DigitalFlop } from '@jiaminghi/data-view-react'

报错:无法找到模块“@jiaminghi/data-view-react”的声明文件

解决方法:

在项目下随便找个位置 创建一个 datav.d.ts (随便起的名字),内容:

declare module "@jiaminghi/data-view-react"; 

 

2.地图第一次会显示,但一刷新就报错

Map china not exists. The GeoJSON of the map must be provided.
Uncaught TypeError: Cannot read properties of undefined (reading 'regions')

原因:需要确保 registerMap 在 setOption 之前执行。

// 注册地图
 useEffect(() => {
   echarts.registerMap('china', chinaJson) // 'china' 是地图注册名称
   setEchartsOption(option) // 确保 registerMap 在 setEchartsOption 之前执行
 }, [])

if (echartsOption) {
    return <ReactECharts option={echartsOption} style={{ height: '52vh' }} />
  }
return <></>

 3.想要不显示南海诸岛具体图形,只显示缩略图

修改china.json文件,我是从第三方示例下载的:https://www.makeapie.cn/echarts_content/x---RvEDTa.html

 

posted @ 2025-05-30 11:41  前端-xyq  阅读(270)  评论(0)    收藏  举报