0
点赞
收藏
分享

微信扫一扫

vue使用echart绘制全国地图,叠加图表

脱下愤怒的小裤衩 2022-04-29 阅读 59

场景:

效果图:

在这里插入图片描述

完整代码:

mapOption.js配置项:
let obj ={
    
}
export default {
    geo: {
        map: 'china',
        show: false,
        roam: false,
        label: {
            emphasis: {
                show: false
            }
        },
        layoutSize: "100%",
        itemStyle: {
            normal: {
            }
        }
    },
    visualMap: {
        min: 0,
        max: 1000,
        left: 100,
        bottom: 45,
        showLabel: !0,
        backgroundColor:"#fff",
        text: ["高", "低"],
        pieces: [],
    },
    series: [
        {
            type: 'map',
            zoom:1.1,
            aspectScale: 0.9,
            layoutCenter: ["50%", "60%"], //地图位置
            layoutSize: "100%",
            zlevel: 3,
            scaleLimit: {
                //滚轮缩放的极限控制
                min: 1,
                max: 1.5,
            },
            geo: {
                show: true,
                map: 'china',
                label: {
                    normal: {
                        show: false
                    },
                    emphasis: {
                        show: false,
                    }
                },
                roam: false,
                itemStyle: {
                    normal: {
                        areaColor: '#031525',
                        borderColor: '#3B5077',
                    },
                    emphasis: {
                        areaColor: '#2B91B7',
                    }
                }
            },
            roam: true,  // 是否开启鼠标缩放和平移漫游
            selectedMode: 'false', // 是否允许选中多个区域
            emphasis:{
                label:{
                    show:true,
                    color:'#ffffff',
                }
            },
            label: {
                show: true,
                color: "#FFFFFF",
                fontSize: 12,
            },
            itemStyle: {
                normal: {
                    areaColor: "#0c3653",
                    borderColor: "#1cccff",
                    borderWidth: 2,
                },
                emphasis: {
                    areaColor:"rgb(12,76,107)",   //鼠标悬停/选中颜色
                    label: {
                        show: true,
                        color: "#fff",
                        borderColor:"rgb(2,241,177)",
                       
                    },
                },
            },
            data: [],
        },
    ]
};
  
其他例如china.json移步到datav下载即可:结构如下

在这里插入图片描述

<template>
  <div class="chart pt-10">
    <el-button type="primary" size="mini" @click="options.id=1">模式1</el-button>
    <el-button type="primary" size="mini" @click="options.id=11">模式2</el-button>
    <div id="mapChart" class="mapChart"></div>
  </div>
</template>

<script>
import mapOption from './echarts/map'

import chinaData from '@/assets/china.json'
import liaoningPro from './echarts/liaoning.json'
import shenyangCity from './echarts/shenyang.json'


