唯杰地图 logo唯杰地图
VJMAP
EN

theme-switch

vjmap/references/map-style/theme-switch.md 4.0 KB120 行
原文

本文回答: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)

九、常见坑

  1. 切换主题后 CAD 图没变 → 只调了 svc.cmdUpdateStyle 没刷瓦片(用 map.updateStyle 或补 map.changeSourceTiles),或没传对 svrStyleVar。
  2. 白闪问题:背景色没改。
  3. 同时打开 light + dark 两张地图对比:用不同 map 实例,各自 style。
  4. 用户自定义 CAD 图层色 vs 主题色:主题色通常是"反色"逻辑,前端改 CAD 图层独立颜色时需关闭反色。