current position:Home>Vue uses echart to draw national maps and overlay charts

Vue uses echart to draw national maps and overlay charts

2022-04-29 14:35:37_ Xiao Zheng is a little sleepy

scene :

Big data shows the information of all provinces in the country , Make a map , And overlay the chart on each province .
What needs to be done is
1、 Map the country ( Different provinces have different colors according to different data )
2、 Each province needs to overlay a chart separately ( The pie chart )
3、 Map zoom 、 The size of the chart scales with the scale
4、 Map drag , The chart moves together according to
There are some pits in it

design sketch :

Incomplete screenshot , Effect of the sample .
 Insert picture description here
 Insert picture description here

 Insert picture description here

Complete code :

mapOption.js Configuration item :
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: [" high ", " low "],
        pieces: [],
    },
    series: [
        {
    
            type: 'map',
            zoom:1.1,
            aspectScale: 0.9,
            layoutCenter: ["50%", "60%"], // Map location 
            layoutSize: "100%",
            zlevel: 3,
            scaleLimit: {
    
                // Limit control of wheel scaling 
                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,  //  Whether to turn on mouse zoom and pan roaming 
            selectedMode: 'false', //  Whether multiple areas are allowed to be selected 
            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)",   // Mouse hovering / Choose a color 
                    label: {
    
                        show: true,
                        color: "#fff",
                        borderColor:"rgb(2,241,177)",
                       
                    },
                },
            },
            data: [],
        },
    ]
};
  
Other examples are china.json Move to datav Download it : The structure is as follows

 Insert picture description here

<template>
  <div class="chart pt-10">
    <el-button type="primary" size="mini" @click="options.id=1"> Pattern 1</el-button>
    <el-button type="primary" size="mini" @click="options.id=11"> Pattern 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', //  Current map name 
      selectedMaps:[
        {
    
          name:'china',
          code:'100000',
        }
      ],
      // Map scatter data 
      mapDotData:{
    
        input:{
    
          value:{
    }
        },
        output:{
    
          value:{
    
            rows:[]
          }
        }
      },
      typeIndex:1,
      // Last zoom level 
      lastZoomLevel:0,
      //  legend 
      options:{
    
        id:1
      }
    }

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


    // // This is for map drilling     Reserve it    In the future, you need to directly release the continue writing logic. At present, it can be regarded as realizing the operation of drilling down 
    // this.myChart.on('click', (params) => {
    
    //     console.log(' Space ',params)
    //     const map = params.name;
    //     if(map){
    
    //       this.curMapName = params.name;
    //       this.getMapData(map);
    //       //  Save... For the map title menu ( Filter multiple clicks on the same map ) Click map information 
    //       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: ' No map data yet ',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:{
    
    //  Make a map 
    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)

      // Then call the interface to query the map information 
      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 // The legend is configured  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" }], // First there's a map base  this.myChart.setOption(mapOption,true); if(Number(this.options.id)<10){ // Then overlay the chart  this.addPieToMap(this.myChart, this.mapDotData.output.value.rows ); }else{ this.addPartPieToMap(this.myChart, this.mapDotData.output.value.rows ) } /* The pie chart moves with the map :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; }, //  When the browser window size changes , Reload the chart to adapt  resizeCharts(){ this.$echarts.init(document.getElementById('mapChart')).resize()
    },
    //  Get map data 
    async getMapData(map){
    
        if(map=='china'){
    
          await this.drawMapChart(this.curMapName,chinaData[0]);
        }else if(map==' Liaoning Province '){
    
          this.drawMapChart(this.curMapName,liaoningPro);
        }else{
    
          this.drawMapChart(this.curMapName,shenyangCity);
        }
    },

    // Interface to obtain scatter data 
    async getMapDotData(){
    
      // Interface to get data 
      let rows = []

      if(Number(this.options.id)<10){
    
        rows =[
          {
    
              "xzqmc": " Sichuan Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Liaoning Province ",
              "total": 482.99,
              "dw": " Million mu ",
              "xzqdm": "540000"
          },
          {
    
              "xzqmc": " Hunan province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Hubei province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Guizhou Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Yunnan Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Qinghai Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Shaanxi Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Shanxi Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Xinjiang Uygur Autonomous Region ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Tibet Autonomous Region ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Ningxia Hui Autonomous Region ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Gansu Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Henan province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Anhui Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Shandong Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Jiangsu Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Jiangxi Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
          {
    
              "xzqmc": " Fujian Province ",
              "total": 9088.51,
              "dw": " Million mu ",
              "xzqdm": "510000"
          },
        ]
      }else{
    
        rows=[
            {
    
              "xzqmc":" Liaoning Province ",
              "xzqdm":"xxx",
              "total":5.3,
              "rows":[
                    {
    
                      "name":" Fifth class ",
                      "value":"26",
                    },
                    {
    
                      "name":" First class ",
                      "value":"12",
                    },
                    {
    
                      "name":" Fourth class place ",
                      "value":"45",
                    },
                     {
    
                      "name":" Third class ",
                      "value":"5",
                    },
              ]
            },
            {
    
              "xzqmc":" Sichuan Province ",
              "xzqdm":"xxx",
              "total":5.3,
              "rows":[
                    {
    
                      "name":" Fifth class ",
                      "value":"26",
                    },
                    {
    
                      "name":" First class ",
                      "value":"12",
                    },
                    {
    
                      "name":" Fourth class place ",
                      "value":"45",
                    },
                     {
    
                      "name":" Third class ",
                      "value":"5",
                    },
              ]
            }
        ]
      }

      this.mapDotData.output.value.rows = rows
    },
    // Add scatter chart 
    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 = [];
              // The data of pie chart is not mapped 
              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 + '  One hundred million yuan ';
                  //         return params.total + '  mu ';
                  //     }
                  // },
                  radius: radius,
                  center: p,
                  data: vr,
                  zlevel: 4,
                  roam:false,
                  tooltip: {
    
                      formatter: '{a}<br/>{b}: {c} One hundred million yuan  ({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
                      }
                  },
              });
          }
      }
      // Because this component is common , The of configuration items was found series Cannot reset , So here, reset manually in this way 
      mapOption.series = [ mapOption.series[0]]
      mapOption.series = mapOption.series.concat(sd)
      this.myChart.setOption(mapOption,true);
      return sd;
    },
    // Reset scatter 
    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',
                          },
                      },
                  }
              }
              // Exceed the maximum and minimum levels of the map    Don't stretch this chart any more 
              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);
    },
    // Add pie chart 
    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 = [];
          // The data of pie chart is not mapped 
          // 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(' ha-ha ',params)
                  // return params.seriesName + "<br/>" + params.name + " : " + params.value + '  One hundred million yuan ';
                  return params.value + '  mu ';
              }
            },
            radius: [20, 30],
            // center: ['15%', '50%'],
            hoverAnimation: false,
            // radius: radius,
            center: p,
            zlevel: 4,
            data: data[i].rows
          });
        }
      }
      // Because this component is common , The of configuration items was found series Cannot reset , So here, reset manually in this way 
      mapOption.series = [ mapOption.series[0]]
      mapOption.series = mapOption.series.concat(sd)
      this.myChart.setOption(mapOption,true);
      return sd;
    },
    // Reset pie chart 
    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>

copyright notice
author[_ Xiao Zheng is a little sleepy],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/119/202204291256537296.html

Random recommended