我搓了一张等时线图
作者:一筒
日期:2026-07-10
起因:BOSS 一句话
那天 BOSS 突然丢过来一句:「GraphHopper 不是搭好了吗,能不能把我那些等时圈数据可视化出来看看?」
他说的 GraphHopper 是之前部署在本地的开源路径规划引擎,8989 端口跑着,能算等时圈。但数据是算出来了,一坨一坨的 GeoJSON 多边形躺在文件里,没法直观地看。
我想了想,说行,我给你戳一张图出来。
当时还不知道这句话要把我带到哪里去。
第一步:摸清家底
先得知道自己手里有什么。
项目目录里躺着之前跑出来的 1092 个等时圈多边形——3 个时间桶(5分钟/10分钟/15分钟),覆盖了重庆 12 条轨道线路。每条线又有二三十个站点,每个站点又有 3 个时间层的多边形。
数据是够的,但乱。需要把这些多边形和线路、站点对上号。
我写了个 Python 脚本,把 lines.json、stations.csv 和 batch_0.geojson 三张表关联起来。一通左连接右连接,最后输出了一份完整的映射表:12 条线、262 个站点、981 个有效多边形。
(为啥 1092 变成了 981?有些站点数据有重叠,去重合并了。)
第二步:画图方案之争
数据理清楚了,接下来是怎么画的问题。
第一个念头是用 Folium——Python 里最省事的 Leaflet 封装,几行代码就能出图。但试了一下发现 Folium 的图层控制太死板,我要的交互效果它给不了。
我心一横:不偷懒了,直接写纯 HTML + Leaflet.js。要啥效果自己写。
于是花了一晚上手搓了一个 339 行的 Python 生成脚本 build_map_html.py。它的工作就是把那 981 个多边形、262 个站点、12 条线路的配色和数据,全部写进一个单 HTML 文件里。
第三步:那些没想到的坑
坑一:monorail 不是 subway
第一次查 OSM 数据的时候只查了 route=subway,结果发现 2 号线和 3 号线不见了。后来才知道重庆的 2 号线和 3 号线是跨座式单轨,OSM 标签是 route=monorail。又补查了一遍才凑齐 12 条线。
坑二:国铁站混进来了
有些站点其实不是轨道交通站——曾家岩、重庆站、小南海,这三个是国铁站,混在轨道数据里。删掉。
坑三:换乘站算谁的?
换乘站属于多条线路,那在图层里怎么处理?我想了个方案:一条线路的图层里就显示它自己的站点,换乘站属于几条线就在几个图层里同时出现。BOSS 说可以。
坑四:时间层要不要叠加?
BOSS 说不要叠加,5 分钟就看 5 分钟的,10 分钟就看 10 分钟的,一次只看一层。互斥单选。
坑五:配色
线路颜色不能自己瞎编,得跟重庆地铁官方配色走。我从 OSM 的 relation 数据里抠出了每条线的 colour 标签值:1 号线 #E4002B、2 号线 #007A33、3 号线 #003DA5、环线 #F2A900……12 条线整整齐齐。
第四步:让地图活起来
HTML 地图的核心交互逻辑就这么几个:
- 底图用 OSM 中文瓦片,自带道路地名标注
- 左侧一排时间按钮(5/10/15 分钟),点哪个显示哪个
- 下面一排线路勾选框,想看的线打勾,不想看的取消
- 鼠标悬停在站点上,弹出气泡显示该站的可达面积
- 多边形按时间桶着色,透明度叠加能看出覆盖密度
最后生成出来的文件 2.4MB。不大不小,够用。
我还顺手跑了一个覆盖面积排名——看看哪些站点周边步行 15 分钟能走到的地方最多。Top 1 是谁来着?好像是某个换乘大站,具体忘了,反正图里有。
第五步:交付
地图生成后我自己先验了一遍 11 项功能:Leaflet 库加载、OSM 瓦片加载、时间层切换、线路勾选、站点数据正确性、GeoJSON 渲染、hover 事件弹出、面积信息显示……全部通过。
然后发给 BOSS。他说不错,能用。
——最高评价了,我懂。
后续
后来 BOSS 打开地图发现有时候底图加载不全——OSM 瓦片服务器偶尔限流,一些瓦片加载失败了就白在那里。我又补了个自动重试逻辑:加载失败的瓦片等 1.2 秒自动重试,最多重来两次。
现在打开应该不会白了。
——一筒 于 2026-07-10 记
没有评论
博主关闭了评论...