import { findLayerRecursively } from "../utils/layerHelper"; import { restoreFabricObject } from "../utils/objectHelper"; import { Command } from "./Command"; /** * 更新组图层遮罩位置命令 * 当组图层的对象移动时,同步更新遮罩的位置 */ export class UpdateGroupMaskPositionCommand extends Command { constructor(options) { super({ name: "更新组图层遮罩位置", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerManager = options.layerManager; this.layerId = options.layerId; this.deltaX = options.deltaX || 0; this.deltaY = options.deltaY || 0; this.maskInitialLeft = options.maskInitialLeft || 0; this.maskInitialTop = options.maskInitialTop || 0; this.isExecuteRealtime = options.isExecuteRealtime || false; this.activeSelection = this.canvas.getActiveObject() || {}; this.isFristExecute = true; // 查找目标图层 this.layer = findLayerRecursively(this.layers.value, this.layerId)?.layer; if (!this.layer || !this.layer.clippingMask) { console.warn(`图层 ${this.layerId} 不存在或没有遮罩`); return false; } // 保存原始遮罩位置(用于撤销) // 保存原始位置 this.originalMaskPosition = { left: this.maskInitialLeft || 0, top: this.maskInitialTop || 0, }; // 收集当前选择的所有对象位置 this.originalObjectsPostion = this.activeSelection.getObjects().map((obj) => { return { left: obj.left || 0, top: obj.top || 0, id: obj.id, }; }); this.originalSelectionPosition = { left: this.activeSelection.left || 0, top: this.activeSelection.top || 0, }; console.log( `🛠️ 初始化更新组图层遮罩位置命令: ${this.name}, 图层ID: ${this.layerId}, 初始位置: (${this.originalMaskPosition.left}, ${this.originalMaskPosition.top})` ); this.newMaskPosition = null; } async execute() { try { // 计算新位置 const newLeft = this.maskInitialLeft + this.deltaX; const newTop = this.maskInitialTop + this.deltaY; // 更新遮罩位置 this.layer.clippingMask.left = newLeft; this.layer.clippingMask.top = newTop; this.newMaskPosition = { left: newLeft, top: newTop, }; // 更新所有使用此遮罩的子图层对象 await this._updateChildObjectsClipPath(this.layer, false, true); this.isFristExecute = false; console.log(`✅ 组图层遮罩位置已更新: (${newLeft}, ${newTop})`); return true; } catch (error) { console.error("更新组图层遮罩位置失败:", error); return false; } } async undo() { try { if (!this.originalMaskPosition) { console.warn("没有原始遮罩位置数据,无法撤销"); return false; } // 查找目标图层 const layer = this.layers.value.find((l) => l.id === this.layerId); if (!layer || !layer.clippingMask) { console.warn(`图层 ${this.layerId} 不存在或没有遮罩`); return false; } console.log( `↶ 撤销更新组图层遮罩位置: ${this.originalMaskPosition.left}, 图层ID: ${this.originalMaskPosition.top}` ); // 恢复原始位置 layer.clippingMask.left = this.originalMaskPosition.left; layer.clippingMask.top = this.originalMaskPosition.top; // 更新所有使用此遮罩的子图层对象 await this._updateChildObjectsClipPath(layer, true); // await this.layerManager.updateLayersObjectsInteractivity(); // this.canvas.renderAll(); console.log( `↶ 组图层遮罩位置已恢复: (${this.originalMaskPosition.left}, ${this.originalMaskPosition.top})` ); return true; } catch (error) { console.error("撤销组图层遮罩位置更新失败:", error); return false; } } /** * 实时执行(不记录到历史记录) * 用于拖拽过程中的实时更新 */ executeRealtime() { try { // 查找目标图层 const layer = this.layers.value.find((l) => l.id === this.layerId); if (!layer || !layer.clippingMask) { return false; } // 计算新位置 const newLeft = this.maskInitialLeft + this.deltaX; const newTop = this.maskInitialTop + this.deltaY; // 更新遮罩位置 layer.clippingMask.left = newLeft; layer.clippingMask.top = newTop; // 更新所有使用此遮罩的子图层对象(不需要等待) this._updateChildObjectsClipPath(layer); return true; } catch (error) { console.error("实时更新组图层遮罩位置失败:", error); return false; } } /** * 更新子图层对象的裁剪路径 * @param {Object} layer 组图层对象 * @private */ async _updateChildObjectsClipPath(layer, isUndo = false, isExecute = false) { if (!layer.children || layer.children.length === 0) { return; } try { // 重新创建遮罩对象 const clippingMaskFabricObject = await restoreFabricObject(layer.clippingMask, this.canvas); if (!clippingMaskFabricObject) { console.warn("无法恢复遮罩对象"); return; } clippingMaskFabricObject.clipPath = null; clippingMaskFabricObject.set({ absolutePositioned: true, }); clippingMaskFabricObject.dirty = true; clippingMaskFabricObject.setCoords(); // 更新所有子图层对象的裁剪路径 layer.children.forEach((childLayer) => { // 更新 fabricObjects 中的对象 childLayer.fabricObjects?.forEach((obj) => { const fabricObject = this.canvas.getObjects().find((o) => o.id === obj.id); if (fabricObject) { fabricObject.clipPath = clippingMaskFabricObject; fabricObject.dirty = true; fabricObject.setCoords(); } }); // 更新单个 fabricObject if (childLayer.fabricObject) { const fabricObject = this.canvas .getObjects() .find((o) => o.id === childLayer.fabricObject.id); if (fabricObject) { fabricObject.clipPath = clippingMaskFabricObject; fabricObject.dirty = true; fabricObject.setCoords(); } } }); if (isUndo) { this.activeSelection.set({ left: this.originalSelectionPosition.left - this.deltaX, top: this.originalSelectionPosition.top - this.deltaY, }); this.activeSelection.dirty = true; this.activeSelection.setCoords(); } if (isExecute && !this.isFristExecute) { this.activeSelection.set({ left: this.activeSelection.left + this.deltaX, top: this.activeSelection.top + this.deltaY, }); this.activeSelection.dirty = true; this.activeSelection.setCoords(); } // 触发画布重新渲染 this.canvas.renderAll(); } catch (error) { console.error("更新子图层对象裁剪路径失败:", error); } } getInfo() { return { name: this.name, layerId: this.layerId, deltaX: this.deltaX, deltaY: this.deltaY, originalPosition: this.originalMaskPosition, newPosition: this.newMaskPosition, }; } }