目录

地图视野范围如何设置

问题现象

当地图上显示多个Marker标记等覆盖物时,如何自动缩放和移动相机视野,使所有覆盖物都在一屏内展示出来。

背景知识

解决方案

  1. 计算覆盖物的边界:遍历所有添加到地图上的覆盖物所在的坐标,计算每个覆盖物坐标的最小和最大经纬度。
    calculateBounds(positions: mapCommon.LatLng[]): mapCommon.LatLngBounds {
      let minLat: number = 31.9844;
      let maxLat: number = 31.9844;
      let minLng: number = 118.7662;
      let maxLng: number = 118.7662;
    
      positions.forEach(pos => {
        minLat = Math.min(minLat, pos.latitude);
        maxLat = Math.max(maxLat, pos.latitude);
        minLng = Math.min(minLng, pos.longitude);
        maxLng = Math.max(maxLng, pos.longitude);
      });
      return {
        southwest: { latitude: minLat, longitude: minLng },
        northeast: { latitude: maxLat, longitude: maxLng }
      };
    }
    
  2. 设置地图视图:使用计算出的边界范围,创建一个LatLngBounds对象,使用newLatLngBounds方法创建一个CameraUpdate对象,传入刚才创建的LatLngBounds和适当的padding值,以确保覆盖物边缘有足够的缓冲空间。

    最后,使用moveCamera或animateCamera方法应用这个CameraUpdate对象到地图上,实现视图的更新。

    const latLngBounds = this.calculateBounds(this.markerPositions);
    // 自动调整视野
    try {
      let cameraUpdate = map.newLatLngBounds(latLngBounds, 50); // 50是padding值,可以根据需要调整
      this.mapController.moveCamera(cameraUpdate);
    } catch (error) {
      console.error('Adjust camera failed:', (error as BusinessError).message);
    }

    效果图:

    完整代码:

    import { MapComponent, mapCommon, map } from '@kit.MapKit';
    import { AsyncCallback } from '@kit.BasicServicesKit';
    import { display } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct AdjustCamera {
      private mapOptions?: mapCommon.MapOptions;
      private callback?: AsyncCallback<map.MapComponentController>;
      private mapController?: map.MapComponentController;
      private markerPositions: Array<mapCommon.LatLng> = [
        { latitude: 31.9844, longitude: 118.7662 },
        { latitude: 32.0844, longitude: 118.8662 },
        { latitude: 32.0044, longitude: 118.9062 },
        { latitude: 31.9544, longitude: 118.7262 },
        { latitude: 32.0244, longitude: 118.7962 }
      ];
      @State mapHeight: number = 0;
    
      calculateBounds(positions: mapCommon.LatLng[]): mapCommon.LatLngBounds {
        let minLat: number = 31.9844;
        let maxLat: number = 31.9844;
        let minLng: number = 118.7662;
        let maxLng: number = 118.7662;
    
        positions.forEach(pos => {
          minLat = Math.min(minLat, pos.latitude);
          maxLat = Math.max(maxLat, pos.latitude);
          minLng = Math.min(minLng, pos.longitude);
          maxLng = Math.max(maxLng, pos.longitude);
        });
        return {
          southwest: { latitude: minLat, longitude: minLng },
          northeast: { latitude: maxLat, longitude: maxLng }
        };
      }
    
    
      aboutToAppear(): void {
        let displayClass = display.getDefaultDisplaySync();
        this.mapHeight = this.getUIContext().px2vp(displayClass.height);
        // 初始化地图中心点参数
        let cameraPosition: mapCommon.CameraPosition = {
          target: { latitude: 32.0, longitude: 118.8 }, // 初始中心点
          zoom: 10 // 初始缩放级别
        };
        this.mapOptions = { position: cameraPosition };
    
        // 地图初始化回调
        this.callback = async (err, mapController) => {
          if (!err) {
            this.mapController = mapController;
            // 创建5个不同位置的Marker
            await Promise.all(this.markerPositions.map(pos =>
            this.mapController?.addMarker({
              position: pos,
              anchorU: 0.5,
              anchorV: 0.5
            })
            ));
            const latLngBounds = this.calculateBounds(this.markerPositions);
            // 自动调整视野
            try {
              let cameraUpdate = map.newLatLngBounds(latLngBounds, 50); // 50是padding值,可以根据需要调整
              this.mapController.moveCamera(cameraUpdate);
            } catch (error) {
              console.error('Adjust camera failed:', (error as BusinessError).message);
            }
          }
        };
      }
    
      build() {
        Stack() {
          Column() {
            MapComponent({
              mapOptions: this.mapOptions,
              mapCallback: this.callback
            })
              .height(this.mapHeight);
          }
          .width('100%');
        }
        .ignoreLayoutSafeArea();
      }
    }

常见FAQ

Q:为什么开启3D地球效果后,地图上绘制的点,线,图片覆盖物在地图缩放为球体后不显示?

A:3D状态下,传统2D覆盖物(如点、线、图片覆盖物)不会被渲染,只有当地图放大到2D平面模式(缩放级别较高)时,这些覆盖物才会重新显示。当地图需要显示覆盖物时,通过setSphereEnabled动态关闭3D效果。