目录

如何实现通过自定义滑块控制地图缩放

问题现象

当前地图Map Kit支持双指缩放和按钮缩放,如何实现通过滑动滑块控制地图的缩放。

背景知识

解决方案

方案逻辑:通过监听滑块的滑动,将滑动数值转换为地图缩放级别的大小,动态设置地图的setMaxZoom、setMinZoom即最大、最小缩放级别,实现地图的缩放。

  1. 使用Stack组件,将Slider组件展示在地图MapComponent的右侧。
  2. 监听Slider的滑动,将当前滑动组件获取的设置值,动态赋值给地图的缩放级别zoom,并设置最大、最小缩放级别。因为地图缩放级别取值范围为[2,20],Slider的value值为[0,100],所以需计算value对应最大值20的相对取值。
    Slider({
      value: this.zoom / 20 * 100,
      style: SliderStyle.InSet,
      direction: Axis.Vertical,
      reverse: true
    })
      .height(200)
      .onChange((value: number) => {
        this.zoom = value / 100 * 20;
        this.mapController?.setMaxZoom(this.zoom);
        this.mapController?.setMinZoom(this.zoom);
      })

实现效果:

完整示例参考如下:

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

@Entry
@Component
struct SliderScale {
  private mapOptions?: mapCommon.MapOptions;
  private mapController?: map.MapComponentController;
  private callback?: AsyncCallback<map.MapComponentController>;
  @State zoom: number = 15;
  @State mapHeight: number = 0;

  aboutToAppear(): void {
    let displayClass = display.getDefaultDisplaySync();
    this.mapHeight = this.getUIContext().px2vp(displayClass.height);
    this.mapOptions = {
      position: {
        target: {
          latitude: 31.984410259206815,
          longitude: 118.76625379397866
        },
        zoom: 15
      },
      zoomControlsEnabled: false
    };

    this.callback = async (err, mapController) => {
      if (!err) {
        this.mapController = mapController;
      }
    };
  }

  build() {
    Stack({ alignContent: Alignment.End }) {
      Column() {
        MapComponent({
          mapOptions: this.mapOptions,
          mapCallback: this.callback,
        })
          .width('100%')
          .height(this.mapHeight)
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
      }.width('100%')

      Slider({
        value: this.zoom / 20 * 100,
        style: SliderStyle.InSet,
        direction: Axis.Vertical,
        reverse: true
      })
        .height(200)
        .onChange((value: number) => {
          this.zoom = value / 100 * 20;
          this.mapController?.setMaxZoom(this.zoom);
          this.mapController?.setMinZoom(this.zoom);
        })
    }.height('100%')
    .ignoreLayoutSafeArea()
  }
}