A CesiumJS plugin that provides an interactive scene tree panel for BimAngle-exported 3D Tiles datasets.
基于 CesiumJS 的场景树扩展插件,用于在 Cesium Viewer 中加载和管理 BimAngle 导出的 3D Tiles 数据集时提供可交互的场景树面板。
- 🔍 Auto-detect BimAngle 3D Tiles datasets via
asset.extras.engine.info
自动识别 BimAngle 3D Tiles 数据集 - 🌲 Floating scene tree panel — collapsible, draggable, resizable
悬浮场景树面板 — 可折叠、可拖拽、可调整大小 - ⚡ Virtual scrolling — DOM rows capped at ~50, supports datasets with tens of thousands of nodes
虚拟滚动 — DOM 行上限约 50,支持数万节点的大型数据集 - 🔀 Multi-dataset switching — dropdown selector manages multiple simultaneous tilesets
多数据集切换 — 下拉选择器管理多个同时加载的 tileset - 👁 Node visibility toggle — checkbox cascades to all descendants
节点显示/隐藏 — 勾选框级联控制子孙节点 - 📍 Zoom to node — double-click flies the camera to the node's bounding sphere
缩放定位 — 双击飞行至节点包围盒(兼容 ECEF 和 ENU 坐标模式) - 🔗 Bidirectional sync with
cesium-info-accessor— click a tree node to show properties; pick a feature in the viewport to highlight the tree node
与cesium-info-accessor双向联动 — 点击树节点显示属性;在 Cesium 画面点选构件后场景树自动高亮对应节点 - 🌐 Bilingual UI — automatically uses Simplified Chinese or English based on
navigator.language
双语界面 — 根据navigator.language自动切换简体中文或英文 - 🚫 Zero runtime dependencies — only peer-depends on Cesium
零运行时依赖 — 仅依赖 Cesium
npm install @bimangle/cesium-scene-tree<!-- 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-scene-tree -->
<script src="https://unpkg.com/@bimangle/cesium-scene-tree/dist/cesium-scene-tree.js"></script><!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-info-accessor/dist/cesium-info-accessor.js"></script>
<script src="https://unpkg.com/@bimangle/cesium-scene-tree/dist/cesium-scene-tree.js"></script>
<style>
html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<script type="module">
const viewer = new Cesium.Viewer('cesiumContainer');
// Step 1: Load cesium-info-accessor FIRST.
// SceneTreeMixin will auto-detect viewer.infoAccessor at init time
// and subscribe to its selectionChanged event — no extra wiring needed.
viewer.extend(InfoAccessorMixin, { autoAttach: true });
// Step 2: Load the scene tree plugin.
// onNodeSelect is optional; bidirectional sync with infoAccessor is automatic.
viewer.extend(CesiumSceneTree.SceneTreeMixin, {
onNodeSelect: (tileset, dbId, name) => {
console.log('Node selected:', name, 'dbId:', dbId);
}
});
// Step 3: Add a BimAngle 3D Tiles dataset — auto-detected by both plugins.
const tileset = await Cesium.Cesium3DTileset.fromUrl('./tileset.json');
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);
</script>
</body>
</html>import * as Cesium from 'cesium';
import { SceneTreeMixin } from '@bimangle/cesium-scene-tree';
const viewer = new Cesium.Viewer('cesiumContainer');
viewer.extend(SceneTreeMixin, {
onNodeSelect: (tileset, dbId, name) => {
console.log('Selected:', name, dbId);
},
// showInfoNodes: true // show nodes that have no geometry (property-only nodes)
});Mixin function to be called via viewer.extend(SceneTreeMixin, options).
After calling, viewer.sceneTree exposes the SceneTree instance.
| Option | Type | Default | Description |
|---|---|---|---|
onNodeSelect |
function |
— | Callback fired when a tree node is clicked: (tileset, dbId, name) => void |
showInfoNodes |
boolean |
false |
Show nodes whose boundingBoxes[dbId] is null (pure property/info nodes with no geometry) |
Destroy the plugin: removes the DOM panel, unregisters all event listeners, and clears internal state.
viewer.sceneTree.destroy();A tileset is recognized as a BimAngle dataset when:
tileset.asset.extras.engine.info === trueinfo/index.jsonis present under the tileset root directory
When a component is picked in the Cesium viewport via cesium-info-accessor:
- If the scene tree panel is collapsed → the sync event is ignored entirely (no panel auto-expansion).
- If the picked component belongs to a different dataset → the plugin switches datasets first and shows a status message ("Switching dataset..." / "正在切换数据集...") with a 60-second timeout.
- Once the target dataset is ready, the tree expands the path to the node, scrolls it into view, and highlights it.
Checking/unchecking a node's checkbox cascades the visibility change to all descendant nodes. The actual feature.show property on each Cesium3DTileFeature is updated as tiles load/unload.
Double-clicking a tree node flies the camera to the node's bounding sphere. The bounding box stored in index.json is automatically transformed to ECEF using tileset.root.computedTransform, so both ECEF and ENU export modes are handled correctly.
db.boundingBoxes[dbId] coordinates depend on the export mode chosen at BimAngle export time:
- ECEF mode: coordinates are world-space ECEF (metres)
- ENU local mode: coordinates are model-local; the plugin applies
tileset.root.computedTransformautomatically
No extra configuration is needed — the plugin handles both cases transparently.
When db.boundingBoxes[dbId] === null, the node is an info node:
- It and all its descendants have no 3D geometry
- Hidden by default; enable with
showInfoNodes: true - Displayed with a distinct icon (◈) when visible
cesium-scene-tree is designed to work alongside cesium-info-accessor v2.0+.
No extra wiring is required — the scene tree subscribes to infoAccessor.selectionChanged automatically when both plugins are mounted on the same viewer.
// Mount both plugins — order matters: info-accessor first
viewer.extend(InfoAccessorMixin, { autoAttach: true });
viewer.extend(SceneTreeMixin, { showInfoNodes: false });
// Bidirectional sync works out of the box:
// • Click tree node → property panel opens
// • Pick in viewport → tree node highlighted (panel must be expanded)The loaded 3D Tiles must include a valid info/index.json file in BimAngle format:
<tileset root>/
├── tileset.json ← must have asset.extras.engine.info = true
├── info/
│ ├── index.json ← scene tree descriptor
│ └── 0.json, 1.json … ← property chunk files
└── 0/
└── … ← tile geometry
index.json schema (v1.4):
{
"version": "1.4",
"schema": "3D Tiles",
"db": {
"rootDbId": 1,
"parentIds": [-1, -1, 1, 1, 3],
"names": [null, "Project", "SubSet", "LayerA", "Column-1"],
"types": [-1, 5, 4, 2, 0],
"boundingBoxes": [null, [x1,y1,z1,x2,y2,z2], null, "..."]
}
}db.types value |
Meaning |
|---|---|
5 |
Model (root) |
4 |
Composite / assembly |
3 |
Collection |
2 |
Layer |
1 / 0 |
Leaf component (has geometry) |
- Cesium ≥ 1.110.0
- Chrome 90+, Firefox 88+, Edge 90+
All CSS classes use the ba-cst- prefix (ba = BimAngle, cst = cesium-scene-tree).
所有 CSS 类名采用 ba-cst- 前缀(ba = BimAngle,cst = cesium-scene-tree)。
⚠️ v2.0.0 Breaking Change: All class names were renamed from thecst-prefix toba-cst-. If your project overrides anycst-*styles with external CSS, those rules must be updated.
v2.0.0 破坏性变更:所有类名由cst-前缀统一更名为ba-cst-。如有外部 CSS 引用cst-*类名,需同步更新。
| Class / 类名 | Purpose / 用途 |
|---|---|
.ba-cst-panel |
Scene tree floating panel / 场景树浮动面板 |
.ba-cst-panel--hidden |
Panel hidden state / 面板隐藏态 |
.ba-cst-panel-header |
Panel title bar (draggable) / 面板标题栏(可拖拽) |
.ba-cst-panel-title |
Title text / 标题文字 |
.ba-cst-panel-close |
Panel close button / 面板关闭按钮 |
.ba-cst-panel-toolbar |
Panel toolbar area (dataset selector) / 面板工具栏(数据集选择器) |
.ba-cst-dataset-select |
Dataset dropdown selector / 数据集下拉选择框 |
.ba-cst-panel-body |
Panel content area / 面板内容区 |
.ba-cst-status-msg |
Status message (loading, empty, etc.) / 状态提示(加载中、无数据等) |
.ba-cst-error-msg |
Error message / 错误提示 |
.ba-cst-retry-btn |
Retry button / 重试按钮 |
.ba-cst-resize-handle |
Resize drag handle (bottom-right) / 调整大小句柄(右下角) |
.ba-cst-scroller |
Virtual-scroll container / 虚拟滚动容器 |
.ba-cst-row-container |
Absolute-positioned row wrapper / 绝对定位行容器 |
.ba-cst-row |
Single tree row / 单条树行 |
.ba-cst-row--selected |
Selected row state / 选中行 |
.ba-cst-row--info |
Info node row (dimmed) / Info 节点行(半透明) |
.ba-cst-indent |
Indentation spacer / 缩进占位 |
.ba-cst-expand-icon |
Expand/collapse icon / 展开收起图标 |
.ba-cst-expand-icon--leaf |
Leaf node icon (invisible) / 叶节点图标(不可见) |
.ba-cst-checkbox |
Visibility checkbox / 可见性复选框 |
.ba-cst-node-icon |
Node type icon / 节点类型图标 |
.ba-cst-node-name |
Node name label / 节点名称 |
.ba-cst-node-name--info |
Info node name style / Info 节点名称样式 |
.ba-cst-zoom-btn |
Zoom-to-node button (hover visible) / 缩放定位按钮(悬停显示) |
.ba-cst-zoom-btn--disabled |
Disabled zoom button / 禁用的缩放按钮 |
npm install
npm run build
# Output: dist/cesium-scene-tree.js- Bug fix: 修复 tileset URL 为
./tileset.json等相对路径时下拉框显示.或..的问题
- Improvement: 优化数据集下拉框名称规则:优先用
asset.extras.title,其次取 URL 上一级路径段(文件名为tileset.json时)
- Bug fix: 修复数据集无场景树信息时「无场景树」提示文字被
_scroller遮盖不可见的问题
- Bug fix: 修复手动调整面板大小后虚拟滚动不自动补充渲染新增可视行的问题(
ResizeObserver+ RAF)
- Bug fix: 修复虚拟滚动场景下,取消勾选父节点后向下滚动时子节点勾选框状态未同步的问题
- Initial release
- Virtual-scrolling scene tree panel with drag/resize support
- Multi-dataset dropdown switching
- Node visibility toggle (cascading)
- Double-click zoom to node bounding sphere (ECEF + ENU)
- Bidirectional sync with
cesium-info-accessorv2.0+ viaselectionChangedevent - Panel-collapsed reverse-sync ignore rule
- Dataset switching with 60-second timeout and status message
- Bilingual UI (Simplified Chinese / English)
MIT © BimAngle