import { findLayerRecursively, OperationType } from "../utils/layerHelper"; import { Command } from "./Command"; import { generateId, optimizeCanvasRendering, findObjectById, objectIsInCanvas, removeCanvasObjectByObject, getObjectZIndex, insertObjectAtZIndex, } from "../utils/helper"; import { fabric } from "fabric-with-all"; import { imageModeHandler } from "../utils/imageHelper"; import { restoreFabricObject } from "../utils/objectHelper"; /** * 设置活动图层命令 */ export class SetActiveLayerCommand extends Command { constructor(options) { super({ name: "设置活动图层", saveState: false, }); this.layers = options.layers; this.canvas = options.canvas; this.activeLayerId = options.activeLayerId; this.layerId = options.layerId; this.parentId = options.parentId; this.oldActiveLayerId = this.activeLayerId.value; this.layerManager = options.layerManager; this.oldActiveObjects = []; this.newLayer = null; this.editorMode = options.editorMode; } execute() { const { layer } = findLayerRecursively( this.layers.value, this.layerId, this.parentId ); this.newLayer = layer; if (!this.newLayer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 如果是背景层,不设置为活动图层 if (this.newLayer.isBackground) { console.warn("背景层不能设为活动图层"); return false; } // 如果图层已锁定,不设置为活动图层 if (this.newLayer.locked) { console.warn("锁定图层不能设为活动图层"); return false; } this.oldActiveObjects = this.canvas.getActiveObjects(); // 设置为活动图层 this.activeLayerId.value = this.layerId; // 如果在选择模式下,取消所有选择 if (this.editorMode === OperationType.SELECT && this.canvas) { this.canvas.discardActiveObject(); // 设置为新的图层下的对象为激活,但需要确保对象存在于画布上 if ( this.newLayer.fabricObjects && this.newLayer.fabricObjects.length > 0 ) { const canvasObjects = this.canvas.getObjects(); const validObjects = this.newLayer.fabricObjects.filter( (obj) => obj && canvasObjects.includes(obj) ); if (validObjects.length > 0) { if (validObjects.length === 1) { // 只有一个对象时直接设置 this.canvas.setActiveObject(validObjects[0]); } else { // 多个对象时创建活动选择组 const activeSelection = new fabric.ActiveSelection(validObjects, { canvas: this.canvas, }); this.canvas.setActiveObject(activeSelection); } } } this.canvas.renderAll(); } return true; } undo() { // 恢复原活动图层ID this.activeLayerId.value = this.oldActiveLayerId; // 如果在选择模式下,恢复取消的所有选择 if (this.editorMode === OperationType.SELECT && this.canvas) { this.canvas.discardActiveObject(); // 修复:确保对象存在于画布上才激活 if (this.oldActiveObjects && this.oldActiveObjects.length > 0) { const canvasObjects = this.canvas.getObjects(); const validObjects = this.oldActiveObjects.filter( (obj) => obj && canvasObjects.includes(obj) ); if (validObjects.length > 0) { if (validObjects.length > 1) { // 如果有多个对象,需要创建一个活动选择组 const activeSelection = new fabric.ActiveSelection(validObjects, { canvas: this.canvas, }); this.canvas.setActiveObject(activeSelection); } else { // 只有一个对象时直接设置 this.canvas.setActiveObject(validObjects[0]); } } } this.canvas.renderAll(); } } getInfo() { return { name: this.name, layerId: this.layerId, oldActiveLayerId: this.oldActiveLayerId, }; } } /** * 添加对象到图层命令 */ export class AddObjectToLayerCommand extends Command { constructor(options) { super({ name: "添加对象到图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.fabricObject = options.fabricObject; this.layerManager = options.layerManager; // 保存对象原始状态和ID this.objectId = this.fabricObject.id || `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.fabricObject.set({ id: this.objectId, layerId: options.layerId, layerName: options.layerName || "", }); // 保存完整的对象状态,包括位置和变换信息 this.originalObjectState = this.fabricObject.toObject([ "id", "layerId", "layerName", ]); // // 新增:保存详细的位置和变换信息,用于重做时恢复 // this.originalPosition = { // left: this.originalObjectState.left || 0, // top: this.originalObjectState.top || 0, // scaleX: this.fabricObject.scaleX || 1, // scaleY: this.fabricObject.scaleY || 1, // angle: this.fabricObject.angle || 0, // flipX: this.fabricObject.flipX || false, // flipY: this.fabricObject.flipY || false, // opacity: this.fabricObject.opacity || 1, // originX: this.fabricObject.originX || "left", // originY: this.fabricObject.originY || "top", // }; // 记录执行状态,用于区分首次执行和重做 this.isFirstExecution = true; } async execute() { // 查找目标图层 const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); if (!layer) { console.error(`图层 ${this.layerId} 不存在`); return null; } // 如果是背景层,不允许添加对象 if (layer.isBackground) { console.warn("不能向背景层添加对象"); return null; } console.log(this.originalObjectState); // 优化渲染 - 统一批处理 支持异步回调 await optimizeCanvasRendering(this.canvas, async () => { fabric.util.enlivenObjects( [this.originalObjectState], async (objects) => { this.fabricObject = objects[0]; // 将对象添加到画布 this.fabricObject.set({ id: this.objectId, // 确保对象有唯一ID layerId: this.layerId, // 设置图层ID layerName: layer.name, // 设置图层名称 isBackground: layer.isBackground || false, // 是否为背景层 isFixed: layer.isFixed || false, // 是否为固定层 isLocked: layer.locked || false, // 是否锁定 isVisible: layer.visible !== false, // 是否可见 eraser: layer.eraser || false, // 是否为橡皮擦 type: this.fabricObject.type || "object", // 对象类型 selectable: true, // 设置对象可选择 evented: true, // 设置对象可事件 }); // 如果对象父图层有 裁剪 则更新裁剪 if (parent.clippingMask) { const clippingMaskFabricObject = await restoreFabricObject( parent.clippingMask, this.canvas ); clippingMaskFabricObject.clipPath = null; clippingMaskFabricObject.set({ absolutePositioned: true }); this.fabricObject.clipPath = clippingMaskFabricObject; // 标记为脏对象 this.fabricObject.dirty = true; this.fabricObject.setCoords(); } } ); // this.canvas.renderAll(); this.canvas.add(this.fabricObject); // this.canvas.setActiveObject(this.fabricObject); // 将对象添加到图层的fabricObjects数组 layer.fabricObjects = layer.fabricObjects || []; layer.fabricObjects.push( this.fabricObject?.toObject?.(["id", "layerId", "layerName"]) || this.fabricObject ); // 标记为非首次执行 this.isFirstExecution = false; console.log( `✅ 对象已添加到图层 "${layer.name}",位置: (${this.fabricObject.left}, ${this.fabricObject.top})` ); }); await this.layerManager?.updateLayersObjectsInteractivity?.(); this.layerManager?.updateLayersObjectsInteractivity?.(); // 如果是重做,使用保存的原始位置 // this.canvas.discardActiveObject(); // // 确保对象确实存在于画布上才激活 // const canvasObjects = this.canvas.getObjects(); // const validObjects = layer.fabricObjects.filter( // (obj) => obj && canvasObjects.includes(obj) // ); // if (validObjects.length > 0) { // if (validObjects.length === 1) { // // 只有一个对象时直接设置 // this.canvas.setActiveObject(validObjects[0]); // } else { // // 多个对象时创建活动选择组 // const activeSelection = new fabric.ActiveSelection(validObjects, { // canvas: this.canvas, // }); // this.canvas.setActiveObject(activeSelection); // } // } return this.fabricObject; } async undo() { // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); if (!layer) { return false; } // 从图层的fabricObjects数组中移除对象 if (layer.fabricObjects) { layer.fabricObjects = layer.fabricObjects.filter( (obj) => obj.id !== this.objectId ); } // 优化渲染 - 统一批处理 支持异步回调 optimizeCanvasRendering(this.canvas, async () => { // 从画布移除对象 const object = this.canvas .getObjects() .find((obj) => obj.id === this.objectId); if (object) { // 先丢弃活动对象,避免控制点渲染错误 this.canvas.discardActiveObject(); this.canvas.remove(object); } await this.layerManager?.updateLayersObjectsInteractivity?.(false); // 重置为首次执行状态,以便重做时能正确恢复位置 this.isFirstExecution = false; // 保持为false,因为已经执行过一次了 }); return true; } getInfo() { return { name: this.name, layerId: this.layerId, objectId: this.objectId, isFirstExecution: this.isFirstExecution, originalPosition: this.originalPosition, }; } } /** * 从图层中移除对象命令 */ export class RemoveObjectFromLayerCommand extends Command { constructor(options) { super({ name: "从图层中移除对象", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.objectId = options.objectId; // 查找对象和图层 this.object = typeof options.objectOrId === "object" ? options.objectOrId : this.canvas.getObjects().find((obj) => obj.id === this.objectId); if (this.object) { this.layerId = this.object.layerId; this.objectData = this.object.toObject(["id", "layerId", "layerName"]); } } execute() { if (!this.object) { console.error(`对象 ${this.objectId} 不存在`); return false; } if (!this.layerId) { console.error(`对象 ${this.objectId} 未关联到任何图层`); return false; } // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); if (!layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 从画布移除对象 this.canvas.remove(this.object); // 从图层的fabricObjects数组移除对象 if (layer.fabricObjects) { layer.fabricObjects = layer.fabricObjects.filter( (obj) => obj.id !== this.objectId ); } // 更新画布 this.canvas.renderAll(); return true; } undo() { if (!this.objectData || !this.layerId) { return false; } // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); if (!layer) { return false; } // 恢复对象到画布 fabric.util.enlivenObjects([this.objectData], (objects) => { const restoredObject = objects[0]; // 将对象添加到画布 this.canvas.add(restoredObject); // 将对象添加回图层 layer.fabricObjects = layer.fabricObjects || []; layer.fabricObjects.push(restoredObject); // 更新画布 this.canvas.renderAll(); }); return true; } getInfo() { return { name: this.name, objectId: this.objectId, layerId: this.layerId, }; } } /** * 更换固定图层图像命令 * 专门用于更换固定图层(如背景图层)的图像 */ export class ChangeFixedImageCommand extends Command { constructor(options = {}) { super(); this.canvas = options.canvas; this.layerManager = options.layerManager; this.imageUrl = options.imageUrl; this.targetLayerType = options.targetLayerType || "fixed"; // 'background', 'fixed', etc. this.position = options.position || { x: 0, y: 0 }; this.scale = options.scale || { x: 1, y: 1 }; this.preserveTransform = options.preserveTransform ?? false; // 默认不保留变换 this.options = options || {}; this.scale.x = options.scaleX || 1; this.scale.y = options.scaleY || 1; this.position.x = options.left || this.canvas.width / 2; this.position.y = options.top || this.canvas.height / 2; this.canvasWidth = options?.canvasWidth?.value || this.canvas.width; this.canvasHeight = options?.canvasHeight?.value || this.canvas.height; // 底图加载方式 1.平铺 2.拉伸 3.拉伸平铺 4.拉伸平铺并裁剪 5.包含 this.imageMode = options?.imageMode || ""; // 默认 contains, stretch,tile, stretchTile, stretchTileCrop // 用于回滚的状态 this.previousImage = null; this.previousTransform = null; this.previousObjectId = null; // 保存之前对象的ID this.targetLayer = null; this.newObjectId = generateId("fixed_"); // 保存新对象的ID this.isExecuted = false; // 错误处理 this.maxRetries = options.maxRetries || 3; this.retryCount = 0; this.timeoutMs = options.timeoutMs || 10000; // 查找目标图层 this.targetLayer = this.findTargetLayer(); } async execute() { try { // 查找目标图层 this.targetLayer = this.findTargetLayer(); if (!this.targetLayer) { throw new Error(`找不到目标图层类型: ${this.targetLayerType}`); } // 保存当前状态 await this.saveCurrentState(); // 加载新图像 const newImage = await this.loadImageWithRetry(); // 应用图像到图层 await this.applyImageToLayer(newImage); this.isExecuted = true; return { success: true, layerId: this.targetLayer.id, imageUrl: this.imageUrl, }; } catch (error) { console.error("ChangeFixedImageCommand执行失败:", error); // 如果已经执行了部分操作,尝试回滚 if (this.isExecuted) { try { await this.undo(); } catch (rollbackError) { console.error("回滚失败:", rollbackError); } } throw error; } } async undo() { if (!this.isExecuted || !this.targetLayer) { throw new Error("命令未执行或目标图层不存在"); } try { await optimizeCanvasRendering(this.canvas, async () => { if (this.previousImage && this.previousObjectId) { // 恢复之前的图像 await this.restorePreviousImage(); } else { // 如果没有之前的图像,移除当前图像 await this.removeCurrentImage(); } }); this.isExecuted = false; return { success: true, action: "reverted", layerId: this.targetLayer.id, }; } catch (error) { console.error("ChangeFixedImageCommand撤销失败:", error); throw error; } } findTargetLayer() { const layers = this.layerManager.layers?.value || []; switch (this.targetLayerType) { case "background": return layers.find((layer) => layer.isBackground); case "fixed": return layers.find((layer) => layer.isFixed); default: return layers.find((layer) => layer.type === this.targetLayerType); } } async saveCurrentState() { // 通过画布查找当前图层的对象,而不是直接使用图层引用 const currentObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.targetLayer.id); if (currentObjects.length > 0) { const currentObj = currentObjects[0]; // 固定图层通常只有一个对象 // 验证对象确实在画布中 const canvasCheck = objectIsInCanvas(this.canvas, currentObj); if (!canvasCheck.flag) { console.warn("图层对象不在画布中,跳过状态保存"); return; } this.previousObjectId = currentObj.id; // 使用帮助函数获取z-index位置 this.previousZIndex = getObjectZIndex(this.canvas, currentObj); // 保存当前图像URL(如果存在) this.previousImage = { url: currentObj.getSrc ? currentObj.getSrc() : null, element: currentObj._element ? currentObj._element.cloneNode() : null, objectData: currentObj.toObject(["id", "layerId", "layerName"]), // 保存完整对象数据 zIndex: this.previousZIndex, // 保存z-index }; // 保存变换状态 this.previousTransform = { left: currentObj.left, top: currentObj.top, scaleX: currentObj.scaleX, scaleY: currentObj.scaleY, angle: currentObj.angle, flipX: currentObj.flipX, flipY: currentObj.flipY, opacity: currentObj.opacity, }; console.log(`保存渲染顺序: z-index = ${this.previousZIndex}`); } } async loadImageWithRetry() { for (let attempt = 0; attempt <= this.maxRetries; attempt++) { try { return await this.loadImage(); } catch (error) { this.retryCount = attempt; if (attempt === this.maxRetries) { throw new Error( `图像加载失败,已重试${this.maxRetries}次: ${error.message}` ); } // 指数退避重试 const delay = Math.pow(2, attempt) * 1000; await new Promise((resolve) => setTimeout(resolve, delay)); console.warn( `图像加载重试 ${attempt + 1}/${this.maxRetries}:`, error.message ); } } } loadImage() { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject( new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`) ); }, this.timeoutMs); fabric.Image.fromURL( this.imageUrl, (img) => { clearTimeout(timeout); if (!img || !img.getElement()) { reject(new Error("图像加载失败或无效")); return; } resolve(img); }, { crossOrigin: "anonymous", } ); }); } async applyImageToLayer(newImage) { await optimizeCanvasRendering(this.canvas, async () => { // 设置基本属性 newImage.set({ id: this.targetLayer?.fabricObject?.id || this.newObjectId, layerId: this.targetLayer.id, layerName: this.targetLayer.name, isBackground: this.targetLayer.isBackground, isFixed: this.targetLayer.isFixed, }); // 移除旧对象(如果存在) if (this.previousObjectId) { const { object: oldObject } = findObjectById( this.canvas, this.previousObjectId ); if (oldObject) { const removeSuccess = removeCanvasObjectByObject( this.canvas, oldObject ); if (!removeSuccess) { console.warn("移除旧对象失败,但继续执行"); } } } // 应用位置和变换 if (this.preserveTransform && this.previousTransform) { newImage.set(this.previousTransform); } else { newImage.set({ left: this.position.x || this.canvas.width / 2, top: this.position.y || this.canvas.height / 2, scaleX: this.scale.x || 1, scaleY: this.scale.y || 1, originX: "center", originY: "cehnter", }); } // 通用处理图片模式 imageModeHandler({ imageMode: this.imageMode, newImage, canvasWidth: this.canvasWidth, canvasHeight: this.canvasHeight, }); // 使用帮助函数在指定z-index位置插入新图像 if (this.previousZIndex !== undefined && this.previousZIndex >= 0) { const insertSuccess = insertObjectAtZIndex( this.canvas, newImage, this.previousZIndex, false ); if (insertSuccess) { console.log(`新图像插入到z-index位置: ${this.previousZIndex}`); } else { // 如果插入失败,回退到普通添加 this.canvas.add(newImage); console.log("z-index插入失败,新图像添加到顶层"); } } else { // 否则直接添加到顶层 this.canvas.add(newImage); console.log("新图像添加到顶层"); } newImage.setCoords(); // 更新图层引用 this.targetLayer.fabricObject = newImage; // 更新图层管理器 this.layerManager.updateLayerObject(this.targetLayer.id, newImage); }); } async restorePreviousImage() { if (!this.previousImage?.objectData) { throw new Error("没有可恢复的图像数据"); } return new Promise((resolve, reject) => { fabric.util.enlivenObjects( [this.previousImage.objectData], async (objects) => { try { const restoredImage = objects[0]; await optimizeCanvasRendering(this.canvas, async () => { // 移除当前对象 if (this.newObjectId) { const { object: currentObject } = findObjectById( this.canvas, this.newObjectId ); if (currentObject) { removeCanvasObjectByObject(this.canvas, currentObject); } } // 恢复之前的变换 if (this.previousTransform) { restoredImage.set(this.previousTransform); } // 设置图层属性 restoredImage.set({ id: this.previousObjectId, layerId: this.targetLayer.id, layerName: this.targetLayer.name, isBackground: this.targetLayer.isBackground, isFixed: this.targetLayer.isFixed, }); // 使用帮助函数在正确的z-index位置恢复对象 if ( this.previousZIndex !== undefined && this.previousZIndex >= 0 ) { const insertSuccess = insertObjectAtZIndex( this.canvas, restoredImage, this.previousZIndex, false ); if (insertSuccess) { console.log(`恢复图像到z-index位置: ${this.previousZIndex}`); } else { // 如果插入失败,回退到普通添加 this.canvas.add(restoredImage); console.log("z-index恢复失败,恢复图像添加到顶层"); } } else { // 如果没有保存的z-index,添加到顶层 this.canvas.add(restoredImage); console.log("恢复图像添加到顶层"); } restoredImage.setCoords(); // 更新引用 this.targetLayer.fabricObject = restoredImage; this.layerManager.updateLayerObject( this.targetLayer.id, restoredImage ); }); resolve(); } catch (error) { reject(error); } } ); }); } async removeCurrentImage() { await optimizeCanvasRendering(this.canvas, async () => { if (this.newObjectId) { const { object: currentObject } = findObjectById( this.canvas, this.newObjectId ); if (currentObject) { const removeSuccess = removeCanvasObjectByObject( this.canvas, currentObject ); if (removeSuccess) { this.targetLayer.fabricObject = null; this.layerManager.updateLayerObject(this.targetLayer.id, null); } } } }); } emitEvent(eventName, data) { if (this.canvas && this.canvas.fire) { this.canvas.fire(eventName, data); } } // 获取命令信息用于调试 getCommandInfo() { return { type: "ChangeFixedImageCommand", targetLayerType: this.targetLayerType, imageUrl: this.imageUrl, isExecuted: this.isExecuted, retryCount: this.retryCount, targetLayerId: this.targetLayer?.id, preserveTransform: this.preserveTransform, }; } } /** * 向图层添加图像命令 * 用于向指定图层添加新的图像对象 */ export class AddImageToLayerCommand extends Command { constructor(options = {}) { super(); this.canvas = options.canvas; this.layerManager = options.layerManager; this.imageUrl = options.imageUrl; this.layerId = options.layerId; this.position = options.position || { x: 100, y: 100 }; this.scale = options.scale || { x: 1, y: 1 }; this.zIndex = options.zIndex || null; // 可选的层级控制 // 用于回滚的状态 this.addedObject = null; this.targetLayer = null; this.isExecuted = false; this.imageId = generateId("image_"); // 错误处理 this.maxRetries = options.maxRetries || 3; this.retryCount = 0; this.timeoutMs = options.timeoutMs || 10000; } async execute() { try { this.validateInputs(); // 查找目标图层 this.targetLayer = this.findTargetLayer(); if (!this.targetLayer) { throw new Error(`找不到目标图层: ${this.layerId}`); } // 检查图层是否可编辑 // this.validateLayerEditability(); // 加载新图像 const newImage = await this.loadImageWithRetry(); // 添加图像到图层 await this.addImageToLayer(newImage, this.imageId); this.isExecuted = true; // 触发成功事件 this.emitEvent("image:added", { layerId: this.layerId, objectId: this.addedObject.id, imageUrl: this.imageUrl, command: this, }); return { success: true, layerId: this.layerId, objectId: this.addedObject.id, imageUrl: this.imageUrl, }; } catch (error) { console.error("AddImageToLayerCommand执行失败:", error); // 如果已经添加了对象,尝试移除 if (this.addedObject) { try { await this.undo(); } catch (rollbackError) { console.error("回滚失败:", rollbackError); } } throw error; } } async undo() { if (!this.isExecuted || !this.addedObject) { throw new Error("命令未执行或没有添加的对象"); } try { // 移除添加的对象 this.canvas.remove(this.addedObject); // 从图层管理器中移除 this.layerManager.removeObjectFromLayer( this.addedObject.id, this.layerId ); this.isExecuted = false; // 触发撤销事件 this.emitEvent("image:removed", { layerId: this.layerId, objectId: this.addedObject.id, command: this, }); // 重新渲染 this.canvas.renderAll(); return { success: true, action: "removed", layerId: this.layerId, objectId: this.addedObject.id, }; } catch (error) { console.error("AddImageToLayerCommand撤销失败:", error); throw error; } } validateInputs() { if (!this.canvas) throw new Error("Canvas实例是必需的"); if (!this.layerManager) throw new Error("LayerManager实例是必需的"); if (!this.imageUrl) throw new Error("图像URL是必需的"); if (!this.layerId) throw new Error("图层ID是必需的"); // 验证URL格式 try { new URL(this.imageUrl); } catch { throw new Error("无效的图像URL格式"); } } findTargetLayer() { const layers = this.layerManager.layers?.value || []; return layers.find((layer) => layer.id === this.layerId); } validateLayerEditability() { if (this.targetLayer.locked) { throw new Error("目标图层已锁定,无法添加对象"); } if (!this.targetLayer.visible) { console.warn("目标图层不可见,添加的对象可能不会显示"); } } async loadImageWithRetry() { for (let attempt = 0; attempt <= this.maxRetries; attempt++) { try { return await this.loadImage(); } catch (error) { this.retryCount = attempt; if (attempt === this.maxRetries) { throw new Error( `图像加载失败,已重试${this.maxRetries}次: ${error.message}` ); } // 指数退避重试 const delay = Math.pow(2, attempt) * 1000; await new Promise((resolve) => setTimeout(resolve, delay)); console.warn( `图像加载重试 ${attempt + 1}/${this.maxRetries}:`, error.message ); } } } loadImage() { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject( new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`) ); }, this.timeoutMs); fabric.Image.fromURL( this.imageUrl, (img) => { clearTimeout(timeout); if (!img || !img.getElement()) { reject(new Error("图像加载失败或无效")); return; } resolve(img); }, { crossOrigin: "anonymous", } ); }); } async addImageToLayer(newImage, objectId) { // 设置图像属性 newImage.set({ id: objectId, layerId: this.layerId, layerName: this.targetLayer.name, left: this.position.x, top: this.position.y, scaleX: this.scale.x, scaleY: this.scale.y, selectable: true, evented: true, }); // 添加到画布 this.canvas.add(newImage); // 设置层级 if (this.zIndex !== null) { this.setObjectZIndex(newImage, this.zIndex); } newImage.setCoords(); // 保存引用用于回滚 this.addedObject = newImage; // 添加到图层管理器 this.layerManager.addObjectToLayer(newImage, this.layerId); // 重新渲染画布 this.canvas.renderAll(); } setObjectZIndex(object, zIndex) { if (zIndex === "top") { object.bringToFront(); } else if (zIndex === "bottom") { object.sendToBack(); } else if (typeof zIndex === "number") { object.moveTo(zIndex); } } emitEvent(eventName, data) { if (this.canvas && this.canvas.fire) { this.canvas.fire(eventName, data); } } // 获取命令信息用于调试 getCommandInfo() { return { type: "AddImageToLayerCommand", layerId: this.layerId, imageUrl: this.imageUrl, position: this.position, scale: this.scale, isExecuted: this.isExecuted, retryCount: this.retryCount, addedObjectId: this.addedObject?.id, }; } } export class SelectAllLayersCommand extends Command { constructor(options) { super({ name: "设置全选图层", saveState: false, }); this.layers = options.layers; this.canvas = options.canvas; this.layerManager = options.layerManager || null; this.activeLayerId = options.activeLayerId; this.oldActiveLayerId = this.activeLayerId.value; this.editorMode = options.editorMode || OperationType.SELECT; } execute() { this.oldActiveObjects = this.canvas.getActiveObjects(); // 如果在选择模式下,取消所有选择 if (this.editorMode === OperationType.SELECT && this.canvas) { this.canvas.discardActiveObject(); // 设置为新的图层下的对象为激活,但需要确保对象存在于画布上 const canvasObjects = this.canvas.getObjects()?.filter((fItem) => { const layerId = fItem.layerId; if (!layerId) return false; // 忽略没有图层ID的对象 // 确保当前图层存在且可见 const currLayer = this.layers.value.find((l) => l.id === layerId); return ( !currLayer.isBackground && !currLayer.isFixed && !currLayer.isLocked && !currLayer.isVisible ); }) || []; // 多个对象时创建活动选择组 const activeSelection = new fabric.ActiveSelection(canvasObjects, { canvas: this.canvas, }); // 设置活动选择组 this.canvas.setActiveObject(activeSelection); } this.canvas.renderAll(); return true; } undo() { // 恢复原活动图层ID this.activeLayerId.value = this.oldActiveLayerId; // 如果在选择模式下,恢复取消的所有选择 if (this.canvas) { this.canvas?.discardActiveObject(); // 修复:确保对象存在于画布上才激活 if (this.oldActiveObjects && this.oldActiveObjects.length > 0) { const canvasObjects = this.canvas.getObjects(); const validObjects = this.oldActiveObjects.filter( (obj) => obj && canvasObjects.includes(obj) ); if (validObjects.length > 0) { if (validObjects.length > 1) { // 如果有多个对象,需要创建一个活动选择组 const activeSelection = new fabric.ActiveSelection(validObjects, { canvas: this.canvas, }); this.canvas.setActiveObject(activeSelection); } else { // 只有一个对象时直接设置 this.canvas.setActiveObject(validObjects[0]); } } } this.canvas.renderAll(); } } getInfo() { return { name: this.name, layerId: this.layerId, oldActiveLayerId: this.oldActiveLayerId, }; } } export class ClearSelectionCommand extends Command { constructor(options) { super({ name: "设置取消所有图层", saveState: false, }); this.layers = options.layers; this.canvas = options.canvas; this.layerManager = options.layerManager || null; this.activeLayerId = options.activeLayerId; this.oldActiveLayerId = this.activeLayerId.value; this.editorMode = options.editorMode || OperationType.SELECT; } execute() { this.oldActiveObjects = this.canvas.getActiveObjects(); // 如果在选择模式下,取消所有选择 if (this.editorMode === OperationType.SELECT && this.canvas) { this.canvas.discardActiveObject(); } this.canvas.renderAll(); return true; } undo() { // 恢复原活动图层ID this.activeLayerId.value = this.oldActiveLayerId; // 如果在选择模式下,恢复取消的所有选择 if (this.canvas) { this.canvas?.discardActiveObject(); // 修复:确保对象存在于画布上才激活 if (this.oldActiveObjects && this.oldActiveObjects.length > 0) { const canvasObjects = this.canvas.getObjects(); const validObjects = this.oldActiveObjects.filter( (obj) => obj && canvasObjects.includes(obj) ); if (validObjects.length > 0) { if (validObjects.length > 1) { // 如果有多个对象,需要创建一个活动选择组 const activeSelection = new fabric.ActiveSelection(validObjects, { canvas: this.canvas, }); this.canvas.setActiveObject(activeSelection); } else { // 只有一个对象时直接设置 this.canvas.setActiveObject(validObjects[0]); } } } this.canvas.renderAll(); } } getInfo() { return { name: this.name, layerId: this.layerId, oldActiveLayerId: this.oldActiveLayerId, }; } } /** * 移动图层到顶部命令 */ export class MoveLayerToTopCommand extends Command { constructor(options) { super({ name: "置顶图层", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.layerSort = options.layerSort; this.parentLayer = null; // 父图层 const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); // 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶 if (parent?.id) { // 查找子图层索引 this.layerIndex = parent?.children?.findIndex( (layer) => layer.id === this.layerId ); this.parentLayer = parent; } else { // 查找图层索引 this.layerIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); } this.layer = layer; this.originalIndex = this.layerIndex; // 目标位置 this.targetIndex = 0; } async execute() { if (this.layerIndex === -1 || !this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 检查是否是背景层或固定层(不允许移动) if (this.layer.isBackground || this.layer.isFixed) { console.warn("背景层和固定层不能移动"); return false; } // 如果已经在顶部,无需移动 if (this.layerIndex === this.targetIndex) { console.log("图层已在顶部位置"); return true; } // 执行移动 if (this.parentLayer) { this.parentLayer?.children?.splice(this.layerIndex, 1); this.parentLayer?.children?.splice(this.targetIndex, 0, this.layer); } else { this.layers.value.splice(this.layerIndex, 1); this.layers.value.splice(this.targetIndex, 0, this.layer); } // 使用LayerSort工具重新排列画布对象(如果可用) await this.layerSort?.rearrangeObjects(); console.log(`✅ 图层 ${this.layer.name} 已置顶`); return true; } async undo() { const tempOldIndex = this.layerIndex; this.targetIndex = tempOldIndex; this.layerIndex = this.targetIndex; await this.execute(); // 执行完成恢复索引 this.layerIndex = tempOldIndex; this.targetIndex = this.layerIndex; console.log(`↩️ 图层 ${this.layer.name} 已恢复到原位置`); } getInfo() { return { name: this.name, layerId: this.layerId, layerName: this.layer?.name, originalIndex: this.originalIndex, targetIndex: this.targetIndex, }; } } /** * 移动图层到底部命令 */ export class MoveLayerToBottomCommand extends Command { constructor(options) { super({ name: "置底图层", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.layerSort = options.layerSort; this.parentLayer = null; // 父图层 const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); // 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶 if (parent?.id) { // 查找子图层索引 this.layerIndex = parent?.children?.findIndex( (layer) => layer.id === this.layerId ); this.parentLayer = parent; } else { // 查找图层索引 this.layerIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); } this.layer = layer; this.originalIndex = this.layerIndex; // 计算目标位置(最后一个非背景、非固定图层的位置) this.targetIndex = this._calculateBottomPosition(); } async execute() { if (this.layerIndex === -1 || !this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 检查是否是背景层或固定层(不允许移动) if (this.layer.isBackground || this.layer.isFixed) { console.warn("背景层和固定层不能移动"); return false; } // 如果已经在底部,无需移动 if (this.layerIndex === this.targetIndex) { console.log("图层已在底部位置"); return true; } // 执行移动 this.layers.value.splice(this.layerIndex, 1); this.layers.value.splice(this.targetIndex, 0, this.layer); // 更新画布渲染顺序 this.layerSort?.rearrangeObjects?.(); console.log(`✅ 图层 ${this.layer.name} 已置底`); return true; } async undo() { if (this.originalIndex !== -1 && this.layer) { // 获取当前位置 const currentIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); if (currentIndex !== -1) { // 移除当前位置 this.layers.value.splice(currentIndex, 1); // 插入到原位置 this.layers.value.splice(this.originalIndex, 0, this.layer); // 更新画布渲染顺序 this._rearrangeCanvasObjects(); console.log(`↩️ 图层 ${this.layer.name} 已恢复到原位置`); } } } /** * 计算置底的目标位置 * @returns {number} 目标索引 * @private */ _calculateBottomPosition() { // 找到最后一个非背景、非固定图层的位置 for (let i = this.layers.value.length - 1; i >= 0; i--) { const layer = this.layers.value[i]; if (!layer.isBackground && !layer.isFixed) { return i; } } return this.layers.value.length - 1; } /** * 重新排列画布对象 * @private */ _rearrangeCanvasObjects() { if (!this.canvas) return; // 获取画布上的所有对象 const canvasObjects = [...this.canvas.getObjects()]; // 清空画布 this.canvas.clear(); // 按图层顺序(从底到顶)重新添加对象 for (let i = this.layers.value.length - 1; i >= 0; i--) { const layer = this.layers.value[i]; if (layer.isBackground && layer.fabricObject) { // 背景图层 const originalObj = canvasObjects.find( (o) => o.id === layer.fabricObject.id ); if (originalObj) { this.canvas.add(originalObj); } } else if ( Array.isArray(layer.fabricObjects) && layer.fabricObjects.length > 0 ) { // 普通图层和固定图层 layer.fabricObjects.forEach((obj) => { const originalObj = canvasObjects.find((o) => o.id === obj.id); if (originalObj) { this.canvas.add(originalObj); } }); } } this.canvas.renderAll(); } getInfo() { return { name: this.name, layerId: this.layerId, layerName: this.layer?.name, originalIndex: this.originalIndex, targetIndex: this.targetIndex, }; } }