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

场景:

大数据展示全国各省份信息,绘制地图,并在每个省份上叠加图表。
需要做的就是
1、绘制全国地图(不同省份根据数据的不同而颜色不同)
2、每个省份都需要单独叠加一个图表(饼图)
3、地图缩放、图表的大小跟随比例一起缩放
4、地图拖拽,图表根据一起移动
这里面有一些坑

效果图:

截图未截完整,示例效果。
vue使用echart绘制全国地图,叠加图表_第1张图片
vue使用echart绘制全国地图,叠加图表_第2张图片

vue使用echart绘制全国地图,叠加图表_第3张图片

完整代码:

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下载即可:结构如下

vue使用echart绘制全国地图,叠加图表_第4张图片

<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 + "
"
+ params.name + " : " + params.value + ' 亿元'; // return params.total + ' 亩'; // } // }, radius: radius, center: p, data: vr, zlevel: 4, roam:false, tooltip: { formatter: '{a}
{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 + "
"
+ 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>

你可能感兴趣的:(vue,echart,vue.js,echarts,地图)