switching
本文回答:三种切换当前图的方式(保留 map / 销毁重建 / 换 div),以及图层级开关控制。
一、三种切图方式
| 方式 | 什么时候用 | 优劣 |
|---|---|---|
map.switchMap({mapid}) |
同一 map 对象,切换服务端的另一张图 | 状态保留、但必须确保两张图的打开方式一致 |
map.destory() + new vjmap.Map(...) |
想换空白图 / 换打开方式 | 彻底重来,代价高 |
重建 div + 新 map |
DOM 结构需要刷新 | 最彻底,但闪一下 |
二、switchMap(推荐)
// 签名
map.switchMap(
param, // IOpenMapParam:与 svc.openMap 同结构
isKeepOldLayers, // 可选,是否保留之前添加的图层,默认 false
isVectorStyle, // 可选
isSetCenter, // 可选,是否默认设中心点
isFitBounds, // 可选,默认是否 fit
source // 可选,source id
): Promise;
使用:
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 事件:
map.on("mapopenstart", () => showLoading());
map.on("mapopenfinish", () => hideLoading());
三、销毁地图
map.destory(); // 注意:是 destory,不是 destroy(历史拼写)
然后就可以 new vjmap.Map(...) 挂到同一个 div 上。典型流程:
setInterval(async () => {
map.destory();
map = await newMap(SERVICE_URL, NEXT_MAPID);
}, 10_000);
newMap 是自己封装的完整 "打开 + 关联 + onLoad + 加业务图层" 流程。
四、换 div 重建
页面里每次 map 关联一个独立 div;旧 div 先清空,再挂新 div:
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 矢量走两条不同路径:
栅格瓦片:通过后端样式
await map.switchLayers(svc, onLayerNames);
// onLayerNames: ["图层A", "图层C"] 数组里的图层会显示,其他隐藏
矢量瓦片:通过前端 filter
思路是修改每个矢量图层的 filter 表达式,按 layer 索引过滤:
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);
六、常见坑
map.remove()vsmap.destory():remove释放 WebGL 上下文等底层资源;destory是 vjmap 扩展(兼容旧代码,内部会调用 remove 并清理 svc/prj 引用)。切图前用destory更彻底。- 切图后拿到旧
svc→map.switchMap只换 map;如果要同时换服务,需要重新new vjmap.Service并map.attach(newSvc, newPrj)。 - 切图时大量历史监听没清 →
map.off所有业务监听或统一通过一个 bus 管理。 - 用
switchMap却传了不兼容的mapopenway→ 报错或空白。建议切图前先确认新图的打开方式。