22 KiB
Toolbar 按钮调用链文档
本文档详细记录 Toolbar 中每个按钮的完整调用链,从用户点击到底层 3D 引擎 API。
目录
- 首页 (Home)
- 框选放大 (Zoom Box)
- 测量 (Measure)
- 剖切菜单 (Section)
- 漫游 (Walk)
- 地图 (Map)
- 构件详情 (Property)
- 设置 (Setting)
- 信息 (Info)
- 全屏 (Fullscreen)
1. 首页 (Home)
按钮 ID: home
功能: 相机回到初始位置(主视角)
保持激活: 否
调用链
用户点击 [首页] 按钮
│
▼
Button onClick (buttons/home/index.ts)
│ registry.engine3d?.CameraGoHome()
▼
EngineManager.CameraGoHome() (managers/engine-manager.ts)
│ this.engineInstance.CameraGoHome()
▼
Engine.CameraGoHome() (components/engine/index.ts)
│ this.engine.viewCube.CameraGoHome()
▼
底层引擎 API: engine.viewCube.CameraGoHome()
代码摘要
按钮定义 (buttons/home/index.ts):
onClick: (button) => {
const registry = ManagerRegistry.getInstance();
registry.engine3d?.CameraGoHome();
}
EngineManager (managers/engine-manager.ts):
public CameraGoHome(): void {
this.engineInstance.CameraGoHome();
}
Engine 组件 (components/engine/index.ts):
public CameraGoHome() {
this.engine.viewCube.CameraGoHome();
}
2. 框选放大 (Zoom Box)
按钮 ID: zoom-box
功能: 激活框选放大模式,用户可以框选区域进行放大
保持激活: 否
调用链
用户点击 [框选放大] 按钮
│
▼
Button onClick (buttons/zoom-box/index.ts)
│ registry.engine3d?.activateZoomBox()
▼
EngineManager.activateZoomBox() (managers/engine-manager.ts)
│ this.engineInstance.activateZoomBox()
▼
Engine.activateZoomBox() (components/engine/index.ts)
│ this.engine.rangeScale?.active()
▼
底层引擎 API: engine.rangeScale.active()
代码摘要
按钮定义 (buttons/zoom-box/index.ts):
onClick: () => {
const registry = ManagerRegistry.getInstance();
registry.engine3d?.activateZoomBox();
}
EngineManager (managers/engine-manager.ts):
public activateZoomBox(): void {
this.engineInstance.activateZoomBox();
}
Engine 组件 (components/engine/index.ts):
public activateZoomBox(): void {
this.engine.rangeScale?.active();
}
3. 测量 (Measure)
按钮 ID: measure
功能: 打开测量对话框,支持距离、角度、标高、体积等多种测量
保持激活: 是
调用链
3.1 打开测量对话框
用户点击 [测量] 按钮(激活)
│
▼
Button onClick (buttons/measure/index.ts)
│ registry.measure?.show()
▼
MeasureDialogManager.show() (继承自 BaseDialogManager)
│ createContent() → 创建 MeasurePanel
│ onDialogCreated()
▼
对话框显示,等待用户选择测量模式
3.2 用户选择测量模式
用户在 Panel 中选择测量模式(如:距离测量)
│
▼
MeasurePanel.onModeChange('distance')
│
▼
MeasureDialogManager 回调 (managers/measure-dialog-manager.ts)
│ registry.engine3d?.activateMeasure(mode)
▼
EngineManager.activateMeasure('distance') (managers/engine-manager.ts)
│ this.engineInstance.activateMeasure(mode)
▼
Engine.activateMeasure('distance') (components/engine/index.ts)
│ switch(mode) → activateDistanceMeasure()
▼
Engine.activateDistanceMeasure()
│ this.engine.measure.active() // 激活主测量模块
│ this.engine.measure.distanceMeasure.active() // 激活距离测量
▼
底层引擎 API:
- engine.measure.active()
- engine.measure.distanceMeasure.active()
3.3 清除所有测量
用户点击 [删除全部] 按钮
│
▼
MeasurePanel.onClearAll()
│
▼
MeasureDialogManager 回调
│ registry.engine3d?.clearAllMeasures()
▼
EngineManager.clearAllMeasures()
│ this.engineInstance.clearAllMeasures()
▼
Engine.clearAllMeasures()
│ this.engine.measure.clearAll()
▼
底层引擎 API: engine.measure.clearAll()
3.4 关闭测量对话框
用户关闭对话框 / 再次点击按钮
│
▼
MeasureDialogManager.onBeforeDestroy()
│ registry.engine3d.deactivateMeasure()
▼
EngineManager.deactivateMeasure()
│ this.engineInstance.deactivateMeasure()
▼
Engine.deactivateMeasure()
│ this.engine.measure.disActive()
▼
底层引擎 API: engine.measure.disActive()
测量模式与底层 API 对照表
| 模式 | Engine 方法 | 底层 API |
|---|---|---|
| distance (距离) | activateDistanceMeasure() |
engine.measure.distanceMeasure.active() |
| minDistance (最小距离) | activateMinDistanceMeasure() |
engine.measure.clearDistanceMeasure.active() |
| angle (角度) | activateAngleMeasure() |
engine.measure.angleMeasure.active() |
| elevation (标高) | activateElevationMeasure() |
engine.measure.elevationMeasure.active() |
| volume (体积) | activateVolumeMeasure() |
engine.measure.areaMeasure.active() |
| slope (坡度) | activateSlopeMeasure() |
engine.measure.slopeMeasure.active() |
| laserDistance (激光测距) | activateLaserDistanceMeasure() |
⚠️ 暂未实现 |
| spaceVolume (空间体积) | activateSpaceVolumeMeasure() |
⚠️ 暂未实现 |
4. 剖切菜单 (Section)
按钮 ID: section
类型: 菜单按钮,展开后显示子按钮
4.1 拾取面剖切 (Section Plane)
按钮 ID: section-plane
功能: 拾取模型表面进行剖切
保持激活: 是
互斥: 是(同一时间只能激活一种剖切)
调用链
用户点击 [拾取面剖切] 按钮(激活)
│
▼
Button onClick (buttons/section/section-plane/index.ts)
│ registry.sectionPlane?.show()
▼
SectionPlaneDialogManager.show() (继承自 BaseDialogManager)
│ createContent() → 创建 SectionPlanePanel
│ onDialogCreated()
▼
对话框显示(拾取面剖切需要用户在3D场景中点击表面)
⚠️ 注意: 拾取面剖切的底层 API 对接尚未完成,目前仅显示 UI 面板。
4.2 轴向剖切 (Section Axis)
按钮 ID: section-axis
功能: 沿 X/Y/Z 轴向进行剖切
保持激活: 是
互斥: 是
调用链 - 打开对话框
用户点击 [轴向剖切] 按钮(激活)
│
▼
Button onClick (buttons/section/section-axis/index.ts)
│ registry.sectionAxis?.show()
▼
SectionAxisDialogManager.show() (继承自 BaseDialogManager)
│ createContent() → 创建 SectionAxisPanel
│ onDialogCreated()
│ └── registry.engine3d.activateSectionAxis('x') // 默认激活 X 轴
▼
EngineManager.activateSectionAxis('x')
│ this.engineInstance.activateSectionAxis(axis)
▼
Engine.activateSectionAxis('x')
│ this.engine.clipping.sectionPlaneX.active()
▼
底层引擎 API: engine.clipping.sectionPlaneX.active()
调用链 - 切换轴向
用户在 Panel 中切换轴向(如:Y 轴)
│
▼
SectionAxisPanel.onAxisChange('y')
│
▼
SectionAxisDialogManager 回调
│ registry.engine3d?.activateSectionAxis('y')
▼
EngineManager.activateSectionAxis('y')
│ this.engineInstance.activateSectionAxis(axis)
▼
Engine.activateSectionAxis('y')
│ // 1. 先停用当前轴向 (X)
│ this.engine.clipping.sectionPlaneX.disActive()
│ // 2. 再激活新轴向 (Y)
│ this.engine.clipping.sectionPlaneY.active()
▼
底层引擎 API:
- engine.clipping.sectionPlaneX.disActive()
- engine.clipping.sectionPlaneY.active()
调用链 - 关闭对话框
用户关闭对话框 / 再次点击按钮
│
▼
SectionAxisDialogManager.onBeforeDestroy()
│ registry.engine3d?.deactivateSectionAxis()
▼
EngineManager.deactivateSectionAxis()
│ this.engineInstance.deactivateSectionAxis()
▼
Engine.deactivateSectionAxis()
│ this.engine.clipping.disActive()
▼
底层引擎 API: engine.clipping.disActive()
轴向与底层 API 对照表
| 轴向 | Engine 内部调用 | 底层 API |
|---|---|---|
| x | planeMap['x'] |
engine.clipping.sectionPlaneX.active() |
| y | planeMap['y'] |
engine.clipping.sectionPlaneY.active() |
| z | planeMap['z'] |
engine.clipping.sectionPlaneZ.active() |
4.3 剖切盒 (Section Box)
按钮 ID: section-box
功能: 六面体剖切盒,可调节 X/Y/Z 轴的最小/最大范围
保持激活: 是
互斥: 是
调用链 - 打开对话框
用户点击 [剖切盒] 按钮(激活)
│
▼
Button onClick (buttons/section/section-box/index.ts)
│ registry.sectionBox?.show()
▼
SectionBoxDialogManager.show() (继承自 BaseDialogManager)
│ createContent() → 创建 SectionBoxPanel
│ onDialogCreated()
│ └── registry.engine3d?.activateSectionBox()
▼
EngineManager.activateSectionBox()
│ this.engineInstance.activateSectionBox()
▼
Engine.activateSectionBox()
│ this.engine.clipping.sectionBox.active()
▼
底层引擎 API: engine.clipping.sectionBox.active()
调用链 - 调整范围(拖动滑块)
用户拖动 X/Y/Z 轴滑块调整范围
│
▼
SectionBoxPanel.onRangeChange(range)
│ range = { x: {min, max}, y: {min, max}, z: {min, max} } // 百分比 0-100
▼
SectionBoxDialogManager 回调
│ registry.engine3d?.setSectionBoxRange(range)
▼
EngineManager.setSectionBoxRange(range)
│ this.engineInstance.setSectionBoxRange(range)
▼
Engine.setSectionBoxRange(range)
│ this.engine.clipping.sectionBox.setboxPercent(range) // 直传百分比
▼
底层引擎 API: engine.clipping.sectionBox.setboxPercent(range)
│ (底层负责百分比→坐标转换)
调用链 - 适应到模型
用户点击 [适应到模型] 按钮
│
▼
SectionBoxPanel.onFitToModel()
│
▼
SectionBoxDialogManager 回调
│ registry.engine3d?.fitSectionBoxToModel()
▼
EngineManager.fitSectionBoxToModel()
│ this.engineInstance.fitSectionBoxToModel()
▼
Engine.fitSectionBoxToModel()
│ const box = this.engine.octreeBox?.getBoundingBox()
│ this.engine.clipping.sectionBox.setBox(box)
▼
底层引擎 API:
- engine.octreeBox.getBoundingBox()
- engine.clipping.sectionBox.setBox(box)
调用链 - 重置
用户点击 [重置] 按钮
│
▼
SectionBoxPanel.onReset()
│
▼
SectionBoxDialogManager 回调
│ registry.engine3d?.resetSectionBox()
▼
EngineManager.resetSectionBox()
│ this.engineInstance.resetSectionBox()
▼
Engine.resetSectionBox()
│ this.fitSectionBoxToModel() // 内部调用适应到模型
▼
(同上 "适应到模型" 流程)
调用链 - 关闭对话框
用户关闭对话框 / 再次点击按钮
│
▼
SectionBoxDialogManager.onBeforeDestroy()
│ registry.engine3d?.deactivateSectionBox()
▼
EngineManager.deactivateSectionBox()
│ this.engineInstance.deactivateSectionBox()
▼
Engine.deactivateSectionBox()
│ this.engine.clipping.sectionBox.disActive()
▼
底层引擎 API: engine.clipping.sectionBox.disActive()
剖切盒 API 汇总
| 操作 | Engine 方法 | 底层 API |
|---|---|---|
| 激活 | activateSectionBox() |
engine.clipping.sectionBox.active() |
| 停用 | deactivateSectionBox() |
engine.clipping.sectionBox.disActive() |
| 设置范围(百分比) | setSectionBoxRange(range) |
engine.clipping.sectionBox.setboxPercent(range) |
| 设置范围(坐标) | - | engine.clipping.sectionBox.setboxXyz(xyz) |
| 适应到模型 | fitSectionBoxToModel() |
engine.clipping.sectionBox.setBox(box) |
| 获取包围盒 | - | engine.octreeBox.getBoundingBox() |
数据格式说明
| 层级 | 数据格式 | 示例 |
|---|---|---|
| UI / SDK | 百分比 (0-100) | { x: {min: 20, max: 80}, y: {...}, z: {...} } |
| 底层引擎 | 百分比 → 内部转换为坐标 | 底层负责转换 |
5. 漫游 (Walk) - 第一人称漫游
标注说明:
[SDK]= SDK 层代码,[底层]= bim_engine_base 底层引擎
按钮 ID: walk
功能: 打开漫游控制面板,支持第一人称漫游模式
保持激活: 否
5.1 第一人称漫游模式开关
UI 点击漫游按钮
→ [SDK] WalkControlPanel.onWalkModeToggle(isActive)
→ [SDK] WalkControlManager.onWalkModeToggle
→ [SDK] EngineManager.activateFirstPersonMode() / deactivateFirstPersonMode()
→ [SDK] Engine.activateFirstPersonMode() / deactivateFirstPersonMode()
→ [底层] engine.controlModule.switchFirstPersonMode() / switchDefaultMode()
5.2 速度调节
UI 速度按钮 (1-10)
→ [SDK] WalkControlPanel.onSpeedChange(speed)
→ [SDK] WalkControlManager.onSpeedChange
→ [SDK] EngineManager.setWalkSpeed(speed * 0.01) // 值转换: UI 1-10 → 引擎 0.01-0.1
→ [SDK] Engine.setWalkSpeed(speed)
→ [底层] engine.controlModule.firstPersonControls.moveSpeed = speed
5.3 重力开关
UI 重力复选框
→ [SDK] WalkControlPanel.onGravityToggle(enabled)
→ [SDK] WalkControlManager.onGravityToggle
→ [SDK] EngineManager.setWalkGravity(enabled)
→ [SDK] Engine.setWalkGravity(enabled)
→ [底层] engine.controlModule.firstPersonControls.applyGravity = enabled
5.4 碰撞检测开关
UI 碰撞复选框
→ [SDK] WalkControlPanel.onCollisionToggle(enabled)
→ [SDK] WalkControlManager.onCollisionToggle
→ [SDK] EngineManager.setWalkCollision(enabled)
→ [SDK] Engine.setWalkCollision(enabled)
→ [底层] engine.controlModule.firstPersonControls.applyCollision = enabled
6. 地图 (Map)
按钮 ID: map
功能: 打开/关闭地图对话框
保持激活: 是
调用链
用户点击 [地图] 按钮
│
▼
Button onClick (buttons/map/index.ts)
│ if (registry.map?.isOpen()) {
│ registry.map?.hide()
│ } else {
│ registry.map?.show()
│ }
▼
MapDialogManager.show() / hide()
│
▼
地图对话框显示/隐藏
事件监听
// 按钮定义中监听地图开关事件,同步按钮激活状态
registry.on('map:opened', () => {
registry.toolbar?.setBtnActive('map', true);
});
registry.on('map:closed', () => {
registry.toolbar?.setBtnActive('map', false);
});
7. 构件详情 (Property)
按钮 ID: property
功能: 打开构件属性面板
保持激活: 否
调用链
用户点击 [构件详情] 按钮
│
▼
Button onClick (buttons/property/index.ts)
│ registry.propertyPanel?.show()
▼
PropertyPanelManager.show()
│
▼
属性面板显示
8. 设置 (Setting)
按钮 ID: setting
功能: 打开设置面板
保持激活: 否
调用链
用户点击 [设置] 按钮
│
▼
Button onClick (buttons/setting/index.ts)
│ console.log('设置按钮被点击')
▼
⚠️ 暂未实现具体功能
9. 信息 (Info)
按钮 ID: info
功能: 打开信息对话框
保持激活: 否
调用链
用户点击 [信息] 按钮
│
▼
Button onClick (buttons/info/index.ts)
│ registry.emit('ui:open-dialog', { id: 'info' })
▼
事件系统广播 'ui:open-dialog' 事件
│
▼
监听该事件的组件响应并打开信息对话框
10. 全屏 (Fullscreen)
按钮 ID: fullscreen
功能: 切换全屏模式
保持激活: 否
调用链
用户点击 [全屏] 按钮
│
▼
Button onClick (buttons/fullscreen/index.ts)
│ // 检测当前是否全屏
│ const isFullscreen = !!document.fullscreenElement
│
├── 如果不是全屏:
│ targetElem.requestFullscreen({ navigationUI: 'hide' })
│ ▼
│ 浏览器 API: Element.requestFullscreen()
│
└── 如果是全屏:
document.exitFullscreen()
▼
浏览器 API: Document.exitFullscreen()
注意事项
- 全屏功能使用浏览器原生 API,不涉及底层 3D 引擎
- 支持多种浏览器前缀:
webkitRequestFullscreen、mozRequestFullScreen、msRequestFullscreen - 在 iframe 中使用需要父级 iframe 标签添加
allow="fullscreen"属性
附录:调用链层级说明
┌─────────────────────────────────────────────────────────────────────┐
│ L1: Toolbar Button │
│ 文件: src/components/button-group/toolbar/buttons/*/index.ts │
│ 职责: 定义按钮配置,处理 onClick 事件 │
└────────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ L2: DialogManager │
│ 文件: src/managers/*-dialog-manager.ts │
│ 职责: 管理对话框生命周期,绑定 Panel 回调到 EngineManager │
└────────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ L3: EngineManager │
│ 文件: src/managers/engine-manager.ts │
│ 职责: 代理 Engine 组件,提供统一 API,检查初始化状态 │
└────────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ L4: Engine Component │
│ 文件: src/components/engine/index.ts │
│ 职责: 封装底层引擎,维护状态,进行数据转换 │
└────────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ L5: 底层 3D 引擎 (iflow-engine-base) │
│ 来源: 第三方 SDK │
│ 职责: 实际 3D 渲染和功能实现 │
└─────────────────────────────────────────────────────────────────────┘
附录:ManagerRegistry 访问方式
// 在 Button 中获取 Registry
const registry = ManagerRegistry.getInstance();
// 访问各个 Manager
registry.engine3d // EngineManager - 3D 引擎
registry.toolbar // ToolbarManager - 工具栏
registry.dialog // DialogManager - 对话框
registry.measure // MeasureDialogManager - 测量
registry.sectionPlane // SectionPlaneDialogManager - 拾取面剖切
registry.sectionAxis // SectionAxisDialogManager - 轴向剖切
registry.sectionBox // SectionBoxDialogManager - 剖切盒
registry.walkControl // WalkControlManager - 漫游控制
registry.map // MapDialogManager - 地图
registry.propertyPanel // PropertyPanelManager - 属性面板