发布于 

Echarts + DataV.GeoAtlas 实现大区划分地图下钻

因业务驱动,需要实现天朝行政地图下钻大区(自定义)、省、市四级,本文讲解如何实现地图自定义区域下钻。

思路

  • 需要各省市行政地图数据
  • 各级之间需存在关联关系,方便下钻
  • 大区是几个省份的集合,需要做地图数据

首先我查阅了网上的相关资料,发现基于行政地图下钻的案例很多,但基于自定义区域下钻的案例很少。

搜遍了全网,发现了一个阿里云旗下的一个的数据可视化平台 DataV.GeoAtlas 很好用。

因公司项目代码地图数据不方便透漏,这里以一个DEMO举例。

举个例子

我们把天朝地图划分为5大区,分别是北部大区、中部大区、西部大区、南部大区、东部大区。每个大区是由几个省份组合而成。

先做大区数据,以北部大区举例,下属省份为黑龙江、吉林、辽宁。

在范围选择器中,点击取消包含子区域,把省份json数据下载到本地。

点击边界生成器,点击上传,把刚才下载下来的省份数据依次上传

选中所有区域,点击合并,然后点击交集

新增列,字段名称为name,值输入北部大区,选中然后导出GeoJSON

点击层级生成器,根节点绑定天朝

点击新增子节点

点击绑定数据,切换到自定义数据,将刚才导出的GeoJSON上传

重命名为北部大区

在北部大区下点击批量导入子节点,把刚才下载下来的省份数据上传

至此,一份天朝包含北部大区以及其下所有省份的地图数据做完了。

接下来点击导出层级(开放格式),会得到两份文件,一份是地图json,一份是关系映射。其中地图json是渲染地图时所用的数据,而关系映射主要用来实现下一步地图下钻或页面交互。

做到这里需要注意,阿里云下载下来的数据直接放到我们的echarts中是加载无法使用的,这里涉及到一个知识点,请先自行科普topojson和geojson的区别。下载下来的数据是topojson格式的,需要我们转换一下,转换成我们需要的geojson格式。

接下来是代码实现(vue举例,其实和框架关系不大,其他框架做参考)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import * as echarts from "echarts";
import * as topojson from "topojson-client";
export default {
props: ["mapJson", "width", "height"],
data() {
return {
dataList: [ // 这里是天朝和大区之间的映射关系
{
name: "天朝",
treeID: "1",
parent: null,
treeName: "天朝_1",
},
{
name: "北部大区",
treeID: "1-1",
parent: "1",
treeName: "北部大区_1-1",
ename: 'north' // 为我自己新增的字段,方便地图下钻
}
],
chart: null,
};
},
methods: {
initEchart() {
// 刚才下载下来的地图json
const areaMapJson = require("./area.json");
// 通过组件topojson-client把topojson转换为geojson 只取payload
const ChinaResult = topojson.feature(
areaMapJson.payload,
areaMapJson.payload.objects.collection
);
// 因为是一级一级下钻,所以只遍历第一层子级即可
this.dataList.forEach((i, index) => {
if (index > 0) {
let result = topojson.feature(
areaMapJson.children[i.treeID].payload,
areaMapJson.children[i.treeID].payload.objects.collection
);
ChinaResult.features = [...ChinaResult.features, ...result.features];
}
});
echarts.registerMap("china", ChinaResult);
let dataList = this.dataList;
const _this = this;
this.chart = echarts.init(this.$el);
var option = {
tooltip: {
padding: 0,
textStyle: {
fontSize: 14,
color: "#7DD1FF",
},
},
visualMap: {
min: 0,
max: 1000,
left: "left",
top: "bottom",
text: ["高", "低"], //取值范围的文字
inRange: {
color: ["lightskyblue", "yellow", "orangered"], //取值范围的颜色
},
show: true, //图注
},
geo: {
map: "china", //引入地图数据
roam: true, //不开启缩放和平移
zoom: 1, //视角缩放比例
label: {
normal: {
show: true,
fontSize: "16",
color: "rgba(0,0,0,0.7)",
},
},
itemStyle: {
normal: {
borderColor: "rgba(0, 0, 0, 0.2)",
},
emphasis: {
//高亮的显示设置
areaColor: "skyblue", //鼠标选择区域颜色
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
// 鼠标悬浮提示框
series: [
{
name: "大区",
type: "map",
geoIndex: 0,
data: this.dataList,
},
],
};
this.chart.setOption(option);
// 点击大区事件,进行下钻
this.chart.on("click", function (params) {
if (!params.data.ename) {
alert("暂无" + params.name + "地图数据");
return;
}
// 这里写下钻代码,有多种方式,可页面跳转可组件传参
// 传值把ename(板块英文名),name(板块中文名)带过去

});
},
},
mounted() {
// this.initEchart();
},
};

总结

以上,基本实现了天朝地图包含自定义大区的效果,实际应用中可以把其他几个大区补全即可,方法一致。

以上实现了天朝>大区,但要实现下钻还要实现大区>省份、省份(直辖市)>市(区)。

因过程有所重复,不做详细展示,简单说一下接下来要做的事:

  1. 进入层级选择器根节点上传geojson文件绑定大区
  2. 新建子节点省份,绑定【行政区数据集】,取消选中【同时添加所有下游节点】
  3. 导出层级(开放格式)

依次把每个大区的层级导入下来,几个大区就导几个文件,文件名称要与映射中起名的ename一致,加载方法与上面代码一致。

接下来是下钻,在上级地图中把ename传入下级地图组件,下级地图组件通过文件名称加载数据

1
2
3
4
// 下级地图组件接收入参,加载地图
const areaEname = this.mapJson.ename;
const areaMapJson = require("./areaData/" + areaEname + ".json");
// 与上面代码加载方式一致

如再往下钻,则直接操作行政区数据集即可,以此类推。

以上就是Echarts + DataV.GeoAtlas 实现地图下钻。过程虽有些繁琐,但想我泱泱大国,地域之广泛,岂是简简单单就能写出来的,哈哈,开个玩笑。

欢迎有问题随时留言交流。