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)
相关推荐
laboratory agent开发1 天前
多维度拆解小程序平台:数字化经营工具的理性选择指南
微信小程序
T01156182 天前
独立开发者商单实战|商超门店小程序(自提 + 同城配送):小程序全端页面 & 业务流程总图汇总
微信小程序·小程序·个人开发·前端实战
驳是2 天前
入坑 UniApp 写小程序,一些感受
微信小程序
不如摸鱼去3 天前
Wot UI 2.3.0 发布:二维码组件来了,Open Wot 与 wot-starter 同步更新
前端·ui·微信小程序·前端框架·uni-app
万亿少女的梦1684 天前
基于微信小程序、Express与MongoDB的校园失物招领系统设计
mongodb·微信小程序·node.js·express·系统设计
小徐_23334 天前
Wot UI 2.3.0 发布:二维码组件来了,Open Wot 与 wot-starter 同步更新
前端·微信小程序·uni-app
2601_953720824 天前
【计算机毕业设计】基于微信小程序的拼车服务系统设计与实现
微信小程序·小程序·课程设计
FungLeo5 天前
Taro 4 微信小程序:RootPortal CSS 变量继承问题与自建 PagePortal 解决方案
微信小程序·taro·css 变量
海纳百川·纳海川7 天前
租房行业数字化:换个思路解决“老问题”
大数据·微信小程序·小程序
JasonMa1538 天前
从零搭建一个微信小程序活动管理平台(一):架构设计与技术选型
javascript·微信小程序·node.js