theme-switch
本文回答:CAD 深色 / 浅色主题切换 ——
openMapDarkStyle/openMapLightStyle/svc.cmdUpdateStyle。
一、内置两套主题
// 浅色(白底黑线)
const res = await svc.openMap({
mapid,
mapopenway: vjmap.MapOpenWay.GeomRender,
style: vjmap.openMapLightStyle()
});
// 深色(黑底白线)
await svc.openMap({
mapid,
mapopenway: vjmap.MapOpenWay.GeomRender,
style: vjmap.openMapDarkStyle()
});
传给 openMap 的 style 是后端渲染表达式,不是前端样式规范。
二、openMapDarkStyle 实际是什么
vjmap.openMapDarkStyle(); // → { backcolor: 0 }
vjmap.openMapLightStyle(); // → { backcolor: 16777215 }(0xFFFFFF)
注意:返回值只有 backcolor 一个字段——深/浅主题的实际反色逻辑由服务端按 backcolor 推断(svc.currentMapParam().darkMode 也是 style.backcolor === 0 判定)。要自定义反色规则,在 style 里自行加 expression(见 backend/svr-style-var)。
三、动态切换主题
方式 A:重新 openMap
const res = await svc.openMap({
mapid: curMapId,
style: isDark ? vjmap.openMapDarkStyle() : vjmap.openMapLightStyle(),
mapopenway: vjmap.MapOpenWay.GeomRender
});
// 重新设置 map.style(setStyle 会清掉自定义 source/layer;只换主题优先用方式 B 的 map.updateStyle)
map.setStyle(svc.rasterStyle());
方式 B:只改后端样式 + 刷新瓦片
// map.updateStyle = svc.cmdUpdateStyle + 换瓦片 URL 刷新(栅格模式只换 tiles,自定义图层不丢)
await map.updateStyle(svc, {
name: "customStyle",
backcolor: 0,
expression: "gOutColorRed := 255 - gInColorRed; gOutColorGreen := 255 - gInColorGreen; gOutColorBlue := 255 - gInColorBlue;"
});
若已单独调过 svc.cmdUpdateStyle(...),再 map.changeSourceTiles(svc.rasterTileUrl()) 刷新。⚠️ raster 源没有 setTiles(只有 vector 源有),map.getSource(...).setTiles(...) 会抛 TypeError。
四、前端 div 背景色同步
深色主题时地图底色如果是白色,出现闪白。必须同步:
#map { background: #000; }
或 JS:
map.getContainer().style.background = isDark ? "#000" : "#fff";
五、UI 主题色
Marker / Popup / ContextMenu 都有 light / dark 选择:
new vjmap.ContextMenu({ event, theme: "dark", items: [...] });
new vjmap.Popup({ className: "dark-popup" });
Marker 和 Popup 的 CSS 可以通过 className 覆盖。
六、Marker 图标的明暗
如果 Marker 用 PNG,切换主题时可以切两张图:
marker.getElement().style.backgroundImage = `url(${isDark ? "pin-light.png" : "pin-dark.png"})`;
七、矢量 CAD 主题
矢量瓦片模式下,颜色存在 properties.color 里,可以用样式表达式动态反色:
// 矢量瓦片模式同样走 updateStyle:darkMode(backcolor)变化时,内部用 svc.vectorStyle() 的同名图层替换当前图层配色
await map.updateStyle(svc, { backcolor: isDark ? 0 : 0xFFFFFF });
(表达式里不能调用 JS 函数,invertHex(["get", "color"]) 之类写法无法运行。)
更简单的做法:提前在前端写两套配色。
八、互联网地图主题
| 底图 | 深色样式 |
|---|---|
| 高德 | 无公开的深色 XYZ 样式:style=8 是矢量道路图,style=6 是卫星影像(不是黑夜样式) |
| 天地图 | T=vec_w(白底) / T=ter_w(地形) |
| 标准国际底图 | streets-v12 / dark-v11 / light-v11 等主题 |
| 百度 | v1 / dark / midnight(需参数 customid) |
九、常见坑
- 切换主题后 CAD 图没变 → 只调了
svc.cmdUpdateStyle没刷瓦片(用map.updateStyle或补map.changeSourceTiles),或没传对svrStyleVar。 - 白闪问题:背景色没改。
- 同时打开 light + dark 两张地图对比:用不同 map 实例,各自 style。
- 用户自定义 CAD 图层色 vs 主题色:主题色通常是"反色"逻辑,前端改 CAD 图层独立颜色时需关闭反色。