前言

由于百度仅支持别的坐标系的坐标转换为百度坐标并且在百度地图上显示,但我们在实际的业务需求是,我们利用百度地图去安装设备,需要将百度坐标转换为WGS84坐标并显示到诸如天地图上。

官方说明

这里我们贴一张关于国内常见的坐标系的说明:这个也是截图自百度示例说明。

国内常用地图所用的坐标系

因此,本文将利用三方库coordtransformgcoord来纠偏百度坐标,坐标点采集自百度提供的坐标拾取系统,然后将坐标系从BD09转换为WGS84,通过实际的对比看看三方库的纠偏效果。

测试方法

我们分别在左右两侧加载百度地图和天地图,左侧添加百度自家的点 Overlay,坐标用的就是初始的百度坐标,右侧添加 Openlayers 实现的 Icon 图标,分别添加未纠偏的 Icon 点和纠偏后的 Icon 点,然后对比纠偏后的Icon点和在百度地图上的点位置。我这里采集了34个省会城市、直辖市、自治区的比较好辨认的 poi 坐标点。先说结论:纠偏比较准确,肉眼基本看不出来有多少误差

我这里将百度地图的缩放等级设置为16,经过反复调整,天地图在缩放等级为14.4时比较接近百度地图的缩放。

我直接将结果都截图:经过我反复测试,两个三方库纠偏效果都挺准确的,肉眼看不出来有多少误差。

北京天安门

哈尔滨太阳岛国家湿地公园

长春市南湖公园

辽宁市图书馆

天津水上公园

呼和浩特成吉思汗公园

乌鲁木齐市政府

银川市宝湖公园

西宁市体育公园

兰州站

西安世博园

拉萨滨河公园

成都东湖公园

重庆园博园

贵阳首开紫郡

昆明小白龙森林公园

太原晋阳湖公园

石家庄西三教

济南趵突泉

郑州市人民公园

合肥天鹅湖体育公园

南京八卦洲

上海长风公园

武汉梦泽湖公园

长沙秀峰山公园

南昌青山湖风景区

杭州东站

福州晋安公园

台北南港展览馆站

南宁金湖广场

海口恒大旅游城

广州越秀公园

香港山顶公园

澳门国际机场

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<template>
<div class="wrap">
<div class="bd" ref="bdDivRef"></div>
<div class="divider"></div>
<div class="tdt">
<TdtMap @mapCreated="mapCreated" />
</div>
<!-- 下拉框 -->
<el-select
class="select"
v-model="id"
placeholder="空"
@change="handleSelectChange">
<el-option
v-for="item in options"
:key="item.id"
:label="item.label"
:value="item.id" />
</el-select>
</div>
</template>

<script setup>
import { AddLocation } from "@/utils/utils.js";
import coordtransform from "coordtransform";
import gcoord from "gcoord";

//#region --------------------- 定义变量----------------
const bdDivRef = ref();

let bdMap, bdMarker;

let tdtMap, addLocationInstance;

const id = ref("1");
const center = ref([116.404, 39.915]);

/**
* 下列坐标利用百度拾取坐标系统拾取的坐标。
* 访问地址:https://api.map.baidu.com/lbsapi/getpoint/
*/
const options = [
{ id: "1", label: "北京天安门", value: [116.404, 39.915] },
{
id: "2",
label: "哈尔滨太阳岛国家湿地公园",
value: [126.544486, 45.801535],
},
{ id: "3", label: "长春市南湖公园", value: [125.314365, 43.862527] },
{ id: "4", label: "辽宁市图书馆", value: [123.458123, 41.684045] },
{ id: "5", label: "天津水上公园", value: [117.172877, 39.093623] },
{ id: "6", label: "呼和浩特成吉思汗公园", value: [111.717666, 40.865822] },
{ id: "7", label: "乌鲁木齐市政府", value: [87.623272, 43.831565] },
{ id: "8", label: "银川市宝湖公园", value: [106.260271, 38.457067] },
{ id: "9", label: "西宁市体育公园", value: [101.750095, 36.665025] },
{ id: "10", label: "兰州站", value: [103.856768, 36.039997] },
{ id: "11", label: "西安世博园", value: [109.06461, 34.32843] },
{ id: "12", label: "拉萨滨河公园", value: [91.107169, 29.651013] },
{ id: "13", label: "成都东湖公园", value: [104.094448, 30.622388] },
{ id: "14", label: "重庆园博园", value: [106.55815, 29.687418] },
{ id: "15", label: "贵阳首开紫郡", value: [106.772919, 26.548091] },
{ id: "16", label: "昆明小白龙森林公园", value: [103.100742, 24.939493] },
{ id: "17", label: "太原晋阳湖公园", value: [112.51414, 37.772326] },
{ id: "18", label: "石家庄西三教", value: [114.483763, 38.023109] },
{ id: "19", label: "济南趵突泉", value: [117.022339, 36.665586] },
{ id: "20", label: "郑州市人民公园", value: [113.669142, 34.768246] },
{ id: "21", label: "合肥天鹅湖体育公园", value: [117.231429, 31.817742] },
{ id: "22", label: "南京八卦洲", value: [118.798802, 32.157515] },
{ id: "23", label: "上海长风公园", value: [121.406232, 31.231112] },
{ id: "24", label: "武汉梦泽湖公园", value: [114.249998, 30.597099] },
{ id: "25", label: "长沙秀峰山公园", value: [112.983558, 28.296357] },
{ id: "26", label: "南昌青山湖风景区", value: [115.942486, 28.706438] },
{ id: "27", label: "杭州东站", value: [120.219175, 30.29681] },
{ id: "28", label: "福州晋安公园", value: [119.352338, 26.097562] },
{ id: "29", label: "台北南港展览馆站", value: [121.628112, 25.05792] },
{ id: "30", label: "南宁金湖广场", value: [108.376787, 22.819808] },
{ id: "31", label: "海口恒大旅游城", value: [110.350014, 19.963868] },
{ id: "32", label: "广州越秀公园", value: [113.272148, 23.146901] },
{ id: "33", label: "香港山顶公园", value: [114.155718, 22.277579] },
{ id: "34", label: "澳门国际机场", value: [113.588002,22.16052] },
];
//#endregion

