---
title: "Coordinate Conversion"
description: "Convert points and GeoJSON between WGS84, GCJ02, BD09 and EPSG3857 with transformPoint and transformGeoJSON, powered by gcoord."
canonical_url: "https://mapbox.mhaibaraai.cn/en/docs/extensions/coordinate"
---
# Coordinate Conversion

> Convert points and GeoJSON between WGS84, GCJ02, BD09 and EPSG3857 with transformPoint and transformGeoJSON, powered by gcoord.

## Introduction

`transformPoint` / `transformGeoJSON` are powered by [gcoord](https://github.com/hujiulong/gcoord) to convert coordinates between WGS84 / GCJ02 / BD09 / EPSG3857: the former converts a single longitude/latitude point, while the latter transforms any GeoJSON and returns a new object without mutating the input. Commonly used to correct data from Amap / Tencent (GCJ02) or Baidu (BD09) to WGS84, aligning it with Tianditu and Mapbox basemaps.

> [!NOTE]
> 
> Different basemaps use different coordinate systems — unify them before overlaying data:
> 
> - **Tianditu**: CGCS2000, compatible with WGS84 at centimeter level. `MapboxTiandituLayer` uses `w` (EPSG:3857 Web Mercator) tiles, so WGS84 data **aligns directly — no conversion needed**.
> - **Amap / Tencent**: GCJ02 (Mars Coordinates, encrypted offset). Data must be converted `GCJ02 → WGS84` before overlaying on Tianditu / Mapbox.
> - **Baidu**: BD09, requires `BD09 → WGS84` conversion.

Both functions are imported from `@movk/mapbox/utils/coordinate` (not auto-imported).

## Usage

WGS84 coordinates align directly on the Tianditu basemap. Converting them to GCJ02 (Amap / Tencent CRS) and overlaying on Tianditu instead causes a visible offset:

```vue [CoordinateExample.vue]
<script setup lang="ts">
import { transformPoint } from '@movk/mapbox/utils/coordinate'

// 上海人民广场（WGS84 原始坐标，天地图直接对齐）
const wgs84: [number, number] = [121.4737, 31.2304]
// 转成 GCJ02（高德/腾讯坐标系）后叠在天地图上会偏移
const gcj02 = transformPoint(wgs84, 'WGS84', 'GCJ02')
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap :options="{ style: 'mapbox://styles/mapbox/light-v11', center: wgs84, zoom: 15 }">
      <MapboxTiandituLayer layer="vec" annotation />
      <MapboxMarker :lnglat="wgs84">
        <div class="rounded bg-success px-2 py-0.5 text-xs font-medium text-inverted">
          WGS84：对齐天地图
        </div>
      </MapboxMarker>
      <MapboxMarker :lnglat="gcj02">
        <div class="rounded bg-error px-2 py-0.5 text-xs font-medium text-inverted">
          GCJ02：用于高德/腾讯，叠天地图会偏移
        </div>
      </MapboxMarker>
    </MapboxMap>
  </div>
</template>
```

## Examples

### Correcting GeoJSON

Use `transformGeoJSON` to convert an Amap-exported GCJ02 polyline back to WGS84, aligning it with the Tianditu basemap. The red line is the original GCJ02 (offset), the green line is the converted WGS84 (aligned):

```vue [CoordinateGeoJsonExample.vue]
<script setup lang="ts">
import type { FeatureCollection } from 'geojson'
import { transformGeoJSON } from '@movk/mapbox/utils/coordinate'

// 高德导出的一段折线（GCJ02 坐标，叠在天地图上会偏移）
const raw: FeatureCollection = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    properties: {},
    geometry: {
      type: 'LineString',
      coordinates: [
        [121.4737, 31.2304],
        [121.4800, 31.2330],
        [121.4860, 31.2352],
        [121.4920, 31.2360]
      ]
    }
  }]
}

// 整体纠偏为 WGS84 对齐天地图，返回新对象，不修改 raw
const fixed = transformGeoJSON(raw, 'GCJ02', 'WGS84')
</script>

<template>
  <div class="h-115 w-full overflow-hidden rounded-(--ui-radius) border border-default">
    <MapboxMap :options="{ style: 'mapbox://styles/mapbox/light-v11', center: [121.484, 31.234], zoom: 14 }">
      <MapboxTiandituLayer layer="vec" annotation />
      <MapboxLayer
        layer-id="line-raw"
        type="line"
        :source="{ type: 'geojson', data: raw }"
        :paint="{ 'line-color': '#ef4444', 'line-width': 4 }"
      />
      <MapboxLayer
        layer-id="line-fixed"
        type="line"
        :source="{ type: 'geojson', data: fixed }"
        :paint="{ 'line-color': '#22c55e', 'line-width': 4 }"
      />
    </MapboxMap>
  </div>
</template>
```

### Controlling Coordinate Precision

`precision` specifies the number of decimal places in the output coordinates, useful for reducing jitter and minimizing transfer size. When omitted, full precision is preserved:

```ts
import { transformGeoJSON } from '@movk/mapbox/utils/coordinate'

const compact = transformGeoJSON(raw, 'GCJ02', 'WGS84', { precision: 6 })
```

## API

### `transformPoint()`

Converts a single longitude/latitude point and returns new coordinates.

**point** (`[number, number]`) *required*: Longitude/latitude point [lng, lat].

**from** (`CRS`) *required*: Source coordinate system.

**to** (`CRS`) *required*: Target coordinate system.

**options.precision** (`number`): Number of decimal places in the output coordinates. Omit to preserve full precision.

Returns `[number, number]`: the converted `[lng, lat]`.

### `transformGeoJSON()`

Converts any GeoJSON (point / line / polygon / collection) and returns a new object of the same type as the input, without mutating it.

**geojson** (`T`) *required*: Any GeoJSON object (Feature / Geometry / FeatureCollection, etc.).

**from** (`CRS`) *required*: Source coordinate system.

**to** (`CRS`) *required*: Target coordinate system.

**options.precision** (`number`): Number of decimal places in the output coordinates. Omit to preserve full precision.

Returns `T`: a new GeoJSON object of the same type as the input.

### `CRS`

Coordinate system identifier: `'WGS84'` | `'GCJ02'` | `'BD09'` | `'EPSG3857'`.

## Changelog

See commit history for [src/runtime/utils/coordinate Conversion.ts](https://github.com/mhaibaraai/movk-mapbox/commits/main/src/runtime/utils/coordinate Conversion.ts).

---

- [gcoord](https://github.com/hujiulong/gcoord)


## Sitemap

See the full [sitemap](https://mapbox.mhaibaraai.cn/sitemap.md) for all pages.
