包阅导读总结
1. `Echarts`、`地图下钻`、`Vue3`、`县`、`json数据`
2. 本文主要介绍了在 Vue3 中使用 Echarts 实现中国地图下钻到县的功能,包括准备工作、获取地图 JSON 数据的方法、更新地图配置 options、渲染地图、实现地图点击下钻和返回上一级等核心内容。
3.
– 引言
– 简述 Echarts 常用于图表绘制和大屏可视化。
– 准备工作
– 提供地图 JSON 数据获取的网址及解决请求报错 403 的参考。
– 说明技术栈为 vue-echarts: 6.6.1 。
– 实现过程
– 模板部分:包含 Echarts 节点和返回按钮。
– 获取 mapJson :介绍线上 API 和本地资源两种获取方式,指出本地资源方式打包存在问题。
– 更新地图配置 options :设置 tooltip、visualMap、geo 等配置。
– 渲染地图 :获取地图数据,生成随机数据,更新地图 options 。
– 实现地图点击下钻 :根据点击数据触发下钻,记录地图。
– 返回上一级实现 :通过记录的地图信息返回上一级。
– 代码部分:展示模板和脚本的完整代码。
思维导图:
文章地址:https://mp.weixin.qq.com/s/vgvu4k5kaHgyydBBGI_Ymg
文章来源:mp.weixin.qq.com
作者:树深遇鹿
发布时间:2024/7/3 8:52
语言:中文
总字数:2582字
预计阅读时间:11分钟
评分:87分
标签:Echarts,Vue3,地图下钻,数据可视化,前端开发
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
引言
Echarts 大家都不陌生吧,时常被用于绘制各种图表,也作为大屏可视化的常驻用户,这里就不多说了,今天主要是讲述一下 Echarts 的地图下钻,支持下钻到县、返回上一级。
准备工作
地图JSON数据
DataV.GeoAtlas地理小工具系列 (aliyun.com) 支持在线调用API和下载json资源(我这里是调用的API)
如果地图json API请求报错403,可参考这个解决办法 :地图请求阿里的geojson数据时,返回403Forbidden解决方案 – 掘金 (juejin.cn)
技术栈
-
vue-echarts: 6.6.1 (直接使用 Echarts 也是一样的,这个只是对 Echarts 的组件封装)
地图效果
项目预览地址:UnusualAdmin
项目代码地址:UnusualAdmin
实现
template
这里只需要一个 Echarts 节点和一个按钮就行了
<template>
<div:style="`height:${calcHeight('main')};`"class="wh-fullpos-relative">
<v-chart:option="mapOption":autoresize="true"@click="handleClick"/>
<n-buttonv-show="isShowBack"class="pos-absolutetop-10left-10"@click="goBack">返回</n-button>
</div>
</template>
获取mapJson
//使用线上API
constgetMapJson=async(mapName:string)=>{
consturl=`https://geo.datav.aliyun.com/areas_v3/bound/${mapName}.json`
constmapJson=awaitfetch(url).then(res=>res.json())
returnmapJson
}
//使用本地资源
constgetMapJson=async(mapName:string)=>{
consturl=`@/assets/mapJson/${mapName}.json`
constmapJson=awaitimport(/*@vite-ignore*/url)
returnmapJson
}
第二种方法(使用本地资源)存在问题:这个方法后续发现,vite打包不会把json文件打包到dist,线上会报错,目前没找到可靠的解决办法(如果放到public文件夹下会打包进去),故舍弃。
如果大家有什么解决这个问题的好办法,请在评论区留言,博主会一一去尝试的🙏🙏🙏
更新地图配置options
constsetOptions=(mapName:string,mapData:any)=>{
return{
//鼠标悬浮提示
tooltip:{
show:true,
formatter:function(params:any){
//根据需要进行数据处理或格式化操作
if(params&¶ms.data){
const{adcode,name,data}=params.data;
//返回自定义的tooltip内容
return`adcode:${adcode}<br>name:${name}<br>data:${data}`;
}
},
},
//左下角的数据颜色条
visualMap:{
show:true,
min:0,
max:100,
left:'left',
top:'bottom',
text:['高','低'],//文本,默认为数值文本
calculable:true,
seriesIndex:[0],
inRange:{
color:['#00467F','#A5CC82']//蓝绿
}
},
//geo地图
geo:{
map:mapName,
roam:true,
select:false,
//图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。
selectedMode:'single',
label:{
show:true
},
emphasis:{
itemStyle:{
areaColor:'#389BB7',
borderColor:'#389BB7',
borderWidth:0
},
label:{
fontSize:14,
},
}
},
series:[
//地图数据
{
type:'map',
map:mapName,
roam:true,
geoIndex:0,
select:false,
data:mapData
},
//散点
{
name:'散点',
type:'scatter',
coordinateSystem:'geo',
data:mapData,
itemStyle:{
color:'#05C3F9'
}
},
//气泡点
{
name:'点',
type:'scatter',
coordinateSystem:'geo',
symbol:'pin',//气泡
symbolSize:function(val:any){
if(val){
returnval[2]/4+20;
}
},
label:{
show:true,
formatter:function(params:any){
returnparams.data.data||0;
},
color:'#fff',
fontSize:9,
},
itemStyle:{
color:'#F62157',//标志颜色
},
zlevel:6,
data:mapData,
},
//地图标点
{
name:'Top5',
type:'effectScatter',
coordinateSystem:'geo',
data:mapData.map((item:{data:number})=>{
if(item.data>60)returnitem
}),
symbolSize:15,
showEffectOn:'render',
rippleEffect:{
brushType:'stroke'
},
label:{
formatter:'{b}',
position:'right',
show:true
},
itemStyle:{
color:'yellow',
shadowBlur:10,
shadowColor:'yellow'
},
zlevel:1
},
]
}
}
渲染地图
constrenderMapEcharts=async(mapName:string)=>{
constmapJson=awaitgetMapJson(mapName)
registerMap(mapName,mapJson);//注册地图
//为地图生成一些随机数据
constmapdata=mapJson.features.map((item:{properties:any})=>{
constdata=(Math.random()*80+20).toFixed(0)//20-80随机数
consttempValue=item.properties.center?[...item.properties.center,data]:item.properties.center
return{
name:item.properties.name,
value:tempValue,//中心点经纬度
adcode:item.properties.adcode,//区域编码
level:item.properties.level,//层级
data//模拟数据
}
});
//更新地图options
mapOption.value=setOptions(mapName,mapdata)
}
实现地图点击下钻
//点击下砖
constmapList=ref<string[]>([])//记录地图
consthandleClick=(param:any)=>{
//只有点击地图才触发
if(param.seriesType!=='map')return
const{adcode,level}=param.data
constmapName=level==='district'?adcode:adcode+'_full'
//防止最后一个层级被重复点击,返回上一级出错
if(mapList.value[mapList.value.length-1]===mapName){
returnnotification.warning({content:'已经是最下层了',duration:1000})
}
//每次下转都记录下地图的name,在返回的时候使用
mapList.value.push(mapName)
renderMapEcharts(mapName)
}
返回上一级实现
//点击返回上一级地图
constgoBack=()=>{
constmapName=mapList.value[mapList.value.length-2]||'100000_full'
mapList.value.pop()
renderMapEcharts(mapName)
}
全部代码
<template>
<div:style="`height:${calcHeight('main')};`"class="wh-fullpos-relative">
<v-chart:option="mapOption":autoresize="true"@click="handleClick"/>
<n-buttonv-show="isShowBack"class="pos-absolutetop-10left-10"@click="goBack">返回</n-button>
</div>
</template>
<scriptsetuplang="ts"name="EchartsMap">
import{use,registerMap}from'echarts/core'
importVChartfrom'vue-echarts'
import{CanvasRenderer}from'echarts/renderers'
import{MapChart,ScatterChart,EffectScatterChart}from'echarts/charts'
import{TitleComponent,TooltipComponent,LegendComponent,GridComponent,VisualMapComponent}from'echarts/components'
import{calcHeight}from'@/utils/help';
use([
CanvasRenderer,
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
VisualMapComponent,
MapChart,
ScatterChart,
EffectScatterChart
])
constnotification=useNotification()
constmapOption=ref()
constmapList=ref<string[]>([])//记录地图
constisShowBack=computed(()=>{
returnmapList.value.length!==0
})
constgetMapJson=async(mapName:string)=>{
consturl=`https://geo.datav.aliyun.com/areas_v3/bound/${mapName}.json`
constmapJson=awaitfetch(url).then(res=>res.json())
returnmapJson
}
constsetOptions=(mapName:string,mapData:any)=>{
return{
tooltip:{
show:true,
formatter:function(params:any){
//根据需要进行数据处理或格式化操作
if(params&¶ms.data){
const{adcode,name,data}=params.data;
//返回自定义的tooltip内容
return`adcode:${adcode}<br>name:${name}<br>data:${data}`;
}
},
},
visualMap:{
show:true,
min:0,
max:100,
left:'left',
top:'bottom',
text:['高','低'],//文本,默认为数值文本
calculable:true,
seriesIndex:[0],
inRange:{
color:['#00467F','#A5CC82']//蓝绿
}
},
geo:{
map:mapName,
roam:true,
select:false,
//zoom:1.6,
//layoutCenter:['45%','70%'],
//layoutSize:750,
//图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。
selectedMode:'single',
label:{
show:true
},
emphasis:{
itemStyle:{
areaColor:'#389BB7',
borderColor:'#389BB7',
borderWidth:0
},
label:{
fontSize:14,
},
}
},
series:[
//数据
{
type:'map',
map:mapName,
roam:true,
geoIndex:0,
select:false,
data:mapData
},
{
name:'散点',
type:'scatter',
coordinateSystem:'geo',
data:mapData,
itemStyle:{
color:'#05C3F9'
}
},
{
name:'点',
type:'scatter',
coordinateSystem:'geo',
symbol:'pin',//气泡
symbolSize:function(val:any){
if(val){
returnval[2]/4+20;
}
},
label:{
show:true,
formatter:function(params:any){
returnparams.data.data||0;
},
color:'#fff',
fontSize:9,
},
itemStyle:{
color:'#F62157',//标志颜色
},
zlevel:6,
data:mapData,
},
{
name:'Top5',
type:'effectScatter',
coordinateSystem:'geo',
data:mapData.map((item:{data:number})=>{
if(item.data>60)returnitem
}),
symbolSize:15,
showEffectOn:'render',
rippleEffect:{
brushType:'stroke'
},
label:{
formatter:'{b}',
position:'right',
show:true
},
itemStyle:{
color:'yellow',
shadowBlur:10,
shadowColor:'yellow'
},
zlevel:1
},
]
}
}
constrenderMapEcharts=async(mapName:string)=>{
constmapJson=awaitgetMapJson(mapName)
registerMap(mapName,mapJson);
constmapdata=mapJson.features.map((item:{properties:any})=>{
constdata=(Math.random()*80+20).toFixed(0)//20-80随机数
consttempValue=item.properties.center?[...item.properties.center,data]:item.properties.center
return{
name:item.properties.name,
value:tempValue,//中心点经纬度
adcode:item.properties.adcode,//区域编码
level:item.properties.level,//层级
data//模拟数据
}
});
mapOption.value=setOptions(mapName,mapdata)
}
renderMapEcharts('100000_full')//初始化绘制中国地图
//点击下砖
consthandleClick=(param:any)=>{
//只有点击地图才触发
if(param.seriesType!=='map')return
const{adcode,level}=param.data
constmapName=level==='district'?adcode:adcode+'_full'
//防止最后一个层级被重复点击,返回上一级出错
if(mapList.value[mapList.value.length-1]===mapName){
returnnotification.warning({content:'已经是最下层了',duration:1000})
}
mapList.value.push(mapName)
renderMapEcharts(mapName)
}
//点击返回上一级地图
constgoBack=()=>{
constmapName=mapList.value[mapList.value.length-2]||'100000_full'
mapList.value.pop()
renderMapEcharts(mapName)
}
</script>
博客主要记录一些学习的文章,如有不足,望大家指出,谢谢。