HarmonyOS 鸿蒙Next应用开发与华为地图之经纬度精度偏差-优化方案
HarmonyOS 鸿蒙Next应用开发与华为地图之经纬度精度偏差-优化方案
问题背景
- 在鸿蒙App开发中,调用鸿蒙定位服务API获取的当前定位坐标后,传入华为地图后,在华为地图上显示的定位坐标,与实际预期的定位位置不一样
- 例如:鸿蒙定位服务API获取的当前定位坐标,预期在华为地图上应该显示在湖附近,但是实际华为地图上显示的位置,在几百米外的陆地上。具体效果见下面截图
- 即,应用内通过鸿蒙定位服务API获取的当前定位坐标,与华为地图中显示的坐标位置存在偏差
问题原因
- 鸿蒙定位服务API使用的是WGS84坐标系,但是在显示到华为地图上需要使用GCJ02 坐标系
- 华为地图坐标系介绍:华为地图坐标系介绍
- 鸿蒙定位服务API坐标系介绍:鸿蒙定位服务API坐标系介绍
问题原因总结
- 华为官方设计上存在不一致:华为地图需要使用标准的大陆的GCJ02 坐标系,与鸿蒙定位服务API的WGS84坐标系,设计上不一致
修复方案:
核心答案
- 封装一套坐标系转换的方法,将WGS84坐标系的坐标转换为GCJ02坐标系的坐标
实现步骤
- 鸿蒙原生通过鸿蒙定位服务API获取到坐标后,调用封装的经纬度坐标系转换方法,将转换后的坐标,传入到华为地图中显示
经纬度坐标转换方法,见如下代码设计思路
经纬度坐标转换,代码设计思路
- 先定义一个接受经度、纬度两个参数的方法,并返回number数组,如下:gcj02ToWgs84(lng: number, lat: number)
- 判断是否为国内坐标,若是则继续转化,否则退出
- 封装一个转换经度的方法,如下:transformLng
- 封装一个转换纬度的方法,如下:transformLat
- 再经过固定算法,在gcj02ToWgs84返回number数组
完整代码
const PI = Math.PI;
const a = 6378245.0;
const ee = 0.00669342162296594323;
function outOfChina(lng: number, lat: number): boolean {
if (lng < 72.004 || lng > 137.8347) {
return true;
}
if (lat < 0.8293 || lat > 55.8271) {
return true;
}
return false;
}
function transformLat(lng: number, lat: number): number {
let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
function transformLng(lng: number, lat: number): number {
let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
function gcj02ToWgs84(lng: number, lat: number): number[] {
if (outOfChina(lng, lat)) {
return [lng, lat];
}
let dlat = transformLat(lng - 105.0, lat - 35.0);
let dlng = transformLng(lng - 105.0, lat - 35.0);
let radlat = lat / 180.0 * PI;
let magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
let sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
let mglat = lat + dlat;
let mglng = lng + dlng;
return [lng * 2 - mglng, lat * 2 - mglat];
}
总结
- 鸿蒙地图相关开发中,若存在应用内app获取定位后,需要在华为地图中显示定位坐标位置,则需要转换坐标。
- 开发者需了解鸿蒙中此种经纬度坐标系,不同标准。若遇到类似问题,可快速解决,无需查阅很多资料花费较多时间来定位此种类型的问题
- 若遇到类似定位相关的问题,查阅鸿蒙官网API时,需留意坐标系相关的说明,可快速定界出是否是坐标系的问题
更多关于HarmonyOS 鸿蒙Next应用开发与华为地图之经纬度精度偏差-优化方案的实战教程也可以访问 https://www.itying.com/category-93-b0.html
2 回复
鸿蒙Next应用开发中优化华为地图经纬度精度偏差的方案如下:
- 使用HarmonyOS Location Kit提供的GNSS定位服务获取高精度坐标
- 调用华为地图SDK的CoordinateConverter.convert()方法进行WGS84到GCJ02坐标系的转换
- 在MapView初始化时设置
setMyLocationScale(100)
提高定位精度显示 - 通过
LocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
启用高精度模式 - 实现
LocationCallback
接口实时接收位置更新,过滤低精度定位结果
定位结果建议保留6位小数精度,关键参数配置:
- 最小更新间隔:1000ms
- 最小位移变化:0.1m
- 定位超时:30s
更多关于HarmonyOS 鸿蒙Next应用开发与华为地图之经纬度精度偏差-优化方案的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
这是一个典型的坐标系转换问题。HarmonyOS定位服务使用WGS84坐标系,而华为地图在中国大陆地区使用GCJ02坐标系,导致直接显示时出现位置偏移。
解决方案的核心是进行WGS84到GCJ02的坐标转换。您提供的代码已经实现了这一转换逻辑,主要包括:
- 判断坐标是否在中国境内(outOfChina)
- 实现经纬度转换算法(transformLat/transformLng)
- 完成最终坐标转换(gcj02ToWgs84)
在实际应用中,建议:
- 将坐标转换逻辑封装为独立工具类
- 在获取定位后立即进行转换
- 使用转换后的坐标显示在地图上
这种方案能有效解决因坐标系差异导致的位置偏移问题。