Echarts 地圖如何點(diǎn)擊定位到自己的家鄉(xiāng)城市區(qū)縣
最近實(shí)現(xiàn)了通過(guò)Echarts地圖,定位到自己的家鄉(xiāng),覺(jué)得挺有趣的,所以分享給大家,希望大家也可以實(shí)現(xiàn)一遍,在Echarts上定位到自己的家鄉(xiāng)看一看~
圖片
地圖的繪制
地圖數(shù)據(jù)
地圖的數(shù)據(jù)我們可以通過(guò)網(wǎng)上提供的 API 來(lái)進(jìn)行獲取
API URL:https://geo.datav.aliyun.com/areas_v3/bound/{mapCode}.json
圖片
繪制地圖
首先需要一個(gè) DOM 節(jié)點(diǎn)來(lái)進(jìn)行 Echarts 的繪制。
圖片
接著需要初始化 Echarts 實(shí)例,并進(jìn)行配置,完成渲染。
圖片
這樣就能把地圖渲染出來(lái)了。
圖片
往下和往上定位
實(shí)現(xiàn)完整個(gè)地圖的渲染,我們還需要實(shí)現(xiàn):
- 點(diǎn)擊某個(gè)地區(qū),進(jìn)行往下定位
- 點(diǎn)擊按鈕,進(jìn)行往上定位
所以我們首先需要增加一個(gè)按鈕。
圖片
接著我們需要:
1、監(jiān)聽(tīng) Echarts 的點(diǎn)擊事件。
2、獲取點(diǎn)擊的是哪個(gè)地區(qū),進(jìn)行數(shù)據(jù)獲取并渲染。
3、維護(hù)一個(gè)地區(qū)數(shù)組,記錄點(diǎn)擊的鏈路。
圖片
最終可以實(shí)現(xiàn)效果
圖片
完整源碼
<template>
<Button @click="back" type="primary" :loading="loading">返回上一級(jí)</Button>
<Spin :spinning="loading">
<div class="container" ref="echartsRef"></div>
</Spin>
</template>
<script setup lang="ts">
import * as echarts from 'echarts';
import { ref, onMounted } from 'vue';
import { Button, Spin } from 'ant-design-vue';
// 最頂層地圖的代號(hào)
const ROOR_MAP_CODE = '100000_full';
const echartsRef = ref<HTMLDivElement | null>(null);
const echartInstance = ref<echarts.ECharts | null>(null);
const loading = ref(false);
// 請(qǐng)求地圖數(shù)據(jù)
const fetchMapJson = async (mapCode: string) => {
const response = await fetch(`https://geo.datav.aliyun.com/areas_v3/bound/${mapCode}.json`);
const result = await response.json();
return result;
};
// 記錄點(diǎn)擊鏈路
const mapCodes: string[] = [];
// 初始化 Echarts 實(shí)例
const initInstance = () => {
if (!echartsRef.value) return;
echartInstance.value = echarts.init(echartsRef.value);
echartInstance.value.on('click', params => {
if (params.seriesType === 'map') {
const { adcode, level } = params.data;
const mapCode = level === 'district' ? adcode : adcode + '_full';
// 防止重復(fù)點(diǎn)擊最后一層
if (mapCodes[mapCodes.length - 1] === mapCode) return;
mapCodes.push(mapCode);
updateOptions(mapCode);
}
});
};
// 返回上一級(jí)
const back = () => {
// 無(wú)法再往上了
if (!mapCodes.length) return;
mapCodes.pop();
if (mapCodes.length) {
// 取最后一個(gè)去渲染數(shù)據(jù)
updateOptions(mapCodes[mapCodes.length - 1]);
} else {
// 沒(méi)了說(shuō)明需要渲染最頂層了
updateOptions(ROOR_MAP_CODE);
}
};
// 生成 Echarts 配置
const generateOptions = (mapCode: string, mapData: any): echarts.EChartsCoreOption => {
return {
tooltip: {
show: true,
// 格式化 tooltip 信息
formatter: function (params: any) {
if (params && params.data) {
const { name } = params.data;
return name;
}
},
},
geo: {
// 傳進(jìn)來(lái) code,echarts 會(huì)去讀取已注冊(cè)的地圖數(shù)據(jù)
map: mapCode,
label: {
show: true,
},
},
series: [
// 傳進(jìn)來(lái) code,echarts 會(huì)去讀取已注冊(cè)的地圖數(shù)據(jù)
{
type: 'map',
map: mapCode,
roam: true,
geoIndex: 0,
select: false,
data: mapData,
},
],
};
};
// 更新地圖 Echarts 配置
const updateOptions = async (mapCode: string) => {
if (!echartInstance.value) return;
loading.value = true;
const mapResult = await fetchMapJson(mapCode);
echarts.registerMap(mapCode, mapResult);
const mapdata = mapResult.features.map((item: any) => {
const { name, adcode, level } = item.properties;
return {
name, // 地名
adcode, // 區(qū)域編碼
level, // 層級(jí)
};
});
const options = generateOptions(mapCode, mapdata);
// 配置 Echarts
echartInstance.value.setOption(options);
loading.value = false;
};
onMounted(() => {
// 初始化
initInstance();
updateOptions(ROOR_MAP_CODE);
});
</script>
<style scoped lang="less">
.container {
width: 800px;
height: 800px;
}
</style>