点击添加的marker位置与点击的位置不一致
======================

#### 问题现象

在地图上通过手指点击添加marker，添加的marker的位置与手指点击的位置不一致，总是显示在左上角。

原问题代码如下：

import { map, mapCommon, MapComponent } from '@kit.MapKit';
import { AsyncCallback } from '@kit.BasicServicesKit';


@Entry
@Component
struct IncorrectCode {
  private mapOptions?: mapCommon.MapOptions;
  private mapController?: map.MapComponentController;
  private callback?: AsyncCallback<map.MapComponentController>;
  @State screenX: number = 0;
  @State screenY: number = 0;
  @State latitudeA: number = 0;
  @State longitudeA: number = 0;
  @State latitudeB: number = 0;
  @State longitudeB: number = 0;


  aboutToAppear(): void {
   _ // 地图初始化参数_
    this.mapOptions = {
      position: {
        target: {
          latitude: 31.984410259206815,
          longitude: 118.76625379397866
        },
        zoom: 15
      },
    };
    this.callback = async (err, mapController) => {
      if (!err) {
        this.mapController = mapController;
      } else {
        console.error(\`地图初始化失败, code is：${err.code}, message is ${err.message}\`);
      }
    };
  }


  build() {
    Stack() {
      Column() {
        MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
          .onTouch((event: TouchEvent) => {
            if (event.type === TouchType.Up) {
              this.screenX = event.touches\[0\].x;
              this.screenY = event.touches\[0\].y;


              const projection = this.mapController?.getProjection();
              const screenPoint: mapCommon.MapPoint = {
                positionX: this.screenX,
                positionY: this.screenY
              };
              const latLng = projection?.fromScreenLocation(screenPoint);
              this.latitudeA = latLng?.latitude as number;
              this.longitudeA = latLng?.longitude as number;


              let wgs84Position: mapCommon.LatLng = {
                latitude: this.latitudeA,
                longitude: this.longitudeA
              };


          _    // 转换经纬度坐标_
              let gcj02Position: mapCommon.LatLng =
                map.convertCoordinateSync(mapCommon.CoordinateType.WGS84, mapCommon.CoordinateType.GCJ02,
                  wgs84Position);
              this.latitudeB = gcj02Position.latitude;
              this.longitudeB = gcj02Position.longitude;


           _   // 添加一个红色标记点_
              const markerOptions: mapCommon.MarkerOptions = {
                position: {
                  latitude: this.latitudeB,
                  longitude: this.longitudeB
                },
              };
              this.mapController?.addMarker(markerOptions);
            }
            return true;
          })
      }.width('100%')
    }.height('100%')
  }
}

#### 背景知识

*   [fromScreenLocation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-map-projection#section1784991054119)：将屏幕像素点坐标转换成经纬度。添加的像素点坐标，单位为px。
*   开通地图服务：需先[开通地图服务](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/map-config-agc#section16133115441516)，再进行后续地图开发活动。

#### 问题定位

1.  问题代码中，获取点击位置的像素点坐标后，直接将像素点坐标值用于转换经纬度。此时获取的像素点的坐标单位是vp，而将屏幕像素点坐标转换成经纬度fromScreenLocation接口需要传入px单位，导致像素点坐标输入值与实际点击位置有差异。
    
    this.screenX = event.touches\[0\].x;
    this.screenY = event.touches\[0\].y;
    
    
    const projection = this.mapController?.getProjection();
    const screenPoint: mapCommon.MapPoint = {
      positionX: this.screenX,
      positionY: this.screenY
    };
    
2.  问题代码中，对屏幕像素点坐标转换后的经纬度，又进行了一次WGS84坐标系转换GCJ02坐标系，屏幕像素点坐标转换后的经纬度本身应就GCJ02坐标系，无需再转换。
    
    let wgs84Position: mapCommon.LatLng = {
      latitude: this.latitudeA,
      longitude: this.longitudeA
    };
    
    _// 转换经纬度坐标_
    let gcj02Position: mapCommon.LatLng =
      map.convertCoordinateSync(mapCommon.CoordinateType.WGS84, mapCommon.CoordinateType.GCJ02,
        wgs84Position);
    this.latitudeB = gcj02Position.latitude;
    this.longitudeB = gcj02Position.longitude;
    

#### 分析结论

问题代码存在两处错误导致添加marker不准确。

1.  onTouch获取的像素点坐标单位是vp，fromScreenLocation转化为经纬度坐标时，需要输入的单位是px，没有进行像素点坐标单位转换。
2.  屏幕像素点坐标转换后的经纬度本身应是GCJ02坐标系，问题代码中额外进行了一次WGS84坐标系转换GCJ02坐标系。

#### 修改建议

1.  onTouch获取的像素点坐标进行vp转px单位转换。
    
    const screenPoint: mapCommon.MapPoint = {
      positionX: this.getUIContext().vp2px(this.screenX),
      positionY: this.getUIContext().vp2px(this.screenY)
    };
    
2.  去掉WGS84坐标系转换GCJ02坐标系的操作。

修改后的完整代码：

import { map, mapCommon, MapComponent } from '@kit.MapKit';
import { AsyncCallback } from '@kit.BasicServicesKit';


@Entry
@Component
struct IncorrectCode {
  private mapOptions?: mapCommon.MapOptions;
  private mapController?: map.MapComponentController;
  private callback?: AsyncCallback<map.MapComponentController>;
  @State screenX: number = 0;
  @State screenY: number = 0;
  @State latitudeA: number = 0;
  @State longitudeA: number = 0;


  aboutToAppear(): void {
    _// 地图初始化参数_
    this.mapOptions = {
      position: {
        target: {
          latitude: 31.984410259206815,
          longitude: 118.76625379397866
        },
        zoom: 15
      },
    };
    this.callback = async (err, mapController) => {
      if (!err) {
        this.mapController = mapController;
      } else {
        console.error(\`地图初始化失败, code is：${err.code}, message is ${err.message}\`);
      }
    };
  }


  build() {
    Stack() {
      Column() {
        MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
          .onTouch((event: TouchEvent) => {
            if (event.type === TouchType.Up) {
              this.screenX = event.touches\[0\].x;
              this.screenY = event.touches\[0\].y;


              const projection = this.mapController?.getProjection();
              const screenPoint: mapCommon.MapPoint = {
                positionX: this.getUIContext().vp2px(this.screenX),
                positionY: this.getUIContext().vp2px(this.screenY)
              };
              const latLng = projection?.fromScreenLocation(screenPoint);
              this.latitudeA = latLng?.latitude as number;
              this.longitudeA = latLng?.longitude as number;


            _  // 添加一个红色标记点_
              const markerOptions: mapCommon.MarkerOptions = {
                position: {
                  latitude: this.latitudeA,
                  longitude: this.longitudeA
                },
              };
              this.mapController?.addMarker(markerOptions);
            }
            return true;
          })
      }.width('100%')
    }.height('100%')
  }
}