根据大家的私信、留言,还是决定对地图这块的东西进行拓展讲解一下,希望大家能够真正了解、使用、绘制自己想要的地图效果,让大家彻底弄懂Echarts地图,涉及绘制原理、行政区划、SVG地图、地图打点、线路图、飞线图等内容。开始吧!
gitee: echarts-map
// Echarts 官网案例
$.get('map/china_geo.json', function (chinaJson) {
echarts.registerMap('china', {geoJSON: geoJson});
var chart = echarts.init(document.getElementById('main'));
chart.setOption({
geo: [{
map: 'china',
...
}]
});
});
Echarts 允许我们加载 json 文件(地图渲染文件),进而使用 registerMap 注册地图名称,通过 setOption来渲染地图。因此,地图json文件就是Echarts Map 的核心,可以根据不同的 json 文件渲染出不同效果的地图。(所以,自定义地图也是绘制的图形,生成json文件,供map使用)
我们上一篇文章Vue 使用 Apache Echarts 绘制地图(省市、地区、自定义)中,已经给出了地图渲染数据,根据dataV.数据可视化平台中的中国地图,我们渲染出以下地图:
但是这个南海区域拖的太长了,我们需要处理一下,根据上一节原理,是渲染的json数据太多了。我们目前是axios请求得来,不能直接修改,因此,我们需要下载下来,手动处理。
我们把海南的下地市数据删除,仅剩一个海南省主数据时,得到了下图:
还是剩一条线,因此,它可能是独立的数据了,我们看一下拿到的json数据,
最后一项数据没有表明名称,因此,我们可以删除,
如果Echarts没有提供右侧的南海诸岛的缩略图的话,自已一定一定要补上!不然中国地图不完整!!!
如果Echarts没有提供右侧的南海诸岛的缩略图的话,自已一定一定要补上!不然中国地图不完整!!!
如果Echarts没有提供右侧的南海诸岛的缩略图的话,自已一定一定要补上!不然中国地图不完整!!!
如果,Echarts 没有默认提供该缩略图,我们该如何处理?
使用边界生成器,绘制边界,导出为svg,得到下图:
在定位处理一下,即可得到想要的完整的中国地图。
**温馨提示**
这里说一下,Echarts默认使用 china注册的地图,都会加上南海诸岛缩略图,不论你的JSON文件是什么内容,如下:
甚至!,空的json文件,也能渲染出缩略图!这个问题我找了一上午,所以大家注册名字时,尽量规范取名。
中国区划:https://github.com/echarts-maps/echarts-china-misc-js
Echarts官网默认给我们提供了很多类型的地图,包括各种区划,但是提供给我们的是地图JS文件,包装了导出方法,不能直接使用,需要使用 map-maker 工具转换,具体方法我就不再这细说了,可以百度一下 echarts-mapmaker 的使用,我们研究一下源码,看它的实现思路:
gulp.task('华中', function(){
utils.disolve_internal_borders('./node_modules/echarts-china-provinces-js/echarts-china-provinces-js/henan.js', 'henan.geojson', '河南').then(()=>{
utils.disolve_internal_borders('./node_modules/echarts-china-provinces-js/echarts-china-provinces-js/hubei.js', 'hubei.geojson', '湖北').then(()=>{
utils.disolve_internal_borders('./node_modules/echarts-china-provinces-js/echarts-china-provinces-js/hunan.js', 'hunan.geojson', '湖南').then(()=>{
maker.merge('hubei.geojson', 'henan.geojson');
maker.merge('hunan.geojson', 'merged_hubei.geojson');
maker.makeJs('merged_hunan.geojson', path.join(constants.dist, 'hua_zhong.js'), '华中');
});
});
});
});
核心就是加载区划所属省份的json文件,进行合并,得到区划的json文件,进行地图渲染。
根据上诉原理,我们可以自定义区划了,我们已经有了全国省份的json文件,就是china.json文件里的数据项,实现步骤:
计算名称映射
json文件中 adcode是唯一标识每一个省份的,因此,我们需要获取到省份名称及adcode 的映射文件
// 生成映射文件
setDataMap() {
const data = require("./json/china.json");
this.map = [];
data.features.forEach((i) => {
this.map.push({
name: i.properties.name,
adcode: i.properties.adcode,
});
});
},
拿到对应省份的json文件
// 拿到省份对应的 json 文件
getGeoJson(list) {
const adcodeList = [];
const json = {
type: "FeatureCollection",
features: [],
};
const data = require("./json/china.json");
// 先获取 adcode
list.forEach((item) => {
adcodeList.push(this.map.find((i) => i.name === item)?.adcode);
});
adcodeList.forEach((code) => {
json.features.push(data.features.find((i) => i.properties.adcode === code));
});
// 返回拼凑的json文件
return json;
},
这个 name与adcode的转换,大家不要觉得没用,用name也能检索,使用adcode是为了数据库存储唯一ID,作为唯一值时,不推荐使用中文。
渲染返回结果
mounted() {
this.setDataMap();
const qhJson = this.getGeoJson(["广西壮族自治区", "广东省"]);
echarts.registerMap("mapName", {
geoJSON: qhJson,
});
var chart = echarts.init(this.$refs.map);
chart.setOption({
geo: [
{
map: "mapName",
},
],
});
},
中国的七大区划如下(Echarts官网给出的 preview):
区划 |
包含的省份 |
苏皖浙 |
苏州、安徽、浙江,三省合体 |
华南 |
广东、广西、海南、香港、澳门 |
华南2 |
广东、广西、海南(海南诸岛)、香港、澳门 |
华北 |
内蒙古、河北、山西、北京,天津 |
华中 |
河南、湖北、湖南 |
西北 |
宁夏、'新疆、青海、陕西、甘肃 |
西南 |
四川、云南、贵州、西藏、重庆 |
我们直接验证一个西北(名称一定以我们 json文件为准哈):
mounted() {
this.setDataMap();
// 宁夏 新疆 青海 陕西 甘肃
const qhJson = this.getGeoJson(["宁夏回族自治区", "新疆维吾尔自治区", "青海省", "陕西省", "甘肃省"]);
echarts.registerMap("mapName", {
geoJSON: qhJson,
});
var chart = echarts.init(this.$refs.map);
chart.setOption({
geo: [
{
map: "mapName",
},
],
});
},
我们的实现思路没问题。
mapshaper 是强大的地图文件编辑器,可以用于合并地图json数据。上一节我们说了,渲染地图的核心是 json文件,文件中的 coordinates 是二维点数据,因此,实现的原理是边界点重复出现时,删除该点:
如上,广东、广西公用一条边界线。下面演示下,如何使用 mapshaper 删除内部边界线:
拖拽文件或手动选择要合并的json,
选择导入 import
点击右上角 console,输入:
dissolve -o result.json
// dissolve 合并命令
// -o output edited content(输出编辑内容,就是另存为)
// result.json 要输出的文件名
可以输入 help 查看所有的命令,包括 删除、合并等操作。
选择某几个省:
使用工具选择:(ctrl 可多选,以两广为例)
delete 从原json 中删除选中;
keep 仅保留选中;
split 与delete相似;
clear 清除操作;
选择 keep 后,点击 console,输入合并命令:
dissolve -o result.json
然后,打开输出的文件,就是合并后的json文件啦:
通常实现的效果是添加省级、国界线,需要取消内部边界,实现效果如下:
单列市的存在比较特殊,是某些特殊的地市级,需要单独以单元出现在中国地图上,简单来说,我想看 北上广深的经济情况,很明显,深圳不是省份,正常是不能与上广深同时出现的。如何处理呢?
下载单列市的json文件【第一个能看到单列市的层级:意思是你要深圳,你在那一层最先看到它?广东省嘛,因此,下载广东省的json】
深圳太小了,我拿新疆的地市做测试,道理是一样的
// 处理单列市
dlsHandle(adcode = 440300) {
// 在单列市json中找到单列市的json配置项
const dlsJson = xjJson.features.find(
(i) => i.properties.adcode === adcode
);
const newJson = chinaJson;
// json 文件渲染存在先后顺序,先渲染的在图层底,后渲染的在顶层(canvas)
newJson.features.push(dlsJson);
return newJson;
},
上诉,自治州也能在全国地图显示了。这样,就能根据自己的业务,实现单列市的处理了。
原理是:
{
"type": "Feature",
"properties": {
"adcode": 110000,
"name": "北京市",
....
}
这个是北京市的 json数据
{
"type": "Feature",
"properties": {
"adcode": 652800,
"name": "巴音郭楞蒙古自治州",
...
}
这个是单列市的json数据,类型都是 Feature 一样的,因此,可以直接添加到 全国json数据。
世界各地json文件映射:https://github.com/echarts-maps/echarts-countries-js
世界各地 json文件地址:https://github.com/pissang/starbucks/tree/gh-pages/json
上诉两个地址,就是世界地图的json,直接爬虫下来,汇总处理数据就行了(文件我已经处理好了,放在项目里了)
效果图如下:
掌握了原理之后,你想绘制啥,那不是手到擒来。
自定义地图,多用在绘制非常规地图上,比如,绘制校园建筑人数热力、公园景点旅游热度等这些自定义的。下面还是举例说明一下吧(以上海海洋大学人员分布图为例)
使用 边界生成器绘制地图基础数据
上一篇文章中提到了区域相同导致浮窗都一样,添加了自定义name属性,建议在属性面板中处理,不然导出文件太大,根本处理不了,这样也能在绘制的时候,做合并、裁剪操作,使得绘制更加清晰,数据结构合理。
裁剪:想要两个面是独立的,就需要裁剪
先勾选减数,再勾选裁剪,后勾选被减数
执行完后,只会留下一个面,这个面是剪掉被减数后的
但是这个区域我们是需要的,因此,再绘制一遍
这两个面都是独立的面,导出json,看看效果:
这就是面的处理,已经很详细了,下面我就不细说了。需要注意点我会说一下。
再修饰一下,基本上就能出来了
加载SVG地图相对简单,但是我们加载自己的svg图的话,需要每一个
边界生成器导出为svg,加载svg:
// 该加载svg的方式会报错
echarts.registerMap("map", {
svg: require('../public/svg/data.svg'),
});
var chart = echarts.init(this.$refs.map);
chart.setOption({
geo: [
{
map: "map",
},
],
});
因此,不能直接 require或者 import ,应该使用网络请求:
mounted() {
// 这里用请求的形式,
axios.get("/svg/data.svg").then((res) => {
echarts.registerMap("map", {
svg: res.data,
});
var chart = echarts.init(this.$refs.map);
chart.setOption({
geo: [
{
map: "map",
},
],
});
});
},
得到如下:
但是这样子是没有交互的,就是鼠标放上去,也没有显示名称啥的,因此,需要手动添加 name属性:
这样就行了,我们实现一下官网的飞机选座图:
边界生成器自定义地图,就可以得到空的页面
绘制 飞机座位
标记name
导出,并处理
geo: {
map: "iceland_svg",
roam: true,
selectedMode: "multiple",
select: {
itemStyle: {
color: "green",
},
},
},
就这样,剩下的不可选中,直接判断一下就行了。
地图打点,需要svg底图实现,不可以加载 json文件。
按上例,先加载SVG,然后处理打点:
// 添加series配置项,
series: {
type: "effectScatter",
coordinateSystem: "geo",
geoIndex: 0,
data: [[...positionMap[0].position, 100]],
},
positionMap 就是点数据坐标,可以通过下方法,快速获取点在svg中的坐标
myChart.getZr().on("click", function (params) {
var pixelPoint = [params.offsetX, params.offsetY];
var dataPoint = myChart.convertFromPixel({ geoIndex: 0 }, pixelPoint);
// 在 SVG 上点击时,坐标会被打印。
// 这些坐标可以在 `series.data` 里使用。
console.log(dataPoint);
});
地图的打点,还可以做线路图 series type = lines
路径图
用于带有起点和终点信息的线数据的绘制,主要用于地图上的航线,路线的可视化。
连续位置的线段(用于绘制线路图等连续性坐标)
非连续的位置,可以实现飞线图:
这个问题通常出现在请求后端数据时,返回的数据与渲染地图数据不一致,使用nameMap处理(如官网香港18区人口密度 (2011))
思路就是找到两者数据的id,对名称进行数据映射即可。
其实这些东西都是官网的样例,好好研究官网配置文件,相信大家也可以写出来的。以上就是Echarts地图的拓展,有问题交流呀。