createui-no-theme
本文回答:控件 / Popup / Marker 显示异常 —— 缺 vjmap 主题 CSS。
一、症状
- 缩放控件
+/-按钮没边框、没图标 - Popup 尖角不对 / 颜色全白 / 字体异常
- 比例尺、全屏按钮错位
- vjmapext 的命令行 UI 空白(
createUI未调用的典型表现)
二、根因:未引入 CSS
vjmap 的内置 UI 依赖样式表:
<link rel="stylesheet" href="https://vjmap.com/demo/js/vjmap/vjmap.min.css" />
npm:
import 'vjmap/dist/vjmap.min.css';
vjmapext 没有独立 CSS 文件(dist/ 只有 vjmapext.min.js + vjmapext.d.ts)——它的 UI 样式由 createUI 内置主题管理器用 JS 注入 <style data-mapcad-theme>(buildCSS() 生成,mapcad-ui / data-theme / mapcad-* 前缀),不需要也不能 import css。
三、检查是否已加载
DevTools → Network 过滤 CSS → 应看到:
vjmap.min.css200
(vjmapext 样式不走网络——在 Elements 里找 <style data-mapcad-theme> 节点;没有则说明 createUI 没被调用。)
四、npm 方式
main.js:
import 'vjmap/dist/vjmap.min.css';
import * as vjmap from 'vjmap';
Vite 下这样就会自动打包 CSS。
五、按需加载
如果不用 vjmapext UI,只用核心功能:
import * as vjmapext from 'vjmapext';
用 UI 组件也只是调 createUI()——样式由 JS 注入,无需额外 import。
六、CSS 类名命名
vjmap 内置 UI 元素一律使用 vjmapgis-* 前缀的 CSS 类名,如:
.vjmapgis-map
.vjmapgis-canvas-container
.vjmapgis-canvas
.vjmapgis-popup
.vjmapgis-popup-content
.vjmapgis-popup-tip
.vjmapgis-popup-close-button
.vjmapgis-ctrl
.vjmapgis-ctrl-group
.vjmapgis-marker
自定义样式时用这些类名覆写 —— 而不是改名。
vjmapext UI 用另一套前缀:
mapcad-*(容器mapcad-ui、主题属性data-theme="dark|light"、注入节点style[data-mapcad-theme])。
七、Scoped CSS 陷阱
Vue scoped 样式不会作用于动态插入的 DOM:
<style scoped>
.vjmapgis-popup { border: 1px solid red; } /* 不生效 */
</style>
修法:
<style scoped>
::v-deep .vjmapgis-popup { border: 1px solid red; }
</style>
或用全局样式:
<style>
.vjmapgis-popup { border: 1px solid red; }
</style>
八、主题变量
某些场景下 vjmap UI 支持 CSS 变量切换主题:
:root {
--vj-primary: #2188ff;
--vj-bg: #fff;
--vj-text: #222;
}
[data-theme="dark"] {
--vj-primary: #4fc3f7;
--vj-bg: #1e1e1e;
--vj-text: #ddd;
}
切换 <html data-theme="dark"> 即可换色(UI 组件支持时有效)。
九、createUI 自定义 UI
vjmapext 的 createUI 方法生成命令行 / 工具栏 DOM,并把主题样式以 <style data-mapcad-theme> 注入容器:
import * as vjmapext from 'vjmapext';
const mapcadLayer = new vjmapext.MapCadLayer();
map.addControl(mapcadLayer);
const ui = mapcadLayer.createUI({ theme: 'dark' }); // 'dark' | 'light',生成命令栏等 DOM + 注入样式
// 运行期换肤:ui.setTheme('light') / ui.getTheme()
createUI 返回 ToolbarManager(不接收返回值就丢掉控制面)——程序化控制内置 UI:
ui.showToolbar() / hideToolbar() / toggleToolbar() / isToolbarVisible()
ui.setToolbarPinned(pinned) / isToolbarCollapsed()
ui.showPropertyPanel() / hidePropertyPanel() / togglePropertyPanel()
ui.showCommandInput() / hideCommandInput() / setAutoShowCommandInput(auto)
ui.showDrawOptions() / hideDrawOptions() // 绘图选项面板
ui.showAll() / ui.hideAll()
ui.setExportDwgCallback(cb) // 接管导出 DWG 完成回调(不再弹默认对话框)
mapcadLayer.getUI() 可取回上一次 createUI() 创建的同一实例。
如果 createUI 没被调用(或容器被重建后样式节点丢失)→ DOM 在但样式全无 → 看起来"UI 错乱"。重建 UI 时先销毁旧实例:createUI() 每次都 new 一个 ToolbarManager 挂上去,不会释放上一个(重复工具栏 + eventBus 上残留旧监听):
mapcadLayer.getUI()?.dispose(); // 摘 DOM + off 掉它挂的 eventBus 监听
mapcadLayer.createUI({ theme: 'dark' });
十、CDN vs npm 共存冲突
同一页同时 CDN 加 vjmap.min.css,npm 里又 import → 两份 CSS,后加载的胜出。一般无害,但注意版本一致。
十一、主题 CSS 重写顺序
<link rel="stylesheet" href="https://vjmap.com/demo/js/vjmap/vjmap.min.css" />
<link rel="stylesheet" href="./my-theme.css" /> <!-- 后加载,可覆盖 -->
npm:
import 'vjmap/dist/vjmap.min.css';
import './my-theme.css';
后加载的优先级高。
十二、第三方 UI 冲突
Ant Design / Element 的 .ant-btn 可能和 vjmap .vjmapgis-ctrl 样式冲突:
.ant-btn { all: unset; ... }
这种全局 reset 会破坏 vjmap 控件。修法:
.my-app .ant-btn { ... } /* 限定作用域 */
或用 ID / 类作为"沙箱"。
十三、常见坑
- 生产环境没打包 CSS:Vite 把开发时 CSS import 进了 HMR 但未打进产物;检查
dist/下有没有 css。 - CSS 404:URL 错;浏览器没警告但样式全失。
- 用了
* { box-sizing: border-box; }全局 reset:vjmap 某些布局受影响;用类限制作用域。 - iframe 里 CSS 没继承:iframe 独立 DOM,需独立 import CSS。
- 小程序 / WebView 环境:CSS 路径需相对,检查打包产物。
相关
- 安装 → setup/install
- 控件 → interaction/controls
- Popup 样式 → popup/styling