二.Echarts+Amap实现点击下钻功能

·  阅读 5108
二.Echarts+Amap实现点击下钻功能

最近公司需要做大数据可视化页面,地图本来打算用arcgis的,但是arcgis3.x的页面整体风格与可视化页面不符,所以就来研究了下echarts加载地图,但是要求有点击下钻和筛选加载地图功能,如果把所有的市县行政区的都下载下来那可太麻烦了;所以这里选择用aMap去获取行政区边界的geoJson

前提准备:首先你要去高德api上申请密钥,免费的,一天可以发出5000次请求,次数太多了你要去花钱申请企业版,直通车:developer.amap.com/

1. vue加载Amap

打开index.html,引入amap和mapUI

<script src='https://webapi.amap.com/maps?v=1.3&key=你申请的key&plugin=AMap.DistrictSearch'>  </script>  <script src="https://webapi.amap.com/ui/1.0/main.js"></script>
复制代码

2.获取行政区geoJson具体方法

因为这里我们是要用echarts加载,所以高德api我们只是用他的获取行政区的api方法也就是 AMapUI 组件库的 DistrictExplorer 进行行政区geoJson的获取

AMapUI.loadUI(['geo/DistrictExplorer'], function(DistrictExplorer) {

   //创建一个实例
   var districtExplorer = new DistrictExplorer();
   var adcode = 100000; //全国的区划编码

   districtExplorer.loadAreaNode(adcode, function(error, areaNode) {
      if (error) {
         console.error(error);
         return;
      }
      let mapJson={}
      //geoJson必须这种格式
       mapJson.features = areaNode.getSubFeatures()

    });
});
复制代码

3.使用Echarts加载地图

echarts加载地图大致分为4种,热力图,散点图,分布图,航线图,但都大同小异

公共方法封装:

获取行政区geoJson封装

searchCity(adcode){ 
   AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {
     var districtExplorer = new DistrictExplorer()
   districtExplorer.loadAreaNode(adcode, (error, areaNode) => {
         if (error) {
             console.error(error);
             return;
          }
          mapJson.features = areaNode.getSubFeatures()
          this.geoJsonData = mapJson
        //如果到下钻到县,就有个逻辑判断,因为高德获取不了县的geoJson,只能从市里面去取县的geoJson
        //所以这个要加个判断
        //方法有很多,1.比如每次都把获取的geoJson存起来,高德的获取的geoJson为空时,就说明获取到了县
        //或者高德没数据,就从之前存的那个里面去取

        //获取地图数据
          this.getMapData()
        })
    })
}
复制代码

这里我把获取高德的方法封装了一下

/**
*  adcode   行政区code(如果点击到了县,这个地方就是市的code)
*  countyCode  县的行政区code  下钻到县了必传
*/
export function getGeoJson(adcode,countyCode=''){
   return new Promise((resolve,reject)=>{      AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {     var districtExplorer = new DistrictExplorer()
     districtExplorer.loadAreaNode(adcode, (error, areaNode) => {
         if (error) {
             console.error(error);
             reject(error)
             return;
          }
          let mapJson={
              features:{}
          }
          let Json = areaNode.getSubFeatures()
          //如果countyCode存在,那么说明当前是县,那就用市获取到的geoJson去截取
          if(countyCode){
              Json=Json.filter(item=>item.properties.adcode == countyCode)          }
          mapJson.features=Json
          resolve(mapJson)        })
    })
   })
}
复制代码

页面里面: 先引入进来

然后:

getGeoJson(10000).then(data=>{

}).catch(error=>{

})
复制代码

这样就能拿到geoJson数据了

1.分布图   

上面拿到了地图geoJson,接下来我们要获取数据,不同地图需要的地图数据格式也不同

类似于这种图:

需要的数据格式是这样的:

getMapData(){
   //这里我们模拟数据进行数据获取
   //实际项目中会调接口把坐标和值返回来
   //必须将数据写成数组对象格式,name,value是必须参数,后面的根据自己实际情况自定义添加
   //除了name和value,其他的名字可以随便取
   //分布图不需要坐标就可以实现,只需要名字和地图行政区的名字对应上了就行
     let mapData = this.geoJsonData.map(item => {
        return ({
            name: item.properties.name,
            value: Math.random() * 1000,
            level: item.properties.level,
            cityCode: item.properties.adcode
        })
    })
    this.initEchartsMap()
}
复制代码

