rabet
rabet
  • 发布:2016-01-05 10:44
  • 更新:2018-07-30 09:17
  • 阅读:9221

openSysMap调用第三方导航坐标转gps坐标JS,解决坐标偏离问题

分类:HTML5+

调用第三方导航传入的坐标必须是WGS-84 坐标,所以需要将坐标转换成 wgs坐标,下面提供坐标转换的js方法,经过测试,与实际坐标位定位,基本误差不大,可以做导航使用,如项目要求非常精确的位置。我目前项目解决方案是 ,导航到目的地,然后在APP中的地图中查看具体的精确位置。

>
文件请下载附件

WGS-84:是国际标准,GPS坐标(Google Earth使用、或者GPS模块)
GCJ-02:中国坐标偏移标准,Google Map、高德、腾讯使用
BD-09:百度坐标偏移标准,Baidu Map使用

//WGS-84 to GCJ-02
GPS.gcj_encrypt();

//GCJ-02 to WGS-84 粗略
GPS.gcj_decrypt();

//GCJ-02 to WGS-84 精确(二分极限法)
// var threshold = 0.000000001; 目前设置的是精确到小数点后9位,这个值越小,越精确,但是javascript中,浮点运算本身就不太精确,九位在GPS里也偏差不大了
GSP.gcj_decrypt_exact();

//GCJ-02 to BD-09
GPS.bd_encrypt();

//BD-09 to GCJ-02
GPS.bd_decrypt();

//求距离
GPS.distance();

示例:
document.write("GPS: 39.933676862706776,116.35608315379092<br />");
var arr2 = GPS.gcj_encrypt(39.933676862706776, 116.35608315379092);
document.write("中国:" + arr2['lat']+","+arr2['lon']+'<br />');
var arr3 = GPS.gcj_decrypt_exact(arr2['lat'], arr2['lon']);
document.write('逆算:' + arr3['lat']+","+arr3['lon']+' 需要和第一行相似(目前是小数点后9位相等)');

2016-01-05 10:44 2 条评论 负责人:无 分享
已邀请:

最佳回复

老火

老火

很强,刚开始存入库中的全部是BD-0911坐标,直接调用第三方导航后偏差的太严重,现在用这个转换以后导航偏差基本不太大了,下面就附上我的调用方式

//在需要导航的页面引入
<script type="text/javascript" src="gps.js"></script>
//导航 下面的obj是我从数据库中取出来的目的地信息
function navigateWithMap(){
//BD-09 to GCJ-02先将百度坐标转成中国坐标
var tmp = GPS.bd_decrypt(parseFloat(obj.baidu_lat),parseFloat(obj.baidu_lng));
//GCJ-02 to WGS-84再将中国坐标转成GPS坐标
var dstarr = GPS.gcj_decrypt_exact(tmp['lat'],tmp['lon']);

var dst = new plus.maps.Point(dstarr['lon'],dstarr['lat']); //目的地  
var shop = obj.name_info;  
map.showUserLocation( true );  
map.getUserLocation(function(state,pos){  
    if(0==state){  
        var src = new plus.maps.Point(pos.longitude,pos.latitude); //起始地  
        // 调用系统地图显示   
        plus.maps.openSysMap( dst, shop, src );  
    }  
});  

}

  • 7***@qq.com

    obj是在什么地方定义的?

    2016-07-14 11:25

  • 老火

    obj是ajax回来的数据

    2016-08-16 15:50

  • 尔梭

    貌似在IOS上使用系统自带地图导航只能用GCJ-02才准确,用WGS-84偏差太大,但是安卓上必须要用WGS-84才准确

    2016-11-02 09:21

  • 9***@qq.com

    回复 老火:你好,为什么在var tmp = GPS.bd_decrypt(parseFloat(obj.baidu_lat),parseFloat(obj.baidu_lng)); 这一行老是报错呢

    2017-02-16 16:24

  • 9***@qq.com

    能把你的那个gps.js给我吗 我估计是这个原因

    2017-02-16 16:43

小谭

