基于Umi大屏项目--使用echarts绘制中国地图--生成柱状体--点击事件

428 阅读5分钟

1.变量说明

geoCoordMap:是在地图上特别的存在,它会根据坐标限制地图上的位置,比如在这个项目上是生成柱状体

customerBatteryCityData:是生成柱状体的title,高度value,还附带着其它属性,比如柱状体上方的弹窗

2.柱状体点击事件

        dataTrendChart.getZr().on('click',function(param){
          let index = dataTrendChart.convertFromPixel({ seriesIndex: 0 }, [param.offsetX, param.offsetY])[0]
          let local = parseInt(index)
          let keyValue = ''
          Object.keys(geoCoordMap).map((item)=>{
            geoCoordMap[item] = geoCoordMap[item].map(v => {
                return parseInt(v)
             })
             if(geoCoordMap[item].includes(local)){  //这里存在精度问题,后续需要改
              keyValue =item
             } 
          })
          props.goback('./datadetails',keyValue)
          console.log(param,'点击数据',keyValue)
        })
        //通过getZr()的点击事件,可以拿到当前点击位置在地图上的坐标,与生成柱状体的坐标想匹配,匹配成功后跳转页面

3.项目代码

    import { useState,useEffect } from 'react';
    import styles from './index.less';
    import * as echarts from 'echarts';
    import geoJson100000_Full from './100000_full.json';

    const DataTrend = (props) => {
      console.log(props,'地图数据')
      const [baceSecond,setbaceSecond] = useState([])
      const [baceThird,setbaceThird] = useState([])
      const [baceSix,setbaceSix] = useState([])


      useEffect(() => {
        myData();
      }, [baceSecond,baceThird,baceSix]);

      var geoCoordMap = {
        '622旅': [102.54136, 24.35232],
        '623旅':[110.29864, 25.26356],
        '666旅':[114.07521, 32.11854],
        '631旅':[109.52504, 27.01410],
      }
      const myData = ()=>{
        var dataTrendChart = echarts.init(
          document.getElementById('trendChartWrap'),
        );
        window.addEventListener('resize',() => {
          dataTrendChart && dataTrendChart.resize();
        });
        if(props.databrigadeMap[1]){
          setbaceSecond(props.databrigadeMap[1])
        }
        if(props.databrigadeMap[2]){
          setbaceThird(props.databrigadeMap[2])
        }
        if(props.databrigadeMap[0]){
          setbaceSix(props.databrigadeMap[0])
        }

        dataTrendChart.getZr().on('click',function(param){
          let index = dataTrendChart.convertFromPixel({ seriesIndex: 0 }, [param.offsetX, param.offsetY])[0]
          let local = parseInt(index)
          let keyValue = ''
          Object.keys(geoCoordMap).map((item)=>{
            geoCoordMap[item] = geoCoordMap[item].map(v => {
                return parseInt(v)
             })
             if(geoCoordMap[item].includes(local)){
              keyValue =item
             } 

          })
          props.goback('./datadetails',keyValue)
          console.log(param,'点击数据',keyValue)
        })

        var customerBatteryCityData = [
            {name: "622旅", value: 1200, dataTotal: 12, collection: 23,apply: 34,talk: 45},
            {name: "623旅", value: 600, dataTotal: 12, collection: 23,apply: 34,talk: 45},
            {name: "666旅", value: 1300, dataTotal: 12, collection: 23,apply: 34,talk: 45},
            {name: "631旅", value: 1200, dataTotal: 12, collection: 23,apply: 34,talk: 45},
        ]

        const mapArr = Object.entries(geoCoordMap)
        echarts.registerMap('guangdong', geoJson100000_Full);
        const option = {
          // backgroundColor: '#131C38',
          tooltip: {
              trigger: 'item',
              show: false,
              enterable: true,
              textStyle:{
                  fontSize:20,
                  color: '#fff'
              },
              backgroundColor: 'rgba(0,2,89,0.8)',

              formatter: '{b}<br />{c}'
          },
          geo: [
            {
              map: 'guangdong',
              aspectScale: 0.9,
              roam: false, // 是否允许缩放
              zoom: 0.9, // 默认显示级别
              layoutSize: '95%',
              layoutCenter: ['55%', '50%'],
              itemStyle: {
                normal: {
                  areaColor: {
                    type: 'linear-gradient',
                    x: 0,
                    y: 400,
                    x2: 0,
                    y2: 0,
                    colorStops: [{
                      offset: 0,
                      color: 'rgba(37,108,190,0.8)' // 0% 处的颜色
                    }, {
                      offset: 1,
                      color: 'rgba(15,169,195,1)' // 50% 处的颜色
                    }],
                    global: true // 缺省为 false
                  },
                  borderColor: '#4ecee6',
                  borderWidth: 1
                },
                emphasis: {
                  areaColor: {
                    type: 'linear-gradient',
                    x: 0,
                    y: 300,
                    x2: 0,
                    y2: 0,
                    colorStops: [{
                      offset: 0,
                      color: 'rgba(37,108,190,0.9)' // 0% 处的颜色
                    }, {
                      offset: 1,
                      color: 'rgba(15,169,195,1)' // 50% 处的颜色
                    }],
                    global: true // 缺省为 false
                  }
                }
              },
              emphasis: {
                itemStyle: {
                  areaColor: '#0160AD'
                },
                label: {
                  show: 0,
                  color: '#fff'
                }
              },
              zlevel: 3
            },
            {
              map: 'guangdong',
              aspectScale: 0.9,
              roam: false, // 是否允许缩放
              zoom: 0.9, // 默认显示级别
              layoutSize: '95%',
              layoutCenter: ['55%', '50%'],
              itemStyle: {
                normal: {
                  borderColor: 'rgba(192,245,249,.6)',
                  borderWidth: 2,
                  shadowColor: '#2C99F6',
                  shadowOffsetY: 0,
                  shadowBlur: 120,
                  areaColor: 'rgba(29,85,139,.2)'
                }
              },
              zlevel: 2,
              silent: true
            },
            {
              map: 'guangdong',
              aspectScale: 0.9,
              roam: false, // 是否允许缩放
              zoom: 0.9, // 默认显示级别
              layoutSize: '95%',
              layoutCenter: ['55%', '51.7%'],
              itemStyle: {
                // areaColor: '#005DDC',
                areaColor: 'rgba(0,27,95,0.6)',
                borderColor: '#004db5',
                borderWidth: 2
              },
              zlevel: 1,
              silent: true
            }
          ],
          series: [
            // map
            {
              geoIndex: 0,
              // coordinateSystem: 'geo',
              showLegendSymbol: true,
              type: 'map',
              roam: true,
              label: {
                normal: {
                  show: false,
                  textStyle: {
                    color: '#fff'
                  }
                },
                emphasis: {
                  show: false,
                  textStyle: {
                    color: '#fff'
                  }
                }
              },

              itemStyle: {
                normal: {
                  borderColor: '#2ab8ff',
                  borderWidth: 1.5,
                  areaColor: '#12235c'
                },
                emphasis: {
                  areaColor: '#2AB8FF',
                  borderWidth: 0,
                  color: 'red'
                }
              },
              map: 'guangdong', // 使用
              data: customerBatteryCityData
              // data: this.difficultData //热力图数据   不同区域 不同的底色
            },
            // 柱状体的主干
            {
              type: 'lines',
              zlevel: 5,
              effect: {
                show: false,
                // period: 4, //箭头指向速度,值越小速度越快
                // trailLength: 0.4, //特效尾迹长度[0,1]值越大,尾迹越长重
                // symbol: 'arrow', //箭头图标
                // symbol: imgDatUrl,
                symbolSize: 5 // 图标大小
              },
              lineStyle: {
                width: 20, // 尾迹线条宽度
                color: 'rgb(22,255,255, .6)',

                // colorStops: [{
                //   offset: 0,
                //   color: 'rgb(22,255,255, .2)' // 0% 处的颜色
                // }, {
                //   offset: 1,
                //   color: 'rgb(22,255,255, .6)' // 50% 处的颜色
                // }],

                opacity: 1, // 尾迹线条透明度
                curveness: 0 // 尾迹线条曲直度
              },
              label: {
                show: 0,
                position: 'end',
                formatter: '245'
              },
              silent: true,
              data: lineData()
            },
            // 柱状体的顶部
            {
              type: 'scatter',
              coordinateSystem: 'geo',
              geoIndex: 0,
              zlevel: 5,
              label: {
                show: true,
                width: 130,
                height: 93,
                backgroundColor: '#01477C', 
                textStyle: {
                  borderWidth: "1",
                  borderColor:"#A7FAFF",
                  opacity: 0.25,
                },

                // borderColor:'#4ecee6',
                // borderColor:'1 solid red',
                opacity: 0.7,
                padding:[0,0,0,25],
                formatter: function (a) {
                  const index = a.dataIndex
                  const name = mapArr[index][0]
                  const item = customerBatteryCityData.find(n => n.name === name)
                  const cpm = [
                    `{d1|●}`,
                    `{b|会商总量: ${item.dataTotal}} \n`,
                    `{d2|●}`,
                    `{b|采集总量: ${item.collection}} \n`,
                    `{d3|●}`,
                    `{b|支援申请总量: ${item.apply}} \n`,
                    `{d4|●}`,
                    `{b|数据总量: ${item.talk}} \n`,  
                  ]
                  return cpm.join('')

                },
                rich: {
                  d1: {
                      color: '#B3D5FF',
                      align: 'left',
                      opacity: 1,
                      padding:[3,3,0,0]
                  },
                  d2: {
                    color: '#56A0FF',
                    align: 'left',
                    opacity: 1,
                    padding:[3,3,0,0]
                  },
                  d3: {
                    color: '#5DDCFF',
                    align: 'left',
                    opacity: 1,
                    padding:[3,3,0,0]
                  },
                  d4: {
                    color: '#FFCD61',
                    align: 'left',
                    opacity: 1,
                    padding:[3,3,0,0]
                },
                  b: {
                      // width: 1,
                      height: 20,
                      bottom:20,
                      borderWidth: 1,
                      color: '#FFF',
                      align: 'left',
                      opacity: 1,
                      padding:[3,0,0,0]
                  },
              },
                position: "top"
              },
              symbol: 'rect',
              symbolSize: [20, 10],
              itemStyle: {
                color: 'rgb(22,255,255, 1)',
                opacity: 1
              },
              silent: true,
              data: scatterData()
            },
            // 柱状体的底部
            {
              type: 'scatter',
              coordinateSystem: 'geo',
              geoIndex: 0,
              zlevel: 4,
              label: {
                // 这儿是处理的
                formatter: '{b}',
                position: 'bottom',
                color: '#fff',
                fontSize: 12,
                distance: 10,
                show: true
              },
              symbol: 'rect',
              symbolSize: [20, 10],
              itemStyle: {
                // color: '#F7AF21',
                color: 'rgb(22,255,255, 1)',
                opacity: 1
              },
              silent: true,
              data: scatterData2()
            },
            // 底部外框
            {
              type: 'scatter',
              coordinateSystem: 'geo',
              geoIndex: 0,
              zlevel: 4,
              label: {
                show: false
              },
              symbol: 'circle',
              symbolSize: [40, 20],
              itemStyle: {
                  color: {
                  type: 'radial',
                  x: 0.5,
                  y: 0.5,
                  r: 0.5,
                  colorStops: [
                      {
                          offset: 0, color: 'rgb(22,255,255, 0)' // 0% 处的颜色
                      }, 
                      {
                          offset: .75, color: 'rgb(22,255,255, 0)' // 100% 处的颜色
                      },
                      {
                          offset: .751, color: 'rgb(22,255,255, 1)' // 100% 处的颜色
                      },
                      {
                          offset: 1, color: 'rgb(22,255,255, 1)' // 100% 处的颜色
                      }
                  ],
                  global: false // 缺省为 false
              },

                opacity: 1
              },
              silent: true,
              data: scatterData2()
            },


          ]
        }
        dataTrendChart.setOption(option);
        // 动态计算柱形图的高度(定一个max)
        function lineMaxHeight () {
          const maxValue = Math.max(...customerBatteryCityData.map(item => item.value))
          return 11/maxValue
        }
        // 柱状体的主干
        function lineData () {
          return customerBatteryCityData.map((item) => {
            return {
              coords: [geoCoordMap[item.name], [geoCoordMap[item.name][0], geoCoordMap[item.name][1] + item.value * lineMaxHeight()]]
            }
          })
        }

        // 柱状体的顶部
        function scatterData () {
          return customerBatteryCityData.map((item) => {
            return [geoCoordMap[item.name][0], geoCoordMap[item.name][1] + item.value * lineMaxHeight()]
            })
        }
        // 柱状体的底部
        function scatterData2 () {
          return customerBatteryCityData.map((item) => {
            return {
              name: item.name,
              value: geoCoordMap[item.name]
            }
          })
        }
      }


      return (
        <div className={styles.chartsMap}>
          <div id="trendChartWrap" className={styles.ecsMap} />
        </div>
      );
    };

    export default DataTrend;

这里注释的内容,是根据 make a pie 网上的源码进行二次修改,将不需要的内容注释了,这其中有个难点是在柱状体上继续写弹框。引入的json文件是中国地图坐标。