React 实现 Echarts 3D地图 + 部分散点陷入地图解决方案

 推荐两个写地图组件常用到的网站:

获取地图json网站:https://datav.aliyun.com/portal/school/atlas/area_selector

拾取坐标点网站:拾取坐标系统

import React, {forwardRef, useEffect, useState} from "react";
import * as echarts from "echarts";
import chinaMap from "./chinaMap.json" //地图json
import locationPng from "./location.png";

const ThreeModelMap = ({height, width, chartInfo}) => {
  const [myMap, setMyMap] = useState()
  const [areaData, setAreaData] = useState([])
  
  const getPointColor = (value) => {
    if (value >= 100 && value < 200) {
      return '#00ff07'
    } else if (value >= 200 && value < 500) {
      return '#ffff00'
    } else if (value >= 500 && value < 900) {
      return '#ff5100'
    }
  }

  useEffect(async () => {
    const mapDom = document.getElementById('myMap')
    const myChart = echarts.init(mapDom)

    echarts.registerMap('chinaMap', chinaMap);


    //const scatterData = [
      // 每个数据点的格式为 [经度, 纬度, 数值(越大距离地面越高)]
      //{name: '上海市', value: [121.474216,31.234941, 300]},
      //{name: '南昌市', value: [115.871484,28.688441, 700]}
    //]

    //scatter3D陷入地图(解决方案一: 当点过多时可能会不生效):
      //需要有几个垫底数值的点防止值比较小的点陷入地图(定位到上海,不会影响当前区域)
      // for (let i = 0; i < 10; i++) {
      //   scatterData.push({
      //     name: `陷进地图垫底打点00${i+1}`,
      //     value: [121.475366, 31.232471, 101],
      //     id: `test00${i+1}`,
      //     symbol: 'circle',
      //     symbolSize: pointSymbolSize
      //   })
      // }
    //解决方案二:所有点的数值都使用一个高度适中的值,给每个点自定义区间的颜色或者symbol等样式,配合geo3D设置boxHeight=1可使地图地名处于地图表面而不偏移

    const resData = [
        {
            id: '001',
            value: 800,
            name: 'point1',
            ln: 121.474216,
            la: 31.239941
        },
        {
            id: '002',
            value: 200,
            name: 'point2',
            ln: 121.474216,
            la: 31.239941
        },
        {
            id: '003',
            value: 400,
            name: 'point3',
            ln: 121.474216,
            la: 31.239941
        },
        {
            id: '004',
            value: 600,
            name: 'point4',
            ln: 121.474216,
            la: 31.239941
        }
    ]
    
    const scatterData = resData.map(item => {
        return {
            name: 'point1', 
            value: [item.ln, item.la, 800], 
            itemStyle: {color: getPointColor(item.value)}
        }
    })

    //实现地图渐变
    let canvas = document.createElement("canvas");
    let ctx = canvas.getContext('2d');
    canvas.width = 65;
    canvas.height = 65;
    //绘制颜色偏向
    const Grd = ctx.createLinearGradient(0, 100, 100, 0);
    Grd.addColorStop(0, "orange");
    Grd.addColorStop(1, "blue");
    ctx.fillStyle = Grd;
    ctx.fillRect(0, 0, 100, 100);

    const option = {
      backgroundColor: 'rgba(0,0,0,1)',
      tooltip:{
        show:true
      },
      visualMap: { //可视化图例(点击可控制地图点的显隐)
          type: 'piecewise',
          right: 0,
          bottom: 0,
          textStyle: {
            color: '#FFFF',
            fontSize: 12,
          },
          align: 'left',
          itemWidth: 9.5,
          itemHeight: 9.5,
          itemSymbol: 'rect',
          itemGap: 15,
          inverse: true, //图例展示顺序:上小下大
          z: 4,
          pieces: [
            {
              gte: 500,
              lt: 900,
              color: '#ff5100',
              label: '500-900'
            },
            {
              gte: 200,
              lt:500,
              color: '#ffff00',
              label: '200-500'
            },
            {
              gte: 100,
              lt: 200,
              color: '#00ff07',
              label: '100-200'
            },
          ]
      },
      geo3D: {
        map: 'chinaMap', // 地图类型,这里以中国地图为例
        roam: false, // 是否开启鼠标缩放和平移漫游
        viewControl: {
          beta: 10, // 设置视角的左右旋转度数
          alpha: 40, // 设置视角的上下旋转度数
          // 设置视角的距离
          distance: 140
        },
        shading: 'realistic',
        // 设置渐变色
        realisticMaterial: {
          roughness: 1,
          textureTiling: 1,
          detailTexture: ctx.canvas.toDataURL()
        },
        label: {
          show: true,
          textStyle: {
            color: '#fff',
          },
          formatter: (params) => {
            return params.name;
          },
          borderRadius: 4,
        },
        regionHeight: 10, //地图厚度,
        boxHeight: 1,
        itemStyle: {
          color: '#65a9dc',
          borderColor: '#FFFFFF',
          borderWidth: 1,
          opacity: 1,
        },
        aspectScale: 0.9, //长宽比
        selectedMode: false, //是否允许选中多个区域
        data: [],
      },
      series: [
        {
          type: 'scatter3D',
          coordinateSystem: 'geo3D',
          itemStyle: {
            color: '#00FFF6',
          },
          // symbol: 'image://' + locationPng, //使用图片需加上前缀
          symbol: 'circle',
          symbolSize: 20,
          z: 999,
          data: scatterData,
        },
      ],
    }

    myChart.setOption(option);
  },[])


  return <div id={"myMap"} style={{height: height, width: width}}></div>
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值