百度地图是国内使用最广泛的地图服务之一,但在OpenLayers中加载百度瓦片并正确放置BD09坐标数据,涉及坐标系转换和瓦片坐标适配两个核心问题。本文基于实际项目代码,详细讲解如何在Vue3 + OpenLayers项目中加载百度瓦片地图,并使用gcoord库实现BD09坐标的准确投放。

一、核心问题分析

1.1 为什么百度地图不能直接加载?

百度地图存在两层特殊性

  1. 瓦片坐标系特殊:百度地图的瓦片编号规则与标准XYZ方案不同——Y轴从下到上递增(标准是从上到下),且起始编号为1(标准从0开始),负数用"M"前缀表示。
  2. 坐标系加密:百度使用BD09坐标系,是在GCJ02(国测局坐标系)基础上进一步偏移的坐标系。OpenLayers默认使用EPSG:3857(Web墨卡托),两者之间需要转换。

1.2 两种转换需求

转换类型 说明 用途
瓦片坐标转换 OpenLayers瓦片编号 → 百度瓦片编号 加载百度瓦片底图
地理坐标转换 BD09经纬度 → BD09MC(百度墨卡托) 在百度底图上正确放置要素

二、百度瓦片加载:BaiduSource封装

2.1 瓦片坐标转换原理

百度地图的瓦片坐标转换核心公式:

baiduY = -openLayersY - 1
baiduX = openLayersX < 0 ? 'M' + (-openLayersX) : openLayersX
finalY = baiduY < 0 ? 'M' + (-baiduY) : baiduY

OpenLayers的Y轴从上往下递增,百度从下往上递增,且起始偏移1位。负数情况下百度要求用"M"前缀表示。

2.2 使用方式

import Map from 'ol/Map'
import View from 'ol/View'
import TileLayer from 'ol/layer/Tile'
import {createBDXYZSource} from './utils/BaiduSource.js'

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: createBDXYZSource({
        url: 'http://online3.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=20151021'
      })
    })
  ],
  view: new View({
    center: [116.404, 39.915], // 注意:这里需要是BD09MC坐标
    zoom: 10,
    projection: 'EPSG:3857'
  })
})

三、BD09坐标转换:gcoord的使用

3.1 为什么需要坐标转换?

OpenLayers中设置地图中心点和添加矢量要素时,传入的坐标必须与底图的投影体系匹配。百度瓦片底图虽然使用EPSG:3857作为投影,但其瓦片偏移是基于百度自有坐标系计算的,因此中心点和要素坐标也需要使用百度的墨卡托坐标(BD09MC)

3.2 gcoord坐标转换库

项目使用gcoord进行坐标转换,它支持多种中国常用坐标系之间的相互转换:

npm install gcoord

支持的坐标系

坐标系标识 说明
BD09 百度经纬度坐标
BD09MC 百度墨卡托坐标
GCJ02 国测局坐标(高德、腾讯使用)
WGS84 GPS原始坐标(国际标准)
EPSG:4326 WGS84经纬度
EPSG:3857 Web墨卡托

3.3 转换示例

import gcoord from 'gcoord'

// 百度经纬度 → 百度墨卡托
const bd09MC = gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC)
// 结果: [12958575.92, 4826387.62](近似值)

// WGS84 → BD09
const bd09 = gcoord.transform([116.404, 39.915], gcoord.WGS84, gcoord.BD09)

// GCJ02 → BD09
const bd09FromGcj = gcoord.transform([116.404, 39.915], gcoord.GCJ02, gcoord.BD09)

关键点:使用百度瓦片底图时,地图中心点和所有要素坐标都必须转换为BD09MC坐标,否则会出现位置偏移。


四、完整Vue3组件实现

以下是基于项目ol-bd-baidu.vue的完整实现,包含百度底图加载和BD09坐标验证:

<template>
  <div class="wh100" ref="olMapRef"></div>
</template>

<script setup>
import {ref, onMounted} from 'vue'
import Map from 'ol/Map'
import View from 'ol/View'
import TileLayer from 'ol/layer/Tile'
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import {GeoJSON} from 'ol/format'
import gcoord from 'gcoord'
import {createBDXYZSource} from './utils/BaiduSource.js'

