> **本文回答**：Marker 随缩放级别的可见性、自动缩放、视野裁剪 —— 让 Marker 在合适的 zoom 才出现。
>
> 注意：`minZoom`/`maxZoom`/`scaleMaxZoom`/`height`/`removeWhenNoInMapView` 是 vjmap 扩展字段，`new Marker()` 构造器不读它们——须用 `vjmap.createMarker({...})` 或运行时 setter（`setMinZoom`/`setScaleMaxZoom`/`setHeight`/`setRemoveWhenNoInMapView`）。

## 一、minZoom / maxZoom（显示级别区间）

```js
vjmap.createMarker({ minZoom: 10, maxZoom: 18 })
  .setLngLat([lng, lat]).addTo(map);
```

当前 zoom 在 `[10, 18)` 区间内才显示（`zoom >= minZoom && zoom < maxZoom`）。

运行时：

```js
marker.setMinZoom(12);
marker.setMaxZoom(20);
```

原理：超出区间时内部 `remove(true)` 把 DOM 从文档摘除（触发 `autoRemove`），回到区间重新插入（触发 `autoAdd`），不是 `display:none`。

> ⚠️ 可见性判定挂在地图 `zoomend` / `moveend` 事件上——`addTo` 时**不做**初始评估，`setMinZoom`/`setMaxZoom` 之后也要等下一次 zoom 结束才生效（源码：`_options._minZoom/_maxZoom` 在 zoomend 回调里比较）。要立刻生效得触发一次缩放（`map.zoomTo(..., {duration:0})`）。

## 二、scaleMaxZoom（低 zoom 自动缩小）

```js
vjmap.createMarker({ scaleMaxZoom: 16 })
  .setLngLat([lng, lat]).addTo(map);
```

- `zoom >= 16`：正常大小
- `zoom < 16`：按 `2^(zoom - 16)` 指数比例缩小（每低一级再减半：15 级→0.5、14 级→0.25），避免低 zoom 下图标互相挤堆。

运行时：

```js
marker.setScaleMaxZoom(14);
```

## 三、removeWhenNoInMapView（视野裁剪 / 回收复用）

```js
vjmap.createMarker({
  removeWhenNoInMapView: true,
  removeWhenNoInMapViewPadding: 400      // 默认 500
})
.setLngLat([lng, lat]).addTo(map);
```

- 平移地图时：Marker 离开视野（+padding 范围）自动从文档 DOM 移除；回到视野再回插 DOM。
- 事件：`autoAdd` / `autoRemove`。

场景：几千个 Marker 时，只在视野内渲染，性能大幅提升。

**坑**：如果 Marker 是 Vue/React 组件渲染，每次 remove/add DOM 都会触发 onMount/onUnmount，可能重新触发网络请求。

## 四、随 pitch 变高度（3D 悬浮）

```js
vjmap.createMarker({ height: 300 })       // 300 米高
  .setLngLat([lng, lat]).addTo(map);
```

设置 `height` 后，Marker 显示在"离地面 300 米"的位置。`map.setPitch(60)` 才看得到。

运行时：

```js
marker.setHeight(500);
```

## 五、多级显隐（典型写法）

```js
// 一级：仅 >=15 显示
const markerHigh = vjmap.createMarker({ minZoom: 15 })
  .setLngLat([lng1, lat1]);
markerHigh.addTo(map);

// 二级：仅 >=12 显示
const markerMid  = vjmap.createMarker({ minZoom: 12 })
  .setLngLat([lng2, lat2]);
markerMid.addTo(map);

// 三级：全局显示
const markerAll  = new vjmap.Marker()
  .setLngLat([lng3, lat3]);
markerAll.addTo(map);
```

## 六、监听缩放决定行为

```js
map.on("zoomend", () => {
  const z = map.getZoom();
  if (z > 18) {
    marker.getElement().style.background = "#f00";
  } else {
    marker.getElement().style.background = "";
  }
});
```

## 七、isHidden / show / hide

```js
marker.isHidden();     // true 表示因缩放级别不在区间 / 视野外 / hide()
marker.show();         // 显示
marker.hide();         // 隐藏
```

## 八、setVisible

```js
marker.setVisible(false, true);   // isDisplay=true：display:none，等价 hide()
marker.setVisible(true,  true);   // display:""，等价 show()
marker.setVisible(false, false);  // isDisplay 假分支：调 this.remove()，等价 remove()
marker.setVisible(true,  false);  // 调 addTo(this._map)：仅对"自动摘除但 _map 还在"的 marker 有意义
```

`isDisplay=true` 走 CSS `display` 显隐（DOM 保留）；`isDisplay` 假则走 `addTo`/`remove` 真挂真摘。

⚠️ `setVisible(false,false)` 是真移除（`_map` 已删），之后 `setVisible(true,false)` 会 `addTo(undefined)` 报错——恢复要用 `marker.addTo(map)`。需要"摘除 DOM 但保留登记"请用 `removeWhenNoInMapView`（内部 `remove(true)` 路径）。

## 九、组合最佳实践

1. 数量 < 500：只用 minZoom/maxZoom 控制层级，开销可接受。
2. 数量 500~5000：开 `removeWhenNoInMapView: true`。
3. 数量 > 5000：改用 Symbol Layer + cluster。

## 十、常见坑

1. **setMinZoom 不生效**：判定要等下一次 `zoomend` / `moveend` 才执行；超出区间是摘除 DOM（不是 display），自己持有的 DOM 引用此时不在文档里。
2. **removeWhenNoInMapView 闪烁**：视野 padding 太小；建议 >= 500。
3. **scaleMaxZoom 对任意 element 生效**（官方示例即用于自定义 DOM）：它把 `scale()` 拼进根节点的 CSS transform，会覆盖你写在根节点上的 transform——自定义动画 / 旋转放到子节点上。
4. **height 高了图标被遮挡**：3D fill-extrusion 图层在 Marker 之上；Marker 是 DOM，fixed 在 canvas 之上，但高度是模拟的。
