HarmonyOS鸿蒙NEXT地图使用详解(三)标点定位问题
HarmonyOS鸿蒙NEXT地图使用详解(三)标点定位问题
背景
在使用geoLocationManager的getCurrentLocation方法获得的用户定位经纬度的坐标系为 WGS84 ,但是mapkit使用的是GCJ02坐标系。因此,我们在使用获取用户经纬度然后直接生成标记时,会出现坐标偏移问题。
实现效果:
解决方案
使用map.convertCoordinateSync方法,对已有的经纬度进行坐标系转换,生成GCJ02坐标系下的经纬度数值。 其中this.LocationLongitude和this.LocationLatitude都是viewmodel类中定义的经纬度。
直接获取经纬度代码
/**
* 更新用户定位
*/
public async UpdateLocation() {
try {
const result = await geoLocationManager.getCurrentLocation();
this.LocationLongitude = result.longitude;
this.LocationLatitude = result.latitude;
} catch (err) {
console.info("VM", "errCode:" + JSON.stringify(err));
}
}
获取转换后经纬度代码
public async UpdateLocationByConvert() {
try {
const result = await geoLocationManager.getCurrentLocation();
let wgs84Position: mapCommon.LatLng = {
latitude: result.latitude,
longitude: result.longitude
};
let gcj02Position: mapCommon.LatLng =
map.convertCoordinateSync(mapCommon.CoordinateType.WGS84, mapCommon.CoordinateType.GCJ02, wgs84Position);
this.LocationLongitude = gcj02Position.longitude;
this.LocationLatitude = gcj02Position.latitude;
} catch (err) {
console.info("VM", "errCode:" + JSON.stringify(err));
}
}
完整代码
View
import { MapComponent } from "@kit.MapKit"
import { MapBlogViewModel } from "../ViewModels/MapBlogViewModel"
@Entry
@ComponentV2
export struct MapBlogDemo {
@Local MapVM: MapBlogViewModel = new MapBlogViewModel()
aboutToAppear(): void {
}
build() {
RelativeContainer() {
MapComponent({
mapOptions: this.MapVM.MapOption,
mapCallback: this.MapVM.MapCallBack
})
.width("100%")
.height('70%')
.id("Map")
Column({ space: 10 }) {
Button("在我的位置创造一个标点")
.onClick(() => {
this.MapVM.CreateLocationMarkerEvent();
})
Button("在我的位置创造一个转换后的标点")
.onClick(async () => {
await this.MapVM.UpdateLocationByConvert();
this.MapVM.CreateLocationMarkerEvent();
})
}
.width("100%")
.height('30%')
.alignRules({
top: { anchor: "Map", align: VerticalAlign.Bottom },
bottom: { anchor: "__container__", align: VerticalAlign.Bottom }
})
}
.height('100%')
.width('100%')
}
}
ViewModel
import { map, mapCommon, sceneMap } from "@kit.MapKit"
import { AsyncCallback } from "@kit.BasicServicesKit"
import { geoLocationManager } from "@kit.LocationKit"
import { common } from "@kit.AbilityKit"
import { trustedAppService } from "@kit.DeviceSecurityKit"
@ObservedV2
export class MapBlogViewModel {
/**
* 地图初始化参数设置
*/
@Trace MapOption?: mapCommon.MapOptions
/**
* 地图回调方法
*/
MapCallBack?: AsyncCallback<map.MapComponentController>
/**
* 地图控制器
*/
@Trace MapController?: map.MapComponentController
/**
* 地图监听管理器
*/
@Trace MapEventManager?: map.MapEventManager
/**
* 当前位置的维度
*/
public LocationLatitude: number = 39.9;
/**
* 当前位置的经度
*/
public LocationLongitude: number = 116.4;
/**
* 缩放数值
*/
public ZoomNumber: number = 20
/**
* 定位标记
*/
@Trace LocationMarker?: map.Marker
constructor() {
this.MapOption = {
//相机位置
position: {
target: {
latitude: 39.9,
longitude: 116.4
},
zoom: this.ZoomNumber
},
//地图类型
mapType: mapCommon.MapType.STANDARD,
//地图最小图层,默认值为2
minZoom: 2,
//地图最大图层,默认值为20
maxZoom: 20,
//是否支持旋转手势
rotateGesturesEnabled: true,
//是否支持滑动手势
scrollGesturesEnabled: true,
//是否支持缩放手势
zoomGesturesEnabled: true,
//是否支持倾斜手势
tiltGesturesEnabled: true,
//是否展示缩放控件
zoomControlsEnabled: true,
//是否展示定位按钮
myLocationControlsEnabled: true,
//是否展示指南针控件
compassControlsEnabled: true,
//是否展示比例尺
scaleControlsEnabled: false,
//是否一直显示比例尺,只有比例尺启用时该参数才生效。
alwaysShowScaleEnabled: false
};
this.MapCallBack = async (err, mapController) => {
if (!err) {
this.MapController = mapController;
//地图监听时间管理器
this.MapEventManager = this.MapController.getEventManager();
//启用我的位置图层
this.MapController.setMyLocationEnabled(true);
this.UpdateLocation().then(() => {
});
}
}
this.MoveCamera(this.LocationLatitude, this.LocationLongitude)
}
/**
* 创建我的位置定位标记
*/
public async CreateLocationMarkerEvent() {
let markerKey: string = 'DirectionKey';
// Marker初始化参数
let markerOptions: mapCommon.MarkerOptions = {
position: {
latitude: this.LocationLatitude,
longitude: this.LocationLongitude
},
rotation: 0,
visible: true,
zIndex: 0,
alpha: 1,
anchorU: 0.5,
anchorV: 1,
clickable: false,
draggable: false,
flat: false,
icon: "LocationIcon.svg",
infoWindowAnchorU: 0,
infoWindowAnchorV: 0
};
if (this.MapController) {
// 创建Marker
this.LocationMarker = await this.MapController.addMarker(markerOptions);
//设置标记可以拖拽
this.LocationMarker.setDraggable(false);
// 设置信息窗的标题
// this.LocationMarker.setTitle(markerKey);
// 设置标记可点击
this.LocationMarker.setClickable(false);
// 设置信息窗的锚点位置
this.LocationMarker.setInfoWindowAnchor(1, 1);
this.MoveCamera(this.LocationLatitude, this.LocationLongitude);
}
}
/**
* 展示地点选取页,更新标记地点
*/
public async ShowChoosingLocation() {
let locationChoosingOptions: sceneMap.LocationChoosingOptions = {
// 地图中心点坐标
location: { latitude: this.LocationLatitude, longitude: this.LocationLongitude },
language: 'zh_cn',
// 展示搜索控件
searchEnabled: true,
// 展示附近Poi
showNearbyPoi: true
};
// 拉起地点选取页
let result: sceneMap.LocationChoosingResult =
await sceneMap.chooseLocation(getContext(this) as common.UIAbilityContext, locationChoosingOptions);
this.LocationLatitude = result.location.latitude;
this.LocationLongitude = result.location.longitude;
animateTo({
duration: 500
}, () => {
this.MoveCamera(this.LocationLatitude, this.LocationLongitude);
this.UpdateLocationMarker(result.location);
})
}
/**
* 更新定位位置
* @param latLng
*/
private UpdateLocationMarker(latLng: mapCommon.LatLng) {
if (this.LocationMarker) {
this.LocationLatitude = latLng.latitude;
this.LocationLongitude = latLng.longitude;
this.LocationMarker.setPosition(latLng);
}
}
/**
* 更新用户定位
*/
public async UpdateLocation() {
try {
const result = await geoLocationManager.getCurrentLocation();
this.LocationLongitude = result.longitude;
this.LocationLatitude = result.latitude;
} catch (err) {
console.info("VM", "errCode:" + JSON.stringify(err));
}
}
public async UpdateLocationByConvert() {
try {
const result = await geoLocationManager.getCurrentLocation();
let wgs84Position: mapCommon.LatLng = {
latitude: result.latitude,
longitude: result.longitude
};
let gcj02Position: mapCommon.LatLng =
map.convertCoordinateSync(mapCommon.CoordinateType.WGS84, mapCommon.CoordinateType.GCJ02, wgs84Position);
this.LocationLongitude = gcj02Position.longitude;
this.LocationLatitude = gcj02Position.latitude;
} catch (err) {
console.info("VM", "errCode:" + JSON.stringify(err));
}
}
/**
* 移动视图相机
* @param latitude 维度
* @param longitude 经度
*/
public async MoveCamera(latitude: number, longitude: number) {
if (this.MapController) {
//将视图移动到标点位置
let nwPosition = map.newCameraPosition({
target: {
latitude: latitude,
longitude: longitude
},
zoom: 15
})
// 以动画方式移动地图相机
this.MapController.animateCamera(nwPosition, 1000);
}
}
}
总结
上面地图遇到获取当前位置的经纬度的数值直接用来做标点时候,标点位置不正确的bug
更多关于HarmonyOS鸿蒙NEXT地图使用详解(三)标点定位问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙NEXT地图使用详解(三)标点定位问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙NEXT中,标点定位是地图应用的重要功能之一。用户可以通过长按地图任意位置,系统会自动在该位置添加一个标记点,并显示该点的经纬度信息。此外,用户还可以通过搜索功能输入地址或名称,系统会在地图上精确定位并标出该位置。若需删除标记点,只需点击标记点并选择删除选项即可。这些操作均支持手势和语音控制,确保用户在不同场景下都能便捷使用。