const olMapRef = ref(null)

onMounted(() => {
  const map = new Map({
    target: olMapRef.value,
    layers: [
      new TileLayer({
        source: createBDXYZSource({
          url: 'http://online3.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=pl&udt=20151021'
        })
      })
    ],
    view: new View({
      // 坐标需要转换:BD09经纬度 → BD09MC墨卡托
      center: gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC),
      zoom: 10,
      projection: 'EPSG:3857'
    })
  })

  // GeoJSON数据中的坐标也需要转换
  let geoJsonData = {
    "type": "FeatureCollection",
    "features": [
      {
        "type": "Feature",
        "id": 1,
        "properties": {
          "name": '',
          "level": 10,
          "zIndex": 200
        },
        "geometry": {
          "type": "Point",
          "coordinates": gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC)
        }
      }
    ]
  }

  // 添加矢量图层验证坐标是否准确
  const layer = new VectorLayer({
    source: new VectorSource({
      features: new GeoJSON({}).readFeatures(geoJsonData)
    })
  })

  map.addLayer(layer)
})
</script>

百度原始坐标位置
百度地图
openlayers+百度瓦片包
openlayers加载

4.1 代码要点解析

1. 地图初始化

center: gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC)

将百度经纬度 [116.404, 39.915] 转换为百度墨卡托坐标,作为地图中心点。

2. 要素坐标转换

"coordinates": gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC)

GeoJSON中的坐标同样需要转换为BD09MC,确保要素与底图对齐。

3. 坐标验证
通过在相同坐标位置添加一个点要素,可以直观验证底图加载和坐标转换是否正确——如果点标记准确落在目标位置上,说明转换逻辑正确。


五、常见问题与排查

5.1 地图加载但位置偏移

原因:中心点坐标未转换为BD09MC。

// 错误:直接使用百度经纬度
center: [116.404, 39.915]

// 正确:转换为百度墨卡托
center: gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC)

5.2 矢量要素与底图不对齐

原因:GeoJSON中的坐标未进行相同的坐标转换。

// 错误:使用原始经纬度
"coordinates": [116.404, 39.915]

// 正确:转换为BD09MC
"coordinates": gcoord.transform([116.404, 39.915], gcoord.BD09, gcoord.BD09MC)

5.3 瓦片加载不出来

排查步骤

  1. 检查控制台是否有跨域错误,确认是否设置了crossOrigin: 'anonymous'
  2. 确认瓦片URL模板格式正确,占位符为{x}{y}{z}
  3. 确认缩放级别在百度地图支持范围内(0-18级)

5.4 使用其他坐标系的数据

如果数据来源不是百度坐标系,需要先转换:

import gcoord from 'gcoord'

// WGS84(GPS数据)→ BD09MC
const bd09MC = gcoord.transform([116.404, 39.915], gcoord.WGS84, gcoord.BD09MC)

// GCJ02(高德/腾讯数据)→ BD09MC
const fromGcj = gcoord.transform([116.404, 39.915], gcoord.GCJ02, gcoord.BD09MC)

六、总结

6.1 核心要点

步骤 说明
1. 封装百度瓦片Source 使用createBDXYZSource处理瓦片坐标转换
2. 坐标转换 所有坐标使用gcoord.transform从BD09转为BD09MC
3. 地图中心点 必须使用BD09MC坐标
4. 要素坐标 GeoJSON等数据中的坐标同样需要转换
5. 坐标验证 添加点要素验证底图与数据是否对齐

6.2 坐标转换速查

import gcoord from 'gcoord'

// 百度经纬度 → 百度墨卡托(用于百度底图)
gcoord.transform([lng, lat], gcoord.BD09, gcoord.BD09MC)

// WGS84 → 百度墨卡托
gcoord.transform([lng, lat], gcoord.WGS84, BD09MC)

// GCJ02 → 百度墨卡托
gcoord.transform([lng, lat], gcoord.GCJ02, BD09MC)

更新日期:2026年8月
调试版本:OpenLayers 10.9.0

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