图形编辑器:工具管理和切换( 二 )


实现如下:
class ToolManager {toolMap = new Map();currentTool: ITool | null = null;eventEmitter: EventEmitter;_unbindEvent: () => void;constructor(private editor: Editor) {this.eventEmitter = new EventEmitter(); // 模仿 nodejs 的简易版 EventEmitter// 绑定 toolthis.toolMap.set(DrawRectTool.type, new DrawRectTool(editor));this.toolMap.set(DrawEllipseTool.type, new DrawEllipseTool(editor));this.toolMap.set(SelectTool.type, new SelectTool(editor));this.toolMap.set(DragCanvasTool.type, new DragCanvasTool(editor));this.setTool(DrawRectTool.type);this._unbindEvent = this.bindEvent();}getToolName() {return this.currentTool?.type;}bindEvent() {let isPressing = false;const handleDown = (e: PointerEvent) => {if (e.button !== 0) { // 必须是鼠标左键return;}if (!this.currentTool) {throw new Error('未设置当前使用工具');}isPressing = true;this.currentTool.start(e);};const handleMove = (e: PointerEvent) => {if (!this.currentTool) {throw new Error('未设置当前使用工具');}if (isPressing) {this.editor.hostEventManager.disableDragBySpace();this.currentTool.drag(e);} else {this.currentTool.moveExcludeDrag(e);}};const handleUp = (e: PointerEvent) => {if (e.button !== 0) { // 必须是鼠标左键return;}if (!this.currentTool) {throw new Error('未设置当前使用工具');}if (isPressing) {this.editor.hostEventManager.enableDragBySpace();isPressing = false;this.currentTool.end(e);}};const canvas = this.editor.canvasElement;canvas.addEventListener('pointerdown', handleDown);window.addEventListener('pointermove', handleMove);window.addEventListener('pointerup', handleUp);return function unbindEvent() {canvas.removeEventListener('pointerdown', handleDown);window.removeEventListener('pointermove', handleMove);window.removeEventListener('pointerup', handleUp);};}unbindEvent() {this._unbindEvent();this._unbindEvent = noop;}setTool(toolName: string) {const prevTool = this.currentTool;const currentTool = this.currentTool = this.toolMap.get(toolName) || null;if (!currentTool) {throw new Error(`没有 ${toolName} 对应的工具对象`);}prevTool && prevTool.inactive();currentTool.active();this.eventEmitter.emit('change', currentTool.type);}on(eventName: 'change', handler: (toolName: string) => void) {this.eventEmitter.on(eventName, handler);}off(eventName: 'change', handler: (toolName: string) => void) {this.eventEmitter.off(eventName, handler);}destroy() {this.currentTool?.inactive();}}
结尾
工具管理类基础的设计就是这样 。因为是基于生命周期去设计的,所以看起来挺像 React、Vue 的组件写法的 。
我是前端西瓜哥,欢迎关注我,学习更多前端知识 。