WGS84坐标系与GCJ02坐标系相互转换

  最近项目中使用腾讯地图,由于生产环境使用的是私有部署版本,而测试环境使用的是共有云版本,两个版本使用的地图坐标系不同(私有部署的版本使用的 WGS84坐标系 而公有云版本使用的是 GCJ02坐标系 )导致撒点有便宜,虽然腾讯官方提供了地图转换接口WebService API | 腾讯位置服务 (qq.com) 但是公有云版本阉割了接口的能力,而且每次都需要取出数据后再通过一次地图接口响应,撒点速度会受响应时间影响,所以找到了一个JavaScript脚本可以通过前端直接转换两个坐标系,代码如下

复制代码
    // 定义一些常量
    const pi = 3.14159265358979324;
    const a = 6378245.0;
    const ee = 0.00669342162296594323;

    // 判断是否在中国境内
    function outOfChina(lat, lon) {
        if (lon < 72.004 || lon > 137.8347) {
            return true;
        }
        if (lat < 0.8293 || lat > 55.8271) {
            return true;
        }
        return false;
    }

    // 转换经度
    function transformLon(x, y) {
        let 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 * pi) +
                    20.0 * Math.sin(2.0 * x * pi)) *
                2.0) /
            3.0;
        ret +=
            ((20.0 * Math.sin(x * pi) + 40.0 * Math.sin((x / 3.0) * pi)) * 2.0) / 3.0;
        ret +=
            ((150.0 * Math.sin((x / 12.0) * pi) +
                    300.0 * Math.sin((x / 30.0) * pi)) *
                2.0) /
            3.0;
        return ret;
    }

    // 转换纬度
    function transformLat(x, y) {
        let 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 * pi) +
                    20.0 * Math.sin(2.0 * x * pi)) *
                2.0) /
            3.0;
        ret +=
            ((20.0 * Math.sin(y * pi) + 40.0 * Math.sin((y / 3.0) * pi)) * 2.0) / 3.0;
        ret +=
            ((160.0 * Math.sin((y / 12.0) * pi) +
                    320 * Math.sin((y * pi) / 30.0)) *
                2.0) /
            3.0;
        return ret;
    }

    // WGS84坐标系转GCJ02坐标系
    function wgs84ToGcj02(wgsLat, wgsLon) {
        if (outOfChina(wgsLat, wgsLon)) {
            return [wgsLat, wgsLon];
        }
        let dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0);
        let dLon = transformLon(wgsLon - 105.0, wgsLat - 35.0);
        const radLat = (wgsLat / 180.0) * pi;
        let magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        const sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * pi);
        dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * pi);
        const gcjLat = wgsLat + dLat;
        const gcjLon = wgsLon + dLon;
        return {latitude:gcjLat,longitude: gcjLon};
    }

    // GCJ02坐标系转WGS84坐标系
    function gcj02ToWgs84(gcjLat, gcjLon) {
        if (outOfChina(gcjLat, gcjLon)) {
            return [gcjLat, gcjLon];
        }
        let dLat = transformLat(gcjLon - 105.0, gcjLat - 35.0);
        let dLon = transformLon(gcjLon - 105.0, gcjLat - 35.0);
        const radLat = (gcjLat / 180.0) * pi;
        let magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        const sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * pi);
        dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * pi);
        const wgsLat = gcjLat - dLat;
        const wgsLon = gcjLon - dLon;
        return {latitude:wgsLat, longitude: wgsLon};
    }
复制代码

 

根据使用的环境判断应该使用哪种坐标系,然后调用对应方法转换后再撒点,点位就显示正常了。

posted @   安培昌浩  阅读(2753)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示