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

#### 问题现象

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

#### 背景知识

*   setMaxZoom、setMinZoom：设置相机最大、最小缩放级别。
*   Slider：滑动条组件，通常用于快速调节设置值，如音量调节、亮度调节等应用场景。

#### 解决方案

方案逻辑：通过监听滑块的滑动，将滑动数值转换为地图缩放级别的大小，动态设置地图的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()
  }
}
```