- 支持原生 HTML、Vue 2/3、React 框架 - 包含完整的 API 参考和类型定义 - 提供组件封装示例和 Hook 封装 - 添加常见问题解答 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
22 KiB
22 KiB
BIM Engine SDK 使用文档
BIM Engine SDK 是一个用于 3D BIM 模型展示的 JavaScript SDK,支持原生 HTML、Vue 2/3 和 React 框架。
目录
安装
NPM 安装
npm install bim-engine-sdk
CDN / 本地引入
<script src="./lib/bim-engine-sdk.umd.js"></script>
原生 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>
完整功能示例
<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 使用
安装依赖
npm install bim-engine-sdk
组件封装
<!-- 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>
使用组件
<!-- 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 使用
安装依赖
npm install bim-engine-sdk
组件封装
<!-- 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>
使用组件
<!-- 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 使用
安装依赖
npm install bim-engine-sdk
Hook 封装
// 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
};
}
组件封装
// 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';
使用组件
// 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 引擎实例。
构造函数
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
interface EngineOptions {
container: HTMLElement; // 容器元素
backgroundColor?: number | string; // 背景色
version?: 'v1' | 'v2'; // WebGL 版本
showStats?: boolean; // 是否显示性能统计
showViewCube?: boolean; // 是否显示视图立方体
}
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
}
MeasureMode
type MeasureMode =
| 'distance' // 距离测量
| 'minDistance' // 最小距离测量
| 'angle' // 角度测量
| 'elevation' // 标高测量
| 'volume' // 体积测量
| 'laserDistance' // 激光测距
| 'slope' // 坡度测量
| 'spaceVolume'; // 空间体积测量
注意事项
-
容器尺寸:确保容器元素有明确的宽度和高度,否则 3D 引擎可能无法正常渲染。
-
模型路径:模型路径应为相对于 HTML 页面的路径,或者完整的 URL。
-
销毁清理:在组件卸载或页面关闭前,务必调用
destroy()方法释放资源。 -
浏览器兼容性:SDK 需要浏览器支持 WebGL。建议使用现代浏览器(Chrome、Firefox、Safari、Edge)。
-
静态资源:确保 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 方法:
engine.setCustomTheme({
background: '#1a1a2e',
textPrimary: '#ffffff',
textSecondary: '#cccccc',
// ... 更多配置
});
Q: 如何监听引擎事件?
A: 使用 on 方法监听事件:
engine.on('modelLoaded', (data) => {
console.log('模型已加载', data);
});
技术支持
如有问题,请联系技术支持或提交 Issue。