Files
bim_engine/docs/components/3D引擎组件-Engine.md
yuding f2460fb981 refactor: 重命名SDK为iflow-engine,使用npm包引入第三方引擎
- 将包名从 @fishdingding/bim-engine-sdk 改为 iflow-engine
- 将构建输出文件从 bim-engine-sdk.*.js 改为 iflow-engine.*.js
- 将全局变量从 LyzBimEngineSDK 改为 IflowEngine
- 将第三方引擎SDK从本地引入改为npm包引入 (iflow-engine-base)
- 移除本地 src/engine_base 目录,移至回收站
- 更新所有文档和demo中的引用
2026-01-22 11:29:51 +08:00

15 KiB
Raw Blame History

Engine 组件详细文档

本文档详细描述 Engine 组件的实现细节,包括 API、UI 结构、逻辑流程等,供 AI 根据文档重现组件。


1. 组件概述

1.1 基本信息

  • 组件名称: Engine
  • 文件路径: src/components/engine/index.ts
  • 类型定义: src/components/engine/types.ts
  • 实现接口: IBimComponent
  • 用途: 封装第三方 3D 引擎 SDK提供统一的 3D 引擎管理接口

1.2 在 SDK 中的位置

  • Engine 组件是独立的 3D 引擎组件
  • 必须通过 EngineManager 使用,不允许直接使用
  • EngineManager 位于 src/managers/engine-manager.ts
  • 采用延迟初始化模式,需要用户主动调用 init() 方法

1.3 第三方 SDK 依赖

  • 依赖 iflow-engine-base npm 包中的 createEngine 函数
  • 通过依赖注入方式使用,不直接导入

2. 组件类 API 文档

2.1 构造函数

constructor(options: EngineOptions)

参数:

  • options: EngineOptions - 3D 引擎配置选项

默认配置:

{
    backgroundColor: 0x1a1a1a,  // 默认深色背景
    version: 'v1',              // 默认使用 v1 版本
    showStats: false,           // 默认不显示统计
    showViewCube: true          // 默认显示视图立方体
}

行为:

  • 解析容器元素
  • 如果容器没有 id生成一个唯一的 id
  • 保存配置选项(设置默认值)

2.2 公共方法

init(): void

初始化组件(实现 IBimComponent 接口)

功能:

  • 检查是否已初始化或已销毁
  • 创建引擎配置对象
  • 调用 createEngineSDK() 创建引擎实例
  • 标记为已初始化
  • 订阅主题变化
  • 应用当前主题

错误处理:

  • 如果创建失败,抛出错误并标记为未初始化

setTheme(theme: ThemeConfig): void

设置主题(实现 IBimComponent 接口)

参数:

  • theme: ThemeConfig - 全局主题配置

功能:

  • 根据主题名称选择背景色:
    • dark: 使用深色背景 0x1a1a1a
    • light: 使用浅色背景 0xf5f5f5
    • custom: 使用配置中的 backgroundColor 或默认值
  • 尝试更新引擎背景色:
    • 如果引擎有 setBackgroundColor() 方法,调用它
    • 否则,如果引擎有 scene.background,设置其颜色

setLocales(): void

设置语言(实现 IBimComponent 接口)

功能:

  • 3D 引擎组件暂时不需要本地化
  • 方法为空实现

isInitialized(): boolean

检查是否已初始化

返回: boolean - 是否已初始化

loadModel(url: string, options?: ModelLoadOptions): void

加载 3D 模型

参数:

  • url: string - 模型文件 URL必需
  • options: ModelLoadOptions (可选) - 加载选项

功能:

  • 检查引擎是否已初始化
  • 检查 URL 是否提供
  • 调用引擎的 loader.loadModel() 方法加载模型

加载选项:

  • position: [number, number, number] - 模型位置 [x, y, z]
  • rotation: [number, number, number] - 模型旋转(弧度)[x, y, z]
  • scale: [number, number, number] - 模型缩放 [x, y, z]
  • id: string - 模型 ID可选

getEngine(): any

获取原始 3D 引擎实例

返回: 第三方 3D 引擎实例或 null

