手绘地图实现
Echarts 手绘地图实现
业务中需要实现一个手绘地图,原计划是使用 Eva,但是时间有限,最后使用 Echarts 实现,实现效果如下。
(动图太大了,尽可能压缩稍微有点糊,见谅~)
业务中,如上图所示,内部有很多的元素都需要有相应的事件,需要整个地图尽可能地解耦。并且内部有板块/图片/路线等元素。
那么接下来分析一下,这样一个页面有那些需要实现的内容
分析页面
底图
底部有一层图片,没有交互,也没有位置的改变,是固定的。
可以用 Echarts.graphic.image 来实现
手绘板块
这里主要示上图中显示的四个不同的板块,其中三块是有颜色的,第四块是星球最外侧的星空板块,并且是多边形的,如果单个板块需要实现一些特殊的交互,如何判别多边形边界区域?我使用了 Echarts 的 geomap 来实现。
主要的做法就是,从 ui 那里拿到这几块板块的 svg 图,然后将整个图片转换成 geojson 数据(https://labs.mapbox.com/svg-to-geojson/),这个网址在调整完底部时间底图的大小比例后,将 svg 拖进去会自动将 svg 贴进去,并且可以在上面进行微调。然后下载可以得到一个 geojson 数据,那么这个 geojson 数据其实是相对于真实的世界地图来进行映射的,每一个点的数据都是真实的地图数据。
如下图所示:
导出后可以得到结构一个 data.json,同时,原有的 svg 有颜色填充的部分也会被识别,并体现在 data.json 中。data.json 结构类似如下:
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{
'type': 'FeatureCollection',
'features': [
{
'id': '400cfbfc61a37cad9e5f7168fa913b4d',
'type': 'Feature',
'properties': {
'id': 'Fill-8',
'fill': '#efe0c4',
},
'geometry': {
'coordinates': [
[
[
119.75217242139553,
30.189759022525294,
],
[
119.75329376495,
30.191341051272516,
],
]
]
}]
}其中 features 是个数组,其中每一项都是一个多边形。features.properties.id 用来识别每一个不同的多边形。features.properties.fill 是多边形的填充颜色,来自与原来的 svg 图片。
我们可以使用这个导出的 geojson 数据,通过 registerMap 方法来进行注册,并在
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import { mapData } from './data'
echarts.registerMap('LearningMap', mapData, {})
geo: {
map: 'LearningMap',
roam: false,
aspectScale: 0.8,
zoom: 1.02, // 缩放微调
center: [120.070048074111, 30.29092154350316], // 多边形位置微调
data: [],
nameMap: {},
label: {
show: debugGeoTitle,
},
itemStyle: {
areaColor: '#FFFFFF',
},
z: 9,
silent: true,
},路线
通过上面的步骤,我们得到的 geojson 数据中,也有路线的多边形数据,这里我们可以通过 Echarts.series.lines,去绘制路线,并设置 coordinateSystem: ‘geo’ ,因为数据是从 geojson 中获取的,然后通过 lineStyle.type: [10, 10]的方式去实现虚线路线的效果
小图标
小图标的话,只能使用图片的方式贴到对应的位置了,这里可以用 Echarts.scatters.effectScatter,相比较 scatter ,effectScatter 有更多的可操作性
定位点
这个也就是 gif 中路线上的小白点,同样在 geojson 有定义多边形,所以基本上 geo.regions 来实现,代码如下:
1
2
3
4
5
6
7
8
9
10
11const regions = [
{
name: id,
itemStyle: {
areaColor: fill,
borderWidth: 0,
opacity: 1,
},
z: 10,
}
]每个小白点的数据,都需要从 geojson 中拿出来,并解构成如上的结构放到 regions 数组中
人物 Marker
gif 中,随着不同的学习进度,人物头像作为 Marker 会出现在不同的位置
这部分,因为不同的用户头像是不一样的,所以我这里的方案是,将人物的头像,加上 Marker 的样式,一起转成一个图片,然后通过绘制图片的方式将头像 Marker 定位到特定的位置,其中有个 html2img 的操作,转成图像之后,后续操作也和 effectScatter 类似,而且可以做一些 hover 的样式区别
主要实现原理是根据最初导出的 geojson 里进行一系列操作
参考文档
Echarts 配置项:https://echarts.apache.org/zh/option.html#title
感谢阅读,勘误、纠错或其他请联系progerchai@gmail.com,或者点击这里提 issue 给我
欢迎交流 👏,你的每一次指导都可以让我进步
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!