//#region ----------------入口函数----------------
function mapCreated(map) {
tdtMap = map;
createBdMap();
addLocationInstance = new AddLocation(tdtMap);
addTdtMarker(center.value);
}
//#endregion

//#region --------------------- 方法区域----------------
function createBdMap() {
bdMap = new BMapGL.Map(bdDivRef.value);
bdMap.enableScrollWheelZoom(true);

addBdMarker(center.value);
}

function handleSelectChange(id) {
center.value = options.find((item) => item.id === id).value;
addBdMarker(center.value);
addTdtMarker(center.value);
}

function addTdtMarker(lngLat) {
if (addLocationInstance) {
addLocationInstance.clear();
}

tdtMap.getView().animate({ zoom: 14.4 });
//添加百度坐标点标记
addLocationInstance.add(lngLat, "百度坐标");

//添加第三方API转换的坐标的点标记
const wgs84LngLat = convertBdToWgs84(lngLat);
addLocationInstance.add(wgs84LngLat, "纠偏后的百度坐标", true);
}

function addBdMarker(lngLat) {
if (bdMarker) {
bdMap.clearOverlays();
}
const point = new BMapGL.Point(...lngLat);
bdMap.centerAndZoom(point, 15);
bdMarker = new BMapGL.Marker(new BMapGL.Point(...lngLat));
bdMap.addOverlay(bdMarker);
}

// function convertBdToWgs84(lngLat) {
// const gcj02LngLat = coordtransform.bd09togcj02(...lngLat);
// return coordtransform.gcj02towgs84(...gcj02LngLat);
// }

function convertBdToWgs84(lngLat) {
return gcoord.transform(lngLat, gcoord.BD09, gcoord.WGS84);
}
//#endregion
</script>

<style lang="scss" scoped>
.wrap {
height: 100%;
display: flex;
overflow: hidden;

.divider {
height: 100%;
border-right: 2px solid red;
}

.bd,
.tdt {
height: 100%;
width: calc(50% - 1px);
}

.select {
position: absolute;
top: 10px;
right: 10px;
width: 270px;
}
}
</style>

补充

上述我们利用两个方法来借助两个三方库来实现坐标转换,运行代码我们要注释掉其中之一。

注:通过对比源码都是将坐标先转为gcj02(火星坐标系),然后再转为84坐标。

1
2
3
4
5
6
7
8
function convertBdToWgs84(lngLat) {
const gcj02LngLat = coordtransform.bd09togcj02(...lngLat);
return coordtransform.gcj02towgs84(...gcj02LngLat);
}

function convertBdToWgs84(lngLat) {
return gcoord.transform(lngLat, gcoord.BD09, gcoord.WGS84);
}

按照官方的示例引入百度地图api之后,控制台会报如下警告信息,这里我们可以将引入链接改为如下即可解决:即将原来的?前的api改为getscript即可。

1
2
3
<script type="text/javascript"
src="https://api.map.baidu.com/getscript?v=1.0&&type=webgl&ak=你的秘钥">
</script>

参考资料

  1. https://www.npmjs.com/package/coordtransform
  2. https://www.npmjs.com/package/gcoord
  3. https://api.map.baidu.com/lbsapi/getpoint/
  4. https://lbs.baidu.com/index.php?title=jspopularGL/guide/helloworld
  5. https://lbs.baidu.com/index.php?title=jspopularGL/guide/addOverlay
  6. https://lbs.baidu.com/index.php?title=jspopularGL/guide/addOverlay
  7. https://lbs.baidu.com/index.php?title=jspopularGL/guide/coorinfo
  8. https://lbsyun.baidu.com/jsdemo.htm#TranslateggTobd