@bimangle/cesium-ui
v1.0.0
Published
A lightweight UI framework for Cesium viewer plugins, providing toolbar, notification stack, and future UI elements.
Downloads
30
Maintainers
Readme
@bimangle/cesium-ui
A lightweight UI framework for CesiumJS plugins, providing a shared toolbar button strip and notification stack — so multiple plugins can coexist on the same viewer without their buttons overlapping.
面向 CesiumJS 插件的轻量级 UI 框架,提供统一的工具栏按钮条和通知弹窗堆叠机制,解决多插件按钮在 viewer.container 上相互覆盖的问题。
Features / 特性
- 🧩 Pure DOM — no Cesium runtime dependency; only
viewer.containeris used
纯 DOM 实现,不依赖 Cesium 本身(仅使用viewer.container) - ⚡ Idempotent init — safe to call
CesiumUIMixinfrom multiple plugins; the framework initializes only once
幂等初始化:多个插件调用CesiumUIMixin时,框架只初始化一次 - 🔧 Button registration — plugins call
register()to add buttons to the shared toolbar; buttons are laid out automatically
按钮注册机制:各插件通过register()将工具按钮添加到共享工具条,自动排列不重叠 - 🔔 Notification stack — multiple cards stack automatically; each card can be closed individually or all at once
通知弹窗堆叠:支持多条弹窗自动叠放,可单独关闭或一键清除全部 - 🌐 Bilingual UI — automatically uses Simplified Chinese or English based on
navigator.language
双语界面:根据navigator.language自动切换简体中文 / 英文
Installation / 安装
NPM
npm install @bimangle/cesium-uiCDN
<!-- Cesium must be loaded first / 必须先加载 Cesium -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- Then include cesium-ui / 再引入 cesium-ui -->
<script src="https://unpkg.com/@bimangle/cesium-ui/dist/cesium-ui.js"></script>Quick Start / 快速开始
Browser (CDN)
<!DOCTYPE html>
<html>
<head>
<script src="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<script src="https://unpkg.com/@bimangle/cesium-ui/dist/cesium-ui.js"></script>
<style>
html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
const viewer = new Cesium.Viewer('cesiumContainer');
// Initialize the UI framework.
// 初始化 UI 框架。
viewer.extend(CesiumUIMixin, {
position: 'top-left', // toolbar position / 工具条位置
direction: 'vertical', // toolbar direction / 工具条方向
notificationPosition: 'bottom-right', // notification stack position / 通知弹窗位置
});
// Access the instance / 访问实例
// viewer.cesiumUI → CesiumUI instance
</script>
</body>
</html>NPM / ES Modules
import * as Cesium from 'cesium';
import { CesiumUIMixin } from '@bimangle/cesium-ui';
const viewer = new Cesium.Viewer('cesiumContainer');
// Optional — plugins will call this automatically with default options if omitted.
// 可选:各插件会在需要时以默认参数自动调用,也可以提前手动指定配置。
viewer.extend(CesiumUIMixin, {
position: 'top-left', // toolbar position / 工具条位置
direction: 'vertical', // toolbar direction / 工具条方向
notificationPosition: 'bottom-right', // notification stack position / 通知弹窗位置
});
// Access the instance / 访问实例
// viewer.cesiumUI → CesiumUI instanceAPI Reference
CesiumUIMixin(viewer, options?)
Initializes the UI framework and attaches a CesiumUI instance to viewer.cesiumUI.
Idempotent — if viewer.cesiumUI already exists the call is a no-op; subsequent options are ignored.
初始化 UI 框架并将 CesiumUI 实例挂载到 viewer.cesiumUI。
幂等:若 viewer.cesiumUI 已存在,则直接返回,不重复初始化;后续传入的 options 会被忽略。
| Parameter / 参数 | Type / 类型 | Default / 默认值 | Description / 说明 |
|------------------|-------------|------------------|-------------------|
| viewer | Cesium.Viewer | — | Target viewer / 目标 Viewer 实例 |
| options.position | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-left' | Toolbar corner / 工具条位置 |
| options.direction | 'vertical' | 'horizontal' | 'vertical' | Button layout direction / 工具条排列方向 |
| options.notificationPosition | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'bottom-right' | Notification stack corner / 通知弹窗堆叠位置 |
| options.panelCascadeDirection | 'right' | 'down' | 'right' | Direction to cascade sub-panels to avoid overlap / 子面板重叠时的错开方向 |
CesiumUI — via viewer.cesiumUI
Toolbar API / 工具条 API
register(descriptor) → ButtonHandle
Registers a button on the toolbar. If the id already exists the existing button is replaced (hot-update safe).
向工具条注册一个按钮。若 id 已存在则覆盖(可用于热更新)。
const handle = viewer.cesiumUI.register({
id: 'my-tool', // unique key / 唯一标识符
icon: '🔧', // icon character or text / 显示图标(Unicode 字符或文本)
title: 'My Tool', // tooltip / 鼠标悬停提示
onClick: (handle) => { ... } // click callback / 点击回调,参数为 ButtonHandle
});setActive(id, active)
Sets the active (highlighted) state of a button.
设置按钮激活(高亮)状态。
viewer.cesiumUI.setActive('my-tool', true);unregister(id)
Removes a registered button.
移除已注册的按钮。
viewer.cesiumUI.unregister('my-tool');Notification API / 通知弹窗 API
notify(options) → NotificationHandle
Pushes a notification card. New cards are appended at the bottom; older cards shift upward.
Cards do not auto-dismiss — the user must close them manually.
推送一条通知弹窗。新弹窗从底部追加,旧弹窗向上推移。弹窗不会自动消失,需用户手动关闭。
const notif = viewer.cesiumUI.notify({
title: 'Done',
content: '<b>Coordinate:</b> 30.12°N, 120.34°E', // HTML string or HTMLElement
onClose: () => { /* optional close callback */ }
});When there are ≥ 2 cards, a Clear All button appears at the bottom of the stack.
当弹窗数量 ≥ 2 时,弹窗容器底部自动显示清除全部按钮。
clearNotifications()
Closes and removes all notification cards.
关闭并移除所有通知弹窗。
viewer.cesiumUI.clearNotifications();Toolbar helpers / 工具条辅助
getStripRect() → DOMRect
Returns getBoundingClientRect() of the toolbar strip element.
Sub-panels can use this to position themselves next to the toolbar.
返回工具条元素的 getBoundingClientRect() 结果,子面板可用此方法将自身定位到工具条旁边。
direction / position
Read-only properties returning the current direction and position strings.
只读属性,返回当前工具条的方向和位置字符串。
Panel Registry API / 子面板注册 API
Plugin sub-panels should register themselves when visible so the shared cascade logic can avoid overlaps.
插件子面板应在可见时进行注册,以便共享的错开逻辑避免重叠。
registerPanel(el)
Registers a visible panel element.
注册一个当前可见的子面板元素。
unregisterPanel(el)
Unregisters a panel element (call when the panel is hidden or destroyed).
取消注册(面板隐藏或销毁时调用)。
findFreePosition(left, top, panelEl) → {left, top}
Starting from the given (left, top) offset (relative to the viewer container), shifts the position along panelCascadeDirection in 8 px steps until the given panelEl no longer overlaps any registered panel.
Returns the adjusted {left, top}.
以给定的 (left, top)(相对于容器)为起点,沿 panelCascadeDirection 方向以 8 px 为步长逐步偏移,直到不与已注册的其他子面板发生重叠。返回调整后的 {left, top}。
viewer.extend(CesiumUIMixin, { panelCascadeDirection: 'right' });
// In your plugin's show() method:
const pos = viewer.cesiumUI.findFreePosition(initialLeft, initialTop, myPanelEl);
myPanelEl.style.left = pos.left + 'px';
myPanelEl.style.top = pos.top + 'px';
viewer.cesiumUI.registerPanel(myPanelEl);
// In your plugin's hide() method:
viewer.cesiumUI.unregisterPanel(myPanelEl);Lifecycle / 生命周期
destroy()
Destroys the UI framework, removes all DOM elements, and clears internal state.
销毁 UI 框架,移除所有 DOM 元素并清理内部状态。
ButtonHandle
Return value of register().register() 的返回值。
| Member / 成员 | Description / 说明 |
|---------------|-------------------|
| id | Unique button key (read-only) / 按钮唯一标识符(只读) |
| setActive(active) | Shorthand for cesiumUI.setActive(id, active) |
| remove() | Shorthand for cesiumUI.unregister(id) |
NotificationHandle
Return value of notify().notify() 的返回值。
| Member / 成员 | Description / 说明 |
|---------------|-------------------|
| close() | Closes and removes this notification card / 关闭并移除该条通知 |
Visual Layout / 视觉样式
Toolbar (direction: 'vertical', position: 'top-left'):
工具条(direction: 'vertical',position: 'top-left'):
┌──┐ ← top: 8px, left: 8px
│🌲│ ← scene-tree button
├──┤
│📐│ ← measure button (border highlights when active / 激活时边框高亮)
└──┘Notification stack (notificationPosition: 'bottom-right', newest card at bottom):
通知弹窗堆叠(notificationPosition: 'bottom-right',新弹窗在底部):
┌──────────────────────────────┬───┐
│ 📍 Coordinate Result │ × │
├──────────────────────────────┴───┤
│ Latitude: 30.12345678° │
│ Longitude: 120.12345678° │
│ Height: 45.2341 m │
└──────────────────────────────────┘
┌──────────────────────────────┬───┐
│ 📐 Distance Result │ × │
├──────────────────────────────┴───┤
│ Distance: 123.46 m │
└──────────────────────────────────┘
[ Clear All ]Plugin Developer Guide / 插件开发者接入指南
This package is the shared infrastructure for all BimAngle CesiumJS plugins.
本包设计为所有 BimAngle CesiumJS 插件的共享基础设施。
function MyPluginMixin(viewer, options) {
// Safe to call even if already initialized — idempotent.
// 幂等调用,已初始化时安全忽略。
viewer.extend(CesiumUIMixin);
const handle = viewer.cesiumUI.register({
id: 'my-plugin',
icon: '🔧',
title: 'My Plugin',
onClick: () => myPanel.toggle()
});
let _userMoved = false;
function expand() {
handle.setActive(true);
if (!_userMoved) {
// Position next to toolbar, then cascade to avoid other panels.
// 先定位到工具条旁,再错开已有面板。
const stripRect = viewer.cesiumUI.getStripRect();
const cRect = viewer.container.getBoundingClientRect();
const initLeft = stripRect.right - cRect.left + 6;
const initTop = stripRect.top - cRect.top;
const pos = viewer.cesiumUI.findFreePosition(initLeft, initTop, myPanelEl);
myPanelEl.style.left = pos.left + 'px';
myPanelEl.style.top = pos.top + 'px';
}
viewer.cesiumUI.registerPanel(myPanelEl);
}
function collapse() {
handle.setActive(false);
viewer.cesiumUI.unregisterPanel(myPanelEl);
}
function destroy() {
handle.remove();
viewer.cesiumUI.unregisterPanel(myPanelEl);
}
}
// Mount the plugin / 挂载插件
viewer.extend(MyPluginMixin);CSS Class Reference / CSS 命名规范
All CSS classes use the ba-ctb- prefix (ba = BimAngle, ctb = cesium-toolbar).
所有 CSS 类名采用 ba-ctb- 前缀(ba = BimAngle,ctb = cesium-toolbar)。
| Class / 类名 | Purpose / 用途 |
|-------------|---------------|
| .ba-ctb-strip | Toolbar container / 工具条容器 |
| .ba-ctb-btn | Single toolbar button / 单个工具按钮 |
| .ba-ctb-btn--active | Active (highlighted) button state / 按钮激活态 |
| .ba-ctb-notification-stack | Notification stack container / 通知弹窗堆叠容器 |
| .ba-ctb-notification | Single notification card / 单条通知卡片 |
| .ba-ctb-notification-header | Card title bar / 通知标题栏 |
| .ba-ctb-notification-body | Card content area / 通知内容区 |
| .ba-ctb-notification-close | Per-card close button / 单条关闭按钮 |
| .ba-ctb-notification-clear-all | Clear-all button / 清除全部按钮 |
Compatibility / 兼容性
- Chrome 90+, Firefox 88+, Edge 90+
- No Cesium version constraint (DOM-only)
无 Cesium 版本限制(纯 DOM 实现)
Build / 构建
npm install
npm run build
# Output: dist/cesium-ui.jsLicense / 许可证
MIT © BimAngle
