目录

如何将触摸点转换为地图经纬度坐标

问题现象

在集成地图场景的应用中,通常有这样一种场景:需要获取手指触摸点对应地图上的经纬度坐标。获取经纬度坐标后,再进行相关业务处理,譬如放置标记、逆地理编码展示详细地址、查看附近商店等。那么,如何将手指触摸点转换为对应地图上的经纬度坐标?

背景知识

解决方案

  1. 获取手指触摸点对应于(地图可视区域的)屏幕的像素点。本例通过onTouch事件获取手指触摸点,通过LongPressGesture、PanGesture等手势也可获取手指触摸点位置。
  2. 将手指触摸点位置对应的屏幕像素点通过fromScreenLocation转换为地图经纬度坐标。

    示例代码如下:

    import { map, mapCommon, MapComponent } from '@kit.MapKit';
    import { AsyncCallback } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct FromScreenLocationDemo {
      private mapOptions?: mapCommon.MapOptions;
      private callback?: AsyncCallback<map.MapComponentController>;
      private mapController?: map.MapComponentController;
      private mapEventManager?: map.MapEventManager;
    
      aboutToAppear(): void {
        // 地图初始化参数,设置地图中心点坐标及层级
        this.mapOptions = {
          position: {
            target: {
              latitude: 39.9,
              longitude: 116.4
            },
            zoom: 10
          }
        };
    
        // 地图初始化的回调
        this.callback = async (err, mapController) => {
          if (!err) {
            // 获取地图的控制器类,用来操作地图
            this.mapController = mapController;
            this.mapEventManager = this.mapController.getEventManager();
            let callback = () => {
              console.info('on-mapLoad');
            };
            this.mapEventManager.on('mapLoad', callback);
          }
        };
      }
    
      build() {
        Stack() {
          Column() {
            Text('This is a Text').fontSize(40).backgroundColor(Color.Green).width('100%').height('10%');
            Stack() {
              MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
                .width('100%')
                .height('100%');
            }
            .width('100%')
            .height('100%')
            .onTouch((event) => {
              // 获取手指触摸位置对应的屏幕像素点
              let positionX = this.getUIContext().vp2px(event.touches[0].x);
              let positionY = this.getUIContext().vp2px(event.touches[0].y);
              let projection: map.Projection | undefined = this.mapController?.getProjection();
              if (projection) {
                let point: mapCommon.MapPoint = {
                  positionX: positionX,
                  positionY: positionY
                };
                // 转为地图的经纬度坐标
                let latLng: mapCommon.LatLng = projection.fromScreenLocation(point);
                this.getUIContext().getPromptAction().showToast({
                  message: 'longitude: ' + latLng.longitude + '  latitude:' + latLng.latitude,
                  duration: 3000
                });
              }
            });
          }.width('100%');
        }.height('100%');
      }
    }
    • fromScreenLocation的入参为屏幕位置,是以相对于地图左上角(而不是整个屏幕的左上角)的屏幕像素(而非显示像素)指定的。因此,要确保获取的屏幕位置是相对于地图可视区域计算的。
    • onTouch获取的x、y值单位为vp,fromScreenLocation的输入值单位是xp,需要通过vp2px进行转换。
    • fromScreenLocation转后的经纬度为GCJ02坐标系。