功能:

  • 返回底层 3D 引擎实例
  • 用于直接调用第三方引擎的其他 API

destroy(): void

销毁组件(实现 IBimComponent 接口)

功能:

  • 取消主题订阅
  • 清空容器内容
  • 标记为已销毁和未初始化

注意: 不销毁引擎实例本身(由第三方 SDK 管理)


3. 分化组件说明

Engine 组件没有分化组件


4. Manager API 文档

4.1 EngineManager 类

文件路径: src/managers/engine-manager.ts

继承关系: EngineManager extends BimComponent

4.2 构造函数

constructor(engine: BimEngine, container: HTMLElement)

参数:

  • engine: BimEngine - 引擎实例
  • container: HTMLElement - 3D 引擎挂载的目标容器

行为:

  • 保存容器引用
  • 不自动初始化引擎(延迟初始化模式)

4.3 公共方法

initialize(options?: Omit<EngineOptions, 'container'>): boolean

初始化 3D 引擎

参数:

  • options: Omit<EngineOptions, 'container'> (可选) - 引擎配置选项

返回: boolean - 是否初始化成功

功能:

  • 如果已经初始化,先销毁旧的实例
  • 创建 Engine 组件实例
  • 调用组件的 init() 方法初始化引擎
  • 返回初始化结果

错误处理:

  • 如果初始化失败,返回 false 并输出错误信息

isInitialized(): boolean

检查 3D 引擎是否已初始化

返回: boolean - 是否已初始化

loadModel(url: string, options?: ModelLoadOptions): void

加载 3D 模型

参数:

  • url: string - 模型文件 URL
  • options: ModelLoadOptions (可选) - 加载选项

功能:

  • 检查引擎是否已初始化
  • 如果未初始化,输出错误信息
  • 调用引擎组件的 loadModel() 方法

getEngine(): any

获取原始 3D 引擎实例

返回: 第三方 3D 引擎实例或 null

功能:

  • 用于直接调用第三方引擎的其他 API
  • 如果引擎未初始化,返回 null 并输出警告

destroy(): void

销毁 3D 引擎实例

功能:

  • 调用引擎组件的 destroy() 方法
  • 清空引擎实例引用

5. UI 详细描述

5.1 DOM 结构

