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)
相关推荐
程序媛徐师姐3 小时前
Java基于微信小程序的模拟考试系统,附源码+文档说明
java·微信小程序·java模拟考试系统小程序·模拟考试微信小程序·模拟考试系统小程序·模拟考试小程序·java模拟考试小程序
大尚来也3 小时前
微信小程序开发费用全解析:从SaaS到定制的多元选择
微信小程序
如果你好4 小时前
UniApp 路由导航守卫
前端·微信小程序
大尚来也6 小时前
小程序怎么开发自己的小程序
微信小程序
码云数智-园园6 小时前
小程序开发平台有哪些?小程序第三方开发平台评测对比
微信小程序
2501_933907211 天前
深圳本凡科技专业企业APP开发,助力手机应用创新优化
科技·微信小程序·小程序
java1234_小锋1 天前
分享一套优质的微信小程序校园志愿者系统(SpringBoot后端+Vue3管理端)
微信小程序·小程序·校园志愿者
“负拾捌”2 天前
python + uniapp 结合腾讯云实现实时语音识别功能(WebSocket)
python·websocket·微信小程序·uni-app·大模型·腾讯云·语音识别
换日线°3 天前
NFC标签打开微信小程序
前端·微信小程序
菜鸟una3 天前
【微信小程序+Taro 3+NutUI 3】input (nut-input) 、 textarea (nut-texteare)类型使用避坑
前端·vue.js·微信小程序·小程序·taro