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}; }
根据使用的环境判断应该使用哪种坐标系,然后调用对应方法转换后再撒点,点位就显示正常了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理