Engine 组件不直接创建 UI 元素,而是:

  1. 使用容器元素:

    • 容器元素由外部提供(通过 EngineOptions.container
    • 如果容器没有 id组件会生成一个唯一的 id
  2. 第三方 SDK 创建 UI:

    • 第三方 SDK 的 createEngine() 函数会在容器内创建 3D 场景
    • 可能包括:
      • Canvas 元素WebGL 渲染)
      • 统计面板(如果 showStats: true
      • 视图立方体(如果 showViewCube: true

5.2 容器 ID 生成

算法:

containerId = `engine-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

格式: engine-container-[时间戳]-[随机字符串]

示例: engine-container-1704067200000-k3j9x2m1p

5.3 第三方 SDK 配置

传递给 createEngine() 的配置对象:

{
    containerId: string,        // 容器 ID
    backgroundColor: number,     // 背景色(十六进制数字)
    version: 'v1' | 'v2',       // WebGL 版本
    showStats: boolean,         // 是否显示统计
    showViewCube: boolean       // 是否显示视图立方体
}

6. 逻辑流程详细描述

6.1 初始化流程

  1. 构造函数调用:

    • 解析容器元素
    • 生成或使用容器 ID
    • 保存配置选项(设置默认值)
  2. init() 方法执行(用户主动调用):

    • 检查是否已初始化,如果是则返回
    • 检查是否已销毁,如果是则报错
    • 创建引擎配置对象
    • 调用 createEngineSDK() 创建引擎实例
    • 检查引擎实例是否创建成功
    • 标记为已初始化
    • 订阅主题变化:themeManager.subscribe()
    • 应用当前主题

6.2 生命周期

创建阶段

  • 构造函数 → 保存配置

初始化阶段(延迟)

  • 用户调用 init() → 创建引擎实例 → 订阅主题

运行阶段

  • 响应主题变更:setTheme() 被调用
  • 加载模型:loadModel() 被调用
  • 用户交互3D 场景交互(由第三方 SDK 处理)

销毁阶段

  • destroy() 被调用
  • 取消主题订阅
  • 清空容器
  • 更新状态

6.3 主题变更流程

  1. 主题变更 → themeManager 通知订阅者
  2. setTheme() 方法被调用
  3. 根据主题名称选择背景色:
    • dark0x1a1a1a
    • light0xf5f5f5
    • custom → 使用配置值或默认值
  4. 尝试更新引擎背景色:
    • 方法 1: 调用 engine.setBackgroundColor(backgroundColor)
    • 方法 2: 设置 engine.scene.background.setHex(backgroundColor)

6.4 模型加载流程

  1. 用户调用 loadModel(url, options)
  2. 检查引擎是否已初始化
  3. 检查 URL 是否提供
  4. 调用 engine.loader.loadModel(url, options)
  5. 第三方 SDK 处理模型加载

6.5 状态管理

内部状态

  • _isInitialized: 是否已初始化
  • _isDestroyed: 是否已销毁
  • engine: 第三方 3D 引擎实例
  • containerId: 容器 ID
  • options: 引擎配置选项

订阅管理

  • unsubscribeTheme: 主题订阅取消函数

6.6 与其他组件的交互

  • 与 EngineManager: 通过 Manager 创建和管理
  • 与 ThemeManager: 订阅主题变更
  • 与第三方 SDK: 通过 createEngine() 函数创建引擎实例

7. 国际化支持

7.1 使用的翻译键

Engine 组件不使用翻译键3D 引擎不需要国际化)。

7.2 语言变更处理

  • setLocales() 方法为空实现
  • 不订阅语言变更

8. 主题支持

8.1 使用的主题变量

  • 根据主题名称选择背景色:
    • dark 主题 → 0x1a1a1a(深色背景)
    • light 主题 → 0xf5f5f5(浅色背景)
    • custom 主题 → 使用配置值或默认值

8.2 主题变更处理

  • 组件订阅 themeManager.subscribe()
  • 主题变更时,setTheme() 方法被调用
  • 根据主题名称选择背景色
  • 尝试更新引擎背景色(通过引擎 API

8.3 实现细节

public setTheme(theme: ThemeConfig): void {
    let backgroundColor: number;
    if (theme.name === 'dark') {
        backgroundColor = 0x1a1a1a;
    } else if (theme.name === 'light') {
        backgroundColor = 0xf5f5f5;
    } else {
        backgroundColor = this.options.backgroundColor ?? 0x1a1a1a;
    }
    
    // 尝试更新引擎背景色
    if (this.engine && typeof this.engine.setBackgroundColor === 'function') {
        this.engine.setBackgroundColor(backgroundColor);
    } else if (this.engine && this.engine.scene) {
        if (this.engine.scene.background) {
            this.engine.scene.background.setHex(backgroundColor);
        }
    }
}

9. 使用示例

9.1 基本使用(通过 EngineManager

import { BimEngine } from 'iflow-engine';

const engine = new BimEngine('container');

// 初始化 3D 引擎(延迟初始化)
const success = engine.initEngine({
    backgroundColor: 0x333333,
    version: 'v1',
    showStats: true,
    showViewCube: true
});

if (success) {
    console.log('3D 引擎初始化成功');
}

// 加载模型
engine.engine.loadModel('/model/building.glb', {
    position: [0, 0, 0],
    rotation: [0, 0, 0],
    scale: [1, 1, 1]
});

9.2 高级使用

// 检查引擎是否已初始化
if (engine.engine.isInitialized()) {
    // 加载模型
    engine.engine.loadModel('/model/model.glb');
}

// 获取原始引擎实例,调用第三方 API
const rawEngine = engine.engine.getEngine();
if (rawEngine) {
    // 调用第三方 SDK 的其他方法
    rawEngine.someOtherMethod();
}

9.3 主题切换

// 切换主题会自动更新 3D 场景背景色
engine.setTheme('dark');  // 深色背景
engine.setTheme('light'); // 浅色背景

10. 实现细节(供 AI 重现)

10.1 关键算法

容器 ID 生成算法

function generateContainerId(): string {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substr(2, 9);
    return `engine-container-${timestamp}-${random}`;
}

主题背景色选择算法

function selectBackgroundColor(theme: ThemeConfig, defaultColor: number): number {
    if (theme.name === 'dark') {
        return 0x1a1a1a; // 深色背景
    } else if (theme.name === 'light') {
        return 0xf5f5f5; // 浅色背景
    } else {
        return defaultColor; // 自定义主题,使用配置值
    }
}

引擎背景色更新算法

function updateEngineBackground(engine: any, color: number): void {
    // 方法 1: 如果引擎有 setBackgroundColor 方法
    if (engine && typeof engine.setBackgroundColor === 'function') {
        engine.setBackgroundColor(color);
        return;
    }
    
    // 方法 2: 如果引擎有 scene.background
    if (engine && engine.scene && engine.scene.background) {
        engine.scene.background.setHex(color);
        return;
    }
    
    // 方法 3: 无法更新(引擎可能不支持)
}

10.2 性能优化点

  1. 延迟初始化:

    • 引擎不自动初始化,由用户主动调用
    • 减少不必要的资源消耗
  2. 状态检查:

    • 初始化前检查状态,避免重复初始化
    • 销毁后禁止初始化,避免错误
  3. 错误处理:

    • 所有操作都有错误检查
    • 提供有意义的错误信息

10.3 注意事项和边界情况

  1. 容器 ID 唯一性:

    • 容器 ID 必须唯一
    • 如果容器已有 id使用现有 id
    • 如果容器没有 id生成唯一 id
  2. 延迟初始化:

    • 引擎不会自动初始化
    • 用户必须主动调用 init()initialize()
    • 初始化前调用其他方法会报错
  3. 引擎实例管理:

    • 引擎实例由第三方 SDK 创建
    • 组件不负责销毁引擎实例本身
    • 只负责清理订阅和容器
  4. 主题更新兼容性:

    • 不同第三方 SDK 的 API 可能不同
    • 需要尝试多种方式更新背景色
    • 如果都不支持,静默失败
  5. 模型加载:

    • 模型 URL 必须是可访问的
    • 模型格式由第三方 SDK 支持
    • 加载选项由第三方 SDK 处理
  6. 错误处理:

    • 初始化失败时,标记为未初始化
    • 提供有意义的错误信息
    • 不抛出未捕获的异常
  7. 第三方 SDK 依赖:

    • 依赖 iflow-engine-base npm 包
    • 通过 npm 包导入
    • 需要确保依赖已安装

11. 类型定义

11.1 EngineOptions

interface EngineOptions {
    container: HTMLElement;        // 容器元素(必需)
    backgroundColor?: number;      // 背景颜色(可选,默认 0x1a1a1a
    version?: 'v1' | 'v2';         // WebGL 版本(可选,默认 'v1'
    showStats?: boolean;           // 是否显示性能统计(可选,默认 false
    showViewCube?: boolean;        // 是否显示视图立方体(可选,默认 true
}

11.2 ModelLoadOptions

interface ModelLoadOptions {
    position?: [number, number, number];  // 模型位置 [x, y, z](可选)
    rotation?: [number, number, number];  // 模型旋转(弧度)[x, y, z](可选)
    scale?: [number, number, number];     // 模型缩放 [x, y, z](可选)
    id?: string;                          // 模型 ID可选
}

12. 文件清单

12.1 相关文件

  • src/components/engine/index.ts - 主组件类
  • src/components/engine/types.ts - 类型定义
  • src/managers/engine-manager.ts - 管理器类
  • iflow-engine-base - 第三方 SDKnpm 依赖)

12.2 依赖文件

  • src/types/component.ts - IBimComponent 接口
  • src/themes/types.ts - ThemeConfig 类型
  • src/services/theme.ts - ThemeManager

13. 更新记录

日期 修改内容 修改人
2024-XX-XX 初始创建 AI Assistant

重要提醒: 本文档必须与组件代码保持同步。任何组件修改都必须更新本文档!