OpenLayers 加载百度地图与百度坐标转换实战(04)
百度地图是国内使用最广泛的地图服务之一,但在OpenLayers中加载百度瓦片并正确放置BD09坐标数据,涉及坐标系转换和瓦片坐标适配两个核心问题。本文基于实际项目代码,详细讲解如何在Vue3 + OpenLayers项目中加载百度瓦片地图,并使用
gcoord库实现BD09坐标的准确投放。
一、核心问题分析
1.1 为什么百度地图不能直接加载?
百度地图存在两层特殊性:
- 瓦片坐标系特殊:百度地图的瓦片编号规则与标准XYZ方案不同——Y轴从下到上递增(标准是从上到下),且起始编号为1(标准从0开始),负数用"M"前缀表示。
- 坐标系加密:百度使用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+百度瓦片包
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 瓦片加载不出来
排查步骤:
- 检查控制台是否有跨域错误,确认是否设置了
crossOrigin: 'anonymous' - 确认瓦片URL模板格式正确,占位符为
{x}、{y}、{z} - 确认缩放级别在百度地图支持范围内(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
更多推荐



所有评论(0)