最近实现了通过Echarts地图,定位到自己的家乡,觉得挺有趣的,所以分享给大家,希望大家也可以实现一遍,在Echarts上定位到自己的家乡看一看~
图片
地图的绘制
地图数据
地图的数据我们可以通过网上提供的 API 来进行获取
API URL:https://geo.datav.aliyun.com/areas_v3/bound/{mapCode}.json
图片
绘制地图
首先需要一个 DOM 节点来进行 Echarts 的绘制。
图片
接着需要初始化 Echarts 实例,并进行配置,完成渲染。
图片
这样就能把地图渲染出来了。
图片
往下和往上定位
实现完整个地图的渲染,我们还需要实现:
- 点击某个地区,进行往下定位
- 点击按钮,进行往上定位
所以我们首先需要增加一个按钮。
图片
接着我们需要:
1、监听 Echarts 的点击事件。
2、获取点击的是哪个地区,进行数据获取并渲染。
3、维护一个地区数组,记录点击的链路。
图片
最终可以实现效果
图片
完整源码
<template>
<Button @click="back" type="primary" :loading="loading">返回上一级</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';
// 最顶层地图的代号
const ROOR_MAP_CODE = '100000_full';
const echartsRef = ref<HTMLDivElement | null>(null);
const echartInstance = ref<echarts.ECharts | null>(null);
const loading = ref(false);
// 请求地图数据
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;
};
// 记录点击链路
const mapCodes: string[] = [];
// 初始化 Echarts 实例
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';
// 防止重复点击最后一层
if (mapCodes[mapCodes.length - 1] === mapCode) return;
mapCodes.push(mapCode);
updateOptions(mapCode);
}
});
};
// 返回上一级
const back = () => {
// 无法再往上了
if (!mapCodes.length) return;
mapCodes.pop();
if (mapCodes.length) {
// 取最后一个去渲染数据
updateOptions(mapCodes[mapCodes.length - 1]);
} else {
// 没了说明需要渲染最顶层了
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: {
// 传进来 code,echarts 会去读取已注册的地图数据
map: mapCode,
label: {
show: true,
},
},
series: [
// 传进来 code,echarts 会去读取已注册的地图数据
{
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, // 区域编码
level, // 层级
};
});
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>