#ol加载百度离线地图坐标不准确问题
最近由于项目需要,在使用ol加载百度离线地图时候,发现通过ol加载的百度地图,显示的坐标不准确,请看下图
通过以上可以发现百度坐标拾取中获取到的天安门坐标是116.403119,39.912721,而ol加载的坐标确是116.4052,39.7240,纬度相差了0.2,偏差了很大,经过查看网上的一些资料,发现ol加载的默认坐标是EPSG:3857,如果为了显示经纬度直接在加载坐标时候直接写成EPSG:4326就会出现坐标偏差。猜想是不是EPSG:4326是84坐标,而百度是bd09坐标,经过网上查找的方法未果,后来看到网上的一篇博客,对百度原有的js进行了删减,利用百度的js创建新的坐标系,在加载时候使用百度坐标可以达到目的。废话少说,直接上js
var b2, a8 = b2 = a8 || {
version: "1.3.4"
};
a8.guid = "$BAIDU$";
window[a8.guid] = window[a8.guid] || {};
a8.object = a8.object || {};
a8.extend = a8.object.extend = function(cM, T) {
for (var cL in T) {
if (T.hasOwnProperty(cL)) {
cM[cL] = T[cL]
}
}
return cM
};
window.BMap = window.BMap || {};
window.BMap.version = "1.3";
window.BMap._register = [];
window.BMap.register = function(T) {
this._register.push(T)
};
window.BMap.apiLoad = window.BMap.apiLoad || function() {};
window._jsload = function(T, cL) {
cA.run(T, cL)
};
function bu(T, cL) {
this.x = T || 0;
this.y = cL || 0
}
bu.prototype.equals = function(T) {
return T && T.x == this.x && T.y == this.y
};
function cd(T, cL) {
if (isNaN(T)) {
T = bV(T);
T = isNaN(T) ? 0 : T
}
if (b3(T)) {
T = parseFloat(T)
}
if (isNaN(cL)) {
cL = bV(cL);
cL = isNaN(cL) ? 0 : cL
}
if (b3(cL)) {
cL = parseFloat(cL)
}
this.lng = T;
this.lat = cL
}
cd.isInRange = function(T) {
return T && T.lng <= 180 && T.lng >= -180 && T.lat <= 74 && T.lat >= -74
};
cd.prototype.equals = function(T) {
return T && this.lat == T.lat && this.lng == T.lng
};
function bd() {}
bd.prototype.lngLatToPoint = function() {
throw "lngLatToPoint\u65b9\u6cd5\u672a\u5b9e\u73b0"
};
bd.prototype.pointToLngLat = function() {
throw "pointToLngLat\u65b9\u6cd5\u672a\u5b9e\u73b0"
};
function ba() {}
ba.prototype = new bd();
a8.extend(ba, {
EARTHRADIUS: 6370996.81,
MCBAND: [12890594.86, 8362377.87, 5591021, 3481989.83,
1678043.12, 0
],
LLBAND: [75, 60, 45, 30, 15, 0],
MC2LL: [
[1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2],
[-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877,
47.40033549296737, -16.50741931063887,
2.28786674699375, 10260144.86
],
[-3.030883460898826e-8, 0.00000898305509983578,
0.30071316287616, 59.74293618442277,
7.357984074871, -25.38371002664745,
13.45380521110908, -3.29883767235584,
0.32710905363475, 6856817.37
],
[-1.981981304930552e-8, 0.000008983055099779535,
0.03278182852591, 40.31678527705744,
0.65659298677277, -4.44255534477492,
0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06
],
[3.09191371068437e-9, 0.000008983055096812155,
0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4
],
[2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5]
],
LL2MC: [
[-0.0015702102444, 111320.7020616939,
1704480524535203, -10338987376042340,
26112667856603880, -35149669176653700,
26595700718403920, -10725012454188240,
1800819912950474, 82.5
],
[0.0008277824516172526, 111320.7020463578,
647795574.6671607, -4082003173.641316,
10774905663.51142, -15171875531.51559,
12053065338.62167, -5124939663.577472,
913311935.9512032, 67.5
],
[0.00337398766765, 111320.7020202162,
4481351.045890365, -23393751.19931662,
79682215.47186455, -115964993.2797253,
97236711.15602145, -43661946.33752821,
8477230.501135234, 52.5
],
[0.00220636496208, 111320.7020209128,
51751.86112841131, 3796837.749470245,
992013.7397791013, -1221952.21711287,
1340652.697009075, -620943.6990984312,
144416.9293806241, 37.5
],
[-0.0003441963504368392, 111320.7020576856,
278.2353980772752, 2485758.690035394,
6070.750963243378, 54821.18345352118,
9540.606633304236, -2710.55326746645,
1405.483844121726, 22.5
],
[-0.0003218135878613132, 111320.7020701615,
0.00369383431289, 823725.6402795718,
0.46104986909093, 2351.343141331292,
1.58060784298199, 8.77738589078284,
0.37238884252424, 7.45
]
],
getDistanceByMC: function(cP, cN) {
if (!cP || !cN) {
return 0
}
var cL, cO, T, cM;
cP = this.convertMC2LL(cP);
if (!cP) {
return 0
}
cL = this.toRadians(cP.lng);
cO = this.toRadians(cP.lat);
cN = this.convertMC2LL(cN);
if (!cN) {
return 0
}
T = this.toRadians(cN.lng);
cM = this.toRadians(cN.lat);
return this.getDistance(cL, T, cO, cM)
},
getDistanceByLL: function(cP, cN) {
if (!cP || !cN) {
return 0
}
cP.lng = this.getLoop(cP.lng, -180, 180);
cP.lat = this.getRange(cP.lat, -74, 74);
cN.lng = this.getLoop(cN.lng, -180, 180);
cN.lat = this.getRange(cN.lat, -74, 74);
var cL, T, cO, cM;
cL = this.toRadians(cP.lng);
cO = this.toRadians(cP.lat);
T = this.toRadians(cN.lng);
cM = this.toRadians(cN.lat);
return this.getDistance(cL, T, cO, cM)
},
convertMC2LL: function(cL) {
var cM, cO;
cM = new cd(Math.abs(cL.lng), Math.abs(cL.lat));
for (var cN = 0; cN < this.MCBAND.length; cN++) {
if (cM.lat >= this.MCBAND[cN]) {
cO = this.MC2LL[cN];
break
}
}
var T = this.convertor(cL, cO);
var cL = new cd(T.lng.toFixed(6), T.lat.toFixed(6));
return cL
},
convertLL2MC: function(T) {
var cL, cN;
T.lng = this.getLoop(T.lng, -180, 180);
T.lat = this.getRange(T.lat, -74, 74);
cL = new cd(T.lng, T.lat);
for (var cM = 0; cM < this.LLBAND.length; cM++) {
if (cL.lat >= this.LLBAND[cM]) {
cN = this.LL2MC[cM];
break
}
}
if (!cN) {
for (var cM = this.LLBAND.length - 1; cM >= 0; cM--) {
if (cL.lat <= -this.LLBAND[cM]) {
cN = this.LL2MC[cM];
break
}
}
}
var cO = this.convertor(T, cN);
var T = new cd(cO.lng.toFixed(2), cO.lat.toFixed(2));
return T
},
convertor: function(cM, cN) {
if (!cM || !cN) {
return
}
var T = cN[0] + cN[1] * Math.abs(cM.lng);
var cL = Math.abs(cM.lat) / cN[9];
var cO = cN[2] + cN[3] * cL + cN[4] * cL * cL + cN[5] * cL * cL * cL + cN[6] * cL * cL * cL * cL + cN[7] * cL * cL * cL * cL * cL + cN[8] * cL * cL * cL * cL * cL * cL;
T *= (cM.lng < 0 ? -1 : 1);
cO *= (cM.lat < 0 ? -1 : 1);
return new cd(T, cO)
},
getDistance: function(cL, T, cN, cM) {
return this.EARTHRADIUS * Math.acos((Math.sin(cN) * Math.sin(cM) + Math
.cos(cN) * Math.cos(cM) * Math.cos(T - cL)))
},
toRadians: function(T) {
return Math.PI * T / 180
},
toDegrees: function(T) {
return (180 * T) / Math.PI
},
getRange: function(cM, cL, T) {
if (cL != null) {
cM = Math.max(cM, cL)
}
if (T != null) {
cM = Math.min(cM, T)
}
return cM
},
getLoop: function(cM, cL, T) {
while (cM > T) {
cM -= T - cL
}
while (cM < cL) {
cM += T - cL
}
return cM
}
});
a8.extend(ba.prototype, {
lngLatToMercator: function(T) {
return ba.convertLL2MC(T)
},
lngLatToPoint: function(T) {
var cL = ba.convertLL2MC(T);
return new bu(cL.lng, cL.lat)
},
mercatorToLngLat: function(T) {
return ba.convertMC2LL(T)
},
pointToLngLat: function(T) {
var cL = new cd(T.x, T.y);
return ba.convertMC2LL(cL)
},
pointToPixel: function(cL, cP, cO, cN, cQ) {
if (!cL) {
return
}
cL = this.lngLatToMercator(cL, cQ);
var cM = this.getZoomUnits(cP);
var T = Math.round((cL.lng - cO.lng) / cM + cN.width / 2);
var cR = Math.round((cO.lat - cL.lat) / cM + cN.height / 2);
return new bu(T, cR)
},
pixelToPoint: function(T, cS, cO, cM, cL) {
if (!T) {
return
}
var cR = this.getZoomUnits(cS);
var cP = cO.lng + cR * (T.x - cM.width / 2);
var cN = cO.lat - cR * (T.y - cM.height / 2);
var cQ = new cd(cP, cN);
return this.mercatorToLngLat(cQ, cL)
},
getZoomUnits: function(T) {
return Math.pow(2, (18 - T))
}
});
function aj(T, cL) {
window.BMap[T] = cL
}
function b3(T) {
return typeof T == "string"
}
aj("Point", cd);
aj("Pixel", bu);
aj("MercatorProjection", ba);
var projBD09 = new ol.proj.Projection({
code: 'BD:09',
extent: [-20037726.37, -11708041.66, 20037726.37, 12474104.17],
units: 'm',
axisOrientation: 'neu',
global: false
});
ol.proj.addProjection(projBD09);
ol.proj.addCoordinateTransforms("EPSG:3857", "BD:09",
function(coordinate) {
return mercatortoBd09(coordinate[0], coordinate[1]);
},
function(coordinate) {
return bd09toMercator(coordinate[0], coordinate[1]);
}
);
在这个js最后,创建了BD09坐标系,这样我们在创建鼠标位置时候就可以用BD09坐标系了,鼠标显示的位置也正确了。
var mousePositionControl = new ol.control.MousePosition({
//坐标格式
coordinateFormat: ol.coordinate.createStringXY(7),
//地图投影坐标系(若未设置则输出为默认投影坐标系下的坐标)
projection: 'BD:09',
//坐标信息显示样式类名,默认是'ol-mouse-position'
className: 'custom-mouse-position2',
//显示鼠标位置信息的目标容器
target: document.getElementById('mouse-position'),
//未定义坐标的标记
undefinedHTML: ' '
});
/**
* bd09 经纬度坐标转墨卡托坐标。注意这是引用了百度原生的坐标转换,需要对应引入百度离线地图偏移js
* @author lanbizixunlu
* @date 2019-11-21 14:00:21
*/
function bd09toMercator(lng,lat){
if(lng==null||lng==""||lat==null||lat==""){return null;}
var point= new BMap.MercatorProjection().lngLatToPoint(new BMap.Point(lng,lat));
return [point.x,point.y];
}
/**
* 从墨卡托坐标转bd09坐标 。注意这是引用了百度原生的坐标转换,需要对应引入百度离线地图偏移js
* @author lanbizixunlu
* @date 2019-11-21 14:13:00
* @param {Object} x
* @param {Object} y
*/
function mercatortoBd09(x,y){
if(x==null||x==""||y==null||y==""){return null;}
var c=new BMap.MercatorProjection().pointToLngLat(new BMap.Pixel(x,y));
return [c.lng,c.lat];
}
再次显示坐标,可以看到几乎差不多了。
本文如果有侵权,实属抱歉,我必删除此分享。闲暇总结下自己遇到的问题,只为技术交流,希望做ol的的小伙伴们都能互相分享大家遇到的难点,方便自己也方便别人。