Chili3D事件处理:用户交互与命令执行流程
概述
Chili3D作为一款基于浏览器的3D CAD应用,其核心交互机制建立在高效的事件处理和命令执行系统之上。本文将深入解析Chili3D的事件处理架构、用户交互流程以及命令执行机制,帮助开发者理解这一复杂系统的设计哲学和实现细节。
事件处理架构
核心接口设计
Chili3D采用统一的事件处理接口IEventHandler,定义了所有事件处理器的基本行为:
export interface IEventHandler extends IDisposable {
pointerMove(view: IView, event: PointerEvent): void;
pointerDown(view: IView, event: PointerEvent): void;
pointerUp(view: IView, event: PointerEvent): void;
pointerOut?(view: IView, event: PointerEvent): void;
mouseWheel?(view: IView, event: WheelEvent): void;
keyDown(view: IView, event: KeyboardEvent): void;
}
事件处理器类型
系统支持多种事件处理器,每种处理器负责特定的交互场景:
| 处理器类型 | 职责描述 | 适用场景 |
|---|---|---|
| NodeSelectionHandler | 节点选择处理 | 常规对象选择和操作 |
| EditEventHandler | 编辑模式处理 | 特定编辑操作上下文 |
| ShapeSelectionHandler | 形状选择处理 | 几何形状的精确选择 |
事件处理流程
命令执行系统
命令接口设计
Chili3D的命令系统基于ICommand接口,支持可取消的命令执行:
export interface ICommand {
execute(application: IApplication): Promise<void>;
}
export interface ICanclableCommand extends ICommand, IDisposable {
cancel(): Promise<void>;
}
可取消命令基类
CancelableCommand作为所有可取消命令的基类,提供了完整的生命周期管理:
export abstract class CancelableCommand extends Observable implements ICanclableCommand {
// 属性缓存,支持命令间状态保持
private static readonly _propertiesCache: Map<string, any> = new Map();
// 命令执行生命周期方法
protected abstract executeAsync(): Promise<void>;
protected beforeExecute(): void;
protected afterExecute(): void;
// 取消机制
async cancel(): Promise<void>;
}
命令执行流程
核心组件交互
服务层架构
Chili3D采用服务层模式管理核心功能:
| 服务名称 | 职责描述 | 关键方法 |
|---|---|---|
| CommandService | 命令管理服务 | 命令注册、执行、撤销 |
| EditorService | 编辑器服务 | 编辑状态管理、事件处理器切换 |
| HotkeyService | 快捷键服务 | 全局快捷键绑定和处理 |
事件处理器切换机制
系统支持动态切换事件处理器以适应不同的操作模式:
// 在EditorService中切换事件处理器
document.visual.eventHandler = this.editHandler;
// 在Selection中恢复原有处理器
const oldHandler = this.document.visual.eventHandler;
this.document.visual.eventHandler = handler;
// ... 操作完成后
this.document.visual.eventHandler = oldHandler;
编辑事件处理示例
EditEventHandler实现
编辑事件处理器扩展了基础的选择功能,增加了属性显示特性:
export class EditEventHandler extends NodeSelectionHandler {
constructor(
document: IDocument,
readonly selectedNodes: INode[],
) {
super(document, true);
// 发布属性显示事件
PubSub.default.pub("showProperties", document, selectedNodes);
}
override disposeInternal() {
// 清理时隐藏属性面板
PubSub.default.pub("showProperties", this.document, []);
super.disposeInternal();
}
}
属性发布订阅机制
系统使用PubSub模式实现组件间通信:
最佳实践与设计模式
1. 观察者模式应用
Chili3D广泛使用观察者模式实现状态同步:
// 命令基类继承Observable
export abstract class CancelableCommand extends Observable {
// 支持属性变更通知
@Property.define("common.cancel")
async cancel() {
// 取消逻辑
}
}
2. 依赖注入模式
服务层采用依赖注入设计:
// 应用构建时注册服务
new Application({
services: [
new CommandService(),
new EditorService(),
new HotkeyService()
]
})
3. 资源管理策略
所有事件处理器和命令都实现IDisposable接口,确保资源正确释放:
// 确保事件处理器正确释放
this._eventHandler.dispose();
性能优化策略
1. 属性缓存机制
命令系统使用共享属性缓存减少重复计算:
private static readonly _propertiesCache: Map<string, any> = new Map();
private readProperties() {
Property.getProperties(this).forEach((x) => {
let key = this.cacheKeyOfProperty(x);
if (CancelableCommand._propertiesCache.has(key)) {
(this as any)[key] = CancelableCommand._propertiesCache.get(key);
}
});
}
2. 异步控制优化
使用AsyncController管理异步操作的生命周期:
#controller?: AsyncController;
protected get controller() {
return this.#controller;
}
protected set controller(value: AsyncController | undefined) {
if (this.#controller === value) return;
this.#controller?.dispose(); // 确保旧控制器释放
this.#controller = value;
}
总结
Chili3D的事件处理和命令执行系统展现了一个成熟Web CAD应用的核心架构设计。通过统一的事件接口、灵活的命令系统、以及高效的服务层架构,系统能够处理复杂的3D交互场景,同时保持良好的可扩展性和维护性。
关键设计要点包括:
- 统一事件接口:所有事件处理器遵循相同接口,便于替换和扩展
- 命令生命周期管理:完整的执行、取消、资源释放机制
- 发布订阅通信:松耦合的组件间通信方式
- 资源管理:严格的Disposable模式确保资源正确释放
- 性能优化:属性缓存和异步控制优化用户体验
这种架构设计不仅适用于3D CAD应用,也为其他复杂的Web图形应用提供了有价值的参考模式。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



