Konva.JS中基于命令模式的撤销重做功能实现
本文介绍如何在Konva.js绘图应用中,利用命令模式实现撤销(Ctrl+Z)和重做(Ctrl+Y)功能。 我们将图形操作封装成命令对象,并使用命令栈管理这些操作,从而实现图形编辑的回退和前进。
首先,定义一个基础Command类:
class Command { constructor() { this.states = []; // 用于存储状态快照 } execute() { throw new Error('execute method must be implemented'); } undo() { throw new Error('undo method must be implemented'); } saveState(state) { this.states.push(state); } restoreState() { return this.states.pop() || null; // 返回上一个状态,或null } }
接下来,创建一个具体的命令类,例如绘制矩形的命令:
class DrawRectangleCommand extends Command { constructor(stage, layer, rect) { super(); this.stage = stage; this.layer = layer; this.rect = rect; } execute() { this.saveState(this.layer.toJSON()); // 保存当前图层状态 this.layer.add(this.rect); this.layer.draw(); } undo() { this.rect.destroy(); const prevState = this.restoreState(); if (prevState) { this.layer.destroyChildren(); // 清空图层 this.layer = Konva.Node.create(prevState, this.stage); // 恢复上一个状态 this.stage.add(this.layer); this.layer.draw(); } } }
然后,实现命令管理器:
class CommandManager { constructor() { this.undoStack = []; this.redoStack = []; } executeCommand(command) { command.execute(); this.undoStack.push(command); this.redoStack = []; // 执行新命令后,清空重做栈 } undo() { if (this.undoStack.length === 0) return; const command = this.undoStack.pop(); command.undo(); this.redoStack.push(command); } redo() { if (this.redoStack.length === 0) return; const command = this.redoStack.pop(); command.execute(); this.undoStack.push(command); } }
最后,在Konva.js应用中使用:
const stage = new Konva.Stage({ container: 'container', width: window.innerWidth, height: window.innerHeight }); const layer = new Konva.Layer(); stage.add(layer); const commandManager = new CommandManager(); stage.on('click', (e) => { const rect = new Konva.Rect({ x: e.evt.layerX, y: e.evt.layerY, width: 50, height: 50, fill: 'red', draggable: true }); const command = new DrawRectangleCommand(stage, layer, rect); commandManager.executeCommand(command); }); document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.key === 'z') { commandManager.undo(); } else if (e.ctrlKey && e.key === 'y') { commandManager.redo(); } });
这段代码实现了简单的矩形绘制和撤销重做功能。 您可以扩展Command类来支持其他图形操作,例如移动、缩放、旋转等。 记住在每个操作的execute方法中保存当前状态,并在undo方法中恢复之前状态。 这将确保您的撤销重做功能能够正确工作。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END