5.26

从零搭建一个工业风地图面板,坐标转换、飞行动画、在线搜索一气呵成。


最近在做一个铁路站点管理系统,后端是 FastAPI,前端打算做成 SPA。核心需求很简单:能在地图上看到站点在哪、点进去能编辑、能在地图上直接新增。听起来是个"调个 Leaflet 就完事"的活,实际踩了一圈才知道,地图相关的坑远比想象的多。

单文件自包含:把所有东西塞进一个 HTML

这个地图页面最终是一个完整的单文件应用——map.html,CSS inline、JS inline、Leaflet 的样式表也直接嵌进去了,外部依赖只剩一个 jsdelivr 的 Leaflet CDN。

为什么这么干?因为这个项目部署环境不确定,越少外部依赖越稳。CSS 变量定义了一套暖色工业风主题(深色侧边栏 + 琥珀色高亮),视觉上比默认的 Leaflet 控件好看不少。

坐标转换:WGS84 ↔ GCJ-02 双向互转

在中国用地图,绕不开火星坐标系。后端存的都是 WGS84,但高德底图是 GCJ-02。之前只做了 WGS84→GCJ-02 单向转换,显示没问题,但地图上点击取点新增站点的坐标就偏了——因为 Leaflet 拿到的经纬度是 GCJ-02 的,直接存进数据库就会偏几百米。

解决办法是实现 GCJ-02→WGS84 的逆变换。用的是常见的迭代反推法——先正向算出偏移量,再从原坐标减掉偏移,两次迭代精度足够:

function gcjToWgs(lng, lat){
  var g = wgsToGcj(lng, lat);
  var dLng = g[0] - lng, dLat = g[1] - lat;
  return [lng - dLng, lat - dLat];
}

这样无论是从数据库拿来显示(WGS→GCJ),还是从地图点击取点存回去(GCJ→WGS),都能对齐了。

顺便把三个示例站点的经纬度精度从小数点后三位提到四位,石家庄站从 114.487, 38.042 改到 114.4869, 38.0419,在地图上定位明显更准。

flyTo:不止是飞,还要"高亮+自动缩放+侧边栏联动"

之前点了侧边栏的站点卡片,地图只是简单地 flyTo 过去,体验很干。

现在做成了一个完整的交互链条:

  1. 飞行动画——飞到目标点,缩放级别拉到 16,时长 1 秒,节奏感刚好
  2. 高亮脉冲——目标标记点放大到 16px、变色为琥珀色、加粗白色边框,2 秒后恢复原样。一眼就能看到飞到了哪
  3. 自动弹窗——飞行结束后自动打开详情弹窗,加载站点完整信息
  4. 侧边栏滚动——右侧卡片列表同步滚动到该站点,两边联动
// 高亮脉冲
m.setRadius(16);
m.setStyle({fillColor:'#b8852e', color:'#fff', weight:4, fillOpacity:1});
setTimeout(function(){ /* 恢复 */ }, 2000);

在线搜索:用高德 API 找真实坐标

搜索框支持高德 POI 搜索,输入关键词返回真实坐标和名称。搜索结果直接在地图上标注,点击"在此创建车站"就能跳转到新增表单,经纬度自动填入。

这里也处理了坐标转换——高德返回的是 GCJ-02,标记在地图上直接用,但传给新建表单的是转换后的 WGS84。

两个修了一上午的 Bug

Bug 1:window.flyTo is not a function

HTML 的 onclick="flyTo(...)" 调用不到 IIFE 闭包里的函数。一开始把 window.flyTo = flyTo 写在函数定义前面,结果 flyTo 还没声明就是 undefined。最后把所有 window 暴露语句移到 IIFE 末尾——等所有函数定义完再挂到 window 上,这个顺序问题才算彻底解决。

Bug 2:页面加载时 Router 未定义

侧边栏的地图链接跳转会经过 SPA 路由,但如果路由模块还没加载完就点了链接,直接白屏。加了一层守卫检查,模块未就绪时降级为 window.location.href 直接跳转。

小结

一天下来,这个地图从一个"勉强能看"变成"用着顺手"的状态。核心收获三条:

  • 在中国做地图,坐标转换不是"要不要做"的问题,是"不做会偏几百米"的问题。 WGS↔GCJ 双向转换必须从一开始就考虑好数据流向。
  • 单文件自包含在部署端是不确定因素时是最稳的选择。 多一个 CDN 依赖就多一个故障点。
  • window.xxx 赋值要写在定义之后。 看起来简单,但在 IIFE 里代码一长就容易放错位置。

接下来该做的是站点的网格化管理视图和批量导入功能,地图上的交互也应该还有不少优化空间——比如聚合标记、热力图、轨迹回放之类的,慢慢来。


posted @ 2026-05-27 21:40  douzishuo  阅读(24)  评论(0)    收藏  举报