> **本文回答**：三种切换当前图的方式（保留 map / 销毁重建 / 换 div），以及图层级开关控制。

## 一、三种切图方式

| 方式 | 什么时候用 | 优劣 |
|---|---|---|
| `map.switchMap({mapid})` | 同一 map 对象，切换服务端的另一张图 | 状态保留、但必须确保两张图的打开方式一致 |
| `map.destory()` + `new vjmap.Map(...)` | 想换空白图 / 换打开方式 | 彻底重来，代价高 |
| 重建 `div` + 新 map | DOM 结构需要刷新 | 最彻底，但闪一下 |

## 二、switchMap（推荐）

```js
// 签名
map.switchMap(
  param,              // IOpenMapParam：与 svc.openMap 同结构
  isKeepOldLayers,    // 可选，是否保留之前添加的图层，默认 false
  isVectorStyle,      // 可选
  isSetCenter,        // 可选，是否默认设中心点
  isFitBounds,        // 可选，默认是否 fit
  source              // 可选，source id
): Promise;
```

使用：

```js
await map.switchMap({
  mapid: "sys_world",
  mapopenway: vjmap.MapOpenWay.GeomRender,
  style: vjmap.openMapDarkStyle()  // 传给服务端 openMap，影响瓦片渲染风格
});

// 注意：前端用栅格还是矢量样式由第 3 个参数 isVectorStyle 决定，
// 与 param.style 无关。要切矢量：
await map.switchMap(
  { mapid: "sys_world", mapopenway: vjmap.MapOpenWay.GeomRender },
  false,   // isKeepOldLayers
  true     // isVectorStyle → svc.vectorStyle()
);
```

会依次触发 `mapopenstart` / `mapopenfinish` 事件：

```js
map.on("mapopenstart", () => showLoading());
map.on("mapopenfinish", () => hideLoading());
```

## 三、销毁地图

```js
map.destory();   // 注意：是 destory，不是 destroy（历史拼写）
```

然后就可以 `new vjmap.Map(...)` 挂到同一个 div 上。典型流程：

```js
setInterval(async () => {
  map.destory();
  map = await newMap(SERVICE_URL, NEXT_MAPID);
}, 10_000);
```

`newMap` 是自己封装的完整 "打开 + 关联 + onLoad + 加业务图层" 流程。

## 四、换 div 重建

页面里每次 `map` 关联一个独立 div；旧 div 先清空，再挂新 div：

```js
function createNewMapDivId() {
  const parent = document.getElementById("map");
  parent.innerHTML = "";
  const d = document.createElement("div");
  d.id = vjmap.RandomID(6);
  d.style.cssText = "position:absolute;width:100%;height:100%;";
  parent.appendChild(d);
  return d.id;
}
```

这种写法一般不推荐（会丢失引用），但做 A/B 测试或特殊调试时有用。

## 五、切图层（不切图）

不是换图，而是开关某些图层。**栅格 vs 矢量走两条不同路径**：

### 栅格瓦片：通过后端样式

```js
await map.switchLayers(svc, onLayerNames);
// onLayerNames: ["图层A", "图层C"]  数组里的图层会显示，其他隐藏
```

### 矢量瓦片：通过前端 filter

思路是修改每个矢量图层的 `filter` 表达式，按 `layer` 索引过滤：

```js
const onIdx = onLayerNames.map(name =>
  svc.getMapLayers().findIndex(l => l.name === name)
);
if (onIdx.length === 0) onIdx.push(-1);
const filter = ["match", ["get", "layer"], onIdx, true, false];

const style = map.getStyle();
const vectorStyle = svc.vectorStyle();
const vectorIds = new Set(vectorStyle.layers.map(l => l.id));
for (const layer of style.layers) {
  if (vectorIds.has(layer.id)) layer.filter = filter;
}
map.setStyle(style);
```

## 六、常见坑

1. **`map.remove()` vs `map.destory()`**：`remove` 释放 WebGL 上下文等底层资源；`destory` 是 vjmap 扩展（兼容旧代码，内部会调用 remove 并清理 svc/prj 引用）。切图前用 `destory` 更彻底。
2. **切图后拿到旧 `svc`** → `map.switchMap` 只换 map；如果要同时换服务，需要重新 `new vjmap.Service` 并 `map.attach(newSvc, newPrj)`。
3. **切图时大量历史监听没清** → `map.off` 所有业务监听或统一通过一个 bus 管理。
4. **用 `switchMap` 却传了不兼容的 `mapopenway`** → 报错或空白。建议切图前先确认新图的打开方式。