鉴于好多人问我后台返的数据怎么处理成这种,这里就单独写下获取后台数据的处理

这里模拟下后台可能会返回的数据
假如后台返回的数据是这种:data:[{
  area:'湖北省',
  sum:75,
  cityCode:xxxx,
  level:xxxx
},{
 area:'湖南省',
 sum:78,
 cityCode:xxxx,
 level:xxxx
}]那我们就要处理下
getMapData(){
    getData().then(res=>{
       const data=res.data||[]
      //这里的data就是上面的数据
      this.mapData=data.map(item=>{
          name:item.area,
          value:item.sum,
          cityCode:item.cityCode,
          level:item.level
      })
       //切记,在调接口里面调用获取echarts的方法,写在外面echarts数据会渲染不出来
       this.initEchartMap()
    })
}
复制代码

而如果你的后台刚好返的是这种格式:

data:[{
   name:'湖北省',
   vaule:35,
   level:xxxx,
   cityCode:xxxx
},{
   name:'湖南省',
   vaule:75,
   level:xxxx,
   cityCode:xxxx

}]]
复制代码

那么恭喜你,啥都不用处理,直接获取数据然后调渲染echarts的方法吧

地图渲染出来后,去给后台一个赞,太棒了

getMapData(){
  getData().then(res=>{
     this.mapData=res.data||[]
     this.initEchartMap()
  })
}

ps:mapData数据,前面两个必须是 { name:'xxx',vaule:'xxx'}  这种,而且name名字和地图名字必须
一致,不然会渲染不出来  ,后面两个字段看后台相返啥都行,只要你在点击事件里面改成对应的就好了
复制代码

渲染地图:

<template>
   <div class="map" ref="scatterMap" style="height:100%;width:100%">
</template>

initEchartsMap(){
    //这里尽量用ref去获取节点
    this.myChart = echarts.init(this.$refs.scatterMap)
    //注册地图,前面名字自定义,后面是高德获取的geoJson
    echarts.registerMap('myMap', this.geoJsonData)
    //这里要加true表示重新绘制,不然下钻或筛选后,地图会飞出去
    this.myChart.setOption({
       tooltip: {
           trigger: "item",
           formatter: p => {
            //这里可以自定义鼠标悬浮到地图上显示的内容
              let val = p.value;
               if (window.isNaN(val)) {
                    val = 0;
                }
                let txtCon =
                    p.name + "<br>" + "数值 : " + val.toFixed(2);
                return txtCon;
            }
        },
        title: {
            show: true,
            left: "center",
            top: "15",
            text:"分布图",
            textStyle: {
                color: "#fff",
                fontSize: 16
            }
        },
        //这里可以添加echarts内置的,例如下载图片等
        toolbox: {
            feature: {
                dataView: {
                    show: false,
                },
                magicType: {
                    show: false,
                },
                restore: {
                    show: false
                },
                saveAsImage: {
                    show: true,
                    name:"地图",
                    pixelRatio: 2
                }
            },
            iconStyle: {
                normal: {
                    borderColor: "#41A7DE"
                }
            },
            itemSize: 15,
            top: 20,
            right: 22
        },
       //地图颜色划分
        dataRange: {
            right: "2%",
            bottom: "3%",
            icon: "circle",
            align: "left",
            splitList: [{
                    start: 0,
                    end: 0,
                    label: '未发生',
                    color: "#6ead51"
                },
                {
                    start: 0,
                    end: 250,
                    label: '0-150',
                    color: "#92b733"
                },
                {
                    start: 250,
                    end: 500,
                    label: '250-500',
                    color: "#c4aa29"
                },
                {
                    start: 500,
                    end: 750,
                    label: '500-750',
                    color: "#ce6c2b"
                },
                {
                    start: 750,
                    label: '750以上',
                    color: "#c92626"
                }
            ],
            textStyle: {
                color: "#0fccff",
                fontSize: 16
            }
       },
        series: [{
            name: "地图",
            type: "map",
            map: "myMap",
            roam: true, //是否可缩放
            zoom: 1.1, //缩放比例
            data: mapData,
            itemStyle: {
                normal: {
                    show: true,
                    areaColor: 'rgba(0,0,0,0)',  //地图的颜色
                    borderColor: 'rgb(185, 220, 227)',  //边界线颜色
                    borderWidth: '1',   //边界线宽
                },
            },
            label: {
                normal: {
                    show: true, //显示省份标签
                    textStyle: {
                        color: "rgb(249, 249, 249)", //省份标签字体颜色
                        fontSize: 12
                    }
                },
                emphasis: {
                    //对应的鼠标悬浮效果
                    show: true,
                    textStyle: {
                        color: "#000"
                    }
                }
            }
        }]
    },true)
   //这里调用方法时不要加括号,如果点击事件触发了好几次,你可以先:
   this.myChart.off('click');   //解绑
   this.myChart.on('click', this.clickMap)
}
复制代码

