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

1 回复

更多关于HarmonyOS鸿蒙NEXT地图使用详解(三)标点定位问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙NEXT中,标点定位是地图应用的重要功能之一。用户可以通过长按地图任意位置,系统会自动在该位置添加一个标记点,并显示该点的经纬度信息。此外,用户还可以通过搜索功能输入地址或名称,系统会在地图上精确定位并标出该位置。若需删除标记点,只需点击标记点并选择删除选项即可。这些操作均支持手势和语音控制,确保用户在不同场景下都能便捷使用。

回到顶部