唯杰地图 logo唯杰地图
VJMAP
EN

createui-no-theme

vjmapext/references/trouble/createui-no-theme.md 5.7 KB205 行
原文

本文回答:控件 / 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.css 200

(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 / 类作为"沙箱"。

十三、常见坑

  1. 生产环境没打包 CSS:Vite 把开发时 CSS import 进了 HMR 但未打进产物;检查 dist/ 下有没有 css。
  2. CSS 404:URL 错;浏览器没警告但样式全失。
  3. 用了 * { box-sizing: border-box; } 全局 reset:vjmap 某些布局受影响;用类限制作用域。
  4. iframe 里 CSS 没继承:iframe 独立 DOM,需独立 import CSS。
  5. 小程序 / WebView 环境:CSS 路径需相对,检查打包产物。

相关