**   地图点击事件:**

//这里有个参数,就是点击的那个地块的数据信息
clickMap(params){
    let cityCode = params.data.cityCode
    let level =param.data.level
    //说明点击到了县
    if(level=="district"){
        getGeoJson('市的code','县的code').then(data=>{

       }).catch(error=>{

      })
    }else{
       getGeoJson('市的code').then(data=>{            
       }).catch(error=>{

      })
     }

}
复制代码

 2.散点图

   类似于这种:

   

获取geoJson的方法和上面一样,这里就不再重复了,不同的就是数据格式要求和渲染方式

数据格式要求:

getMapData(){
   //这里我们模拟数据进行数据获取
   //实际项目中会调接口把坐标和值返回来
   //散点图必须要返回坐标和值
   //index就是地图上点的大小,如果还有别的值想要在鼠标悬浮后显示,那就放在index后面
     let mapData = this.geoJsonData.map(item => {
        return ({
            name: item.properties.name,
            value: [item.properties.center[0], item.properties.center[1], index],
        })
    })
    this.initEchartsMap()
}
复制代码

渲染地图:

initEchartsMap(){
    //这里尽量用ref去获取节点
    this.myChart = echarts.init(this.$refs.dotMap)
    //注册地图,前面名字自定义,后面是高德获取的geoJson
    echarts.registerMap('myMap', this.geoJsonData)
    //这里要加true表示重新绘制,不然下钻或筛选后,地图会飞出去
    this.myChart.setOption({
       tooltip: {
           trigger: "item",
           formatter: p => {
            //这里可以自定义鼠标悬浮到地图上显示的内容
              let val = p.value;
               if (window.isNaN(val)) {
                    val = 0;
                }
                let txtCon =
                    p.name + "<br>" + "数值 : " + val.toFixed(2);
                return txtCon;
            }
        },
        title: {
            show: true,
            x: "center",
            y: "top",
            text:"散点图",
            textStyle: {
                color: "#fff",
                fontSize: 16
            }
        },
        //这里可以添加echarts内置的,例如下载图片等
        toolbox: {
            feature: {
                dataView: {
                    show: false,
                },
                magicType: {
                    show: false,
                },
                restore: {
                    show: false
                },
                saveAsImage: {
                    show: true,
                    name:"地图",
                    pixelRatio: 2
                }
            },
            iconStyle: {
                normal: {
                    borderColor: "#41A7DE"
                }
            },
            itemSize: 15,
            top: 20,
            right: 22
        },
        geo: {
            show: true,
            map: 'Map', //使用
            roam: true,
            itemStyle: {
                normal: {
                    show: true,
                    areaColor: 'rgba(0,0,0,0)',
                    borderColor: 'rgb(15, 163, 227)',
                    borderWidth: '1',
                    shadowColor: 'rgba(63, 218, 255, 0.5)',
                    shadowBlur: 20
                },
                //emphasis 是图形在高亮状态下的样式,比如在鼠标悬浮或者图例联动高亮时。
                emphasis: {
                    show: true,
                    areaColor: '#050038',
                    borderColor: '#83BAFF'
                }
            },
            label: {
                normal: {
                    show: false //显示省份标签
                },
                emphasis: {
                    //对应的鼠标悬浮效果
                    show: false
                }
            },
            zoom: 1.1
        },
        series: [{
            name: "地图",
            type: "effectScatter",
            data: mapData.slice(0, -5),
            coordinateSystem: 'geo',
            //这里可以设置点的大小
            symbolSize: function(val) {
                return val[2] / 1.3
            },
            showEffectOn: 'emphasis', //高亮时显示特效
            rippleEffect: {
                brushType: 'stroke'
            },
            hoverAnimation: true, //动画效果
            label: {
                normal: {
                    formatter: p => {
                        return p.value[2]
                    },
                    position: 'center', //地图上是否有文字
                    show: true,
                    textStyle: {
                        color: '#fff'
                    }
                },
                emphasis: {
                    show: false
                }
            },
            itemStyle: {
                normal: {
                    color: 'rgba(255, 128, 0,0.8)' //地图点的颜色
                }
            },
            layoutCenter: ['50%', '50%'], //属性定义地图中心在屏幕中的位置,一般结合layoutSize 定义地图的大小
            layoutSize: 430
        }, {
            name: "top5",
            type: "effectScatter",
            data: mapData.slice(-3),
            coordinateSystem: 'geo',
            //这里可以设置点的大小
            symbolSize: function(val) {
                return val[2]
            },
            showEffectOn: 'render', //高亮时显示特效
            rippleEffect: {
                brushType: 'fill'
            },
            hoverAnimation: false,
            label: {
                normal: {
                    formatter: p => {
                        return p.value[2]
                    },
                    position: 'center', //地图上是否有文字
                    show: true,
                    textStyle: {
                        color: '#fff'
                    }
                },
                emphasis: {
                    show: false
                }
            },
            itemStyle: {
                normal: {
                    color: 'rgba(255, 128, 0,0.8)' //地图点的颜色
                }
            },
            layoutCenter: ['50%', '50%'], //属性定义地图中心在屏幕中的位置,一般结合layoutSize 定义地图的大小
            layoutSize: 430
        }]
    },true)
}
复制代码

