~
 Gather ye rosebuds while ye may

复刻了那个交互式旅行博文

𖭀 

之前看到 有一篇交互式的旅行博文 做得很精美,作者本人也发了 codrops 教程,但是只写了思路没给源代码(教程最后说 GitHub link coming soon,但这一等就是十年),在其他人的站也看到过一次。都没有源代码但是我们可以从 codrops 的 demo 页面 直接查看 minify 后的结果逆向出来,github 搜得到很多这样的项目


本博也实现了一份,可以看这一篇这一篇,都改为了互动式文章。


思路

目标效果很清晰,没有太多奇技淫巧可以讲,主要的特效有:

  1. 监听页面滚动,对 SVG 修改 stroke 信息以同步路径进度
  2. 标记原文,在特定内容被展示时同步路径进度、位置、缩放
  3. 路径打点,同步绘制三角形

文章间不同的数据就需要在写文章的时候录入,而相同的部分就抽取为 js 和 css 放到 ejs 当中(本博用的 hexo)了。

综上考虑特效,文章里需要录入的数据也只有:

  1. 地图数据
  2. 路径数据
  3. 原文关联路径,打点位置和放大倍率

所以 md 的格式(hexo 主题用)也就大致能约定出来长这样:

1
2
3
4
5
6
7
layout: storytellingmap
path: 'xxx.SVG'
map: 'xxx.png'
---
<p data-percent='40' data-scale='1.4'>
需要在路径40%处放大1.4倍的内容
</p>

比原始实现的版本简单了不止一点点,剩下的就是单纯的编码实现了。


难点

地图和路线的获取

特定地图图片获取倒是挺容易的:snazzymaps、openstreetmap 都可以免费下载。但路线 SVG 很难搞,自己画另说。我最后是在谷歌地图创建地图,导出KML文件(以获得SVG)和打印地图(以获得地图图片),好处是地方可以同时获取两个数据,还支持导航:输入起止点就可以获得线路。

匹配地图和路线

KML 可以通过命令行工具(mapshaper)或者在线工具(mygeodata)转换成 SVG,但是注意有可能因为投影转换规则不同,最终与地图匹配不上。你知道图片是平的但地球是圆的,对吧。这里需要使用 EPSG:3857 进行转换,不然你会发现不管你怎么拉伸平移旋转,路线就是不在道路上。

谷歌地图的坑

这一篇里遇到有一段是重复的路线,KML 导出 SVG 后可以看到只剩连续的点,丢失了「重复」这个重要信息。最后只能在重复点前后截断,导出两份 KML,转换为两个 SVG 后再合并 SVG,以获得路线。

SVG 转坐标

SVG 是通过 M-移动,L-画线,H-水平,V-垂直,C-贝塞尔等 token 描述矢量的,我们需要把这个 path 信息转换为一系列绝对的坐标供 canvas 画线用。当然这个也有实现了,不用手写。


稍微有些遗憾是没有找到可以下载 SVG 地图的地方,如果可以的话那原数据能更小一点,加载速度会快一些(渲染卡不卡还真难说)。优势就挺明显了,在已有博文的基础上修改一篇不用新开编辑器绘制路线,全程浏览器内就能完成所有编辑工作,标记语法也非常精简,美滋滋。

说了这么多,源代码可以直接在上面两篇HTML里看到,没有混淆压缩甚至还保留了注释,有兴趣的同学自己拿回去改改原数据(估计)就能用。