vue中Echarts地图下钻最优雅实现方案-从零开始实现省市县三级下钻
最近在网上搜Echarts地图下钻的实现方案,发现各种方案层出不穷,几乎都是一大堆的冗余代码,或者是包含各种业务代码,很难找到通俗易懂的实现方案,所以决定写这篇文章记录下来,方便大家查阅。
实现效果
数据准备
1. 地图数据获取
- 数据来源:阿里云 DATAV.GeoAtlas
- 访问地址:https://datav.aliyun.com/portal/school/atlas/area_selector
DataV.GeoAtlas官网地图数据是无法批量下载的,大家如果嫌一个一个下载太麻烦可以直接到我仓库下载全部省市县地图json文件,仓库地址:https://github.com/zhChuXiao/ChinaGeoJson?tab=readme-ov-file。
仓库里也提供一个nodejs脚本,可以随时从DATAV.GeoAtlas官网批量下载最新的地图json文件,并自动生成目录结构。
2. 地图json文件存储目录
地图json文件的存储目录,采用分层存储策略,将不同级别(全国、省、市、县)的地图数据分开存储,这样便于管理。目录结构如下:
src/
└── assets/
└── map-json/
├── chinaNew.json # 全国地图数据
├── province/ # 省级地图数据
│ ├── 110000.json # 北京
│ ├── 120000.json # 天津
│ └── ...
├── citys/ # 市级地图数据
│ ├── 110100.json # 北京市
│ ├── 120100.json # 天津市
│ └── ...
└── county/ # 区县级地图数据
├── 110101.json # 东城区
├── 110102.json # 西城区
└── ...
其次,再查看其他人的文章时,发现很多人都喜欢一次性把所有能用到的json文件全部导入,这样虽然也可以,但是要导入大量的json文件,代码不够优雅,并且大量的json文件会导致加载缓慢,按需加载可以显著提升首屏加载速度。我这里地图json文件的获取,采用
import()
动态获取的方式,通过点击地图上的不同区域,动态获取对应的地图json文件,然后注册到echarts中。
实现代码
附上完整代码,整体功能实现只有几十行代码,通俗易懂,所有注释都写的很清楚,不懂的可以直接看注释,创建一个vue单文件,然后复制粘贴即可使用。这里直接使用的是vue-echarts,所以项目要先安装vue-echarts和echarts。
npm install --save vue-echarts echarts
<template>
<div>
<button @click="handleBack">返回上一级</button>
<v-chart :option="mapOption" class="map-chart" @click="handleMapClick" /> <!-- 通过v-chart组件渲染地图 -->
</div>
</template>
<script setup>
import { ref, provide, onMounted } from 'vue'
import VChart, { THEME_KEY } from 'vue-echarts' // 引入v-chart组件
import * as echarts from 'echarts' // 引入echarts
import ChinaGroJson from '@/assets/map-json/china.json' // 引入全国地图json文件,这里只引入全国地图json文件即可
provide(THEME_KEY, 'light') // 提供主题
const mapOption = ref() // 地图配置
const geoJson = { // 地图json数据 只初始化全国地图json文件,其他省市县地图json文件在下面代码里动态获取,例如:当前地图切换为北京,则geoJson.province存储的就是北京市的地图json数据,切换为天津,则geoJson.province存储的就是天津市的地图json数据
china: ChinaGroJson,
province: null, // 省
city: null, // 市
county: null // 县
}
const currentLevel = ref('china') // 当前地图级别,默认为全国
const levelConfig = { // 地图层级配置,用于描述地图的层级关系
china: {
nextLevel: 'province', // 下一级,表示点击地图后,地图要跳转到的下一级
geoKey: 'china', // 地图key,表示地图的层级名称
jsonPath: 'province' // 地图json路径,表示地图json文件的存储路径
},
province: {
nextLevel: 'city',
geoKey: 'province',
jsonPath: 'citys'
},
city: {
nextLevel: 'county',
geoKey: 'city',
jsonPath: 'county'
}
}
/**
* 设置地图option,这里直接使用最基础的地图配置,可以根据需求自行修改
* @param {Array} mapData 地图要用的data数据
* @param {String} mapName 地图名称
*/
const setMapOption = (mapData, mapName = 'china') => {
mapOption.value = {
series: [
{
type: 'map',
map: mapName,
label: {
show: true
},
data: mapData
}
]
}
}
const handleMapClick = async event => { // 地图点击事件
const currentConfig = levelConfig[currentLevel.value] // 获取当前地图层级配置
if (currentConfig) {
currentLevel.value = currentConfig.nextLevel // 更新当前层级,把下一级作为当前层级存储到currentLevel中
const adcode = geoJson[currentConfig.geoKey].features.find(item => item.properties.name === event.name).properties.adcode // 获取地区编码,从geoJson中对应层级存储的json文件中获取
try {
const newGeoJson = await import(`@/assets/map-json/${currentConfig.jsonPath}/${adcode}.json`) // 动态获取下一级地图json文件, 例如:@/assets/map-json/citys/110100.json
geoJson[currentConfig.nextLevel] = newGeoJson // 将获取到的地图json数据赋值到geoJson里对应的层级
echarts.registerMap(event.name, geoJson[currentConfig.nextLevel]) // 注册新地图
setMapOption(['地图数据'], event.name) // 设置新地图配置
} catch (error) {
console.log('地图数据加载失败', error)
handleBack() // 如果加载失败,则返回上一级
}
}
}
// 返回上一级
const handleBack = () => {
if (currentLevel.value === 'china') return // 如果已经是最顶层则不处理
const prevLevels = {
province: 'china',
city: 'province',
county: 'city'
}
const prevLevel = prevLevels[currentLevel.value] // 获取上一级配置
currentLevel.value = prevLevel // 返回上一级
echarts.registerMap(prevLevel, geoJson[prevLevel]) // 重新注册上一级地图,例如我们当前层级是青岛市地图,geoJson.province依然存储着山东省的地图,此时我们直接使用即可
setMapOption(['地图数据'], prevLevel) // 设置新地图配置
}
// 组件挂载初始化全国地图
onMounted(() => {
echarts.registerMap('china', geoJson.china)
setMapOption(['地图数据'], 'china')
})
</script>
<style lang="scss" scoped>
.map-chart {
width: 800px;
height: 800px;
}
</style>
注意事项
- 一定要使用行政区划代码作为文件名,并保持目录结构清晰,例如:北京市的行政区划代码是110000,所以北京市的地图json文件名必须是110000.json,上面github仓库里提供的node脚本可以批量下载以行政区划代码命名的地图json文件。
- 必须使用areas_v3版本的json地图数据,否则再获取行政区划代码的时候会出现问题