最近公司需要做大数据可视化页面,地图本来打算用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/…
图都在上面,有需要的可以去拿
参考资源
-
lbs.amap.com/api/javascr… -高德行政区获取api
-
datav.aliyun.com/tools/atlas… -全国所有geoJson下载地址
-
gallery.echartsjs.com/editor.html… -echarts社区