Posted in

Echarts 中国地图下钻,支持下钻到县(vue3)_AI阅读总结 — 包阅AI

包阅导读总结

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&&params.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&&params.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>

博客主要记录一些学习的文章,如有不足,望大家指出,谢谢。