Files
bim_engine/docs/SDK_USAGE.md

985 lines
22 KiB
Markdown
Raw Normal View History

# 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。