uniappx 开发微信小程序 腾讯地图偏移量计算

javascript 复制代码
// utils/coordTransform.uts

/**
 * 坐标转换工具类
 * 提供WGS84与腾讯地图坐标系之间的高精度转换
 */
class CoordTransform {
    
    // 定义常量
    private static readonly a: number = 6378245.0
    private static readonly ee: number = 0.00669342162296594323
    private static readonly pi: number = 3.1415926535897932384626
    
    /**
     * WGS84转腾讯地图坐标系(GCJ02)
     * @param wgLat WGS84纬度
     * @param wgLon WGS84经度
     * @returns 腾讯地图坐标系 { lat: number, lng: number }
     */
    static wgs84ToTencent(wgLat: number, wgLon: number): { lat: number, lng: number } {
        // 如果坐标在国外,直接返回
        if (!this.isInChina(wgLon, wgLat)) {
            return { lat: wgLat, lng: wgLon }
        }
        
        let dLat = this.transformLat(wgLon - 105.0, wgLat - 35.0)
        let dLng = this.transformLng(wgLon - 105.0, wgLat - 35.0)
        let radLat = wgLat / 180.0 * this.pi
        let magic = Math.sin(radLat)
        magic = 1 - this.ee * magic * magic
        let sqrtMagic = Math.sqrt(magic)
        dLat = (dLat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtMagic) * this.pi)
        dLng = (dLng * 180.0) / (this.a / sqrtMagic * Math.cos(radLat) * this.pi)
        
        const mgLat = wgLat + dLat
        const mgLng = wgLon + dLng
        
        return { 
            lat: Number(mgLat.toFixed(6)), 
            lng: Number(mgLng.toFixed(6))
        }
    }
    
    /**
     * 腾讯地图坐标系转WGS84(使用高精度算法)
     * @param tcLat 腾讯地图纬度
     * @param tcLon 腾讯地图经度
     * @returns WGS84坐标系 { lat: number, lng: number }
     */
    static tencentToWgs84(tcLat: number, tcLon: number): { lat: number, lng: number } {
        // 如果坐标在国外,直接返回
        if (!this.isInChina(tcLon, tcLat)) {
            return { lat: tcLat, lng: tcLon }
        }
        
        // 使用高精度迭代算法
        let wgsLat = tcLat
        let wgsLng = tcLon
        
        for (let i = 0; i < 5; i++) {
            const gcj02 = this.wgs84ToTencent(wgsLat, wgsLng)
            const deltaLat = tcLat - gcj02.lat
            const deltaLng = tcLon - gcj02.lng
            
            wgsLat += deltaLat
            wgsLng += deltaLng
            
            // 如果误差已经很小,提前结束
            if (Math.abs(deltaLat) < 1e-7 && Math.abs(deltaLng) < 1e-7) {
                break
            }
        }
        
        return {
            lat: Number(wgsLat.toFixed(6)),
            lng: Number(wgsLng.toFixed(6))
        }
    }
    
    /**
     * 批量转换坐标(内部使用高精度转换)
     * @param devices 设备数组
     * @param targetSystem 目标坐标系 'tencent' | 'wgs84'
     * @returns 转换后的设备数组
     */
    static batchConvertCoordinates(devices: Array<any>, targetSystem: string = 'tencent'): Array<any> {
        if (!Array.isArray(devices)) return []
        
        return devices.map(device => {
            if (!device) return device
            
            const lat = Number(device.latitude)
            const lng = Number(device.longitude)
            
            if (isNaN(lat) || isNaN(lng)) {
                console.warn('设备经纬度无效', device)
                return device
            }
            
            let converted
            if (targetSystem === 'tencent') {
                // WGS84转腾讯地图
                converted = this.wgs84ToTencent(lat, lng)
            } else {
                // 腾讯地图转WGS84(使用高精度算法)
                converted = this.tencentToWgs84(lat, lng)
            }
            
            return {
                ...device,
                latitude: converted.lat,
                longitude: converted.lng,
                originalLatitude: lat, // 保留原始坐标
                originalLongitude: lng
            }
        })
    }
    
    /**
     * 转换单个坐标点(内部使用高精度转换)
     * @param lat 纬度
     * @param lng 经度
     * @param fromSystem 原坐标系 'wgs84' | 'tencent'
     * @param toSystem 目标坐标系 'tencent' | 'wgs84'
     * @returns 转换后的坐标 { lat: number, lng: number }
     */
    static convertCoordinate(lat: number, lng: number, fromSystem: string = 'wgs84', toSystem: string = 'tencent'): { lat: number, lng: number } {
        if (fromSystem === 'wgs84' && toSystem === 'tencent') {
            return this.wgs84ToTencent(lat, lng)
        } else if (fromSystem === 'tencent' && toSystem === 'wgs84') {
            return this.tencentToWgs84(lat, lng)
        } else {
            console.warn('不支持的坐标系转换', fromSystem, '->', toSystem)
            return { lat, lng }
        }
    }
    
    /**
     * 检查坐标是否在中国境内
     * @param lat 纬度
     * @param lng 经度
     * @returns 是否在中国境内
     */
    static isInChina(lng: number, lat: number): boolean {
        return lng >= 72.004 && lng <= 137.8347 && lat >= 0.8293 && lat <= 55.8271
    }
    
    // 私有方法:纬度转换
    private static transformLat(x: number, y: number): number {
        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 * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0
        ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0
        ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0
        return ret
    }
    
    // 私有方法:经度转换
    private static transformLng(x: number, y: number): number {
        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 * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0
        ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0
        ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0
        return ret
    }
}

// 导出工具类
export default CoordTransform

使用方法:

javascript 复制代码
//页面里引入插件
import CoordTransform from '../../utils/coordTransform.uts'
//使用
const getLatLog = CoordTransform.wgs84ToTencent(latitude, longitude)

console.log(getLatLog)
相关推荐
Chloe.Zz13 分钟前
微信小程序接入大模型实战 4:塔罗咨询室(含代码)
语言模型·微信小程序·小程序
风月歌40 分钟前
小程序项目之“健康早知道”微信小程序源码(java+小程序+mysql)
java·微信小程序·小程序·毕业设计·源码
ee82ee17 小时前
uniapp小程序底部键盘唤起问题处理,包含间隙处理,动画处理
微信小程序
qq_124987075318 小时前
基于springboot健康养老APP的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·mysql·微信小程序·毕业设计
夏源19 小时前
【微信小程序】实现引入 Echarts 并实现更新数据
微信小程序
猿究院_xyz20 小时前
微信小程序与echarts联动安卓真机测试出现黑色阴影
前端·javascript·微信小程序·小程序·echarts
李慕婉学姐1 天前
基于微信小程序的运动会信息管理系统k6kqgy34(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·微信小程序·小程序
咸虾米_1 天前
uniapp+unicloud实战项目,九两酒微信小程序商城及后台管理系统前后端部署运行步骤
微信小程序·uni-app·uniapp实战项目·unicloud云开发·vue3后台管理
阿里巴巴AI编程社区2 天前
用Qoder打造自己的AI工作台,普通人也可10倍提效!
微信小程序
wangpq2 天前
记录曾经打开半屏小程序遇到的事
前端·微信小程序