小谭

牛逼

qiuxiaojun

qiuxiaojun - aaaaaa

不错

我本善良

我本善良

谢谢,解决了一直困扰我的问题,现在调用高德导航基本0误差。

  • 9***@qq.com

    你好,我问一下那个导航偏差怎么解决呢

    2017-02-16 16:52

  • 我本善良

    回复 9***@qq.com:

    var GPS = {

    PI : 3.14159265358979324,

    x_pi : 3.14159265358979324 3000.0 / 180.0,

    delta : function (lat, lon)

    {

    // Krasovsky 1940

    //

    // a = 6378245.0, 1/f = 298.3

    // b = a
    (1 - f)

    // ee = (a^2 - b^2) / a^2;

    var a = 6378245.0;

    var ee = 0.00669342162296594323;

    var dLat = this.transformLat(lon - 105.0, lat - 35.0);

    var dLon = this.transformLon(lon - 105.0, lat - 35.0);

    var radLat = lat / 180.0 this.PI;

    var magic = Math.sin(radLat);

    magic = 1 - ee
    magic magic;

    var sqrtMagic = Math.sqrt(magic);

    dLat = (dLat
    180.0) / ((a (1 - ee)) / (magic sqrtMagic) this.PI);

    dLon = (dLon
    180.0) / (a / sqrtMagic Math.cos(radLat) this.PI);

    return {'lat': dLat, 'lon': dLon};

    },

    //WGS-84 to GCJ-02

    gcj_encrypt : function (wgsLat, wgsLon)

    {

    if (this.outOfChina(wgsLat, wgsLon))

    return {'lat': wgsLat, 'lon': wgsLon};


    var d = this.delta(wgsLat, wgsLon);

    return {'lat' : wgsLat + d.lat,'lon' : wgsLon + d.lon};

    },

    //GCJ-02 to WGS-84

    gcj_decrypt : function (gcjLat, gcjLon)

    {

    if (this.outOfChina(gcjLat, gcjLon))

    return {'lat': gcjLat, 'lon': gcjLon};


    var d = this.delta(gcjLat, gcjLon);

    return {'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon};

    },

    //GCJ-02 to WGS-84 exactly

    gcj_decrypt_exact : function (gcjLat, gcjLon) {

    var initDelta = 0.01;

    var threshold = 0.000000001;

    var dLat = initDelta, dLon = initDelta;

    var mLat = gcjLat - dLat, mLon = gcjLon - dLon;

    var pLat = gcjLat + dLat, pLon = gcjLon + dLon;

    var wgsLat, wgsLon, i = 0;

    while (1) {

    wgsLat = (mLat + pLat) / 2;

    wgsLon = (mLon + pLon) / 2;

    var tmp = this.gcj_encrypt(wgsLat, wgsLon)

    dLat = tmp.lat - gcjLat;

    dLon = tmp.lon - gcjLon;

    if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))

    break;


    if (dLat > 0) pLat = wgsLat; else mLat = wgsLat;

    if (dLon > 0) pLon = wgsLon; else mLon = wgsLon;


    if (++i > 10000) break;

    }

    //console.log(i);

    return {'lat': wgsLat, 'lon': wgsLon};

    },

    //GCJ-02 to BD-09

    bd_encrypt : function (gcjLat, gcjLon)

    {

    var x = gcjLon, y = gcjLat;

    var z = Math.sqrt(x x + y y) + 0.00002 Math.sin(y this.x_pi);

    var theta = Math.atan2(y, x) + 0.000003 Math.cos(x this.x_pi);

    bdLon = z Math.cos(theta) + 0.0065;

    bdLat = z
    Math.sin(theta) + 0.006;

    return {'lat' : bdLat,'lon' : bdLon};

    },

    //BD-09 to GCJ-02

    bd_decrypt : function (bdLat, bdLon)

    {

    var x = bdLon - 0.0065, y = bdLat - 0.006;

    var z = Math.sqrt(x x + y y) - 0.00002 Math.sin(y this.x_pi);

    var theta = Math.atan2(y, x) - 0.000003 Math.cos(x this.x_pi);

    var gcjLon = z Math.cos(theta);

    var gcjLat = z
    Math.sin(theta);

    return {'lat' : gcjLat, 'lon' : gcjLon};

    },

    distance : function (latA, logA, latB, logB) {

    var earthR = 6371000;

    var x = Math.cos(latAMath.PI/180) Math.cos(latBMath.PI/180) Math.cos((logA-logB)Math.PI/180);

    var y = Math.sin(latA
    Math.PI/180) Math.sin(latBMath.PI/180);

    var s = x + y;

    if (s > 1)

    s = 1;

    if (s < -1)

    s = -1;

    var alpha = Math.acos(s);

    var distance = alpha earthR;

    return distance;

    },

    outOfChina : function (lat, lon)

    {

    if (lon < 72.004 || lon > 137.8347)

    return true;

    if (lat < 0.8293 || lat > 55.8271)

    return true;

    return false;

    },

    transformLat : function (x, y)

    {

    var ret = -100.0 + 2.0
    x + 3.0 y + 0.2 y y + 0.1 x y + 0.2 Math.sqrt(Math.abs(x));

    ret += (20.0 Math.sin(6.0 x this.PI) + 20.0 Math.sin(2.0 x this.PI)) 2.0 / 3.0;

    ret += (20.0
    Math.sin(y this.PI) + 40.0 Math.sin(y / 3.0 this.PI)) 2.0 / 3.0;

    ret += (160.0 Math.sin(y / 12.0 this.PI) + 320 Math.sin(y this.PI / 30.0)) 2.0 / 3.0;

    return ret;

    },

    transformLon : function (x, y)

    {

    var ret = 300.0 + x + 2.0
    y + 0.1 x x + 0.1 x y + 0.1 Math.sqrt(Math.abs(x));

    ret += (20.0
    Math.sin(6.0 x this.PI) + 20.0 Math.sin(2.0 x this.PI)) 2.0 / 3.0;

    ret += (20.0 Math.sin(x this.PI) + 40.0 Math.sin(x / 3.0 this.PI)) 2.0 / 3.0;

    ret += (150.0
    Math.sin(x / 12.0 this.PI) + 300.0 Math.sin(x / 30.0 this.PI)) 2.0 / 3.0;

    return ret;

    }

    };


    //选项卡点击事件

    mui('.mui-bar').on('tap', 'a', function(e) {

    var targetTab = this.getAttribute('id');

    if(targetTab == "map")

    {

    if(Coordinates == "")

    {

    mui.toast("对不起,当前客户没有标注坐标信息!");

    }

    else

    {

    ///调用第三方导航

    var map = Coordinates.split(",");

    var lon = map[0];

    var lat = map[1];

    //BD-09 to GCJ-02先将百度坐标转成中国坐标

    var gcj02 = GPS.bd_decrypt(parseFloat(lat),parseFloat(lon));

    //GCJ-02 to WGS-84再将中国坐标转成GPS坐标

    var dstarr = GPS.gcj_decrypt_exact(gcj02['lat'],gcj02['lon']);

    plus.maps.openSysMap( new plus.maps.Point(dstarr['lon'],dstarr['lat']), CustomerName, new plus.maps.Point() );

    }

    }

    });

    2017-03-15 15:39

z***@d-heaven.com

z***@d-heaven.com

大腿,mark,百度有误差怎么处理 跪求

rabet

rabet (作者) - 开发,技术服务

误差超过500m,那就在检查检查代码,误差在10米内,我也没招,

moon小Z

moon小Z

误差十米以内 感谢大神

binladen

binladen

点100个赞

251378520

251378520

来个脚印

紫月

紫月

如果用户没有安装地图软件,我怎么提醒用户?

  • rabet (作者)

    打开第三方导航的代码,会弹出导航app列表,如没有,用户自感是否装一个吧

    2018-08-03 09:12

cxian

cxian -

mark

该问题目前已经被锁定, 无法添加新回复