export default {
  data(){
    return{
      myChart: null,
      chinaCode:100000,
      curMapName:'china', // 当前地图名
      selectedMaps:[
        {
          name:'china',
          code:'100000',
        }
      ],
      //地图散点数据
      mapDotData:{
        input:{
          value:{}
        },
        output:{
          value:{
            rows:[]
          }
        }
      },
      typeIndex:1,
      //上一次的缩放层级
      lastZoomLevel:0,
      // 图例
      options:{
        id:1
      }
    }

  },
  props:{
  },
  async mounted(){
    await this.getMapData('china');
    window.addEventListener('resize',this.resizeCharts);
    
    


    // //这里是做地图下钻   预留一下吧  以后需要直接放开继续写逻辑目前也算是实现了下钻的操作
    // this.myChart.on('click', (params) => {
    //     console.log('空间',params)
    //     const map = params.name;
    //     if(map){
    //       this.curMapName = params.name;
    //       this.getMapData(map);
    //       // 为地图标题菜单存入(过滤同一地图多次点击情况)点击地图信息
    //       let selectedCodes = [];
    //       this.selectedMaps.forEach( item => selectedCodes.push(item.code));
    //       if(!selectedCodes.includes(map)){
    //         this.$set(this.selectedMaps,this.selectedMaps.length,{name: this.curMapName, code: map}); 
    //       }
    //       console.log(selectedCodes)
          
    //     }else{
    //       this.$message({message: '暂无地图数据',type: 'warning',showClose: true});
    //     }
    // });
    window.addEventListener("resize", (params)=> {
      if(Number(this.options.id)<10){
        this.resetDot(this.myChart, params);
      }else{
        this.resetPie(this.myChart, params);
      }
    })
  },
  beforeDestroy() {
    window.addEventListener('resize',this.resizeCharts);
  },
  watch:{
      "options.id":{
          async handler(v){
              if(v){
                  this.myChart.dispose()
                  this.getMapData('china')
              }
          }
      },
  },
  methods:{
    // 绘制地图
    async drawMapChart(mapName,mapJSON){
      if (this.myChart != null && this.myChart != "" && this.myChart != undefined) {
        this.myChart.dispose();
      }
      this.myChart = this.$echarts.init(document.getElementById('mapChart'));
      this.$echarts.registerMap(mapName,mapJSON);
      
      let seriesData = this.initMapData(mapJSON)

      //然后调用接口查询地图信息
      await this.getMapDotData()
      let arr = this.mapDotData.output.value.rows 

      for(var i =0;i<seriesData.length;i++){
        arr.forEach((item,index)=>{
          if(seriesData[i].name==item.xzqmc){
            seriesData[i].value = item.total
          }
        })
      }
      mapOption.series[0].map = mapName
      mapOption.series[0].data = seriesData
      //图例是配置的
      mapOption.visualMap.pieces =[{
            gt: 100,
            color: "#7f1100"
        }, {
            gte: 60,
            lte: 80,
            color: "#ff5428"
        }, {
            gte: 20,
            lt: 60,
            color: "#ff8c71"
        }, {
            gt: 0,
            lt: 20,
            color: "#ffd768"
      }],
      
      //先有个地图底图
      this.myChart.setOption(mapOption,true);
      if(Number(this.options.id)<10){
        //然后再叠加图表上去
        this.addPieToMap(this.myChart, this.mapDotData.output.value.rows );
      }else{
        this.addPartPieToMap(this.myChart, this.mapDotData.output.value.rows )
      }
      

      /*饼图跟着地图移动:pie*/
      this.myChart.on('georoam', (params)=> {
        if(Number(this.options.id)<10){
          this.resetDot(this.myChart, params);
        }else{
          this.resetPie(this.myChart, params);
        }
      });

      
    },
    initMapData(mapJson) {
      let mapData = [];
      for (let i = 0; i < mapJson.features.length; i++) {
        mapData.push({ name: mapJson.features[i].properties.name });
      }
      return mapData;
    },
    // 浏览器窗口大小改变时,重新加载图表以自适应
    resizeCharts(){
      this.$echarts.init(document.getElementById('mapChart')).resize()
    },
    // 获取地图数据
    async getMapData(map){
        if(map=='china'){
          await this.drawMapChart(this.curMapName,chinaData[0]);
        }else if(map=='辽宁省'){
          this.drawMapChart(this.curMapName,liaoningPro);
        }else{
          this.drawMapChart(this.curMapName,shenyangCity);
        }
    },

    //接口获取散点数据
    async getMapDotData(){
      //接口获取数据
      let rows = []

      if(Number(this.options.id)<10){
        rows =[
          {
              "xzqmc": "四川省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "辽宁省",
              "total": 482.99,
              "dw": "万亩",
              "xzqdm": "540000"
          },
          {
              "xzqmc": "湖南省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "湖北省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "贵州省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "云南省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "青海省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "陕西省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "山西省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "新疆维吾尔自治区",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "西藏自治区",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "宁夏回族自治区",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "甘肃省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "河南省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "安徽省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "山东省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "江苏省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "江西省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
          {
              "xzqmc": "福建省",
              "total": 9088.51,
              "dw": "万亩",
              "xzqdm": "510000"
          },
        ]
      }else{
        rows=[
            {
              "xzqmc":"辽宁省",
              "xzqdm":"xxx",
              "total":5.3,
              "rows":[
                    {
                      "name":"五等地",
                      "value":"26",
                    },
                    {
                      "name":"一等地",
                      "value":"12",
                    },
                    {
                      "name":"四等地",
                      "value":"45",
                    },
                     {
                      "name":"三等地",
                      "value":"5",
                    },
              ]
            },
            {
              "xzqmc":"四川省",
              "xzqdm":"xxx",
              "total":5.3,
              "rows":[
                    {
                      "name":"五等地",
                      "value":"26",
                    },
                    {
                      "name":"一等地",
                      "value":"12",
                    },
                    {
                      "name":"四等地",
                      "value":"45",
                    },
                     {
                      "name":"三等地",
                      "value":"5",
                    },
              ]
            }
        ]
      }

      this.mapDotData.output.value.rows = rows
    },
    //添加散点图
    addPieToMap(chart,data){
      var sd = [];
      for (var i = 0; i < data.length; i++) {
          var randomValue = 20;
          var radius = randomValue;
          // var geoCoord = geoCoordMap[data[i].name];
         
          let geoCoord = chinaData[0].features.find((item)=>{
            return item.properties.name==data[i].xzqmc
          }).properties.center
          if (geoCoord) {
              var vr = [];
              //饼图的数据不进行映射
              vr.push({
                  name: data[i].xzqmc,
                  value: data[i].total,
                  visualMap: false
              }); 
              var p = chart.convertToPixel({
                  seriesIndex: 0
              }, geoCoord);
              sd.push({
                  name: data[i].xzqmc,
                  type: 'pie',
                  // roseType: 'radius',
                  // tooltip: {
                  //     formatter: function(params) {
                  //         // return params.seriesName + "<br/>" + params.name + " : " + params.value + ' 亿元';
                  //         return params.total + ' 亩';
                  //     }
                  // },
                  radius: radius,
                  center: p,
                  data: vr,
                  zlevel: 4,
                  roam:false,
                  tooltip: {
                      formatter: '{a}<br/>{b}: {c}亿元 ({d}%)'
                  },
                  label: {
                      normal: {
                          show: true,
                          position: 'inside',
                          formatter: '{value|{c}}',
                          padding:[0,0,radius,0],
                          rich: {
                              value: {
                                  fontSize: 12,
                                  color:'#ffffff',
                              },
                          },
                      }
                  },
                  labelLine: {
                      normal: {
                          show: false
                      }
                  },
              });
          }
      }
      //因为这个组件公用,发现配置项的series不能进行重置,所以在这里以这种方式手动重置
      mapOption.series = [ mapOption.series[0]]
      mapOption.series = mapOption.series.concat(sd)
      this.myChart.setOption(mapOption,true);
      return sd;
    },
    //重置散点图
    resetDot(chart, params) {
      var op = chart.getOption();
      var ops = op.series;
      var currentZoom = this.myChart.getOption().series[0].zoom
      

      let that = this
      ops.forEach(function(v, i) {
          if (i > 0) {
              let geoCoord = chinaData[0].features.find((item)=>{
                return item.properties.name==v.name
              }).properties.center
              var p = chart.convertToPixel({
                  seriesIndex: 0
              }, geoCoord);
              v.center = p;
              v.label = {
                  normal: {
                      show: true,
                      position: 'inside',
                      formatter: '{value|{c}}',
                      padding:[0,0,v.radius * params.zoom||v.radius,0],
                      rich: {
                          value: {
                              fontSize: 12,
                              color:'#ffffff',
                          },
                      },
                  }
              }
              //超过地图的最大最小层级  这个图表就不要再伸缩了
              if (params != 0 && params.zoom &&currentZoom!=1.5&&currentZoom!=1) {
                  v.radius = v.radius * params.zoom;
                  that.lastZoomLevel = params.zoom
                  return
              }
              
          }
      });
      chart.setOption(op, true);
    },
    //添加饼图
    addPartPieToMap(chart,data){
      var sd = [];

      for (var i = 0; i < data.length; i++) {
        var randomValue = Math.round(Math.random() * 30);
        var radius = randomValue <= 10 ? 10 : randomValue;
        let geoCoord = chinaData[0].features.find((item)=>{
          return item.properties.name==data[i].xzqmc
        }).properties.center
        if (geoCoord) {
          var vr = [];
          //饼图的数据不进行映射
          // vr.push({
          //     name: data[i].xzqmc,
          //     value: data[i].total,
          //     visualMap: false
          // }); 
          var p = chart.convertToPixel({
              seriesIndex: 0
          }, geoCoord);
          sd.push({
            name: data[i].xzqmc,
            type: 'pie',
            //clockWise: false,
            itemStyle: {
                normal: {
                    label: {
                        show: false
                    },
                    labelLine: {
                        show: false
                    },
                    shadowBlur: 20,
                    shadowColor: '#203665',
                    opacity:1,
                }
            },
            tooltip: {
              formatter: function(params) {
                console.log('哈哈',params)
                  // return params.seriesName + "<br/>" + params.name + " : " + params.value + ' 亿元';
                  return params.value + ' 亩';
              }
            },
            radius: [20, 30],
            // center: ['15%', '50%'],
            hoverAnimation: false,
            // radius: radius,
            center: p,
            zlevel: 4,
            data: data[i].rows
          });
        }
      }
      //因为这个组件公用,发现配置项的series不能进行重置,所以在这里以这种方式手动重置
      mapOption.series = [ mapOption.series[0]]
      mapOption.series = mapOption.series.concat(sd)
      this.myChart.setOption(mapOption,true);
      return sd;
    },
    //重置饼图
    resetPie(chart, params){
      var op = chart.getOption();
      var ops = op.series;
      ops.forEach(function(v, i) {
          if (i > 0) {
               let geoCoord = chinaData[0].features.find((item)=>{
                return item.properties.name==v.name
              }).properties.center
              var p = chart.convertToPixel({
                  seriesIndex: 0
              }, geoCoord);
              v.center = p;
              if (params != 0 && params.zoom) {
                  v.radius = v.radius * params.zoom;
              }else if (params != 0 && params.selected) {
                  var rangeFirstNumber = params.selected[0];
                  var rangeSecondNumber = params.selected[1];
                  var pd = v.data[this.typeIndex].value;
                  if (pd < rangeFirstNumber || pd > rangeSecondNumber) {
                      // v.itemStyle.normal.opacity = 0;
                      v.itemStyle = {
                          normal: {
                              label: {
                                  show: false
                              },
                              labelLine: {
                                  show: false
                              },
                              shadowBlur: 20,
                              shadowColor: '#203665',
                              opacity:0,
                          }
                      }
                  } else {
                      // v.itemStyle.normal.opacity = 1;
                      v.itemStyle = {
                          normal: {
                              label: {
                                  show: false
                              },
                              labelLine: {
                                  show: false
                              },
                              shadowBlur: 20,
                              shadowColor: '#203665',
                              opacity:1,
                          }
                      }
                  }
              }else{
                  let zoomVal = chart.getOption().series[0].zoom
                  let arr = [10, 15]
                  for(var j = 0;j<arr.length;j++){
                      arr[j] = arr[j] * zoomVal
                  }
                  v.radius = arr
              }
          
              
          }
      });
      chart.setOption(op, true);
    }
  },
}
</script>


<style lang="scss" scoped>
.chart{
  background-size: 100% 100%;
  #mapChart{
    width: 100%;
    height: 1000px;
  }
  .mapChoose {
    color: #eee;
    .title {
      padding: 5px;
      border-top: 1px solid rgba(132, 219, 233, 0.8);
      border-bottom: 1px solid rgba(147, 235, 248, 0.8);
      cursor: pointer;
    }
    .icon {
      font-family: 'simsun';
      font-size: 25px;
      margin: 0 11px;
    }
  }
}
</style>
举报

相关推荐

0 条评论