npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

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.container is used
    纯 DOM 实现,不依赖 Cesium 本身(仅使用 viewer.container)
  • ⚡ Idempotent init — safe to call CesiumUIMixin from 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-ui

CDN

<!-- 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 instance

API 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.js

License / 许可证

MIT © BimAngle