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)
相关推荐
星光一影5 小时前
打车/网约车、代驾、顺风车/拼车、货运、租车等多种出行服务的一站式解决方案
mysql·微信小程序·php·uniapp·html5·web app
QuantumLeap丶8 小时前
《uni-app跨平台开发完全指南》- 04 - 页面布局与样式基础
vue.js·微信小程序·uni-app
www_stdio9 小时前
微信小程序入门:从零构建一个 Blog 小程序
微信·微信小程序
inx17710 小时前
微信小程序开发实战:从结构到数据绑定的完整实现
javascript·微信小程序
云起SAAS1 天前
黄历万年历择吉日抖音快手微信小程序看广告流量主开源
微信小程序·小程序·ai编程·看广告变现轻·黄历万年历择吉日
腾讯云云开发1 天前
小程序数据库权限管理,一看就会!——CloudBase新手指南
前端·数据库·微信小程序
有点笨的蛋1 天前
从零搭建小程序首页:新手也能看懂的结构解析与实战指南
前端·微信小程序
一只小白菜~1 天前
记录一下微信小程序里使用SSE
微信小程序·小程序·sse·小程序sse·小程序eventsource
李慕婉学姐1 天前
【开题答辩过程】以《基于微信小程序垃圾分类图像识别技术实现》为例,不会开题答辩的可以进来看看
spring boot·微信小程序·vue