import { isArray } from "lodash-es"; import { optimizeCanvasRendering } from "../utils/helper"; import { restoreObjectLayerAssociations } from "../utils/layerUtils"; import { Command } from "./Command"; /** * 橡皮擦操作命令 * 支持橡皮擦操作的撤销和重做 */ export class EraserCommand extends Command { /** * 构造函数 * @param {Object} options 命令选项 * @param {Object} options.canvas Fabric画布实例 * @param {Object} options.layerManager 图层管理器 * @param {Object} options.beforeSnapshot 擦除前的状态快照 * @param {Object} options.afterSnapshot 擦除后的状态快照 * @param {Array} options.affectedObjects 擦除影响的对象列表(可选) */ constructor(options) { super({ name: "橡皮擦操作", description: `擦除`, ...options, }); this.canvas = options.canvas; this.layerManager = options.layerManager; this.beforeSnapshot = options.beforeSnapshot; this.afterSnapshot = options.afterSnapshot; this.affectedObjects = options.affectedObjects || []; this.fristLoad = true; // 是否是第一次加载 } /** * 执行橡皮擦操作 */ async execute() { if (!this.beforeSnapshot || !this.afterSnapshot) { console.warn("缺少状态快照,无法执行橡皮擦命令"); return false; } if (!this.fristLoad) await this._restoreCanvasState(this.afterSnapshot); // 应用重做的状态 else await this.layerManager?.updateLayersObjectsInteractivity?.(false); this.fristLoad = false; // 标记为非第一次加载 return true; } /** * 撤销橡皮擦操作 */ async undo() { if (!this.beforeSnapshot) { console.warn("缺少擦除前的状态快照,无法撤销"); return false; } // 恢复到擦除前的状态 await this._restoreCanvasState(this.beforeSnapshot); return true; } /** * 恢复画布状态 * @param {Object} snapshot 状态快照 * @private */ async _restoreCanvasState(snapshot) { // 对比 eraser erasable 两个属性,如果当前对象的eraser属性和erasable属性不一致,则需要更新对象的eraser属性 if (!snapshot || !snapshot.objects) return; // 优化渲染 - 统一批处理 支持异步回调 防止闪屏 await optimizeCanvasRendering(this.canvas, async () => { return new Promise((resolve) => { this.canvas.loadFromJSON(snapshot, async () => { // 恢复图层关联 this._restoreObjectLayerAssociations(); // 确保所有对象的交互性正确设置 await this.layerManager?.updateLayersObjectsInteractivity?.(false); resolve(); }); }); }); } /** * 恢复对象与图层的关联关系 * @private */ _restoreObjectLayerAssociations() { if (!this.layerManager) return; const canvasObjects = this.canvas.getObjects(); restoreObjectLayerAssociations(this.layerManager?.layers?.value, canvasObjects); } }