** 点击下钻功能同上**

3.热力图

类似效果:

需要的数据格式和散点图一样

渲染地图:

热力图不知道为啥鼠标悬浮没有信息

initEchartsMap(){
    //这里尽量用ref去获取节点
    this.myChart = echarts.init(this.$refs.dotMap)
    //注册地图,前面名字自定义,后面是高德获取的geoJson
    echarts.registerMap('myMap', this.geoJsonData)
    //这里要加true表示重新绘制,不然下钻或筛选后,地图会飞出去
    this.myChart.setOption({
       tooltip: {
           trigger: "item",
        },
        title: {
            show: true,
            x: "center",
            y: "top",
            text:"热力图",
            textStyle: {
                color: "#fff",
                fontSize: 16
            }
        },
        //这里可以添加echarts内置的,例如下载图片等
        toolbox: {
            feature: {
                dataView: {
                    show: false,
                },
                magicType: {
                    show: false,
                },
                restore: {
                    show: false
                },
                saveAsImage: {
                    show: true,
                    name:"地图",
                    pixelRatio: 2
                }
            },
            iconStyle: {
                normal: {
                    borderColor: "#41A7DE"
                }
            },
            itemSize: 15,
            top: 20,
            right: 22
        },
        visualMap: {
            show: true,
            left: '2%',
            bottom: '1%',
            min: 0,
            max: 40,
            text: ['40', '0'],
            inRange: {
                color: ['#41A7DE', '#eac736', '#fffc00', '#ff2600']
            },
            textStyle: {
                color: '#0fccff',
                fontSize: 12
            }
        },
        geo: {
            show: true,
            map: 'Map', //使用
            roam: true,
            itemStyle: {
                normal: {
                    show: true,
                    areaColor: 'rgba(0,0,0,0)',
                    borderColor: 'rgb(15, 163, 227)',
                    borderWidth: '1',
                    shadowColor: 'rgba(63, 218, 255, 0.5)',
                    shadowBlur: 20
                },
                //emphasis 是图形在高亮状态下的样式,比如在鼠标悬浮或者图例联动高亮时。
                emphasis: {
                    show: true,
                    areaColor: '#050038',
                    borderColor: '#83BAFF'
                }
            },
            label: {
                normal: {
                    show: false //显示省份标签
                },
                emphasis: {
                    //对应的鼠标悬浮效果
                    show: false
                }
            },
            zoom: 1.1
        },
        series: [{
            name: "地图",
            type: "heatmap",
            data: mapData,
            coordinateSystem: 'geo',
            pointSize: 13, //修改热力图点的半径
            blurSize: 15 //阴影的大小
        }]
    },true)
}
复制代码

  4.航线图

    航线图这里就不写了,有需要的去echarts社区去找

4.Echarts图地址

Echarts社区地址:gallery.echartsjs.com/explore.htm…timeframe=allauthor=all  

我做了几个echarts地图,分布图,散点图点击下钻,热力图,综合图,都放在了github上面,有需要可以看看:github.com/biubiubiu01…

预览地址:gist006.gitee.io/echartsmap/…

图都在上面,有需要的可以去拿

参考资源

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改