2026-01-23 16:27:04 +08:00
|
|
|
|
# iflow-engine SDK 快速开始
|
|
|
|
|
|
|
|
|
|
|
|
## 安装
|
|
|
|
|
|
|
|
|
|
|
|
### NPM
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm install iflow-engine
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Yarn
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
yarn add iflow-engine
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### PNPM
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
pnpm add iflow-engine
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
## 引擎概览
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
SDK 提供三个独立引擎类,按需引入,互不依赖:
|
|
|
|
|
|
|
|
|
|
|
|
| 类名 | 用途 | 定位 |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| `BimEngine` | 3D BIM 模型可视化 | 完整功能(工具栏、测量、剖切、漫游等 UI 组件) |
|
|
|
|
|
|
| `BimEngine2d` | 2D CAD/DWG 图纸查看 | 轻量级,无 UI 管理器 |
|
|
|
|
|
|
| `BimEngine720` | 720° 全景图查看 | 轻量级,无 UI 管理器 |
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// ESM 按需导入
|
|
|
|
|
|
import { BimEngine } from 'iflow-engine'; // 3D
|
|
|
|
|
|
import { BimEngine2d } from 'iflow-engine'; // 2D
|
|
|
|
|
|
import { BimEngine720 } from 'iflow-engine'; // 720°
|
|
|
|
|
|
|
|
|
|
|
|
// 也可以一次导入全部
|
|
|
|
|
|
import { BimEngine, BimEngine2d, BimEngine720 } from 'iflow-engine';
|
|
|
|
|
|
```
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```html
|
2026-03-16 16:13:36 +08:00
|
|
|
|
<!-- UMD 方式(原生 HTML) -->
|
|
|
|
|
|
<script src="./lib/iflow-engine.umd.js"></script>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
const { BimEngine, BimEngine2d, BimEngine720 } = IflowEngine;
|
|
|
|
|
|
</script>
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
> **注意**:三个引擎类共用同一个容器时,需先销毁当前实例再创建新实例。详见 [多引擎切换](#多引擎切换)。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 一、3D 引擎(BimEngine)
|
|
|
|
|
|
|
|
|
|
|
|
完整的 BIM 3D 可视化引擎,包含工具栏、测量、剖切、漫游等全部 UI 功能。
|
|
|
|
|
|
|
|
|
|
|
|
### 基本用法
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { BimEngine } from 'iflow-engine';
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
const engine = new BimEngine('container', {
|
2026-03-30 10:53:39 +08:00
|
|
|
|
locale: 'zh-CN', // 'zh-CN' | 'zh-TW' | 'en-US'
|
2026-03-16 16:13:36 +08:00
|
|
|
|
theme: 'dark' // 'dark' | 'light'
|
2026-01-23 16:27:04 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 初始化 3D 渲染引擎
|
|
|
|
|
|
engine.engine?.initialize({
|
|
|
|
|
|
backgroundColor: 0x333333,
|
|
|
|
|
|
showViewCube: true
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
// 加载模型
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine.engine?.loadModel(['https://example.com/model/'], {
|
|
|
|
|
|
position: [0, 0, 0],
|
|
|
|
|
|
rotation: [0, 0, 0],
|
|
|
|
|
|
scale: [1, 1, 1]
|
2026-01-23 16:27:04 +08:00
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 构造参数
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
| `container` | `HTMLElement \| string` | ✅ | DOM 元素或元素 ID |
|
2026-03-30 10:53:39 +08:00
|
|
|
|
| `options.locale` | `'zh-CN' \| 'zh-TW' \| 'en-US'` | | 界面语言,默认 `'zh-CN'` |
|
2026-03-16 16:13:36 +08:00
|
|
|
|
| `options.theme` | `'dark' \| 'light'` | | 主题,默认 `'dark'` |
|
|
|
|
|
|
|
|
|
|
|
|
### 管理器
|
|
|
|
|
|
|
|
|
|
|
|
BimEngine 构造时自动初始化以下管理器:
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
engine.engine // EngineManager - 3D 引擎(加载模型、控制渲染)
|
|
|
|
|
|
engine.toolbar // ToolbarManager - 底部工具栏
|
|
|
|
|
|
engine.buttonGroup // ButtonGroupManager - 按钮组
|
|
|
|
|
|
engine.dialog // DialogManager - 弹窗管理
|
|
|
|
|
|
engine.rightKey // RightKeyManager - 右键菜单
|
|
|
|
|
|
engine.constructTreeBtn // ConstructTreeManagerBtn - 构件树
|
|
|
|
|
|
engine.measure // MeasureDialogManager - 测量工具
|
|
|
|
|
|
engine.sectionPlane // SectionPlaneDialogManager - 拾取面剖切
|
|
|
|
|
|
engine.sectionAxis // SectionAxisDialogManager - 轴向剖切
|
|
|
|
|
|
engine.sectionBox // SectionBoxDialogManager - 剖切盒
|
|
|
|
|
|
engine.walkControl // WalkControlManager - 漫游控制
|
|
|
|
|
|
engine.componentDetail // ComponentDetailManager - 构件详情
|
|
|
|
|
|
engine.aiChat // AiChatManager - AI 对话
|
|
|
|
|
|
engine.setting // SettingDialogManager - 设置
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Vue 3 示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```vue
|
|
|
|
|
|
<template>
|
2026-03-16 16:13:36 +08:00
|
|
|
|
<div ref="containerRef" style="width: 100vw; height: 100vh;" />
|
2026-01-23 16:27:04 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { ref, onMounted, onUnmounted } from 'vue';
|
|
|
|
|
|
import { BimEngine } from 'iflow-engine';
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
const containerRef = ref<HTMLElement>();
|
2026-01-23 16:27:04 +08:00
|
|
|
|
let engine: BimEngine | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
2026-03-16 16:13:36 +08:00
|
|
|
|
if (!containerRef.value) return;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine = new BimEngine(containerRef.value, {
|
|
|
|
|
|
locale: 'zh-CN',
|
|
|
|
|
|
theme: 'dark'
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine.engine?.initialize({ backgroundColor: 0x333333 });
|
|
|
|
|
|
engine.engine?.loadModel(['https://example.com/model/']);
|
2026-01-23 16:27:04 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
engine?.destroy();
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine = null;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### React 示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```tsx
|
|
|
|
|
|
import { useRef, useEffect } from 'react';
|
|
|
|
|
|
import { BimEngine } from 'iflow-engine';
|
|
|
|
|
|
|
|
|
|
|
|
export function BimViewer() {
|
|
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2026-03-16 16:13:36 +08:00
|
|
|
|
if (!containerRef.current) return;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
const engine = new BimEngine(containerRef.current, {
|
|
|
|
|
|
locale: 'zh-CN',
|
|
|
|
|
|
theme: 'dark'
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine.engine?.initialize({ backgroundColor: 0x333333 });
|
|
|
|
|
|
engine.engine?.loadModel(['https://example.com/model/']);
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
return () => engine.destroy();
|
2026-01-23 16:27:04 +08:00
|
|
|
|
}, []);
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
return <div ref={containerRef} style={{ width: '100vw', height: '100vh' }} />;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
## 二、2D 图纸引擎(BimEngine2d)
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
轻量级 2D CAD/DWG 图纸查看引擎,无 UI 管理器,构造时自动初始化。
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 基本用法
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
import { BimEngine2d } from 'iflow-engine';
|
|
|
|
|
|
|
|
|
|
|
|
const engine2d = new BimEngine2d('container', {
|
|
|
|
|
|
locale: 'zh-CN',
|
|
|
|
|
|
theme: 'dark',
|
|
|
|
|
|
backgroundColor: 0xf0f0f0,
|
|
|
|
|
|
gridEnabled: true,
|
|
|
|
|
|
axesEnabled: true
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 加载图纸
|
|
|
|
|
|
await engine2d.loadDrawing('https://example.com/drawing-id');
|
|
|
|
|
|
|
|
|
|
|
|
// 销毁
|
|
|
|
|
|
engine2d.destroy();
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 构造参数
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
| `container` | `HTMLElement \| string` | ✅ | DOM 元素或元素 ID |
|
2026-03-30 10:53:39 +08:00
|
|
|
|
| `options.locale` | `'zh-CN' \| 'zh-TW' \| 'en-US'` | | 界面语言 |
|
2026-03-16 16:13:36 +08:00
|
|
|
|
| `options.theme` | `'dark' \| 'light'` | | 主题 |
|
|
|
|
|
|
| `options.backgroundColor` | `number` | | 背景色,如 `0xffffff` |
|
|
|
|
|
|
| `options.gridEnabled` | `boolean` | | 是否显示网格 |
|
|
|
|
|
|
| `options.axesEnabled` | `boolean` | | 是否显示坐标轴 |
|
|
|
|
|
|
| `options.selectionColor` | `number` | | 选中构件颜色 |
|
|
|
|
|
|
| `options.highlightColor` | `number` | | 高亮构件颜色 |
|
|
|
|
|
|
| `options.enablePerformanceMonitoring` | `boolean` | | 是否启用性能监控 |
|
|
|
|
|
|
|
|
|
|
|
|
### API
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```typescript
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 图纸操作
|
|
|
|
|
|
await engine2d.loadDrawing(url, options?) // 加载图纸
|
|
|
|
|
|
engine2d.getLayers() // 获取所有图层 → Drawing2dLayer[]
|
|
|
|
|
|
engine2d.setLayerVisible(name, visible) // 设置图层可见性
|
|
|
|
|
|
|
|
|
|
|
|
// 视图控制
|
|
|
|
|
|
engine2d.resetView() // 重置视图
|
|
|
|
|
|
engine2d.fitToView() // 适应全部内容
|
|
|
|
|
|
engine2d.setZoom(zoom) // 设置缩放级别
|
|
|
|
|
|
engine2d.getZoom() // 获取当前缩放级别
|
|
|
|
|
|
|
|
|
|
|
|
// 主题
|
|
|
|
|
|
engine2d.setTheme('dark' | 'light')
|
|
|
|
|
|
|
|
|
|
|
|
// 事件
|
|
|
|
|
|
const unsub = engine2d.on('event-name', (payload) => { ... })
|
|
|
|
|
|
unsub() // 取消订阅
|
|
|
|
|
|
engine2d.onRawEvent(event, handler) // 底层引擎事件
|
|
|
|
|
|
engine2d.offRawEvent(event, handler)
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
engine2d.destroy() // 销毁引擎
|
|
|
|
|
|
```
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### Vue 3 示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div ref="containerRef" style="width: 100%; height: 100vh;" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { ref, onMounted, onUnmounted } from 'vue';
|
|
|
|
|
|
import { BimEngine2d } from 'iflow-engine';
|
|
|
|
|
|
|
|
|
|
|
|
const containerRef = ref<HTMLElement>();
|
|
|
|
|
|
let engine2d: BimEngine2d | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
if (!containerRef.value) return;
|
|
|
|
|
|
|
|
|
|
|
|
engine2d = new BimEngine2d(containerRef.value, {
|
|
|
|
|
|
theme: 'light',
|
|
|
|
|
|
gridEnabled: true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await engine2d.loadDrawing('https://example.com/drawing-id');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
engine2d?.destroy();
|
|
|
|
|
|
engine2d = null;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
});
|
2026-03-16 16:13:36 +08:00
|
|
|
|
</script>
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### React 示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```tsx
|
|
|
|
|
|
import { useRef, useEffect } from 'react';
|
|
|
|
|
|
import { BimEngine2d } from 'iflow-engine';
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
export function DrawingViewer() {
|
|
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (!containerRef.current) return;
|
|
|
|
|
|
|
|
|
|
|
|
const engine2d = new BimEngine2d(containerRef.current, {
|
|
|
|
|
|
theme: 'light',
|
|
|
|
|
|
gridEnabled: true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
engine2d.loadDrawing('https://example.com/drawing-id');
|
|
|
|
|
|
|
|
|
|
|
|
return () => engine2d.destroy();
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
return <div ref={containerRef} style={{ width: '100%', height: '100vh' }} />;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 三、720° 全景引擎(BimEngine720)
|
|
|
|
|
|
|
|
|
|
|
|
轻量级 720° 全景图查看引擎,支持鼠标/触摸旋转和缩放,构造时自动初始化。
|
|
|
|
|
|
|
|
|
|
|
|
### 基本用法
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```typescript
|
2026-03-16 16:13:36 +08:00
|
|
|
|
import { BimEngine720 } from 'iflow-engine';
|
|
|
|
|
|
|
|
|
|
|
|
const engine720 = new BimEngine720('container', {
|
|
|
|
|
|
fov: 75,
|
|
|
|
|
|
enableZoom: true,
|
|
|
|
|
|
enableRotate: true,
|
|
|
|
|
|
sphereRadius: 500
|
2026-01-23 16:27:04 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 加载全景图
|
|
|
|
|
|
await engine720.loadPanorama('https://example.com/panorama.png');
|
|
|
|
|
|
|
|
|
|
|
|
// 销毁
|
|
|
|
|
|
engine720.destroy();
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 构造参数
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
| `container` | `HTMLElement \| string` | ✅ | DOM 元素或元素 ID |
|
2026-03-30 10:53:39 +08:00
|
|
|
|
| `options.locale` | `'zh-CN' \| 'zh-TW' \| 'en-US'` | | 界面语言 |
|
2026-03-16 16:13:36 +08:00
|
|
|
|
| `options.theme` | `'dark' \| 'light'` | | 主题 |
|
|
|
|
|
|
| `options.fov` | `number` | | 视场角,默认 `75` |
|
|
|
|
|
|
| `options.enableZoom` | `boolean` | | 是否启用缩放,默认 `true` |
|
|
|
|
|
|
| `options.enableRotate` | `boolean` | | 是否启用旋转,默认 `true` |
|
|
|
|
|
|
| `options.sphereRadius` | `number` | | 球体半径,默认 `500` |
|
|
|
|
|
|
| `options.rotateSpeed` | `number` | | 旋转速度 |
|
|
|
|
|
|
| `options.zoomSpeed` | `number` | | 缩放速度 |
|
|
|
|
|
|
| `options.enableDamping` | `boolean` | | 是否启用阻尼(惯性效果) |
|
|
|
|
|
|
| `options.dampingFactor` | `number` | | 阻尼因子 |
|
|
|
|
|
|
| `options.minFov` | `number` | | 最小视场角 |
|
|
|
|
|
|
| `options.maxFov` | `number` | | 最大视场角 |
|
|
|
|
|
|
|
|
|
|
|
|
### API
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```typescript
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 全景操作
|
|
|
|
|
|
await engine720.loadPanorama(url, options?) // 加载全景图
|
|
|
|
|
|
await engine720.preloadPanoramas(urls) // 预加载多个全景图
|
|
|
|
|
|
|
|
|
|
|
|
// 视角控制
|
|
|
|
|
|
engine720.setFov(fov) // 设置视场角
|
|
|
|
|
|
engine720.getFov() // 获取当前视场角
|
|
|
|
|
|
engine720.lookAt(phi, theta, animated?) // 设置相机朝向
|
|
|
|
|
|
engine720.resetView() // 重置视图
|
|
|
|
|
|
|
|
|
|
|
|
// 主题
|
|
|
|
|
|
engine720.setTheme('dark' | 'light')
|
|
|
|
|
|
|
|
|
|
|
|
// 事件
|
|
|
|
|
|
const unsub = engine720.on('event-name', (payload) => { ... })
|
|
|
|
|
|
unsub() // 取消订阅
|
|
|
|
|
|
engine720.onRawEvent(event, handler) // 底层引擎事件
|
|
|
|
|
|
engine720.offRawEvent(event, handler)
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
engine720.destroy() // 销毁引擎
|
|
|
|
|
|
```
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### Vue 3 示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```vue
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div ref="containerRef" style="width: 100%; height: 100vh;" />
|
|
|
|
|
|
</template>
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { ref, onMounted, onUnmounted } from 'vue';
|
|
|
|
|
|
import { BimEngine720 } from 'iflow-engine';
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
const containerRef = ref<HTMLElement>();
|
|
|
|
|
|
let engine720: BimEngine720 | null = null;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
if (!containerRef.value) return;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine720 = new BimEngine720(containerRef.value, {
|
|
|
|
|
|
fov: 75,
|
|
|
|
|
|
enableZoom: true,
|
|
|
|
|
|
enableRotate: true,
|
|
|
|
|
|
sphereRadius: 500
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
await engine720.loadPanorama('https://example.com/panorama.png');
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
engine720?.destroy();
|
|
|
|
|
|
engine720 = null;
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### React 示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```tsx
|
|
|
|
|
|
import { useRef, useEffect } from 'react';
|
|
|
|
|
|
import { BimEngine720 } from 'iflow-engine';
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
export function PanoramaViewer() {
|
|
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (!containerRef.current) return;
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
const engine720 = new BimEngine720(containerRef.current, {
|
|
|
|
|
|
fov: 75,
|
|
|
|
|
|
enableZoom: true,
|
|
|
|
|
|
enableRotate: true,
|
|
|
|
|
|
sphereRadius: 500
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
engine720.loadPanorama('https://example.com/panorama.png');
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
return () => engine720.destroy();
|
|
|
|
|
|
}, []);
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
return <div ref={containerRef} style={{ width: '100%', height: '100vh' }} />;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 多引擎切换
|
|
|
|
|
|
|
|
|
|
|
|
三个引擎类可以共用同一个容器,但同一时刻只能有一个实例。切换时需先销毁当前实例:
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```typescript
|
2026-03-16 16:13:36 +08:00
|
|
|
|
import { BimEngine, BimEngine2d, BimEngine720 } from 'iflow-engine';
|
|
|
|
|
|
|
|
|
|
|
|
let current: BimEngine | BimEngine2d | BimEngine720 | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
function destroyCurrent() {
|
|
|
|
|
|
current?.destroy();
|
|
|
|
|
|
current = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 切换到 3D
|
|
|
|
|
|
function switchTo3D() {
|
|
|
|
|
|
destroyCurrent();
|
|
|
|
|
|
const engine = new BimEngine('container', { theme: 'dark' });
|
|
|
|
|
|
engine.engine?.initialize({ backgroundColor: 0x333333 });
|
|
|
|
|
|
engine.engine?.loadModel(['https://example.com/model/']);
|
|
|
|
|
|
current = engine;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 切换到 2D
|
|
|
|
|
|
function switchTo2D() {
|
|
|
|
|
|
destroyCurrent();
|
|
|
|
|
|
const engine2d = new BimEngine2d('container', { theme: 'dark' });
|
|
|
|
|
|
engine2d.loadDrawing('https://example.com/drawing-id');
|
|
|
|
|
|
current = engine2d;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 切换到 720°
|
|
|
|
|
|
function switchTo720() {
|
|
|
|
|
|
destroyCurrent();
|
|
|
|
|
|
const engine720 = new BimEngine720('container', {
|
|
|
|
|
|
fov: 75,
|
|
|
|
|
|
enableZoom: true,
|
|
|
|
|
|
enableRotate: true,
|
|
|
|
|
|
sphereRadius: 500
|
|
|
|
|
|
});
|
|
|
|
|
|
engine720.loadPanorama('https://example.com/panorama.png');
|
|
|
|
|
|
current = engine720;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
## 原生 HTML 完整示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```html
|
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
<title>iflow-engine Demo</title>
|
|
|
|
|
|
<style>
|
|
|
|
|
|
body { margin: 0; font-family: sans-serif; }
|
|
|
|
|
|
#container { width: 100vw; height: 100vh; }
|
|
|
|
|
|
.btn-group { position: fixed; top: 10px; left: 10px; z-index: 100; }
|
|
|
|
|
|
.btn-group button { padding: 8px 16px; margin-right: 8px; cursor: pointer; }
|
|
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div class="btn-group">
|
|
|
|
|
|
<button onclick="switchTo3D()">3D 引擎</button>
|
|
|
|
|
|
<button onclick="switchTo2D()">2D 图纸</button>
|
|
|
|
|
|
<button onclick="switchTo720()">720° 全景</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div id="container"></div>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="./lib/iflow-engine.umd.js"></script>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
var BimEngine = IflowEngine.BimEngine;
|
|
|
|
|
|
var BimEngine2d = IflowEngine.BimEngine2d;
|
|
|
|
|
|
var BimEngine720 = IflowEngine.BimEngine720;
|
|
|
|
|
|
|
|
|
|
|
|
var current = null;
|
|
|
|
|
|
|
|
|
|
|
|
function destroyCurrent() {
|
|
|
|
|
|
if (current) { current.destroy(); current = null; }
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
function switchTo3D() {
|
|
|
|
|
|
destroyCurrent();
|
|
|
|
|
|
var engine = new BimEngine('container', { locale: 'zh-CN', theme: 'dark' });
|
|
|
|
|
|
engine.engine.initialize({ backgroundColor: 0x333333, showViewCube: true });
|
|
|
|
|
|
engine.engine.loadModel(['https://example.com/model/']);
|
|
|
|
|
|
current = engine;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
function switchTo2D() {
|
|
|
|
|
|
destroyCurrent();
|
|
|
|
|
|
var engine2d = new BimEngine2d('container', { theme: 'dark', gridEnabled: true });
|
|
|
|
|
|
engine2d.loadDrawing('https://example.com/drawing-id');
|
|
|
|
|
|
current = engine2d;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
function switchTo720() {
|
|
|
|
|
|
destroyCurrent();
|
|
|
|
|
|
var engine720 = new BimEngine720('container', {
|
|
|
|
|
|
fov: 75, enableZoom: true, enableRotate: true, sphereRadius: 500
|
|
|
|
|
|
});
|
|
|
|
|
|
engine720.loadPanorama('https://example.com/panorama.png');
|
|
|
|
|
|
current = engine720;
|
|
|
|
|
|
}
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 默认加载 3D
|
|
|
|
|
|
switchTo3D();
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
2026-01-23 16:27:04 +08:00
|
|
|
|
## TypeScript 类型
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
SDK 导出所有相关类型,开箱即用:
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import type {
|
2026-03-16 16:13:36 +08:00
|
|
|
|
// 3D 引擎
|
2026-01-23 16:27:04 +08:00
|
|
|
|
EngineOptions,
|
|
|
|
|
|
ModelLoadOptions,
|
2026-03-16 16:13:36 +08:00
|
|
|
|
|
|
|
|
|
|
// 2D 引擎
|
|
|
|
|
|
Engine2dOptions,
|
|
|
|
|
|
DrawingLoadOptions,
|
|
|
|
|
|
Drawing2dLayer,
|
|
|
|
|
|
|
|
|
|
|
|
// 720 引擎
|
|
|
|
|
|
Engine720Options,
|
|
|
|
|
|
PanoramaLoadOptions,
|
|
|
|
|
|
PanoramaAnnotation,
|
|
|
|
|
|
|
|
|
|
|
|
// 通用
|
|
|
|
|
|
ThemeConfig,
|
|
|
|
|
|
ThemeType,
|
|
|
|
|
|
EngineEvents,
|
|
|
|
|
|
|
|
|
|
|
|
// UI 组件(仅 BimEngine 3D 使用)
|
2026-01-23 16:27:04 +08:00
|
|
|
|
DialogOptions,
|
|
|
|
|
|
DialogPosition,
|
|
|
|
|
|
ButtonConfig,
|
|
|
|
|
|
ButtonGroupOptions,
|
|
|
|
|
|
TreeOptions,
|
|
|
|
|
|
TreeNodeConfig,
|
2026-03-16 16:13:36 +08:00
|
|
|
|
} from 'iflow-engine';
|
|
|
|
|
|
```
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
## 主题与语言
|
|
|
|
|
|
|
|
|
|
|
|
三个引擎类均支持主题切换和语言设置:
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 构造时设置
|
|
|
|
|
|
const engine = new BimEngine('container', { theme: 'dark', locale: 'zh-CN' });
|
|
|
|
|
|
const engine2d = new BimEngine2d('container', { theme: 'light' });
|
|
|
|
|
|
const engine720 = new BimEngine720('container', { theme: 'dark' });
|
|
|
|
|
|
|
|
|
|
|
|
// 运行时切换主题
|
|
|
|
|
|
engine.setTheme('light');
|
|
|
|
|
|
engine2d.setTheme('dark');
|
|
|
|
|
|
engine720.setTheme('light');
|
|
|
|
|
|
|
|
|
|
|
|
// 运行时切换语言(仅 3D 引擎支持)
|
|
|
|
|
|
engine.setLocale('en-US');
|
|
|
|
|
|
|
|
|
|
|
|
// 自定义主题(仅 3D 引擎支持)
|
|
|
|
|
|
engine.setCustomTheme({
|
|
|
|
|
|
name: 'custom',
|
|
|
|
|
|
primary: '#1890ff',
|
|
|
|
|
|
primaryHover: '#40a9ff',
|
|
|
|
|
|
// ...
|
|
|
|
|
|
});
|
2026-01-23 16:27:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
2026-01-23 16:27:04 +08:00
|
|
|
|
## 常见问题
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 1. 如何只引入需要的引擎?
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
直接按需 import,构建工具会自动 tree-shaking 未使用的代码:
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
// 只用 2D,不会打包 3D 和 720 的代码
|
|
|
|
|
|
import { BimEngine2d } from 'iflow-engine';
|
|
|
|
|
|
```
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 2. 多个引擎能同时存在吗?
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
可以,但需要**不同的容器**。同一个容器同时只能挂载一个引擎实例:
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
```typescript
|
|
|
|
|
|
const engine3d = new BimEngine('container-3d', { theme: 'dark' });
|
|
|
|
|
|
const engine2d = new BimEngine2d('container-2d', { theme: 'dark' });
|
|
|
|
|
|
const engine720 = new BimEngine720('container-720', { theme: 'dark' });
|
|
|
|
|
|
```
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
### 3. 切换引擎时页面闪烁
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
确保先调用 `destroy()` 再创建新实例。`destroy()` 会清空容器内容。
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 模型/图纸加载失败
|
|
|
|
|
|
|
|
|
|
|
|
- 检查 URL 是否可访问
|
|
|
|
|
|
- 检查浏览器控制台是否有 CORS 错误
|
|
|
|
|
|
- 确保使用 HTTP 服务器运行(不能直接打开 HTML 文件)
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 页面关闭时如何释放资源?
|
|
|
|
|
|
|
|
|
|
|
|
务必调用 `destroy()` 释放 WebGL 上下文和事件监听:
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
window.addEventListener('beforeunload', () => {
|
|
|
|
|
|
engine?.destroy();
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
## 下一步
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
- [架构设计](架构设计.md) — 了解 Manager 模式和分层架构
|
|
|
|
|
|
- [引擎 API 对接](引擎API对接.md) — 底层引擎 API 详细说明
|
|
|
|
|
|
- [API 调用链](API调用链.md) — 调用关系与数据流
|
|
|
|
|
|
- [demo/](../demo/) — 完整可运行示例
|
2026-01-23 16:27:04 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-03-16 16:13:36 +08:00
|
|
|
|
**文档版本**: 2.0.0 | **更新日期**: 2026-03-10
|