持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
序
看过一些可视化大屏展示地图的例子,准备动手做做。
既然要开始比制作,那么先把目标定好,做一个展示中国城市的下钻地图
使用:
- Vue3
- Vite
- Typescript
- echarts
实现效果:
项目地址:echarts-component: echarts的代码示例 (gitee.com)
准备工作
创建项目
因为准备使用Vue3
+ Vite
+ Typescript
所以使用yarn create vite echarts-component --template vue-ts
命令创建出项目
在项目的配置时,需要安装一些库,axios
、echarts
、less
、less-loader
、vue-router
。使用yarn
将这些库分别安装完成
我准备在全局中使用axios
和echarts
,在main.ts
中将这两个挂载到Vue
上面
const app = createApp(App);
app.config.globalProperties.$echarts = echarts;
app.config.globalProperties.$axios = axios;
app.use(router)
app.mount('#app');
数据来源
在echarts
中创建地图,首先需要地图的JSON
数据
这可以从DataV.GeoAtlas地理小工具系列 (aliyun.com)
进行获取,我不准备将这些JSON
数据下载到本地,所以依旧使用JSON API
进行访问
创建一个.vue
文件,在内部通过getCurrentInstance
获取到之前全局配置的$echarts
和$axios
import { ref, reactive, onMounted, getCurrentInstance, watch, Ref } from "vue";
// 获取全局配置项
const { proxy } = getCurrentInstance() as any;
const { $echarts, $axios } = proxy;
通过$axios.get()
去访问一下之前得到的中国省份JSON
的URL:'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json'
获得全国各省份接口数据:
关于接口的Typescript
类型,可以使用Quicktype
进行获取得到类型文件
命令: quicktype https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json -o geodatav.ts
获取到的数据需要通过echarts
的registerMap
进行地图的注册
// 地图名称,地图数据
$echarts.registerMap(currentName, mapdata);
echarts的options配置
在option
配置中,在series
中需要将类型type设置为map
,并且map
属性的地图名称为之前注册的地图名称。并且如果地图上不需要显示过多的数据或者tooltip提示,data
数据不填入也一样可以
const echartsMap1 = ref(null); // 获取DOM节点
let myChart = $echarts.init(echartsMap1.value);
let option = {
title: {
text: `${currentName}地图`,
left: 'center',
top: '2%',
textStyle: {
color: '#fff'
}
},
backgroundColor: '#070d18',
series: [{
name: `${currentName}地图`,
//使用上面注册的地图
map: currentName,
//初始化类型写地图
type: "map",
roam: true,//鼠标滚轮缩放
selectedMode: false, // 点击选中区域
// 区块文字样式
label: {
normal: {
formatter: '{b}',
show: true,
textStyle:{
color:'#fff'
}
},
emphasis: {
show: true,
textStyle: {
color: '#05C3F9'
}
}
},
// 区块样式
itemStyle: {
normal: {
areaColor: '#0C356C',
borderColor: '#3B5077',
borderWidth: 1
},
emphasis: {
areaColor: '#0C356C',
shadowColor: '#1773c3',
shadowBlur: 20
}
},
select: { // 地图选中区域样式
},
data: [
],
}]
}
myChart.setOption(option);
这样一来,界面上就能展示中国地图了
下钻实现
现在已经实现了最开始的中国地图,那么如何实现点击省份进入下一级,点击市进入下一级呢,需要将其扩展一下
在之前的获取的中国地图省份数据中,可以在properties
中得到具体一些数据:
属性 | 含义 |
---|---|
adcode | 该省份或城市的id,可以用于JSON API 获取 |
name | 地区的名称 |
center | 应该是省份中心城市位置 |
childrenNum | 代表下面有多少地区,如果为0,则不进行下钻 |
parent.adcode | 上一级父区域的id |
通过这些属性,就可以去实现下钻的方法了
- 创建一个
allMap
集合,用来存放当前已出现过的地图
// 定义当前所有的地区信息
let allMap: Map<string | number, citymodel> = new Map();
// 第一份信息就是中国
allMap.set(100000, {
name: '中国',
adcode: 100000,
url: 'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json',
childrenNum: 34,
center: [0, 0],
hasRegister: false, // 是否已经注册在echarts
})
- 在绘制中国的
echarts
地图时,将获取到的数据存入allMap
中,并且将中国信息中是否注册变为true
,这样之后再渲染时就不需要registerMap
重新注册了
// 判断是否注册过
if (!cMap?.hasRegister) {
$echarts.registerMap(currentName, mapdata);
// 当前地图下的地区信息
let currentCityMap: Map<string | number, citymodel> = getCurrentadcode(mapdata);
allMap = new Map([...allMap, ...currentCityMap]);
(allMap.get(cMap?.adcode as string | number) as citymodel).hasRegister = true;
}
- 在
echarts
可以通过绑定click
点击方法,点击地区可以获得name
名称属性,然后通过名称,去获取该地区的adcode
// 地图点击事件
myChart.on('click', (params:any)=>{
let n = getMapKey(params.name, allMap);
if (allMap.get(n)?.childrenNum == 0) return ;
(currentadcode.value as number | string) = n;
})
// 根据map中数值,获取key
const getMapKey = (value: string, map: Map<string | number, citymodel>): number | string => {
let arriterator = map.values(), res: number | string = 0;
for (const iterator of arriterator) {
if (iterator.name == value) {
res = iterator.adcode;
break ;
}
}
return res;
}
- 编写一个
watch
监听方法,监听当前地图的currentadcode
改变,然后通过判断是否存在childrenNum
,来决定是否绘制地图。
let currentadcode: Ref<number | string> = ref(100000);
// 当前地图
let currentMap: Ref<null | citymodel> = ref(null);
// 监听currentadcode地图值
watch(currentadcode, (newval, oldval)=>{
// 根据adcode,从allMap中获取该地图信息
let nextMap = allMap.get(newval) as citymodel
// 如果存在子节点
if (nextMap?.childrenNum && nextMap.childrenNum > 0) {
currentMap.value = nextMap;
// 如果出现意外,没呀父节点
if (currentMap.value.parentadcode == undefined) {
currentMap.value.parentadcode = oldval;
}
// 获取地图json, 绘制地图
renderChart(nextMap);
}
})
- 在上面步骤做完后,已经能做到逐层下点,但是并没有返回,所以需要添加返回方法。
因为之前已经写了watch
监听方法,所以返回上一级地图,只需要改变currentadcode
即可。在地图信息中,存在着parentadcode
父地图的adcode
返回元素:
<div class="backParent" v-show="currentadcode != 100000" @click="returnLastMap(currentMap?.parentadcode as string | number)">返回</div>
返回方法returnLastMap
:
// 返回上级地图
const returnLastMap = (adcode: string | number) => {
currentadcode.value = adcode
}
到目前为止,一份中国地图的下钻就使用echarts
完成啦