跳到主要内容

高德地图坐标侧漂记录

这篇文档只记录一个问题:

  • 照片 EXIF 里的 GPS 点位在高德地图上整体偏到一侧
  • 点位群的形状大致还是对的,但整片点会整体偏东、偏北,或者偏到道路另一侧

这不是偶发 UI 问题,也不是经纬度顺序写反,而是典型的坐标系问题。

现象

在 Travel 地图里,照片点位会出现下面这种表现:

  • 一组照片明明拍的是同一片街区,但标记整体落到街对面
  • 点位之间的相对位置看起来基本正确,但整体平移了几十米到几百米
  • 高德逆地理编码返回的地点名称是对的,但地图上的 marker 落点还是不准

只要出现“相对形状差不多,但整体平移”的症状,优先怀疑坐标系,不要先怀疑样式、缩放或 icon anchor。

根因

Travel 照片元数据里保存的是 EXIF 原始 GPS:

  • gps.latitude
  • gps.longitude
  • gps.coordsys: 'gps'

这套值本身是原始卫星坐标来源,和高德底图渲染使用的坐标系不是同一套。

当前项目里,照片元数据脚本在做高德逆地理编码时,已经明确把这批坐标声明成 coordsys: 'gps',所以地址文本可以是对的。

但如果前端把这组原始 GPS 直接传给:

  • new AMap.Marker({ position: [lng, lat] })
  • map.setCenter([lng, lat])
  • map.setZoomAndCenter(zoom, [lng, lat])

那 marker 会直接画在高德底图上,结果就是整片侧漂。

结论:

  • 经纬度顺序 [lng, lat] 可能是对的
  • 但只要没做坐标系转换,点位仍然会漂

这次项目里具体错在哪

错误链路是这样的:

  1. 从照片 EXIF 提取出原始 GPS
  2. 把原始 GPS 存进 travelPhotoMetadata.generated.json
  3. 生成 Travel 地图数据时继续直接使用这组原始 GPS
  4. 前端渲染 marker 时,直接把原始 GPS 喂给高德 JSAPI

其中第 4 步就是问题核心。

正确做法

原则只有一条:

  • 原始 GPS 可以保留在数据层
  • 但在高德底图上渲染前,必须先转换成高德可直接使用的坐标

在当前项目里,统一修复方式是:

  1. 保留 travelPhotoMetadata.generated.json 里的原始 gps
  2. 生成 travelMap.generated.json 时继续保留原始点位,不在生成阶段硬改
  3. 前端真正渲染地图前,调用高德官方 AMap.convertFrom(..., 'gps')
  4. 用转换后的点位再去创建 Marker、设置地图中心和 fit view

这样做的好处是:

  • 元数据仍然保持原始、可追溯
  • 前端渲染逻辑集中处理坐标系,不会污染别的用途
  • 后续换别的地图 SDK 时,仍然能从原始 GPS 出发重新转换

当前仓库里的落地位置

这次修复已经收敛到下面几处:

  • shared.js 这里新增了批量 gps -> 高德坐标 转换 helper,内部统一调用 AMap.convertFrom(..., 'gps')
  • TravelStoryMap.js 文章页地图在创建 marker 前,先转换照片点位
  • TravelOverviewMap.js 分类总览地图在创建地点 marker 前,先转换地点点位

以后如果再新增高德地图组件,优先复用这套 helper,不要重新各写一份转换逻辑。

禁止事项

以后在这个仓库里,下面这些做法都视为错误:

  • 直接把 record.gps.latitude / record.gps.longitude 传给高德 marker
  • 直接把 EXIF 原始 GPS 用来 setCentersetZoomAndCenter
  • 看到点位侧漂后,只去调 icon anchor、offset、zoom 或容器样式
  • 在生成脚本里偷偷把原始 GPS 覆盖成不明来源的“修正值”
  • 没确认坐标系之前,就断言是“高德地图不准”

排查顺序

以后再遇到类似问题,固定按下面顺序排查:

  1. 看数据里保存的坐标系是不是原始 GPS
  2. 看高德逆地理编码时有没有显式传 coordsys: 'gps'
  3. 看前端渲染前有没有调用 AMap.convertFrom(..., 'gps')
  4. 确认传给 marker 的顺序仍然是 [lng, lat]
  5. 转换后如果仍有个别小误差,再考虑手机 GPS 精度、楼宇遮挡、多路径反射

不要跳步骤。

如何判断已经修好

修好之后,应该看到的是:

  • 整组点位不再整体平移到道路另一侧
  • 点位能大致压在真实拍摄街区、景区或建筑群上
  • 剩余误差如果存在,通常是单点级的小偏差,而不是整组统一偏移

如果“整组还是往同一个方向整体偏”,说明转换链路仍然有问题。

一句话规则

以后在这个项目里接高德地图时,永远先问自己一句:

这组坐标是原始 GPS,还是已经转成高德可直接渲染的坐标?

如果答案不明确,就不能直接画点。