import { Command } from "./Command"; import { createLayer, findLayerRecursively, LayerType, OperationType, } from "../utils/layerHelper"; import { createStaticCanvas } from "../utils/canvasFactory"; import { AddObjectToLayerCommand } from "./ObjectLayerCommands"; import { ToolCommand } from "./ToolCommands"; import { findObjectById, findObjectByLayerId, generateId, getObjectZIndex, insertObjectAtZIndex, objectIsInCanvas, optimizeCanvasRendering, removeCanvasObjectByObject, } from "../utils/helper"; import { fabric } from "fabric-with-all"; import { restoreFabricObject } from "../utils/objectHelper"; import EventManager from "../utils/event.js"; /** * 添加图层命令 */ export class AddLayerCommand extends Command { constructor(options) { super({ name: "添加图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.newLayer = options.newLayer; this.activeLayerId = options.activeLayerId; this.insertIndex = options.insertIndex; this.oldActiveLayerId = null; this.beforeLayers = JSON.stringify(this.layers.value); // 备份原图层列表 this.options = options.options || {}; } execute() { // 保存当前活动图层ID this.oldActiveLayerId = this.activeLayerId.value; // 执行添加顶级图层操作 if (this.options?.insertTop) { this.layers.value.splice(0, 0, this.newLayer); this.activeLayerId.value = this.newLayer.id; return this.newLayer.id; } // 智能插入图层到合适位置 this._insertLayerAtCorrectPosition(this.newLayer); // if (this.insertIndex !== undefined && this.insertIndex !== null) { // this.layers.value.splice(this.insertIndex, 0, this.newLayer); // } else { // this.layers.value.push(this.newLayer); // } // // 更新活动图层 if (!this.newLayer.isBackground) { this.activeLayerId.value = this.newLayer.id; } return this.newLayer.id; } undo() { // 从图层列表删除该图层 this.layers.value = JSON.parse(this.beforeLayers); // 恢复原活动图层 this.activeLayerId.value = this.oldActiveLayerId; } /** * 智能插入图层到正确位置 * 根据当前激活图层位置确定新图层插入位置 * @param {Object} newLayer 要插入的新图层 * @private */ _insertLayerAtCorrectPosition(newLayer) { const layers = this.layers.value; const currentActiveLayerId = this.activeLayerId?.value; // 如果没有当前激活图层,插入到顶部(索引0) if (!currentActiveLayerId) { layers.splice(0, 0, newLayer); return; } // 查找当前激活图层的位置 const { layer: activeLayer, parent: parentLayer, index: activeIndex, } = this._findLayerPosition(currentActiveLayerId); if (!activeLayer) { // 没找到激活图层,插入到顶部 layers.splice(0, 0, newLayer); return; } // 确定插入位置 let insertIndex = 0; if (parentLayer) { // 当前激活图层是子图层 // 在同一父图层内,插入到激活子图层之上 insertIndex = Math.max(0, activeIndex); parentLayer.children = parentLayer.children || []; parentLayer.children.splice(insertIndex, 0, newLayer); console.log( `新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})` ); } else { // 当前激活图层是一级图层 // 在一级图层中,插入到激活图层之上 const activeLayerIndex = layers.findIndex( (layer) => layer.id === currentActiveLayerId ); insertIndex = Math.max(0, activeLayerIndex); layers.splice(insertIndex, 0, newLayer); console.log(`新图层已插入到一级图层位置: ${insertIndex}`); } } /** * 查找图层位置信息 * @param {String} layerId 图层ID * @returns {Object} 包含图层、父图层和索引的对象 * @private */ _findLayerPosition(layerId) { const layers = this.layers.value; // 先在一级图层中查找 for (let i = 0; i < layers.length; i++) { const layer = layers[i]; if (layer.isPrintTrimsGroup) continue; if (layer.id === layerId) { return { layer: layer, parent: null, index: i, }; } // 在子图层中查找 if (layer.children && Array.isArray(layer.children)) { for (let j = 0; j < layer.children.length; j++) { const childLayer = layer.children[j]; if (childLayer.id === layerId) { return { layer: childLayer, parent: layer, index: j, }; } } } } return { layer: null, parent: null, index: -1, }; } getInfo() { return { name: this.name, layerName: this.newLayer.name, layerId: this.newLayer.id, }; } } /** * 粘贴并创建图层命令 - 更新为支持异步操作 */ export class PasteLayerCommand extends Command { constructor(options) { super({ name: "粘贴图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.activeLayerId = options.activeLayerId; this.clipboardData = options.clipboardData; this.layerManager = options.layerManager; this.newLayer = null; this.newLayerId = generateId("layer_"); this.insertIndex = null; this.oldActiveLayerId = null; this.createdObjects = []; this.isGroupLayer = false; this.childLayerIdMap = new Map(); } async execute() { if (!this.clipboardData) { console.error("剪贴板中没有图层数据"); return null; } const data = JSON.parse(JSON.stringify(this.clipboardData)); // 判断是否为组图层 this.isGroupLayer = data.type === "group" || !!data?.children?.length; // 保存当前活动图层ID this.oldActiveLayerId = this.activeLayerId.value; // 计算插入位置 this.insertIndex = this.layerManager._getInsertIndexAboveActiveLayer(); if (this.isGroupLayer) { // 粘贴为新的组图层,递归生成子图层ID const { groupLayer, allObjects } = await this._createGroupLayerFromClipboard(data); if (groupLayer?.clippingMask) { // 给遮罩蒙层也添加上偏移 groupLayer.clippingMask.left += 30; groupLayer.clippingMask.top += 30; if (groupLayer.selectObject) { // 如果有选区 则选区位置也要更新 groupLayer.selectObject.left = groupLayer.clippingMask.left; groupLayer.selectObject.top = groupLayer.clippingMask.top; } } this.newLayer = groupLayer; this.newLayer.id = this.newLayerId; // 插入组图层 if (this.insertIndex !== undefined && this.insertIndex !== null) { this.layers.value.splice(this.insertIndex, 0, this.newLayer); } else { this.layers.value.push(this.newLayer); } // 重新创建遮罩对象 const clippingMaskFabricObject = (await restoreFabricObject(groupLayer?.clippingMask, this.canvas)) || null; // clippingMaskFabricObject.clipPath = null; clippingMaskFabricObject.set({ absolutePositioned: true, }); // clippingMaskFabricObject.dirty = true; clippingMaskFabricObject.setCoords(); // 添加所有对象到画布 allObjects.forEach((obj) => { obj.clipPath = clippingMaskFabricObject; obj.dirty = true; obj.setCoords(); this.canvas.add(obj); }); this.createdObjects = allObjects; // 设置活动图层为新组图层 this.activeLayerId.value = this.newLayer.id; } else { // 普通图层粘贴逻辑 this.newLayer = { ...data, id: this.newLayerId, name: `${data.name} 副本`, fabricObjects: [], isCut: undefined, serializedObjects: undefined, }; if (this.insertIndex !== undefined && this.insertIndex !== null) { this.layers.value.splice(this.insertIndex, 0, this.newLayer); } else { this.layers.value.push(this.newLayer); } if (!this.newLayer.isBackground) { this.activeLayerId.value = this.newLayer.id; } if ( data.serializedObjects && Array.isArray(data.serializedObjects) && data.serializedObjects.length > 0 ) { await this._restoreObjectsAsync(data); } else { this._onObjectsRestored(data); } } // 取消画布激活对象 this.canvas.discardActiveObject(); // 取消当前活动对象 // 重新排序 await this.layerManager?.sortLayersWithTool?.(); // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity?.(); return this.newLayerId; } /** * 递归创建组图层及其所有子图层和对象 */ async _createGroupLayerFromClipboard(data) { const groupId = generateId("group_layer_"); const childLayerIdMap = new Map(); const allObjects = []; // 递归处理子图层 const processChildren = async (children) => { const result = []; for (const child of children) { const newChildId = generateId("layer_"); childLayerIdMap.set(child.id, newChildId); // 递归处理子组 let childLayer; if (child.type === "group" && Array.isArray(child.children)) { const { groupLayer, allObjects: childObjs } = await this._createGroupLayerFromClipboard(child); childLayer = groupLayer; allObjects.push(...childObjs); } else { // 普通子图层 childLayer = { ...child, id: newChildId, name: `${child.name} 副本`, fabricObjects: [], isCut: undefined, serializedObjects: undefined, }; // 恢复对象 if ( child.serializedObjects && Array.isArray(child.serializedObjects) && child.serializedObjects.length > 0 ) { const objs = await this._enlivenObjects( child.serializedObjects, newChildId, `${child.name} 副本` ); childLayer.fabricObjects = objs.map((obj) => obj.toObject(["id", "layerId", "layerName"]) ); allObjects.push(...objs); } } result.push(childLayer); } return result; }; // 处理当前组的子图层 const children = await processChildren(data.children); // 创建组图层对象 const groupLayer = { ...data, id: groupId, name: `${data.name} 副本`, type: "group", children, fabricObjects: [], isCut: undefined, serializedObjects: undefined, }; this.childLayerIdMap = childLayerIdMap; // 取消画布激活对象 this.canvas.discardActiveObject(); // 取消当前活动对象 return { groupLayer, allObjects }; } /** * 恢复对象(用于普通图层和组图层的子图层) */ async _enlivenObjects(serializedObjects, layerId, layerName) { return new Promise((resolve, reject) => { fabric.util.enlivenObjects(serializedObjects, (objects) => { try { objects.forEach((obj) => { obj.id = generateId("obj_"); obj.layerId = layerId; obj.layerName = layerName; // 添加偏移 const offset = 30; if (obj.left !== undefined) obj.left += offset; if (obj.top !== undefined) obj.top += offset; }); resolve(objects); } catch (error) { reject(error); } }); }); } async _restoreObjectsAsync(data) { return new Promise((resolve, reject) => { fabric.util.enlivenObjects(data.serializedObjects, (objects) => { try { objects.forEach((obj) => { const newObjId = generateId("obj_"); obj.id = newObjId; obj.layerId = this.newLayerId; obj.layerName = this.newLayer.name; if (!data.isCut) { const offset = 30; if (obj.left !== undefined) obj.left += offset; if (obj.top !== undefined) obj.top += offset; } this.canvas.add(obj); this.newLayer.fabricObjects.push( obj.toObject(["id", "layerId", "layerName"]) ); this.createdObjects.push(obj); }); this._onObjectsRestored(data); resolve(); } catch (error) { reject(error); } }); }); } _onObjectsRestored(data) { this.layerManager?.updateLayersObjectsInteractivity?.(); this.layerManager?._rearrangeObjects?.(); if (data.isCut && this.layerManager) { this.layerManager.clipboardData = null; } if (this.canvas) { this.canvas.renderAll(); } } async undo() { if (!this.newLayer || !this.newLayerId) return; const { layer, parent } = findLayerRecursively( this.layers.value, this.newLayerId ); if (!layer) { console.error(`图层 ${this.newLayerId} 不存在, 无法撤销`); return false; } if (parent) { // 如果是子图层,直接从父图层中删除 const index = parent.children.findIndex( (child) => child.id === this.newLayerId ); if (index !== -1) { parent.children.splice(index, 1); } } else { // 如果是顶级图层,直接从图层列表中删除 const index = this.layers.value.findIndex( (l) => l.id === this.newLayerId ); if (index !== -1) { this.layers.value.splice(index, 1); } } this.createdObjects?.forEach((obj) => { removeCanvasObjectByObject(this.canvas, obj); }); this.activeLayerId.value = this.oldActiveLayerId; // 取消激活对象 this.canvas.discardActiveObject(); // 取消当前活动对象 // 重新排序 await this.layerManager?.sortLayersWithTool?.(); // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity?.(); return true; } getInfo() { return { name: this.name, layerName: this.newLayer?.name || "未知图层", layerId: this.newLayerId, objectCount: this.createdObjects.length, isGroupLayer: this.isGroupLayer, }; } } /** * 移除图层命令 */ export class RemoveLayerCommand extends Command { constructor(options) { super({ name: "移除图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.activeLayerId = options.activeLayerId; this.layerManager = options.layerManager || null; this.IsOnlyLayer = this.layers.value.filter((v => !v.isFixed && !v.isFixedOther && !v.isBackground)).length <= 1 // 查找要删除的图层 this.layerIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); this.removedLayer = this.layers.value[this.layerIndex]; this.isActiveLayer = this.layerId === this.activeLayerId.value; // 从Canvas中找到真实对象并备份,包括当前图层及其所有子图层的对象 this.originalObjects = []; if (this.removedLayer) { this.originalObjects = this._collectAllLayerObjects(this.removedLayer); } // 备份原活动图层ID this.originalActiveLayerId = this.activeLayerId.value; } /** * 收集图层及其所有子图层的画布对象 * @param {Object} layer 要收集对象的图层 * @returns {Array} 所有相关的画布对象 * @private */ _collectAllLayerObjects(layer) { const allObjects = []; // 收集当前图层的对象 const layerObjects = this.canvas.getObjects().filter((obj) => { return obj.layerId === layer.id; }); allObjects.push(...layerObjects); // 如果图层有特殊的fabricObject属性(如背景图层) if (layer.fabricObject) { const { object } = findObjectById(this.canvas, layer.fabricObject.id); if (object && !allObjects.includes(object)) { allObjects.push(object); } } layer.fabricObjects?.forEach((fabric) => { const { object } = findObjectById(this.canvas, fabric.id); if (object && !allObjects.includes(object)) { allObjects.push(object); } }); // 递归收集子图层的对象 if (layer.children && Array.isArray(layer.children)) { layer.children.forEach((childLayer) => { const childObjects = this._collectAllLayerObjects(childLayer); allObjects.push(...childObjects); }); } return allObjects; } async execute() { if (this.layerIndex === -1 || !this.removedLayer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 从画布中移除图层及其所有子图层中的真实对象 this.originalObjects.forEach((obj) => { if (this.canvas.getObjects().includes(obj)) { this.canvas.remove(obj); } }); this.layerIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); // 从图层列表中删除 this.layers.value.splice(this.layerIndex, 1); if(this.IsOnlyLayer){ this.addCmd = await this.layerManager?.createLayer?.(null, LayerType.EMPTY, {}, false); } // 如果删除的是当前活动图层,需要更新活动图层 if (this.isActiveLayer) { // 查找最近的非背景层作为新的活动图层 const newActiveLayer = this.layers.value.find( (layer) => !layer.isBackground ); if (newActiveLayer) { this.activeLayerId.value = newActiveLayer.id; if(this.canvas.toolId === OperationType.SELECT){ this.layerManager.selectLayerObjects(newActiveLayer.id); } } else { this.activeLayerId.value = null; } } // 重新渲染画布 // if (this.canvas) { // this.canvas.renderAll(); // } await this.layerManager?.updateLayersObjectsInteractivity?.(); this.canvas.renderAll(); console.log( `✅ 已移除图层: ${this.removedLayer.name} (ID: ${this.layerId}),包含 ${this.originalObjects.length} 个对象` ); return true; } async undo() { // 恢复图层到原位置 if (this.layerIndex !== -1 && this.removedLayer) { if(this.IsOnlyLayer && this.addCmd){ this.addCmd?.undo?.(); } this.layers.value.splice(this.layerIndex, 0, this.removedLayer); // 使用优化渲染批处理恢复真实对象到画布 await optimizeCanvasRendering(this.canvas, () => { // 倒序添加对象,确保下标越小的子图层在画布中越靠前 this.originalObjects .slice() .reverse() .forEach((obj) => { // 确保对象不在画布中才添加,避免重复添加 if (!this.canvas.getObjects().includes(obj)) { this.canvas.add(obj); // 确保对象的坐标正确 obj.setCoords(); } }); }); await this.layerManager?.updateLayersObjectsInteractivity?.(); this.canvas.renderAll(); // 如果删除的是当前活动图层,恢复活动图层 if (this.isActiveLayer) { this.activeLayerId.value = this.layerId; } console.log( `↩️ 已恢复图层: ${this.removedLayer.name} (ID: ${this.layerId}),包含 ${this.originalObjects.length} 个对象` ); } } getInfo() { return { name: this.name, layerName: this.removedLayer?.name || "未知图层", layerId: this.layerId, objectCount: this.originalObjects.length, }; } } /** * 移动图层命令 */ export class MoveLayerCommand extends Command { constructor(options) { super({ name: `移动图层 ${options.direction === "up" ? "上移" : "下移"}`, saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.direction = options.direction; // "up" or "down" 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 = options.direction === "up" ? this.layerIndex - 1 : this.layerIndex + 1; } 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) { const tempLayer = this.parentLayer.children[this.targetIndex]; this.parentLayer.children[this.layerIndex] = tempLayer; this.parentLayer.children[this.targetIndex] = this.layer; } else { const tempLayer = this.layers.value[this.targetIndex]; this.layers.value[this.layerIndex] = tempLayer; this.layers.value[this.targetIndex] = this.layer; } // 使用LayerSort工具重新排列画布对象(如果可用) await this.layerSort?.rearrangeObjects(); console.log(`图层${this.layer.name}已经移动`); } async undo() { const tempOldIndex = this.layerIndex; this.layerIndex = this.targetIndex; this.targetIndex = tempOldIndex; await this.execute(); // 执行完成恢复索引 this.targetIndex = this.layerIndex; this.layerIndex = tempOldIndex; console.log(`↩️ 图层 ${this.layer.name} 已恢复到原位置`); } getInfo() { return { name: this.name, layerId: this.layerId, direction: this.direction, }; } } /** * 切换图层可见性命令 */ export class ToggleLayerVisibilityCommand extends Command { constructor(options) { super({ name: "切换图层可见性", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.layerManager = options.layerManager; // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; // this.oldVisibility = this.layer ? this.layer.visible : null; } async execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 切换可见性 this.layer.visible = !this.layer.visible; const ids = [this.layerId]; const childLayers = this.layer?.children || []; childLayers.forEach((childLayer) => { childLayer.visible = this.layer.visible; ids.push(childLayer.id); }); // 更新画布上图层对象的可见性 if (this.canvas) { this.canvas.getObjects().forEach((obj) => { if (ids.includes(obj.layerId)) { obj.getObjects?.()?.forEach((item) => { item.visible = this.layer.visible; }); obj.visible = this.layer.visible; } }); } // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); return this.layer.visible; } async undo() { return await this.execute(); // 直接调用execute方法来恢复可见性 } getInfo() { return { name: this.name, layerName: this.layer?.name || "未知图层", layerId: this.layerId, newVisibility: this.layer?.visible, }; } } /** * 切换子图层可见性命令 */ export class ToggleChildLayerVisibilityCommand extends Command { constructor(options) { super({ name: "切换子图层可见性", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.parentId = options.parentId; this.layerManager = options.layerManager; // 查找父图层和子图层 const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); this.parentLayer = parent; this.childLayer = layer; // this.oldVisibility = this.childLayer ? this.childLayer.visible : null; } async execute(visible) { if (!this.childLayer) { throw new Error("找不到要切换可见性的子图层"); } // 切换可见性 this.childLayer.visible = typeof visible === "boolean" ? visible : !this.childLayer.visible; // 更新画布上图层对象的可见性 if (this.canvas) { this.canvas.getObjects().forEach((obj) => { if (obj.layerId === this.layerId) { obj.getObjects?.()?.forEach((item) => { item.visible = this.childLayer.visible; }); obj.visible = this.childLayer.visible; } }); } // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); return this.childLayer.visible; } async undo() { return await this.execute(); // 直接调用execute方法来恢复可见性 } getInfo() { return { name: this.name, layerName: this.childLayer?.name || "未知子图层", layerId: this.layerId, parentId: this.parentId, newVisibility: this.childLayer?.visible, }; } } /** * 重命名图层命令 */ export class RenameLayerCommand extends Command { constructor(options) { super({ name: "重命名图层", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.newName = options.newName; // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.oldName = this.layer ? this.layer.name : null; } execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 更新图层名称 this.layer.name = this.newName; // 更新图层对象上的图层名称 if (this.canvas) { const layerObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.layerName = this.newName; }); } return true; } undo() { if (this.layer && this.oldName) { // 恢复图层名称 this.layer.name = this.oldName; // 恢复图层对象上的图层名称 if (this.canvas) { const layerObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.layerName = this.oldName; }); } } } getInfo() { return { name: this.name, layerId: this.layerId, oldName: this.oldName, newName: this.newName, }; } } /** * 图层锁定/解锁命令 */ export class LayerLockCommand extends Command { constructor(options) { super({ name: "图层锁定/解锁", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.layerManager = options.layerManager; // 查找图层(包括子图层) // 查找图层 const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); this.layer = layer; this.parentLayer = parent || null; // 父图层 this.oldLocked = this.layer ? this.layer.locked : null; } /** * 更新图层及其子图层的锁定状态 * @param {Object} layer 要更新的图层 * @param {boolean} locked 锁定状态 * @private */ _updateLayerLockState(layer, locked) { if (!layer) return; // 更新当前图层的锁定状态 layer.locked = locked; // 如果是组图层,递归更新所有子图层 if ( layer.children && Array.isArray(layer.children) && layer.children.length > 0 ) { layer.children.forEach((child) => { this._updateLayerLockState(child, locked); }); } } async execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 切换锁定状态 const newLocked = !this.oldLocked; // 更新图层及其子图层的锁定状态 this._updateLayerLockState(this.layer, newLocked); // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); console.log( `${newLocked ? "锁定" : "解锁"}图层: ${this.layer.name} (ID: ${ this.layerId })` ); return true; } async undo() { if (this.layer) { // 恢复锁定状态 this._updateLayerLockState(this.layer, this.oldLocked); // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); console.log( `恢复图层锁定状态: ${this.layer.name} (锁定: ${this.oldLocked})` ); } } getInfo() { return { name: this.name, layerName: this.layer?.name || "未知图层", layerId: this.layerId, isChildLayer: !!this.parentLayer, parentLayerName: this.parentLayer?.name, newLocked: this.layer?.locked, oldLocked: this.oldLocked, }; } } /** * 设置图层不透明度命令 */ export class SetLayerOpacityCommand extends Command { constructor(options) { super({ name: "设置图层不透明度", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.opacity = options.opacity; // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.oldOpacity = this.layer ? this.layer.opacity : null; } execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 设置图层不透明度 this.layer.opacity = this.opacity; // 更新画布上对象的不透明度 if (this.canvas) { const layerObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.opacity = this.opacity; }); this.canvas.renderAll(); } EventManager.emit("object:opacity:execute", this.layerId, this.opacity); return true; } undo() { if (this.layer && this.oldOpacity !== null) { // 恢复图层不透明度 this.layer.opacity = this.oldOpacity; // 更新画布上对象的不透明度 if (this.canvas) { const layerObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.opacity = this.oldOpacity; }); this.canvas.renderAll(); } } EventManager.emit("object:opacity:undo", this.layerId, this.opacity); } getInfo() { return { name: this.name, layerName: this.layer?.name || "未知图层", layerId: this.layerId, oldOpacity: this.oldOpacity, newOpacity: this.opacity, }; } } /** * 设置图层混合模式命令 */ export class SetLayerBlendModeCommand extends Command { constructor(options) { super({ name: "设置图层混合模式", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.blendMode = options.blendMode; // 查找图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.oldBlendMode = this.layer ? this.layer.blendMode : null; } execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 设置图层混合模式 this.layer.blendMode = this.blendMode; // 更新画布上对象的混合模式 if (this.canvas) { const layerObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.globalCompositeOperation = this.blendMode; }); this.canvas.renderAll(); } return true; } undo() { if (this.layer && this.oldBlendMode) { // 恢复图层混合模式 this.layer.blendMode = this.oldBlendMode; // 更新画布上对象的混合模式 if (this.canvas) { const layerObjects = this.canvas .getObjects() .filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.globalCompositeOperation = this.oldBlendMode; }); this.canvas.renderAll(); } } } getInfo() { return { name: this.name, layerName: this.layer?.name || "未知图层", layerId: this.layerId, oldBlendMode: this.oldBlendMode, newBlendMode: this.blendMode, }; } } /** * 合并图层命令 */ export class MergeLayersCommand extends Command { constructor(options) { super({ name: "合并图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerIds = options.layerIds; this.newName = options.newName; this.activeLayerId = options.activeLayerId; // <--- 新增 // 备份原图层 this.originalLayers = [...this.layers.value]; // 新图层ID this.newLayerId = `merged_layer_${Date.now()}_${Math.floor( Math.random() * 1000 )}`; } execute() { if ( !this.layerIds || !Array.isArray(this.layerIds) || this.layerIds.length < 2 ) { console.error("合并图层至少需要两个图层"); return null; } // 查找所有要合并的图层 const layersToMerge = this.layerIds .map((id) => this.layers.value.find((layer) => layer.id === id)) .filter(Boolean); if (layersToMerge.length < 2) { console.error("找不到足够的图层进行合并"); return null; } // 检查是否包含背景图层 if (layersToMerge.some((layer) => layer.isBackground)) { console.error("不能合并背景图层"); return null; } // 查找所有要组合的图层 const layersToGroup = this.layerIds .map((id) => { const tempLayer = this.layers.value.find((layer) => layer.id === id); // 需要给子图层加上parentId return tempLayer ? { ...tempLayer, parentId: this.groupId } : false; }) .filter(Boolean); const topLayerIndex = Math.min( ...layersToGroup.map((layer) => this.layers.value.findIndex((fLayer) => fLayer.id === layer.id) ) ); // 获取要保留的所有对象 const allObjects = []; layersToMerge.forEach((layer) => { if (Array.isArray(layer.fabricObjects)) { allObjects.push(...layer.fabricObjects); } }); // 创建新的合并图层 const mergedLayer = createLayer({ id: this.newLayerId, name: this.newName || `合并图层`, type: LayerType.BITMAP, visible: true, locked: false, opacity: 1.0, fabricObjects: allObjects, }); // 更新对象与新图层的关联 allObjects.forEach((obj) => { obj.layerId = mergedLayer.id; obj.layerName = mergedLayer.name; }); // 移除原图层 this.layers.value = this.layers.value.filter( (layer) => !this.layerIds.includes(layer.id) ); // 插入新图层 this.layers.value.splice(topLayerIndex, 0, mergedLayer); // 更新当前活动图层 this.activeLayerId.value = this.newLayerId; // 重新渲染画布 if (this.canvas) { this.canvas.renderAll(); } return this.newLayerId; } undo() { // 恢复原始图层状态 this.layers.value = [...this.originalLayers]; // 恢复活动图层 if (this.activeLayerId) { // 恢复到合并前的活动图层(取第一个合并前图层) this.activeLayerId.value = this.layerIds[0]; } // 重新渲染画布 if (this.canvas) { this.canvas.renderAll(); } } getInfo() { return { name: this.name, layerIds: this.layerIds, newLayerId: this.newLayerId, newName: this.newName, }; } } /** * 图层组合命令 */ export class GroupLayersCommand extends Command { constructor(options) { super({ name: "组合图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerIds = options.layerIds; this.groupName = options.groupName; this.activeLayerId = options.activeLayerId; // <--- 新增 // 备份原图层 this.originalLayers = [...this.layers.value]; // 新组ID this.groupId = options.id || generateId("group_layer_") || `group_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.originalActiveLayerId = this.activeLayerId.value; // 备份原活动图层ID } async execute() { if ( !this.layerIds || !Array.isArray(this.layerIds) || this.layerIds.length < 2 ) { console.error("组合图层至少需要两个图层"); return null; } // 查找所有要组合的图层 const layersToGroup = this.layerIds .map((id) => { const tempLayer = this.layers.value.find((layer) => layer.id === id); // 需要给子图层加上parentId return tempLayer ? { ...tempLayer, parentId: this.groupId } : false; }) .filter(Boolean); if (layersToGroup.length < 2) { console.error("找不到足够的图层进行组合"); return null; } // 检查是否包含背景图层 if (layersToGroup.some((layer) => layer.isBackground)) { console.error("不能组合背景图层"); return null; } // 查找最顶层图层的索引,用于插入组图层 const topLayerIndex = Math.min( ...layersToGroup.map((layer) => this.layers.value.findIndex((fLayer) => fLayer.id === layer.id) ) ); // 创建新的组图层 const groupLayer = createLayer({ id: this.groupId, name: this.groupName || `图层组`, type: LayerType.GROUP, visible: true, locked: false, opacity: 1.0, fabricObjects: [], children: layersToGroup, }); // 移除原图层 this.layers.value = this.layers.value.filter( (layer) => !this.layerIds.includes(layer.id) ); // 插入新组图层 this.layers.value.splice(topLayerIndex, 0, groupLayer); // 更新当前活动图层 this.activeLayerId.value = this.layerIds[0]; this.canvas?.thumbnailManager?.generateLayerThumbnail?.(this.groupId); return this.groupId; } async undo() { // 恢复原始图层状态 this.layers.value = [...this.originalLayers]; // 恢复活动图层为原先第一个合并前层 if (this.activeLayerId) { this.activeLayerId.value = this.originalActiveLayerId; } } getInfo() { return { name: this.name, layerIds: this.layerIds, groupId: this.groupId, groupName: this.groupName, }; } } /** * 解组图层命令 */ export class UngroupLayersCommand extends Command { constructor(options) { super({ name: "解组图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.groupId = options.groupId; this.activeLayerId = options.activeLayerId; // <--- 新增 // 备份原图层 this.originalLayers = [...this.layers.value]; // 子图层ID列表 this.childLayerIds = []; } async execute() { // 查找组图层 const groupIndex = this.layers.value.findIndex( (layer) => layer.id === this.groupId ); if (groupIndex === -1) { console.error(`找不到组图层 ${this.groupId}`); return null; } const groupLayer = this.layers.value[groupIndex]; if (!groupLayer.children || groupLayer.children.length === 0) { console.error(`组图层 ${this.groupId} 没有子图层`); return null; } // 收集子图层ID this.childLayerIds = groupLayer.children.map((layer) => layer.id); // 将子图层添加到原位置 this.layers.value.splice( groupIndex, 1, ...(groupLayer?.children?.map((child) => { // 为子图层添加parentId delete child.parentId; // 删除parentId属性 return { ...child }; }) || {}) ); // 更新当前活动图层为第一个子图层 if (this.childLayerIds.length > 0 && this.activeLayerId) { this.activeLayerId.value = this.childLayerIds[0]; } return this.childLayerIds; } async undo() { // 恢复原始图层状态 this.layers.value = [...this.originalLayers]; // 恢复活动图层为原始组ID if (this.activeLayerId) { this.activeLayerId.value = this.groupId; } } getInfo() { return { name: this.name, groupId: this.groupId, childLayerIds: this.childLayerIds, }; } } /** * 合并图层内对象命令(重构版本) * 将新的图像与图层内现有对象合并为一个高保真图像对象 */ export class MergeLayerObjectsCommand extends Command { constructor(options) { super({ name: "合并图层内对象", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.fabricImage = options.fabricImage; this.activeLayer = options.activeLayer; // 备份原始对象,用于撤销 if (this.activeLayer && Array.isArray(this.activeLayer.fabricObjects)) { this.originalObjects = this.canvas ?.getObjects() ?.filter((fItem) => fItem.layerId === this.activeLayer.id) || []; } else { this.originalObjects = []; } // 新合并图像对象 this.mergedImage = null; this.newImageId = `merged_image_${Date.now()}_${Math.floor( Math.random() * 1000 )}`; } async execute() { if (!this.activeLayer || !this.canvas) { console.error("图层或Canvas未初始化"); return null; } // 获取所有需要合并的对象(按正确的层级顺序) const objectsToMerge = []; // 先添加图层中的现有对象(作为底层) if (this.originalObjects.length > 0) { objectsToMerge.push(...this.originalObjects); } // 再添加新的图像对象(作为顶层) if (this.fabricImage) { objectsToMerge.push(this.fabricImage); } if (objectsToMerge.length === 0) { console.log("没有对象需要合并"); return null; } // 计算所有对象的合并边界 const bounds = this._calculateMergedBounds(objectsToMerge); if (!bounds) { console.error("无法计算合并边界"); return null; } // 异步处理图像合并 try { const mergedImage = await this._createMergedImageAsync( objectsToMerge, bounds ); this._setupMergedImage(mergedImage, bounds); this._replaceObjects(mergedImage); console.log("图像合并完成"); return this.newImageId; } catch (error) { console.error("图像合并执行失败:", error); return null; } } /** * 异步创建合并图像 * @param {Array} objectsToMerge 要合并的对象 * @param {Object} bounds 边界信息 * @returns {Promise} 合并后的图像 * @private */ async _createMergedImageAsync(objectsToMerge, bounds) { return new Promise((resolve, reject) => { try { // 创建高保真临时画布 const tempCanvas = this._createHighQualityTempCanvas(bounds); const tempFabricCanvas = createStaticCanvas(tempCanvas, { width: bounds.width, height: bounds.height, }); // 设置高质量渲染选项 tempFabricCanvas.enableRetinaScaling = true; tempFabricCanvas.imageSmoothingEnabled = true; // 将所有对象添加到临时画布并调整位置 this._addObjectsToTempCanvas(tempFabricCanvas, objectsToMerge, bounds); // 渲染临时画布 tempFabricCanvas.renderAll(); // 生成高质量图像 const dataUrl = tempFabricCanvas.toDataURL({ format: "png", quality: 1.0, multiplier: 1, }); // 创建新的合并图像 fabric.Image.fromURL( dataUrl, (mergedImg) => { try { // 清理临时资源 this._cleanupTempCanvas(tempFabricCanvas); resolve(mergedImg); } catch (error) { console.error("设置合并图像时发生错误:", error); this._cleanupTempCanvas(tempFabricCanvas); reject(error); } }, { crossOrigin: "anonymous", } ); } catch (error) { console.error("合并过程中发生错误:", error); reject(error); } }); } /** * 计算所有对象的合并边界 * @param {Array} objects 要合并的对象数组 * @returns {Object} 边界信息 * @private */ _calculateMergedBounds(objects) { if (!objects || objects.length === 0) return null; let minLeft = Infinity; let minTop = Infinity; let maxRight = -Infinity; let maxBottom = -Infinity; objects.forEach((obj) => { if (!obj) return; const bounds = obj.getBoundingRect(true, true); minLeft = Math.min(minLeft, bounds.left); minTop = Math.min(minTop, bounds.top); maxRight = Math.max(maxRight, bounds.left + bounds.width); maxBottom = Math.max(maxBottom, bounds.top + bounds.height); }); const padding = 1; return { left: minLeft - padding, top: minTop - padding, width: maxRight - minLeft + padding * 2, height: maxBottom - minTop + padding * 2, }; } /** * 创建高质量临时画布 * @param {Object} bounds 边界信息 * @returns {HTMLCanvasElement} 临时画布 * @private */ _createHighQualityTempCanvas(bounds) { const tempCanvas = document.createElement("canvas"); tempCanvas.width = Math.ceil(bounds.width); tempCanvas.height = Math.ceil(bounds.height); tempCanvas.style.width = bounds.width + "px"; tempCanvas.style.height = bounds.height + "px"; const ctx = tempCanvas.getContext("2d"); ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = "high"; return tempCanvas; } /** * 将对象添加到临时画布并调整位置 * @param {fabric.Canvas} tempCanvas 临时画布 * @param {Array} objects 对象数组 * @param {Object} bounds 边界信息 * @private */ _addObjectsToTempCanvas(tempCanvas, objects, bounds) { objects.forEach((obj, index) => { if (!obj) return; try { const clonedObj = fabric.util.object.clone(obj); const objBounds = obj.getBoundingRect(true, true); const offsetX = objBounds.left - bounds.left; const offsetY = objBounds.top - bounds.top; clonedObj.set({ left: offsetX + (clonedObj.width * clonedObj.scaleX) / 2, top: offsetY + (clonedObj.height * clonedObj.scaleY) / 2, originX: "center", originY: "center", }); tempCanvas.add(clonedObj); console.log( `添加对象 ${index + 1}/${objects.length}: ${obj.type || "unknown"}` ); } catch (error) { console.error(`添加对象到临时画布时发生错误:`, error); } }); } /** * 设置合并后的图像属性 * @param {fabric.Image} mergedImg 合并后的图像 * @param {Object} bounds 边界信息 * @private */ _setupMergedImage(mergedImg, bounds) { mergedImg.set({ id: this.newImageId, layerId: this.activeLayer.id, layerName: this.activeLayer.name, left: bounds.left + bounds.width / 2, top: bounds.top + bounds.height / 2, originX: "center", originY: "center", selectable: true, evented: true, }); this.mergedImage = mergedImg; } /** * 替换原有对象为合并后的图像 * @param {fabric.Image} mergedImg 合并后的图像 * @private */ _replaceObjects(mergedImg) { if (!mergedImg || !this.canvas || !this.activeLayer) { console.error("_replaceObjects: 缺少必要的参数"); return; } const wasRenderOnAddRemove = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = false; try { // 清空图层的对象列表 this.activeLayer.fabricObjects = []; // 添加合并后的图像到画布和图层 this.canvas.add(mergedImg); this.activeLayer.fabricObjects.push(mergedImg); // 从画布中移除所有原始对象 this.originalObjects.forEach((obj) => { if (obj && this.canvas.getObjects().includes(obj)) { this.canvas.remove(obj); } }); // 如果有新的图像对象,也要移除 if ( this.fabricImage && this.canvas.getObjects().includes(this.fabricImage) ) { this.canvas.remove(this.fabricImage); } console.log( `成功替换图层 ${this.activeLayer.name} 中的 ${this.originalObjects.length} 个对象为合并图像` ); } catch (error) { console.error("替换对象时发生错误:", error); } finally { this.canvas.renderOnAddRemove = wasRenderOnAddRemove; this.canvas.renderAll(); // 同步渲染画布 // 更新缩略图 if (this.canvas.thumbnailManager) { setTimeout(() => { this.canvas.thumbnailManager.generateLayerThumbnail( this.activeLayer.id ); }, 100); } } } undo() { if (!this.activeLayer || !this.canvas) return; const wasRenderOnAddRemove = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = false; try { // 移除合并后的图像 if (this.mergedImage) { this.canvas.remove(this.mergedImage); const imageIndex = this.activeLayer.fabricObjects.findIndex( (obj) => obj.id === this.newImageId ); if (imageIndex !== -1) { this.activeLayer.fabricObjects.splice(imageIndex, 1); } } // 按原始顺序恢复对象到画布 this.originalObjects.forEach((obj) => { if (obj) { this.canvas.add(obj); } }); // 恢复图层对象列表 this.activeLayer.fabricObjects = [...this.originalObjects]; console.log(`成功撤销图层 ${this.activeLayer.name} 的对象合并操作`); } catch (error) { console.error("撤销合并操作时发生错误:", error); } finally { this.canvas.renderOnAddRemove = wasRenderOnAddRemove; this.canvas.renderAll(); // 更新缩略图 if (this.canvas.thumbnailManager) { setTimeout(() => { this.canvas.thumbnailManager.generateLayerThumbnail( this.activeLayer.id ); }, 100); } } } /** * 安全地清理临时画布资源 * @param {fabric.Canvas} tempCanvas 临时画布 * @private */ _cleanupTempCanvas(tempCanvas) { if (!tempCanvas) return; try { tempCanvas.clear(); const objects = tempCanvas.getObjects(); objects.forEach((obj) => { tempCanvas.remove(obj); }); const canvasEl = tempCanvas.getElement(); if (canvasEl && canvasEl.getContext) { const ctx = canvasEl.getContext("2d"); if (ctx) { ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); } } if (typeof tempCanvas.destroy === "function") { tempCanvas.destroy(); } if (canvasEl && canvasEl.parentNode) { canvasEl.parentNode.removeChild(canvasEl); } console.log("临时画布资源已安全清理"); } catch (error) { console.warn("清理临时画布时发生警告:", error); } } getInfo() { return { name: this.name, layerId: this.activeLayer?.id, layerName: this.activeLayer?.name || "未知图层", originalObjectCount: this.originalObjects.length, hasNewImage: !!this.fabricImage, mergedImageId: this.newImageId, }; } } /** * 合并图层内对象成组的命令 * 将新的图像与图层内现有对象合并为一个组对象 * 支持向现有组添加对象,以及移除空组 */ export class LayerObjectsToGroupCommand extends Command { constructor(options) { super({ name: "图层内对象合并为组", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.fabricImage = options.fabricImage; this.activeLayer = options.activeLayer; this.layerManager = options.layerManager; // 存储对象ID而不是对象引用,避免引用丢失问题 this.originalObjectIds = []; this.addedObjectIds = []; // 备份原始对象,用于撤销 if (this.activeLayer && Array.isArray(this.activeLayer.fabricObjects)) { this.originalObjectIds = this.activeLayer.fabricObjects .filter((obj) => obj && obj.id) .map((obj) => obj.id); } // 组对象相关 this.existingGroupId = null; this.groupObjectId = null; this.newGroupId = generateId("group") || `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.wasGroupCreated = false; // 保存原始位置信息 this.originalObjectPositions = new Map(); this.originalObjectIds.forEach((id) => { const result = findObjectById(this.canvas, id); if (result.object) { this.originalObjectPositions.set(id, { left: result.object.left, top: result.object.top, scaleX: result.object.scaleX, scaleY: result.object.scaleY, angle: result.object.angle, originX: result.object.originX, originY: result.object.originY, flipX: result.object.flipX, flipY: result.object.flipY, layerId: result.object.layerId, layerName: result.object.layerName, }); } }); // 新增:保存新添加对象的位置信息 this.newObjectPositions = new Map(); if (this.fabricImage && this.fabricImage.id) { this.newObjectPositions.set(this.fabricImage.id, { left: this.fabricImage.left, top: this.fabricImage.top, scaleX: this.fabricImage.scaleX, scaleY: this.fabricImage.scaleY, angle: this.fabricImage.angle, originX: this.fabricImage.originX, originY: this.fabricImage.originY, flipX: this.fabricImage.flipX, flipY: this.fabricImage.flipY, layerId: this.fabricImage.layerId, layerName: this.fabricImage.layerName, }); } // 记录执行状态,用于区分首次执行和重做 this.isFirstExecution = true; } async execute() { if (!this.activeLayer || !this.canvas) { console.error("图层或Canvas未初始化"); return null; } this.activeLayer = this.layerManager.getActiveLayer(); // 查找图层中是否已有组对象 const existingGroup = this._findExistingGroup(); this.existingGroupId = existingGroup?.id || null; // 准备要添加的新对象 const newObjectsToAdd = []; if (this.fabricImage) { // 如果是重做,恢复新对象的原始位置 if ( !this.isFirstExecution && this.newObjectPositions.has(this.fabricImage.id) ) { const savedPosition = this.newObjectPositions.get(this.fabricImage.id); this.fabricImage.set({ left: savedPosition.left, top: savedPosition.top, scaleX: savedPosition.scaleX, scaleY: savedPosition.scaleY, angle: savedPosition.angle, originX: savedPosition.originX, originY: savedPosition.originY, flipX: savedPosition.flipX, flipY: savedPosition.flipY, }); console.log( `🔄 重做时恢复新对象位置: (${savedPosition.left}, ${savedPosition.top})` ); } newObjectsToAdd.push(this.fabricImage); this.addedObjectIds.push(this.fabricImage.id); } if (newObjectsToAdd.length === 0) { console.log("没有新对象需要添加到组"); return this.existingGroupId; } try { await optimizeCanvasRendering(this.canvas, async () => { if (existingGroup) { // 向现有组添加对象 this._addObjectsToExistingGroup(existingGroup, newObjectsToAdd); this.groupObjectId = existingGroup.id; this.wasGroupCreated = false; } else { // 创建新组包含所有对象 this._createNewGroupWithAllObjects(newObjectsToAdd); this.groupObjectId = this.newGroupId; this.wasGroupCreated = true; await this.layerManager?.layerSort?.rearrangeObjects(); } // 更新交互性 this.layerManager?.updateLayersObjectsInteractivity?.(false).then(()=>{ // 更新缩略图 this._updateThumbnail(); }); }); // 标记为非首次执行 this.isFirstExecution = false; return this.groupObjectId; } catch (error) { console.error("执行组合操作时发生错误:", error); return null; } } /** * 查找图层中现有的组对象 * @returns {fabric.Group|null} * @private */ _findExistingGroup() { // 查找当前的组对象 if (!this.activeLayer.fabricObjects) return null; if (!this.existingGroupId) { const groupObjects = this.activeLayer.fabricObjects.find( (obj) => obj && obj.type === "group" ) || null; this.existingGroupId = groupObjects?.id || null; } if (!this.existingGroupId) { console.warn("未找到有效的组对象"); return null; } const { object } = findObjectById(this.canvas, this.existingGroupId); if (!object || object.type !== "group") { console.warn("未找到有效的组对象"); return null; } return object; } /** * 将新对象添加到现有组中 * @param {fabric.Group} existingGroup 现有组 * @param {Array} newObjects 要添加的新对象 * @private */ _addObjectsToExistingGroup(existingGroup, newObjects) { // 先从画布移除新对象(避免重复添加) newObjects.forEach((obj) => { removeCanvasObjectByObject(this.canvas, obj); }); // 使用 addWithUpdate 方法正确添加对象到组 newObjects.forEach((obj) => { existingGroup.addWithUpdate(obj); }); } /** * 创建包含所有对象的新组 * @param {Array} newObjects 新添加的对象 * @private */ _createNewGroupWithAllObjects(newObjects) { // 获取原始对象(通过ID重新查找) const originalObjects = this._getOriginalObjectsFromCanvas(); // 如果是重做,恢复原始对象的位置 if (!this.isFirstExecution) { originalObjects.forEach((obj) => { if (this.originalObjectPositions.has(obj.id)) { const savedPosition = this.originalObjectPositions.get(obj.id); obj.set({ left: savedPosition.left, top: savedPosition.top, scaleX: savedPosition.scaleX, scaleY: savedPosition.scaleY, angle: savedPosition.angle, originX: savedPosition.originX, originY: savedPosition.originY, flipX: savedPosition.flipX, flipY: savedPosition.flipY, }); console.log( `🔄 重做时恢复原始对象位置: ${obj.id} (${savedPosition.left}, ${savedPosition.top})` ); } }); } const allObjects = [...originalObjects, ...newObjects]; const clipPath = allObjects?.[0]?.clipPath || null; // 从画布中移除所有要组合的对象 allObjects.forEach((obj) => { obj.clipPath = null; obj.dirty = true; // 标记为脏对象 // obj.setCoords(); obj.opacity = 1; removeCanvasObjectByObject(this.canvas, obj); }); // 创建组对象 const groupObject = new fabric.Group(allObjects, { id: this.newGroupId, layerId: this.activeLayer.id, layerName: this.activeLayer.name, type: "group", selectable: true, evented: true, }); // 添加组对象到画布 this.canvas.add(groupObject); groupObject.clipPath = clipPath; // 恢复剪切路径 groupObject.dirty = true; // 标记为脏对象 groupObject.setCoords(); // 更新图层的对象列表 // this.activeLayer.fabricObjects = [groupObject]; this.activeLayer.fabricObjects = [ groupObject.toObject(["id", "layerId", "layerName"]), ]; } /** * 从画布中重新获取原始对象 * @returns {Array} 原始对象数组 * @private */ _getOriginalObjectsFromCanvas() { const objects = []; for (const objectId of this.originalObjectIds) { const result = findObjectById(this.canvas, objectId); if (result.object) { objects.push(result.object); } } return objects; } async undo() { if (!this.activeLayer || !this.canvas || !this.groupObjectId) return; this.activeLayer = this.layerManager.getActiveLayer(); try { await optimizeCanvasRendering(this.canvas, async () => { if (this.wasGroupCreated) { // 如果是新创建的组,完全撤销到原始状态 this._undoNewGroupCreation(); } else { // 如果是向现有组添加对象,只移除新添加的对象 this._undoAddToExistingGroup(); } await this.layerManager?.updateLayersObjectsInteractivity?.(false); // 更新缩略图 this._updateThumbnail(); }); // 重置为首次执行状态,以便重做时能正确恢复位置 this.isFirstExecution = false; console.log(`↩️ 成功撤销图层 ${this.activeLayer.name} 的对象组合操作`); } catch (error) { console.error("撤销组合操作时发生错误:", error); } } /** * 撤销新组的创建(修正版 - 删除新添加的元素) * @private */ _undoNewGroupCreation() { // 查找当前的组对象 const groupResult = findObjectById(this.canvas, this.groupObjectId); if (!groupResult.object) { console.error("找不到要撤销的组对象"); return; } const groupObject = groupResult.object; // 获取组内的所有对象 const groupObjects = groupObject.getObjects(); if (groupObjects.length === 0) { console.warn("组对象为空,直接移除"); this.canvas.remove(groupObject); return; } // 分离原始对象和新添加的对象 const objectsToRestore = []; const objectsToDelete = []; groupObjects.forEach((obj) => { if (this.originalObjectIds.includes(obj.id)) { // 这是原始对象,需要恢复 const originalPosition = this.originalObjectPositions.get(obj.id); let restorePosition; if (originalPosition) { // 优先使用原始保存的位置 restorePosition = { ...originalPosition }; } else { // 计算对象在画布中的当前绝对位置 restorePosition = this._calculateObjectAbsolutePosition( obj, groupObject ); } objectsToRestore.push({ object: obj, position: restorePosition, }); } else if (this.addedObjectIds.includes(obj.id)) { // 这是新添加的对象,需要删除 objectsToDelete.push(obj); } }); // 从画布中移除组对象 this.canvas.remove(groupObject); // 禁用渲染以提高性能 const wasRenderOnAddRemove = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = false; try { // 逐个恢复原始对象到画布 const restoredObjects = []; objectsToRestore.forEach(({ object: obj, position }) => { try { // 从组中移除对象(这会重置对象的变换状态) groupObject.removeWithUpdate(obj); // 重新设置对象的位置和属性 obj.set({ left: position.left, top: position.top, scaleX: position.scaleX || 1, scaleY: position.scaleY || 1, angle: position.angle || 0, flipX: position.flipX || false, flipY: position.flipY || false, originX: position.originX || "center", originY: position.originY || "center", layerId: this.activeLayer.id, layerName: this.activeLayer.name, selectable: true, evented: true, opacity: position.opacity || 1, }); // 更新对象坐标 obj.setCoords(); // 将对象添加回画布 this.canvas.add(obj); restoredObjects.push(obj.toObject("id", "layerId", "layerName")); console.log( `✅ 恢复原始对象 ${obj.id || obj.type} 到位置 (${position.left}, ${ position.top })` ); } catch (error) { console.error(`恢复对象 ${obj.id || obj.type} 时发生错误:`, error); } }); // 删除新添加的对象(不添加回画布) objectsToDelete.forEach((obj) => { try { // 从组中移除对象 groupObject.removeWithUpdate(obj); // 销毁对象以释放内存 if (typeof obj.destroy === "function") { obj.destroy(); } console.log(`🗑️ 删除新添加的对象 ${obj.id || obj.type}`); } catch (error) { console.error(`删除对象 ${obj.id || obj.type} 时发生错误:`, error); } }); // 更新图层对象列表(只包含恢复的原始对象) this.activeLayer.fabricObjects = restoredObjects; // 销毁组对象释放内存 if (typeof groupObject.destroy === "function") { groupObject.destroy(); } console.log( `✅ 成功撤销组创建,恢复了 ${restoredObjects.length} 个原始对象,删除了 ${objectsToDelete.length} 个新对象` ); } catch (error) { console.error("撤销组创建过程中发生错误:", error); } finally { // 恢复渲染设置 this.canvas.renderOnAddRemove = wasRenderOnAddRemove; this.canvas.renderAll(); } } /** * 计算对象在画布中的绝对位置(改进版) * @param {fabric.Object} obj 组内对象 * @param {fabric.Group} group 组对象 * @returns {Object} 绝对位置信息 * @private */ _calculateObjectAbsolutePosition(obj, group) { try { // 获取组的变换矩阵 const groupTransform = group.calcTransformMatrix(); // 获取对象在组内的相对位置 const objectPoint = new fabric.Point(obj.left || 0, obj.top || 0); // 应用组的变换矩阵计算绝对位置 const absolutePoint = fabric.util.transformPoint( objectPoint, groupTransform ); // 计算缩放比例 const totalScaleX = (group.scaleX || 1) * (obj.scaleX || 1); const totalScaleY = (group.scaleY || 1) * (obj.scaleY || 1); // 计算总旋转角度 const totalAngle = (group.angle || 0) + (obj.angle || 0); return { left: absolutePoint.x, top: absolutePoint.y, scaleX: totalScaleX, scaleY: totalScaleY, angle: totalAngle, flipX: obj.flipX || false, flipY: obj.flipY || false, originX: obj.originX || "center", originY: obj.originY || "center", opacity: obj.opacity || 1, }; } catch (error) { console.warn("使用变换矩阵计算位置失败,使用简化计算:", error); // 备选方案:基于组的中心点和对象的相对偏移计算 const groupCenterX = group.left || 0; const groupCenterY = group.top || 0; // 考虑组的缩放和旋转影响 const scaleX = group.scaleX || 1; const scaleY = group.scaleY || 1; const angle = group.angle || 0; // 计算对象相对于组中心的偏移 const offsetX = (obj.left || 0) * scaleX; const offsetY = (obj.top || 0) * scaleY; // 如果组有旋转,需要旋转偏移量 let finalX = groupCenterX + offsetX; let finalY = groupCenterY + offsetY; if (angle !== 0) { const cos = Math.cos(fabric.util.degreesToRadians(angle)); const sin = Math.sin(fabric.util.degreesToRadians(angle)); finalX = groupCenterX + offsetX * cos - offsetY * sin; finalY = groupCenterY + offsetX * sin + offsetY * cos; } return { left: finalX, top: finalY, scaleX: scaleX * (obj.scaleX || 1), scaleY: scaleY * (obj.scaleY || 1), angle: angle + (obj.angle || 0), flipX: obj.flipX || false, flipY: obj.flipY || false, originX: obj.originX || "center", originY: obj.originY || "center", opacity: obj.opacity || 1, }; } } /** * 撤销向现有组添加对象的操作(优化版) * @private */ _undoAddToExistingGroup() { // 查找现有的组对象 const groupResult = findObjectById(this.canvas, this.existingGroupId); if (!groupResult.object) { console.error("找不到现有的组对象"); return; } const existingGroup = groupResult.object; // 移除新添加的对象 for (const objectId of this.addedObjectIds) { const objResult = objectIsInCanvas(this.canvas, { id: objectId }); if (objResult.flag && objResult.parent === existingGroup) { // 对象在组中,使用 removeWithUpdate 移除 existingGroup.removeWithUpdate(objResult.object); // 从画布中完全移除这个对象 if (this.canvas.getObjects().includes(objResult.object)) { this.canvas.remove(objResult.object); } } } // 检查组的状态 const remainingObjects = existingGroup.getObjects(); if (remainingObjects.length === 0) { // 组为空,移除组 this.canvas.remove(existingGroup); const groupIndex = this.activeLayer.fabricObjects.indexOf(existingGroup); if (groupIndex !== -1) { this.activeLayer.fabricObjects.splice(groupIndex, 1); } } else if (remainingObjects.length === 1) { // 只剩一个对象,解散组 const singleObj = remainingObjects[0]; // 从画布移除组 this.canvas.remove(existingGroup); // 使用 removeWithUpdate 移除最后一个对象(会自动添加到画布) existingGroup.removeWithUpdate(singleObj); // 重新设置对象属性 singleObj.set({ layerId: this.activeLayer.id, layerName: this.activeLayer.name, }); // 更新图层对象列表 const groupIndex = this.activeLayer.fabricObjects.indexOf(existingGroup); if (groupIndex !== -1) { this.activeLayer.fabricObjects[groupIndex] = singleObj; } } } /** * 更新缩略图 * @private */ _updateThumbnail() { this.canvas?.thumbnailManager?.generateLayerThumbnail?.( this.activeLayer.id ); } getInfo() { return { name: this.name, layerId: this.activeLayer?.id, layerName: this.activeLayer?.name || "未知图层", originalObjectCount: this.originalObjectIds.length, addedObjectsCount: this.addedObjectIds.length, groupId: this.groupObjectId, wasGroupCreated: this.wasGroupCreated, }; } } /** * 创建图片图层复合命令 * 包含创建图层、添加对象到图层、切换工具等操作的复合命令 */ export class CreateImageLayerCommand extends Command { constructor(options) { super({ name: "创建图片图层", saveState: true, }); this.layerManager = options.layerManager; this.fabricImage = options.fabricImage; this.toolManager = options.toolManager; this.layerName = options.layerName || null; this.imageId = generateId("image_"); // 存储执行过程中的结果 this.newLayerId = generateId("layer_image_") || `layer_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.commands = []; this.executedCommands = []; } async execute() { if (!this.layerManager || !this.fabricImage) { throw new Error("图层管理器或图片对象无效"); } try { this.commands = []; this.executedCommands = []; // 生成图层名称 const fileName = this.layerName || `${new Date().toLocaleTimeString()}`; this.fabricImage.set({ id: this.imageId, }); // 1. 创建新图层命令 const createLayerCmd = new AddLayerCommand({ canvas: this.layerManager.canvas, layers: this.layerManager.layers, newLayer: createLayer({ id: this.newLayerId, name: fileName, type: LayerType.BITMAP, visible: true, locked: false, opacity: 1.0, fabricObjects: [], }), activeLayerId: this.layerManager.activeLayerId, insertIndex: this.layerManager._getInsertIndexAboveActiveLayer(), }); // 执行创建图层命令 this.newLayerId = await createLayerCmd.execute(); this.commands.push(createLayerCmd); this.executedCommands.push(createLayerCmd); // 新加功能-选区套索内添加图片自动居中 const { parent } = findLayerRecursively(this.layerManager.layers.value, this.newLayerId); if(parent && parent.selectObject){ let {top,left,width,height} = parent.selectObject; const ltop = top + height / 2; const lleft = left + width / 2; this.fabricImage.set({ top: ltop, left: lleft, }) } // 2. 添加图片对象到图层命令 const addObjectCmd = new AddObjectToLayerCommand({ canvas: this.layerManager.canvas, layers: this.layerManager.layers, layerManager: this.layerManager, layerId: this.newLayerId, layerName: this.layerName, fabricObject: this.fabricImage, }); // 执行添加对象命令 await addObjectCmd.execute(); this.commands.push(addObjectCmd); this.executedCommands.push(addObjectCmd); // 3. 切换工具到选择模式命令 if (this.toolManager) { const toolCmd = new ToolCommand({ toolManager: this.toolManager, tool: OperationType.SELECT, previousTool: this.toolManager.getCurrentTool(), }); // 执行工具切换命令 await toolCmd.execute(); this.commands.push(toolCmd); this.executedCommands.push(toolCmd); } console.log(`✅ 创建图片图层完成: ${fileName}, ID: ${this.newLayerId}`); return this.newLayerId; } catch (error) { console.error("创建图片图层失败:", error); // 回滚已执行的命令 await this._rollbackExecutedCommands(); throw error; } } async undo() { if (this.executedCommands.length === 0) { console.warn("没有已执行的命令需要撤销"); return true; } console.log( `↩️ 开始撤销创建图片图层操作,共 ${this.executedCommands.length} 个子命令` ); try { // 逆序撤销已执行的命令 const commands = [...this.executedCommands].reverse(); for (const command of commands) { if (typeof command.undo === "function") { try { console.log(`↩️ 撤销子命令: ${command.constructor.name}`); const result = command.undo(); if (this._isPromise(result)) { await result; } console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } catch (error) { console.error( `❌ 子命令撤销失败: ${command.constructor.name}`, error ); } } } this.executedCommands = []; console.log(`✅ 创建图片图层撤销完成`); return true; } catch (error) { console.error("❌ 撤销创建图片图层过程中发生错误:", error); throw error; } } /** * 回滚已执行的命令(内部使用) * @private */ async _rollbackExecutedCommands() { console.log(`🔄 开始回滚已执行的 ${this.executedCommands.length} 个子命令`); const commands = [...this.executedCommands].reverse(); for (const command of commands) { if (typeof command.undo === "function") { try { console.log(`🔄 回滚子命令: ${command.constructor.name}`); const result = command.undo(); if (this._isPromise(result)) { await result; } console.log(`✅ 子命令回滚成功: ${command.constructor.name}`); } catch (error) { console.error( `❌ 子命令回滚失败: ${command.constructor.name}`, error ); } } } this.executedCommands = []; console.log(`✅ 回滚完成`); } /** * 检查返回值是否为Promise * @private */ _isPromise(value) { return ( value && typeof value === "object" && typeof value.then === "function" && typeof value.catch === "function" ); } getInfo() { return { name: this.name, layerName: this.layerName, layerId: this.newLayerId, commandCount: this.commands.length, executedCount: this.executedCommands.length, }; } } /** * 拖拽排序图层命令 */ export class ReorderLayersCommand extends Command { constructor(options) { super({ name: "拖拽排序图层", saveState: true, }); this.layers = options.layers; this.oldIndex = options.oldIndex; this.newIndex = options.newIndex; this.layerId = options.layerId; this.canvas = options.canvas; this.layerSort = options.layerSort || null; // LayerSort实例 } async execute() { // 验证索引有效性 if ( this.oldIndex < 0 || this.newIndex < 0 || this.oldIndex >= this.layers.value.length || this.newIndex >= this.layers.value.length || this.oldIndex === this.newIndex ) { return false; } // 验证图层ID const layer = this.layers.value[this.oldIndex]; if (!layer || layer.id !== this.layerId) { return false; } // 不允许移动背景层和固定层 if (layer.isBackground || layer.isFixed) { return false; } // 执行排序 - 直接操作数组 不重排页面数据 // const layersArray = [...this.layers.value]; // const [movedLayer] = layersArray.splice(this.oldIndex, 1); // layersArray.splice(this.newIndex, 0, movedLayer); // this.layers.value = layersArray; // this.layers.value // 更新父图层的children数组 this.layers.value[this.oldIndex] = this.layers.value[this.newIndex]; // 确保旧索引位置的图层ID正确 this.layers.value[this.newIndex] = layer; // 确保旧索引位置的图层ID正确 // 使用LayerSort工具重新排列画布对象(如果可用) await this.layerSort?.rearrangeObjects(); return true; } async undo() { // 交换索引进行反向操作 const tempOldIndex = this.oldIndex; this.oldIndex = this.newIndex; this.newIndex = tempOldIndex; const result = await this.execute(); // 恢复原始索引 this.newIndex = this.oldIndex; this.oldIndex = tempOldIndex; return result; } getInfo() { return { name: this.name, layerId: this.layerId, oldIndex: this.oldIndex, newIndex: this.newIndex, }; } } /** * 拖拽排序子图层命令 */ export class ReorderChildLayersCommand extends Command { constructor(options) { super({ name: "拖拽排序子图层", saveState: true, }); this.layers = options.layers; this.parentId = options.parentId; this.oldIndex = options.oldIndex; this.newIndex = options.newIndex; this.layerId = options.layerId; this.canvas = options.canvas; this.layerSort = options.layerSort || null; // LayerSort实例 } async execute() { // 查找父图层 const parentLayer = this.layers.value.find( (layer) => layer.id === this.parentId ); if (!parentLayer) return false; // 获取子图层 const childLayers = parentLayer?.children || []; // 验证索引 if ( this.oldIndex < 0 || this.newIndex < 0 || this.oldIndex >= childLayers.length || this.newIndex >= childLayers.length || this.oldIndex === this.newIndex ) { return false; } // 验证子图层ID const layer = childLayers[this.oldIndex]; if (!layer || layer.id !== this.layerId) return false; // 更新父图层的children数组 parentLayer.children[this.oldIndex] = parentLayer.children[this.newIndex]; // 确保旧索引位置的图层ID正确 parentLayer.children[this.newIndex] = layer; // 确保旧索引位置的图层ID正确 // 使用LayerSort工具重新排列画布对象(如果可用) await this.layerSort?.rearrangeObjects(); return true; } async undo() { // 交换索引进行反向操作 const tempOldIndex = this.oldIndex; this.oldIndex = this.newIndex; this.newIndex = tempOldIndex; const result = await this.execute(); // 恢复原始索引 this.newIndex = this.oldIndex; this.oldIndex = tempOldIndex; return result; } getInfo() { return { name: this.name, parentId: this.parentId, layerId: this.layerId, oldIndex: this.oldIndex, newIndex: this.newIndex, }; } } /** * 复制图层命令 */ export class CopyLayerCommand extends Command { constructor(options) { super({ name: "复制图层", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.layerManager = options.layerManager; this.clipboardData = null; } execute() { const layer = this.layers.value.find((l) => l.id === this.layerId); if (!layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 不允许复制背景图层 if (layer.isBackground) { console.warn("不能复制背景图层"); return false; } // 序列化图层中的对象 const serializedObjects = []; if (layer.fabricObjects && layer.fabricObjects.length > 0) { layer.fabricObjects.forEach((obj) => { if (obj && typeof obj.toObject === "function") { serializedObjects.push(obj.toObject(["id", "layerId", "layerName"])); } }); } // 创建剪贴板数据 this.clipboardData = { ...layer, serializedObjects, isCut: false, originalLayerId: layer.id, }; // 保存到图层管理器的剪贴板 if (this.layerManager) { this.layerManager.clipboardData = this.clipboardData; } console.log(`已复制图层:${layer.name}`); return true; } undo() { // 复制操作无需撤销,只需清空剪贴板 if (this.layerManager) { this.layerManager.clipboardData = null; } } getInfo() { return { name: this.name, layerId: this.layerId, }; } } /** * 剪切图层命令 */ export class CutLayerCommand extends Command { constructor(options) { super({ name: "剪切图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.activeLayerId = options.activeLayerId; this.layerManager = options.layerManager; this.layerIndex = -1; this.cutLayer = null; this.clipboardData = null; this.wasActiveLayer = false; // 生成新图层ID和名称 this.newLayerId = generateId("layer_") || `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } async execute() { const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); const sourceLayer = layer; const parentLayer = parent; if (!sourceLayer) { console.error(`源图层 ${this.layerId} 不存在`); return null; } // 不允许复制背景图层 if (sourceLayer.isBackground) { console.warn("不能复制背景图层"); return null; } const newName = `${sourceLayer.name} copy`; // 创建新图层 this.newLayer = createLayer({ id: this.newLayerId, name: newName, type: sourceLayer.type, visible: sourceLayer.visible, locked: sourceLayer.locked, opacity: sourceLayer.opacity, blendMode: sourceLayer.blendMode, fabricObjects: [], children: sourceLayer.children ? [...sourceLayer.children] : [], layerProperties: sourceLayer.layerProperties ? { ...sourceLayer.layerProperties } : {}, metadata: sourceLayer.metadata ? { ...sourceLayer.metadata } : {}, parentId: parentLayer ? parentLayer.id : undefined, // 保持父图层关系 }); // 计算插入位置 - 区分主图层和子图层 let insertIndex; if (parentLayer) { // 处理子图层:在父图层的children数组中插入 const sourceChildIndex = parentLayer.children.findIndex( (child) => child.id === this.layerId ); insertIndex = this.insertIndex !== null ? this.insertIndex : sourceChildIndex + 1; // 插入到父图层的children数组中 parentLayer.children.splice(insertIndex, 0, this.newLayer); this.isChildLayer = true; this.parentLayer = parentLayer; this.childInsertIndex = insertIndex; } else { // 处理主图层:在主图层数组中插入 const sourceIndex = this.layers.value.findIndex( (l) => l.id === this.layerId ); insertIndex = this.insertIndex !== null ? this.insertIndex : sourceIndex + 1; // 插入到主图层数组中 this.layers.value.splice(insertIndex, 0, this.newLayer); this.isChildLayer = false; this.mainInsertIndex = insertIndex; } // 复制源图层中的对象 if (sourceLayer.fabricObjects && sourceLayer.fabricObjects.length > 0) { await this._duplicateObjects(sourceLayer.fabricObjects); } // 设置为活动图层 this.activeLayerId.value = this.newLayerId; // 重新渲染画布 await this.layerManager?.updateLayersObjectsInteractivity(false); console.log( `已复制图层:${newName} ${this.isChildLayer ? "(子图层)" : "(主图层)"}` ); return this.newLayerId; } async undo() { if (!this.newLayer) return; if (this.isChildLayer && this.parentLayer) { // 撤销子图层:从父图层的children数组中删除 const childIndex = this.parentLayer.children.findIndex( (child) => child.id === this.newLayerId ); if (childIndex !== -1) { this.parentLayer.children.splice(childIndex, 1); } } else { // 撤销主图层:从主图层数组中删除 const index = this.layers.value.findIndex( (l) => l.id === this.newLayerId ); if (index !== -1) { this.layers.value.splice(index, 1); } } // 从画布中移除所有创建的对象 this.createdObjects.forEach((obj) => { this.canvas.remove(obj); }); // 恢复原活动图层 this.activeLayerId.value = this.layerId; // 重新渲染画布 await this.layerManager?.updateLayersObjectsInteractivity(false); } async _duplicateObjects(sourceObjects) { const serializedObjects = sourceObjects.map((obj) => { // 序列化对象时保留必要的属性 const { object } = findObjectById(this.canvas, obj.id); if (object) return object.toObject(["id", "layerId", "layerName"]); return obj; }); return new Promise((resolve) => { fabric.util.enlivenObjects(serializedObjects, (objects) => { objects.forEach((obj) => { // 生成新的对象ID const newObjId = `obj_${Date.now()}_${Math.floor( Math.random() * 1000 )}`; obj.id = newObjId; obj.layerId = this.newLayerId; obj.layerName = this.newLayer.name; // 添加偏移量 const offset = 10; if (obj.left !== undefined) obj.left += offset; if (obj.top !== undefined) obj.top += offset; // 添加到画布 this.canvas.add(obj); // 添加到新图层 this.newLayer.fabricObjects.push(obj); // 记录创建的对象 this.createdObjects.push(obj); }); resolve(); }); }); } getInfo() { return { name: this.name, sourceLayerId: this.layerId, newLayerId: this.newLayerId, newLayerName: this.newLayer?.name, objectCount: this.createdObjects.length, isChildLayer: this.isChildLayer, parentLayerId: this.parentLayer?.id, }; } } /** * 创建调整图层命令 */ export class CreateAdjustmentLayerCommand extends Command { constructor(options) { super({ name: "创建调整图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.activeLayerId = options.activeLayerId; this.adjustmentType = options.adjustmentType || "brightness"; this.adjustmentValue = options.adjustmentValue || 0; this.insertIndex = options.insertIndex || null; this.newLayer = null; // 生成新图层ID this.newLayerId = generateId("adj_layer_") || `adj_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } execute() { // 创建调整图层 this.newLayer = createLayer({ id: this.newLayerId, name: `${this.adjustmentType} 调整`, type: LayerType.ADJUSTMENT, visible: true, locked: false, opacity: 1.0, fabricObjects: [], layerProperties: { adjustmentType: this.adjustmentType, value: this.adjustmentValue, affectedLayerIds: [], // 可以指定受影响的图层 }, }); // 计算插入位置 const insertIndex = this.insertIndex !== null ? this.insertIndex : this._getInsertIndexAboveActiveLayer(); // 插入新图层 this.layers.value.splice(insertIndex, 0, this.newLayer); // 设置为活动图层 this.activeLayerId.value = this.newLayerId; console.log(`已创建调整图层:${this.newLayer.name}`); return this.newLayerId; } _getInsertIndexAboveActiveLayer() { const activeIndex = this.layers.value.findIndex( (layer) => layer.id === this.activeLayerId.value ); return activeIndex !== -1 ? activeIndex : 0; } undo() { if (!this.newLayer) return; // 从图层列表中删除调整图层 const index = this.layers.value.findIndex((l) => l.id === this.newLayerId); if (index !== -1) { this.layers.value.splice(index, 1); } // 恢复原活动图层 // 这里需要记录原来的活动图层ID } getInfo() { return { name: this.name, adjustmentType: this.adjustmentType, adjustmentValue: this.adjustmentValue, newLayerId: this.newLayerId, newLayerName: this.newLayer?.name, }; } } /** * 应用图层样式命令 */ export class ApplyLayerStyleCommand extends Command { constructor(options) { super({ name: "应用图层样式", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.styleType = options.styleType; // 'shadow', 'glow', 'stroke' etc. this.styleOptions = options.styleOptions || {}; const { layer } = findLayerRecursively(this.layers.value, this.layerId); if (!layer) { console.error(`图层 ${this.layerId} 不存在`); return; } this.layer = layer; this.oldStyles = this.layer ? { ...(this.layer.layerProperties?.styles || {}) } : {}; } execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } // 初始化样式属性 if (!this.layer.layerProperties) { this.layer.layerProperties = {}; } if (!this.layer.layerProperties.styles) { this.layer.layerProperties.styles = {}; } // 应用新样式 this.layer.layerProperties.styles[this.styleType] = this.styleOptions; // 更新画布上的对象样式 this._applyStyleToObjects(); // 重新渲染画布 this.canvas.renderAll(); console.log(`已应用${this.styleType}样式到图层:${this.layer.name}`); return true; } _applyStyleToObjects() { if (!this.layer.fabricObjects) return; this.layer.fabricObjects.forEach((obj) => { if (!obj) return; switch (this.styleType) { case "shadow": if (this.styleOptions.enabled) { obj.shadow = new fabric.Shadow({ color: this.styleOptions.color || "rgba(0,0,0,0.5)", blur: this.styleOptions.blur || 5, offsetX: this.styleOptions.offsetX || 5, offsetY: this.styleOptions.offsetY || 5, }); } else { obj.shadow = null; } break; case "stroke": if (this.styleOptions.enabled) { obj.stroke = this.styleOptions.color || "#000000"; obj.strokeWidth = this.styleOptions.width || 1; } else { obj.stroke = null; obj.strokeWidth = 0; } break; // 可以添加更多样式类型 } }); } undo() { if (!this.layer) return; // 恢复原样式 if (this.layer.layerProperties && this.layer.layerProperties.styles) { this.layer.layerProperties.styles = { ...this.oldStyles }; } // 重新应用所有样式 this._reapplyAllStyles(); // 重新渲染画布 this.canvas.renderAll(); } _reapplyAllStyles() { if (!this.layer.fabricObjects) return; this.layer.fabricObjects.forEach((obj) => { if (!obj) return; // 重置样式 obj.shadow = null; obj.stroke = null; obj.strokeWidth = 0; // 重新应用所有保存的样式 const styles = this.layer.layerProperties?.styles || {}; Object.keys(styles).forEach((styleType) => { const styleOptions = styles[styleType]; // 这里可以复用 _applyStyleToObjects 中的逻辑 }); }); } getInfo() { return { name: this.name, layerId: this.layerId, styleType: this.styleType, styleOptions: this.styleOptions, }; } } /** * 图层剪贴蒙版命令 */ export class LayerClippingMaskCommand extends Command { constructor(options) { super({ name: "创建/移除剪贴蒙版", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.maskLayerId = options.maskLayerId || null; // null表示移除蒙版 const { layer } = findLayerRecursively(this.layers.value, this.layerId); if (!layer) { console.error(`图层 ${this.layerId} 不存在`); return; } this.layer = layer; this.oldClippingMask = this.layer ? this.layer.clippingMask : null; } execute() { if (!this.layer) { console.error(`图层 ${this.layerId} 不存在`); return false; } if (this.maskLayerId) { // 创建剪贴蒙版 const maskLayer = this.layers.value.find( (l) => l.id === this.maskLayerId ); if (!maskLayer) { console.error(`蒙版图层 ${this.maskLayerId} 不存在`); return false; } this.layer.clippingMask = maskLayer.fabricObjects?.[0] || null; console.log(`已为图层 ${this.layer.name} 创建剪贴蒙版`); } else { // 移除剪贴蒙版 this.layer.clippingMask = null; console.log(`已移除图层 ${this.layer.name} 的剪贴蒙版`); } // 更新画布上的对象 this._updateObjectClipping(); // 重新渲染画布 this.canvas.renderAll(); return true; } _updateObjectClipping() { if (!this.layer.fabricObjects) return; this.layer.fabricObjects.forEach((obj) => { if (this.layer.clippingMask) { // 应用剪贴蒙版 obj.clipPath = this.layer.clippingMask; } else { // 移除剪贴蒙版 obj.clipPath = null; } }); } undo() { if (!this.layer) return; // 恢复原剪贴蒙版 this.layer.clippingMask = this.oldClippingMask; // 更新画布上的对象 this._updateObjectClipping(); // 重新渲染画布 this.canvas.renderAll(); } getInfo() { return { name: this.name, layerId: this.layerId, maskLayerId: this.maskLayerId, hasClippingMask: !!this.layer?.clippingMask, }; } } /** * 更换固定图层图像命令 * 专门用于更换固定图层(如背景图层)的图像 */ export class ChangeFixedImageCommand extends Command { constructor(options = {}) { super({ name: "更换固定图层图像", saveState: true, }); 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.previousImage = null; this.previousTransform = null; this.previousObjectId = null; // 保存之前对象的ID this.targetLayer = null; this.newObjectId = null; // 保存新对象的ID this.isExecuted = false; // 错误处理 this.maxRetries = options.maxRetries || 3; this.retryCount = 0; this.timeoutMs = options.timeoutMs || 10000; } 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 () => { // 生成新对象ID this.newObjectId = generateId(); // 设置基本属性 newImage.set({ 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: "center", }); } // 使用帮助函数在指定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.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.toObject([ "id", "layerId", "type", ]); 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); } } } }); } getInfo() { return { name: this.name, 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({ name: "向图层添加图像", saveState: true, }); 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.maxRetries = options.maxRetries || 3; this.retryCount = 0; this.timeoutMs = options.timeoutMs || 10000; } async execute() { try { this.validateInputs(); // 查找目标图层 const { layer } = findLayerRecursively( this.layerManager?.layers?.value || [], this.layerId ); this.targetLayer = layer; if (!this.targetLayer) { throw new Error(`找不到目标图层: ${this.layerId}`); } // 检查图层是否可编辑 this.validateLayerEditability(); // 加载新图像 const newImage = await this.loadImageWithRetry(); // 添加图像到图层 await this.addImageToLayer(newImage); 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) { // 生成唯一ID const objectId = generateId(); // 设置图像属性 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); } } getInfo() { return { name: this.name, layerId: this.layerId, imageUrl: this.imageUrl, position: this.position, scale: this.scale, isExecuted: this.isExecuted, retryCount: this.retryCount, addedObjectId: this.addedObject?.id, }; } } /** * 删除子图层命令 */ export class RemoveChildLayerCommand extends Command { constructor(options) { super({ name: "删除子图层", saveState: true, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.parentId = options.parentId; this.activeLayerId = options.activeLayerId; this.layerManager = options.layerManager; // 查找父图层和子图层 const { parent } = findLayerRecursively(this.layers.value, this.layerId); this.parentLayer = parent; this.childIndex = this.parentLayer?.children?.findIndex( (child) => child.id === this.layerId ) ?? -1; this.removedChild = this.parentLayer?.children?.[this.childIndex]; this.isActiveLayer = this.layerId === this.activeLayerId.value; this.originalObjects = this.canvas.getObjects().filter((obj) => { obj.parentId = this.parentId; return obj.layerId === this.layerId; }); } async execute() { if (!this.parentLayer || this.childIndex === -1 || !this.removedChild) { throw new Error("找不到要删除的子图层"); } // 从画布中移除子图层中的所有对象 if ( this.removedChild.fabricObjects && this.removedChild.fabricObjects.length > 0 ) { this.removedChild.fabricObjects.forEach((obj) => { const { object } = findObjectById(this.canvas, obj.id); if (object) { this.canvas.remove(...this.originalObjects); } }); } // 从父图层的children中删除 this.parentLayer.children.splice(this.childIndex, 1); // 如果删除的是当前活动图层,需要更新活动图层 if (this.isActiveLayer) { // 设置父图层为活动图层,或者选择另一个子图层 if (this.parentLayer.children.length > 0) { this.activeLayerId.value = this.parentLayer.children[0].id; } else { this.activeLayerId.value = this.layers.value.find( (layer) => !layer.isBackground || !layer.isFixed )?.[0]?.id || null; } } // 重新渲染画布 await this.layerManager?.updateLayersObjectsInteractivity(); return true; } async undo() { if ( !this.parentLayer || this.childIndex === -1 || !this.removedChild || this.originalObjects.length === 0 ) { return; } // 恢复子图层到原位置 this.parentLayer.children.splice(this.childIndex, 0, this.removedChild); await new Promise((resolve) => { optimizeCanvasRendering(this.canvas, async () => { this.originalObjects.forEach((obj) => { // 恢复对象到画布 this.canvas.add(obj); // 恢复对象的图层信息 obj.layerId = this.layerId; obj.layerName = this.removedChild.name; obj.setCoords(); // 更新坐标 }); // 如果是原活动图层,恢复活动图层 if (this.isActiveLayer) { this.activeLayerId.value = this.layerId; } // 重新渲染画布 await this.layerManager?.updateLayersObjectsInteractivity(false); resolve(true); }); }); return true; } getInfo() { return { name: this.name, layerName: this.removedChild?.name || "未知子图层", layerId: this.layerId, parentId: this.parentId, }; } } /** * 重命名子图层命令 */ export class RenameChildLayerCommand extends Command { constructor(options) { super({ name: "重命名子图层", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.parentId = options.parentId; this.newName = options.newName; // 查找父图层和子图层 const { layer } = findLayerRecursively(this.layers.value, this.layerId); this.childLayer = layer; this.oldName = this.childLayer ? this.childLayer.name : null; } async execute() { if (!this.childLayer) { throw new Error("找不到要重命名的子图层"); } // 更新子图层名称 this.childLayer.name = this.newName; // 更新画布上对象的图层名称 if (this.canvas && this.childLayer.fabricObjects) { this.childLayer.fabricObjects.forEach((obj) => { if (obj.layerName !== undefined) { obj.layerName = this.newName; } }); } return true; } async undo() { if (this.childLayer && this.oldName) { this.childLayer.name = this.oldName; // 恢复画布上对象的图层名称 if (this.canvas && this.childLayer.fabricObjects) { this.childLayer.fabricObjects.forEach((obj) => { if (obj.layerName !== undefined) { obj.layerName = this.oldName; } }); } } } getInfo() { return { name: this.name, layerId: this.layerId, parentId: this.parentId, oldName: this.oldName, newName: this.newName, }; } } /** * 子图层锁定/解锁命令 */ export class ChildLayerLockCommand extends Command { constructor(options) { super({ name: "子图层锁定/解锁", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerId = options.layerId; this.parentId = options.parentId; this.layerManager = options.layerManager; // 查找父图层和子图层 const { layer, parent } = findLayerRecursively( this.layers.value, this.layerId ); this.parentLayer = parent; this.childLayer = layer; this.oldLocked = this.childLayer ? this.childLayer.locked : null; } async execute() { if (!this.childLayer) { throw new Error("找不到要锁定/解锁的子图层"); } // 切换锁定状态 this.childLayer.locked = !this.oldLocked; // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); return true; } async undo() { if (this.childLayer) { // 恢复锁定状态 this.childLayer.locked = this.oldLocked; // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); } } getInfo() { return { name: this.name, layerName: this.childLayer?.name || "未知子图层", layerId: this.layerId, parentId: this.parentId, newLocked: this.childLayer?.locked, oldLocked: this.oldLocked, }; } } /** * 设置图层混合模式 */ export class SetLayerCompositeCommand extends Command { constructor(options) { super({ name: "设置图层混合模式", saveState: false, }); this.canvas = options.canvas; this.layers = options.layers; this.layerManager = options.layerManager; this.layerId = options.layerId; this.newValue = options.newValue; this.oldValue = options.oldValue; } execute(isUndo = false) { const { layer } = findLayerRecursively(this.layers.value, this.layerId); const { object } = findObjectByLayerId(this.canvas, this.layerId); if (!layer || !object) { console.error(`图层${this.layerId}不存在`); return false; } // console.log("==========", this.newValue, this.oldValue); const value = isUndo ? this.oldValue : this.newValue; layer.blendMode = value; object.set("globalCompositeOperation", value); this.canvas.renderAll(); const event = isUndo ? "object:composite:undo" : "object:composite:execute"; EventManager.emit(event, object); return true; } undo() { return this.execute(true); } } /** * 设置颜色图层颜色 */ export class SetColorLayerFillCommand extends Command { constructor(options) { super({ name: "设置颜色图层颜色", saveState: false, }); this.canvas = options.canvas; this.layerManager = options.layerManager; this.object = options.object; this.layer = this.layerManager?.getLayerById(this.object.layerId); this.newFill = options.newFill; this.oldFill = JSON.parse(JSON.stringify(this.object.fill)); this.layer.blendMode = "multiply"; this.object.set("globalCompositeOperation", "multiply"); this.object.set("originColor", options.originColor); } async execute(isUndo = false) { if (!this.object) { console.error(`颜色图层不存在`); return false; } const isVisible = this.layer?.visible; if(!isVisible && this.layer) this.layer.visible = true; const gradient = new fabric.Gradient({ type: "linear", gradientUnits: "percentage", ...(isUndo ? this.oldFill : this.newFill), }); this.object.setFill(gradient); this.canvas.renderAll(); await this.canvas?.thumbnailManager?.generateLayerThumbnail?.( this.object.id ); if(!isVisible && this.layer) this.layer.visible = false; this.layerManager?.updateLayersObjectsInteractivity(); return true; } undo() { this.execute(true); return true; } }