Files
bim_engine/docs/SDK_USAGE.md
yuding a00d83e775 docs: 添加 SDK 使用文档
- 支持原生 HTML、Vue 2/3、React 框架
- 包含完整的 API 参考和类型定义
- 提供组件封装示例和 Hook 封装
- 添加常见问题解答

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 14:22:43 +08:00

985 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BIM Engine SDK 使用文档
BIM Engine SDK 是一个用于 3D BIM 模型展示的 JavaScript SDK支持原生 HTML、Vue 2/3 和 React 框架。
## 目录
- [安装](#安装)
- [原生 HTML 使用](#原生-html-使用)
- [Vue 3 使用](#vue-3-使用)
- [Vue 2 使用](#vue-2-使用)
- [React 使用](#react-使用)
- [API 参考](#api-参考)
- [类型定义](#类型定义)
---
## 安装
### NPM 安装
```bash
npm install bim-engine-sdk
```
### CDN / 本地引入
```html
<script src="./lib/bim-engine-sdk.umd.js"></script>
```
---
## 原生 HTML 使用
### 基础示例
```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BIM Engine Demo</title>
<!-- 引入 SDK -->
<script src="./lib/bim-engine-sdk.umd.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; }
#app { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="app"></div>
<script>
// 1. 创建引擎实例
const engine = new LyzBimEngineSDK.BimEngine('app', {
locale: 'zh-CN', // 语言:'zh-CN' | 'en-US'
theme: 'light' // 主题:'light' | 'dark'
});
// 2. 初始化 3D 引擎
const success = engine.engine.initialize({
version: 'v2', // WebGL 版本:'v1' | 'v2'
showStats: false, // 是否显示性能统计
showViewCube: true // 是否显示视图立方体
});
if (success) {
console.log('3D 引擎初始化成功');
// 3. 加载模型
engine.engine.loadModel('./model/your-model', {
position: [0, 0, 0], // 位置 [x, y, z]
rotation: [0, 0, 0], // 旋转 [x, y, z](弧度)
scale: [1, 1, 1] // 缩放 [x, y, z]
});
}
// 4. 页面卸载时销毁
window.addEventListener('beforeunload', () => {
engine.destroy();
});
</script>
</body>
</html>
```
### 完整功能示例
```html
<script>
let engine = null;
// 初始化
function init() {
engine = new LyzBimEngineSDK.BimEngine('app', {
locale: 'zh-CN',
theme: 'light'
});
engine.engine.initialize({
version: 'v2',
showStats: false,
showViewCube: true
});
// 加载模型
engine.engine.loadModel('./model/building');
}
// 回到主视角
function goHome() {
engine.engine.CameraGoHome();
}
// 激活测量功能
function activateMeasure(mode) {
// mode: 'distance' | 'minDistance' | 'angle' | 'elevation' | 'volume' | 'laserDistance' | 'slope' | 'spaceVolume'
engine.engine.activateMeasure(mode);
}
// 停用测量
function deactivateMeasure() {
engine.engine.deactivateMeasure();
}
// 切换主题
function toggleTheme() {
engine.setTheme('dark'); // 或 'light'
}
// 切换语言
function toggleLocale() {
engine.setLocale('en-US'); // 或 'zh-CN'
}
// 销毁
function destroy() {
engine.destroy();
}
window.onload = init;
</script>
```
---
## Vue 3 使用
### 安装依赖
```bash
npm install bim-engine-sdk
```
### 组件封装
```vue
<!-- BimViewer.vue -->
<template>
<div ref="containerRef" class="bim-viewer"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { BimEngine } from 'bim-engine-sdk';
import type { EngineOptions, ModelLoadOptions } from 'bim-engine-sdk';
// Props
interface Props {
modelUrl?: string;
modelOptions?: ModelLoadOptions;
engineOptions?: Omit<EngineOptions, 'container'>;
locale?: 'zh-CN' | 'en-US';
theme?: 'light' | 'dark';
}
const props = withDefaults(defineProps<Props>(), {
locale: 'zh-CN',
theme: 'light'
});
// Emits
const emit = defineEmits<{
(e: 'ready', engine: BimEngine): void;
(e: 'error', error: Error): void;
}>();
// Refs
const containerRef = ref<HTMLElement | null>(null);
let engine: BimEngine | null = null;
// 初始化引擎
const initEngine = () => {
if (!containerRef.value) return;
try {
// 创建引擎实例
engine = new BimEngine(containerRef.value, {
locale: props.locale,
theme: props.theme
});
// 初始化 3D 引擎
const success = engine.engine?.initialize({
version: 'v2',
showStats: false,
showViewCube: true,
...props.engineOptions
});
if (success) {
emit('ready', engine);
// 加载模型
if (props.modelUrl) {
engine.engine?.loadModel(props.modelUrl, props.modelOptions);
}
} else {
throw new Error('3D 引擎初始化失败');
}
} catch (error) {
emit('error', error as Error);
}
};
// 暴露方法给父组件
defineExpose({
// 获取引擎实例
getEngine: () => engine,
// 加载模型
loadModel: (url: string, options?: ModelLoadOptions) => {
engine?.engine?.loadModel(url, options);
},
// 回到主视角
goHome: () => {
engine?.engine?.CameraGoHome();
},
// 激活测量
activateMeasure: (mode: string) => {
engine?.engine?.activateMeasure(mode as any);
},
// 停用测量
deactivateMeasure: () => {
engine?.engine?.deactivateMeasure();
},
// 切换主题
setTheme: (theme: 'light' | 'dark') => {
engine?.setTheme(theme);
},
// 切换语言
setLocale: (locale: 'zh-CN' | 'en-US') => {
engine?.setLocale(locale);
}
});
// 生命周期
onMounted(() => {
initEngine();
});
onBeforeUnmount(() => {
engine?.destroy();
engine = null;
});
</script>
<style scoped>
.bim-viewer {
width: 100%;
height: 100%;
}
</style>
```
### 使用组件
```vue
<!-- App.vue -->
<template>
<div class="app">
<BimViewer
ref="viewerRef"
model-url="./model/building"
:model-options="{ position: [0, 0, 0] }"
locale="zh-CN"
theme="light"
@ready="onEngineReady"
@error="onEngineError"
/>
<div class="toolbar">
<button @click="goHome">主视角</button>
<button @click="measure('distance')">距离测量</button>
<button @click="stopMeasure">停止测量</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import BimViewer from './components/BimViewer.vue';
import type { BimEngine } from 'bim-engine-sdk';
const viewerRef = ref<InstanceType<typeof BimViewer> | null>(null);
const onEngineReady = (engine: BimEngine) => {
console.log('引擎已就绪', engine);
};
const onEngineError = (error: Error) => {
console.error('引擎错误', error);
};
const goHome = () => {
viewerRef.value?.goHome();
};
const measure = (mode: string) => {
viewerRef.value?.activateMeasure(mode);
};
const stopMeasure = () => {
viewerRef.value?.deactivateMeasure();
};
</script>
<style>
.app {
width: 100vw;
height: 100vh;
position: relative;
}
.toolbar {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
}
</style>
```
---
## Vue 2 使用
### 安装依赖
```bash
npm install bim-engine-sdk
```
### 组件封装
```vue
<!-- BimViewer.vue -->
<template>
<div ref="container" class="bim-viewer"></div>
</template>
<script>
import { BimEngine } from 'bim-engine-sdk';
export default {
name: 'BimViewer',
props: {
modelUrl: {
type: String,
default: ''
},
modelOptions: {
type: Object,
default: () => ({})
},
engineOptions: {
type: Object,
default: () => ({})
},
locale: {
type: String,
default: 'zh-CN'
},
theme: {
type: String,
default: 'light'
}
},
data() {
return {
engine: null
};
},
mounted() {
this.initEngine();
},
beforeDestroy() {
this.destroyEngine();
},
methods: {
initEngine() {
try {
// 创建引擎实例
this.engine = new BimEngine(this.$refs.container, {
locale: this.locale,
theme: this.theme
});
// 初始化 3D 引擎
const success = this.engine.engine.initialize({
version: 'v2',
showStats: false,
showViewCube: true,
...this.engineOptions
});
if (success) {
this.$emit('ready', this.engine);
// 加载模型
if (this.modelUrl) {
this.engine.engine.loadModel(this.modelUrl, this.modelOptions);
}
} else {
throw new Error('3D 引擎初始化失败');
}
} catch (error) {
this.$emit('error', error);
}
},
destroyEngine() {
if (this.engine) {
this.engine.destroy();
this.engine = null;
}
},
// 公开方法
getEngine() {
return this.engine;
},
loadModel(url, options) {
this.engine?.engine?.loadModel(url, options);
},
goHome() {
this.engine?.engine?.CameraGoHome();
},
activateMeasure(mode) {
this.engine?.engine?.activateMeasure(mode);
},
deactivateMeasure() {
this.engine?.engine?.deactivateMeasure();
},
setTheme(theme) {
this.engine?.setTheme(theme);
},
setLocale(locale) {
this.engine?.setLocale(locale);
}
}
};
</script>
<style scoped>
.bim-viewer {
width: 100%;
height: 100%;
}
</style>
```
### 使用组件
```vue
<!-- App.vue -->
<template>
<div class="app">
<BimViewer
ref="viewer"
model-url="./model/building"
:model-options="{ position: [0, 0, 0] }"
locale="zh-CN"
theme="light"
@ready="onEngineReady"
@error="onEngineError"
/>
<div class="toolbar">
<button @click="goHome">主视角</button>
<button @click="measure('distance')">距离测量</button>
<button @click="stopMeasure">停止测量</button>
</div>
</div>
</template>
<script>
import BimViewer from './components/BimViewer.vue';
export default {
name: 'App',
components: {
BimViewer
},
methods: {
onEngineReady(engine) {
console.log('引擎已就绪', engine);
},
onEngineError(error) {
console.error('引擎错误', error);
},
goHome() {
this.$refs.viewer.goHome();
},
measure(mode) {
this.$refs.viewer.activateMeasure(mode);
},
stopMeasure() {
this.$refs.viewer.deactivateMeasure();
}
}
};
</script>
<style>
.app {
width: 100vw;
height: 100vh;
position: relative;
}
.toolbar {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
}
</style>
```
---
## React 使用
### 安装依赖
```bash
npm install bim-engine-sdk
```
### Hook 封装
```tsx
// hooks/useBimEngine.ts
import { useEffect, useRef, useState, useCallback } from 'react';
import { BimEngine } from 'bim-engine-sdk';
import type { EngineOptions, ModelLoadOptions } from 'bim-engine-sdk';
type MeasureMode = 'distance' | 'minDistance' | 'angle' | 'elevation' | 'volume' | 'laserDistance' | 'slope' | 'spaceVolume';
interface UseBimEngineOptions {
locale?: 'zh-CN' | 'en-US';
theme?: 'light' | 'dark';
engineOptions?: Omit<EngineOptions, 'container'>;
onReady?: (engine: BimEngine) => void;
onError?: (error: Error) => void;
}
export function useBimEngine(options: UseBimEngineOptions = {}) {
const containerRef = useRef<HTMLDivElement>(null);
const engineRef = useRef<BimEngine | null>(null);
const [isReady, setIsReady] = useState(false);
const [error, setError] = useState<Error | null>(null);
// 初始化引擎
useEffect(() => {
if (!containerRef.current) return;
try {
// 创建引擎实例
const engine = new BimEngine(containerRef.current, {
locale: options.locale || 'zh-CN',
theme: options.theme || 'light'
});
// 初始化 3D 引擎
const success = engine.engine?.initialize({
version: 'v2',
showStats: false,
showViewCube: true,
...options.engineOptions
});
if (success) {
engineRef.current = engine;
setIsReady(true);
options.onReady?.(engine);
} else {
throw new Error('3D 引擎初始化失败');
}
} catch (err) {
const error = err as Error;
setError(error);
options.onError?.(error);
}
// 清理
return () => {
engineRef.current?.destroy();
engineRef.current = null;
setIsReady(false);
};
}, []);
// 加载模型
const loadModel = useCallback((url: string, modelOptions?: ModelLoadOptions) => {
engineRef.current?.engine?.loadModel(url, modelOptions);
}, []);
// 回到主视角
const goHome = useCallback(() => {
engineRef.current?.engine?.CameraGoHome();
}, []);
// 激活测量
const activateMeasure = useCallback((mode: MeasureMode) => {
engineRef.current?.engine?.activateMeasure(mode);
}, []);
// 停用测量
const deactivateMeasure = useCallback(() => {
engineRef.current?.engine?.deactivateMeasure();
}, []);
// 切换主题
const setTheme = useCallback((theme: 'light' | 'dark') => {
engineRef.current?.setTheme(theme);
}, []);
// 切换语言
const setLocale = useCallback((locale: 'zh-CN' | 'en-US') => {
engineRef.current?.setLocale(locale);
}, []);
return {
containerRef,
engine: engineRef.current,
isReady,
error,
loadModel,
goHome,
activateMeasure,
deactivateMeasure,
setTheme,
setLocale
};
}
```
### 组件封装
```tsx
// components/BimViewer.tsx
import React, { useEffect } from 'react';
import { useBimEngine } from '../hooks/useBimEngine';
import type { ModelLoadOptions } from 'bim-engine-sdk';
interface BimViewerProps {
modelUrl?: string;
modelOptions?: ModelLoadOptions;
locale?: 'zh-CN' | 'en-US';
theme?: 'light' | 'dark';
className?: string;
style?: React.CSSProperties;
onReady?: (engine: any) => void;
onError?: (error: Error) => void;
}
export const BimViewer = React.forwardRef<any, BimViewerProps>((props, ref) => {
const {
modelUrl,
modelOptions,
locale = 'zh-CN',
theme = 'light',
className,
style,
onReady,
onError
} = props;
const {
containerRef,
engine,
isReady,
loadModel,
goHome,
activateMeasure,
deactivateMeasure,
setTheme,
setLocale
} = useBimEngine({
locale,
theme,
onReady,
onError
});
// 暴露方法给父组件
React.useImperativeHandle(ref, () => ({
getEngine: () => engine,
loadModel,
goHome,
activateMeasure,
deactivateMeasure,
setTheme,
setLocale
}));
// 加载模型
useEffect(() => {
if (isReady && modelUrl) {
loadModel(modelUrl, modelOptions);
}
}, [isReady, modelUrl, modelOptions, loadModel]);
return (
<div
ref={containerRef}
className={className}
style={{
width: '100%',
height: '100%',
...style
}}
/>
);
});
BimViewer.displayName = 'BimViewer';
```
### 使用组件
```tsx
// App.tsx
import React, { useRef } from 'react';
import { BimViewer } from './components/BimViewer';
function App() {
const viewerRef = useRef<any>(null);
const handleReady = (engine: any) => {
console.log('引擎已就绪', engine);
};
const handleError = (error: Error) => {
console.error('引擎错误', error);
};
const goHome = () => {
viewerRef.current?.goHome();
};
const measure = (mode: string) => {
viewerRef.current?.activateMeasure(mode);
};
const stopMeasure = () => {
viewerRef.current?.deactivateMeasure();
};
return (
<div style={{ width: '100vw', height: '100vh', position: 'relative' }}>
<BimViewer
ref={viewerRef}
modelUrl="./model/building"
modelOptions={{ position: [0, 0, 0] }}
locale="zh-CN"
theme="light"
onReady={handleReady}
onError={handleError}
/>
<div style={{ position: 'absolute', top: 20, left: 20, zIndex: 100 }}>
<button onClick={goHome}>主视角</button>
<button onClick={() => measure('distance')}>距离测量</button>
<button onClick={stopMeasure}>停止测量</button>
</div>
</div>
);
}
export default App;
```
---
## API 参考
### BimEngine
主引擎类,用于创建和管理 BIM 引擎实例。
#### 构造函数
```typescript
new BimEngine(container: HTMLElement | string, options?: {
locale?: 'zh-CN' | 'en-US';
theme?: 'light' | 'dark';
})
```
| 参数 | 类型 | 说明 |
|------|------|------|
| container | HTMLElement \| string | 容器元素或容器 ID |
| options.locale | string | 语言设置,默认 'zh-CN' |
| options.theme | string | 主题设置,默认 'light' |
#### 属性
| 属性 | 类型 | 说明 |
|------|------|------|
| engine | EngineManager | 3D 引擎管理器 |
| toolbar | ToolbarManager | 工具栏管理器 |
| dialog | DialogManager | 弹窗管理器 |
| measure | MeasureDialogManager | 测量面板管理器 |
#### 方法
| 方法 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| setLocale | locale: 'zh-CN' \| 'en-US' | void | 设置语言 |
| getLocale | - | string | 获取当前语言 |
| setTheme | theme: 'light' \| 'dark' | void | 设置主题 |
| setCustomTheme | theme: ThemeConfig | void | 设置自定义主题 |
| destroy | - | void | 销毁引擎 |
---
### EngineManager
3D 引擎管理器,通过 `engine.engine` 访问。
#### 方法
| 方法 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| initialize | options?: EngineOptions | boolean | 初始化 3D 引擎 |
| isInitialized | - | boolean | 检查是否已初始化 |
| loadModel | url: string, options?: ModelLoadOptions | void | 加载模型 |
| CameraGoHome | - | void | 回到主视角 |
| activateMeasure | mode: MeasureMode | void | 激活测量功能 |
| deactivateMeasure | - | void | 停用测量功能 |
| getCurrentMeasureType | - | MeasureMode \| null | 获取当前测量类型 |
| getEngine | - | any | 获取原始引擎实例 |
| destroy | - | void | 销毁引擎 |
---
## 类型定义
### EngineOptions
```typescript
interface EngineOptions {
container: HTMLElement; // 容器元素
backgroundColor?: number | string; // 背景色
version?: 'v1' | 'v2'; // WebGL 版本
showStats?: boolean; // 是否显示性能统计
showViewCube?: boolean; // 是否显示视图立方体
}
```
### ModelLoadOptions
```typescript
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
}
```
### MeasureMode
```typescript
type MeasureMode =
| 'distance' // 距离测量
| 'minDistance' // 最小距离测量
| 'angle' // 角度测量
| 'elevation' // 标高测量
| 'volume' // 体积测量
| 'laserDistance' // 激光测距
| 'slope' // 坡度测量
| 'spaceVolume'; // 空间体积测量
```
---
## 注意事项
1. **容器尺寸**:确保容器元素有明确的宽度和高度,否则 3D 引擎可能无法正常渲染。
2. **模型路径**:模型路径应为相对于 HTML 页面的路径,或者完整的 URL。
3. **销毁清理**:在组件卸载或页面关闭前,务必调用 `destroy()` 方法释放资源。
4. **浏览器兼容性**SDK 需要浏览器支持 WebGL。建议使用现代浏览器Chrome、Firefox、Safari、Edge
5. **静态资源**:确保 Draco 解码器等静态资源正确部署:
```
/static/js/draco/
├── DRACOLoader.js
├── draco_decoder.js
├── draco_decoder.wasm
├── draco_encoder.js
└── draco_wasm_wrapper.js
```
---
## 常见问题
### Q: 模型加载失败怎么办?
A: 检查以下几点:
- 模型路径是否正确
- 模型格式是否支持
- 网络请求是否正常F12 查看 Network
- Draco 解码器是否正确部署
### Q: 如何自定义主题?
A: 使用 `setCustomTheme` 方法:
```javascript
engine.setCustomTheme({
background: '#1a1a2e',
textPrimary: '#ffffff',
textSecondary: '#cccccc',
// ... 更多配置
});
```
### Q: 如何监听引擎事件?
A: 使用 `on` 方法监听事件:
```javascript
engine.on('modelLoaded', (data) => {
console.log('模型已加载', data);
});
```
---
## 技术支持
如有问题,请联系技术支持或提交 Issue。