feat: 优化测量功能架构与引擎组件
- 重构测量激活逻辑,在 Engine 组件中添加统一的 activateMeasure(mode) 方法 - 简化 MeasureDialogManager,移除冗余的 handleMeasureTypeChange 方法 - 添加 EngineManager.activateMeasure 转发方法 - 修复 loadModel 错误,正确调用 Engine 组件方法 - 为 Engine 组件设置固定背景渐变色 - MeasurePanel 初始化时触发 onModeChange 回调 - 添加 MeasureMode 共享类型定义 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,17 +13,10 @@ export const createHomeButton = (engine: BimEngine): ButtonConfig => {
|
||||
type: 'button',
|
||||
label: 'toolbar.home',
|
||||
icon: getIcon('主视角'),
|
||||
keepActive: true,
|
||||
keepActive: false,
|
||||
onClick: (button) => {
|
||||
console.log('首页按钮被点击:', button.id);
|
||||
// 演示:使用 engine 发送事件
|
||||
// engine.dialog?.showInfoDialog()
|
||||
engine.emit('ui:open-dialog', { id: 'home-info' });
|
||||
|
||||
// 或者直接调用 engine 的方法
|
||||
// if (engine.engine) {
|
||||
// engine.engine.loadModel('...');
|
||||
// }
|
||||
engine.engine?.CameraGoHome()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,15 +9,16 @@ import { getIcon } from '../../../../../utils/icon-manager';
|
||||
* - 当前仅添加 UI 按钮,点击事件先留空(后续接入引擎能力再实现)
|
||||
* - 使用工厂函数模式注入 engine,便于未来调用 engine API
|
||||
*/
|
||||
export const createZoomBoxButton = (_engine: BimEngine): ButtonConfig => {
|
||||
export const createZoomBoxButton = (engine: BimEngine): ButtonConfig => {
|
||||
return {
|
||||
id: 'zoom-box',
|
||||
groupId: 'group-1',
|
||||
keepActive: true,
|
||||
keepActive: false,
|
||||
type: 'button',
|
||||
label: 'toolbar.zoomBox',
|
||||
icon: getIcon('框选放大'),
|
||||
onClick: () => {
|
||||
engine.engine?.getEngine().rangeScale.active();
|
||||
// 事件先留空:后续实现“框选放大/框选缩放”能力时再接入
|
||||
// 这里不做任何动作,避免误触影响用户操作
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ import type { ThemeConfig } from '../../themes/types';
|
||||
import { IBimComponent } from '../../types/component';
|
||||
import { themeManager } from '../../services/theme';
|
||||
import type { EngineOptions, ModelLoadOptions } from './types';
|
||||
import type { MeasureMode } from '../../types/measure';
|
||||
// 导入第三方 SDK 的 createEngine 函数
|
||||
import { createEngine as createEngineSDK } from '../../bim-engine-sdk.es.js';
|
||||
import { createEngine as createEngineSDK } from '../../engine_base/bim-engine-sdk.es.js';
|
||||
|
||||
// 重新导出类型,方便外部引用
|
||||
export type { EngineOptions, ModelLoadOptions };
|
||||
@@ -35,6 +36,10 @@ export class Engine implements IBimComponent {
|
||||
private _isDestroyed = false;
|
||||
/** 主题订阅取消函数 */
|
||||
private unsubscribeTheme: (() => void) | null = null;
|
||||
/** 当前激活的测量类型 */
|
||||
private currentMeasureType: MeasureMode | null = null;
|
||||
/** 主测量功能是否已激活 */
|
||||
private isMeasureActive: boolean = false;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
@@ -53,7 +58,7 @@ export class Engine implements IBimComponent {
|
||||
|
||||
// 保存配置选项(设置默认值)
|
||||
this.options = {
|
||||
backgroundColor: options.backgroundColor ?? 0x1a1a1a, // 默认深色背景
|
||||
backgroundColor: options.backgroundColor ?? 'linear-gradient(to bottom, rgb(214, 224, 235), rgb(246, 250, 255))', // 固定背景渐变色
|
||||
version: options.version ?? 'v1', // 默认使用 v1 版本
|
||||
showStats: options.showStats ?? false, // 默认不显示统计
|
||||
showViewCube: options.showViewCube ?? true, // 默认显示视图立方体
|
||||
@@ -76,6 +81,11 @@ export class Engine implements IBimComponent {
|
||||
}
|
||||
|
||||
try {
|
||||
// 应用背景色到容器
|
||||
if (typeof this.options.backgroundColor === 'string') {
|
||||
this.container.style.background = this.options.backgroundColor;
|
||||
}
|
||||
|
||||
// 创建引擎配置对象
|
||||
const engineConfig = {
|
||||
containerId: this.containerId,
|
||||
@@ -85,6 +95,9 @@ export class Engine implements IBimComponent {
|
||||
showViewCube: this.options.showViewCube,
|
||||
};
|
||||
|
||||
// 输出配置信息
|
||||
console.log('引擎配置信息:', engineConfig);
|
||||
|
||||
// 调用引擎创建函数创建引擎实例
|
||||
// 将 options 中的配置复制给 createEngine
|
||||
this.engine = createEngineSDK(engineConfig);
|
||||
@@ -115,33 +128,8 @@ export class Engine implements IBimComponent {
|
||||
* 根据主题调整 3D 引擎的视觉效果(如背景色)
|
||||
* @param theme 全局主题配置
|
||||
*/
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
if (!this._isInitialized || !this.engine) {
|
||||
return;
|
||||
}
|
||||
public setTheme(_theme: ThemeConfig): void {
|
||||
|
||||
// 根据主题调整背景色
|
||||
// dark 主题使用深色背景,light 主题使用浅色背景
|
||||
let backgroundColor: number;
|
||||
if (theme.name === 'dark') {
|
||||
backgroundColor = 0x1a1a1a; // 深色背景
|
||||
} else if (theme.name === 'light') {
|
||||
backgroundColor = 0xf5f5f5; // 浅色背景
|
||||
} else {
|
||||
// 自定义主题,尝试从主题配置中获取背景色
|
||||
// 如果主题配置中有 backgroundColor,使用它;否则使用默认值
|
||||
backgroundColor = this.options.backgroundColor ?? 0x1a1a1a;
|
||||
}
|
||||
|
||||
// 如果引擎支持设置背景色,则更新
|
||||
if (this.engine && typeof this.engine.setBackgroundColor === 'function') {
|
||||
this.engine.setBackgroundColor(backgroundColor);
|
||||
} else if (this.engine && this.engine.scene) {
|
||||
// 如果引擎有 scene 对象,尝试设置背景色
|
||||
if (this.engine.scene.background) {
|
||||
this.engine.scene.background.setHex(backgroundColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +161,15 @@ export class Engine implements IBimComponent {
|
||||
console.error('[Engine] Model URL is required.');
|
||||
return;
|
||||
}
|
||||
this.engine.loader.loadModel(url, options);
|
||||
this.engine.loaderModule.loadModels([url], options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回到主视角
|
||||
* @returns
|
||||
*/
|
||||
public CameraGoHome() {
|
||||
this.engine.viewCube.CameraGoHome();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,6 +179,181 @@ export class Engine implements IBimComponent {
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
// ==================== 测量功能方法 ====================
|
||||
|
||||
/**
|
||||
* 激活具体测量类型的统一入口(私有方法)
|
||||
* @param type 测量类型
|
||||
* @param activateFunc 第三方引擎的激活函数
|
||||
*/
|
||||
private activateMeasureType(type: MeasureMode, activateFunc: () => void): void {
|
||||
// 1. 检查引擎是否初始化
|
||||
if (!this._isInitialized || !this.engine) {
|
||||
console.error('Cannot activate measure: engine not initialized.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 检查 measure 模块是否存在
|
||||
if (!this.engine.measure) {
|
||||
console.error('Measure module not available.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 如果主功能未激活,先激活主功能
|
||||
if (!this.isMeasureActive) {
|
||||
console.log(`激活测测量功能`);
|
||||
this.engine.measure.active();
|
||||
this.isMeasureActive = true;
|
||||
}
|
||||
|
||||
// 4. 激活具体的测量类型(直接切换,不需要停用前一个)
|
||||
activateFunc();
|
||||
this.currentMeasureType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活距离测量
|
||||
*/
|
||||
public activateDistanceMeasure(): void {
|
||||
this.activateMeasureType('distance', () => {
|
||||
console.log(`激活距离测量`);
|
||||
this.engine.measure.distanceMeasure.active();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活最小距离测量
|
||||
*/
|
||||
public activateMinDistanceMeasure(): void {
|
||||
this.activateMeasureType('minDistance', () => {
|
||||
console.log(`激活最小距离测量`);
|
||||
this.engine.measure.minDistanceMeasure.active();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活角度测量
|
||||
*/
|
||||
public activateAngleMeasure(): void {
|
||||
this.activateMeasureType('angle', () => {
|
||||
console.log(`激活角度测量`);
|
||||
this.engine.measure.angleMeasure.active();
|
||||
console.log('[Engine] Angle measure activated (placeholder)');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活标高测量
|
||||
*/
|
||||
public activateElevationMeasure(): void {
|
||||
this.activateMeasureType('elevation', () => {
|
||||
console.log(`激活标高测量`);
|
||||
this.engine.measure.elevationMeasure.active();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活体积测量
|
||||
*/
|
||||
public activateVolumeMeasure(): void {
|
||||
this.activateMeasureType('volume', () => {
|
||||
console.log(`激活体积测量`);
|
||||
this.engine.measure.volumeMeasure.active();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活激光测距
|
||||
*/
|
||||
public activateLaserDistanceMeasure(): void {
|
||||
this.activateMeasureType('laserDistance', () => {
|
||||
// TODO: 调用第三方引擎方法(当前先空着)
|
||||
// this.engine.measure.laserDistanceMeasure.active();
|
||||
console.log('[Engine] Laser distance measure activated (placeholder)');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活坡度测量
|
||||
*/
|
||||
public activateSlopeMeasure(): void {
|
||||
this.activateMeasureType('slope', () => {
|
||||
console.log(`激活坡度测量`);
|
||||
this.engine.measure.slopeMeasure.active();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活空间体积测量
|
||||
*/
|
||||
public activateSpaceVolumeMeasure(): void {
|
||||
this.activateMeasureType('spaceVolume', () => {
|
||||
// TODO: 调用第三方引擎方法(当前先空着)
|
||||
// this.engine.measure.spaceVolumeMeasure.active();
|
||||
console.log('[Engine] Space volume measure activated (placeholder)');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活测量功能(根据类型统一入口)
|
||||
* @param mode 测量类型
|
||||
*/
|
||||
public activateMeasure(mode: MeasureMode): void {
|
||||
switch (mode) {
|
||||
case 'distance':
|
||||
this.activateDistanceMeasure();
|
||||
break;
|
||||
case 'minDistance':
|
||||
this.activateMinDistanceMeasure();
|
||||
break;
|
||||
case 'angle':
|
||||
this.activateAngleMeasure();
|
||||
break;
|
||||
case 'elevation':
|
||||
this.activateElevationMeasure();
|
||||
break;
|
||||
case 'volume':
|
||||
this.activateVolumeMeasure();
|
||||
break;
|
||||
case 'laserDistance':
|
||||
this.activateLaserDistanceMeasure();
|
||||
break;
|
||||
case 'slope':
|
||||
this.activateSlopeMeasure();
|
||||
break;
|
||||
case 'spaceVolume':
|
||||
this.activateSpaceVolumeMeasure();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停用测量功能(关闭测量时调用)
|
||||
*/
|
||||
public deactivateMeasure(): void {
|
||||
if (!this._isInitialized || !this.engine?.measure) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isMeasureActive) {
|
||||
return; // 已经是停用状态
|
||||
}
|
||||
console.log('停用测量功能');
|
||||
this.engine.measure.disActive();
|
||||
this.isMeasureActive = false;
|
||||
this.currentMeasureType = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前激活的测量类型
|
||||
* @returns 当前测量类型,如果未激活则返回 null
|
||||
*/
|
||||
public getCurrentMeasureType(): MeasureMode | null {
|
||||
return this.currentMeasureType;
|
||||
}
|
||||
|
||||
// ==================== 结束:测量功能方法 ====================
|
||||
|
||||
/**
|
||||
* 销毁组件 (接口实现)
|
||||
* 清理资源、取消订阅、销毁引擎实例
|
||||
@@ -191,14 +362,22 @@ export class Engine implements IBimComponent {
|
||||
if (this._isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 停用测量功能
|
||||
this.deactivateMeasure();
|
||||
|
||||
// 取消主题订阅
|
||||
if (this.unsubscribeTheme) {
|
||||
this.unsubscribeTheme();
|
||||
this.unsubscribeTheme = null;
|
||||
}
|
||||
|
||||
// 清理容器(可选,根据需求决定是否清空容器)
|
||||
this.container.innerHTML = '';
|
||||
|
||||
// 更新状态
|
||||
this.currentMeasureType = null;
|
||||
this.isMeasureActive = false;
|
||||
this._isDestroyed = true;
|
||||
this._isInitialized = false;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
export interface EngineOptions {
|
||||
/** 容器元素 */
|
||||
container: HTMLElement;
|
||||
/** 背景颜色(十六进制数字,如 0x333333) */
|
||||
backgroundColor?: number;
|
||||
/** 背景颜色(十六进制数字如 0x333333,或 CSS 字符串如 'linear-gradient(...)') */
|
||||
backgroundColor?: number | string;
|
||||
/** WebGL 版本 */
|
||||
version?: 'v1' | 'v2';
|
||||
/** 是否显示性能统计 */
|
||||
|
||||
@@ -134,6 +134,11 @@ export class MeasurePanel implements IBimComponent {
|
||||
this.applyActiveModeState();
|
||||
this.applyViewState();
|
||||
this.renderResult();
|
||||
|
||||
// 触发初始测量模式的回调(让外部知道默认激活了哪个模式)
|
||||
if (this.options.onModeChange) {
|
||||
this.options.onModeChange(this.activeMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,27 +1,15 @@
|
||||
/**
|
||||
* 测量面板 - 类型定义
|
||||
*
|
||||
*
|
||||
* 注意:
|
||||
* - 本次只实现 UI,不实现真实测量逻辑(拾取、画线、计算等)。
|
||||
* - 这里的类型以“可读性优先”为原则,尽量直观、易扩展。
|
||||
* - 这里的类型以"可读性优先"为原则,尽量直观、易扩展。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 测量方式(8 种)
|
||||
*
|
||||
* 说明:
|
||||
* - id 采用英文驼峰/小写,便于程序内部使用;
|
||||
* - 显示名称必须通过国际化 key 获取(见 locales)。
|
||||
*/
|
||||
export type MeasureMode =
|
||||
| 'distance' // 距离
|
||||
| 'minDistance' // 最小距离
|
||||
| 'angle' // 角度
|
||||
| 'elevation' // 标高
|
||||
| 'volume' // 体积
|
||||
| 'laserDistance' // 激光测距
|
||||
| 'slope' // 坡度
|
||||
| 'spaceVolume'; // 空间体积
|
||||
// 从通用 types 目录导入 MeasureMode,避免组件间耦合
|
||||
import type { MeasureMode } from '../../types/measure';
|
||||
// 同时重新导出,保持向后兼容
|
||||
export type { MeasureMode };
|
||||
|
||||
/**
|
||||
* 距离/标高等“长度类”单位
|
||||
|
||||
Reference in New Issue
Block a user