Skip to main content

Amap Coordinate Drift Troubleshooting

This document covers one specific problem:

  • GPS points from photo EXIF data drift to one side on Amap (Gaode) maps
  • The overall shape of the point cluster is roughly correct, but the entire group shifts east, north, or to the other side of the road

This is not a random UI bug, nor is it a reversed lat/lng order. It is a classic coordinate system problem.

Symptoms

In the Travel map, photo markers show these behaviors:

  • A group of photos clearly taken on the same block, but markers land on the opposite side of the street
  • Relative positions between points look mostly correct, but the entire group shifts by tens to hundreds of meters
  • Amap reverse geocoding returns the correct place name, but the map marker still lands in the wrong spot

Whenever you see "relative shape looks right, but the entire group shifts", suspect the coordinate system first. Do not jump to styles, zoom, or icon anchor issues.

Root Cause

Travel photo metadata stores raw EXIF GPS:

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

These values are raw satellite coordinates. They use a different coordinate system than the one Amap's base map rendering expects.

In the current project, the photo metadata script correctly declares these coordinates as coordsys: 'gps' when performing Amap reverse geocoding, so the address text can be correct.

But if the frontend passes raw GPS directly to:

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

The marker is drawn directly on the Amap base map, resulting in the entire group drifting.

Conclusion:

  • The [lng, lat] order may be correct
  • But without coordinate system conversion, the points will still drift

What Went Wrong in This Project

The error chain was:

  1. Raw GPS extracted from photo EXIF
  2. Raw GPS stored in travelPhotoMetadata.generated.json
  3. Travel map data generation continued using raw GPS directly
  4. Frontend rendering passed raw GPS straight to the Amap JSAPI

Step 4 is the core of the problem.

The Correct Approach

There is only one rule:

  • Raw GPS can stay in the data layer
  • But before rendering on an Amap base map, it must be converted to coordinates Amap can use directly

In the current project, the unified fix is:

  1. Keep the raw gps in travelPhotoMetadata.generated.json
  2. Continue preserving raw coordinates in travelMap.generated.json; do not hard-convert during generation
  3. Before the frontend actually renders the map, call Amap's official AMap.convertFrom(..., 'gps')
  4. Use the converted coordinates to create markers, set map center, and fit the view

The benefits:

  • Metadata remains original and traceable
  • Frontend rendering logic handles coordinate conversion centrally without polluting other uses
  • If you switch to a different map SDK later, you can still convert from raw GPS

Where the Fix Lives in This Repo

The fix has been consolidated into these files:

  • src/components/TravelMap/shared.js Provides a batch GPS -> Amap coordinate conversion helper, internally calling AMap.convertFrom(..., 'gps')
  • src/components/TravelMap/TravelStoryMap.js The story page map converts photo coordinates before creating markers
  • src/components/TravelMap/TravelOverviewMap.js The overview map converts location coordinates before creating location markers

If you add new Amap components in the future, reuse this helper. Do not write separate conversion logic each time.

Forbidden Practices

In this repo, the following are all considered wrong:

  • Passing record.gps.latitude / record.gps.longitude directly to an Amap marker
  • Using raw EXIF GPS directly for setCenter or setZoomAndCenter
  • When seeing coordinate drift, only adjusting icon anchor, offset, zoom, or container styles
  • Silently overwriting raw GPS in generation scripts with "corrected values" from unknown sources
  • Claiming "Amap is inaccurate" before confirming the coordinate system

Troubleshooting Order

If you encounter similar issues in the future, always follow this sequence:

  1. Check whether the stored coordinates are raw GPS
  2. Check whether Amap reverse geocoding explicitly passes coordsys: 'gps'
  3. Check whether the frontend calls AMap.convertFrom(..., 'gps') before rendering
  4. Confirm the order passed to markers is still [lng, lat]
  5. Only after conversion, if small individual errors remain, consider phone GPS accuracy, building occlusion, or multipath reflection

Do not skip steps.

How to Confirm It Is Fixed

After fixing, you should see:

  • The entire point group no longer shifts uniformly to the other side of the road
  • Points roughly align with the actual streets, scenic areas, or building clusters where photos were taken
  • Any remaining error, if present, is a small single-point deviation, not a uniform group shift

If "the entire group still shifts uniformly in one direction", the conversion pipeline still has a problem.

One-Line Rule

Whenever connecting to Amap in this project, always ask yourself first:

Are these coordinates raw GPS, or have they already been converted to coordinates Amap can render directly?

If the answer is unclear, do not draw the points.