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

#### 问题现象

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

#### 背景知识

*   [层叠布局](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-stack-layout) （Stack）：层叠布局（StackLayout）用于在屏幕上预留一块区域来显示组件中的元素，提供元素可以重叠的布局。
*   [触摸事件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-events-touch)（onTouch）：手指在组件上按下、滑动或抬起时触发。
*   [fromScreenLocation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-map-projection#section1784991054119)：将屏幕像素点坐标转换成经纬度。

#### 解决方案

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%');
      }
    }
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/77/v3/zkLf3w2HRHqgYW0zpywz5g/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T134310Z&HW-CC-Expire=86400&HW-CC-Sign=CB4D54F6903A094A1A9C25A815D4559FA61CCCAC17169D635F00C4FE8856AA88)
    
    *   fromScreenLocation的入参为屏幕位置，是以相对于地图左上角（而不是整个屏幕的左上角）的屏幕像素（而非显示像素）指定的。因此，要确保获取的屏幕位置是相对于地图可视区域计算的。
    *   onTouch获取的x、y值单位为vp，fromScreenLocation的输入值单位是xp，需要通过[vp2px](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-uicontext#vp2px12)进行转换。
    *   fromScreenLocation转后的经纬度为GCJ02坐标系。