diff --git a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js index e52fb108..f979bc47 100644 --- a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js @@ -11,6 +11,7 @@ import { } from "../utils/helper"; import { fabric } from "fabric-with-all"; import { imageModeHandler } from "../utils/imageHelper"; +import { restoreFabricObject } from "../utils/objectHelper"; /** * 设置活动图层命令 @@ -34,7 +35,11 @@ export class SetActiveLayerCommand extends Command { } execute() { - const { layer } = findLayerRecursively(this.layers.value, this.layerId, this.parentId); + const { layer } = findLayerRecursively( + this.layers.value, + this.layerId, + this.parentId + ); this.newLayer = layer; if (!this.newLayer) { @@ -64,7 +69,10 @@ export class SetActiveLayerCommand extends Command { this.canvas.discardActiveObject(); // 设置为新的图层下的对象为激活,但需要确保对象存在于画布上 - if (this.newLayer.fabricObjects && this.newLayer.fabricObjects.length > 0) { + 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) @@ -146,7 +154,9 @@ export class AddObjectToLayerCommand extends Command { this.layerManager = options.layerManager; // 保存对象原始状态和ID - this.objectId = this.fabricObject.id || `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + this.objectId = + this.fabricObject.id || + `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.fabricObject.set({ id: this.objectId, layerId: options.layerId, @@ -154,7 +164,11 @@ export class AddObjectToLayerCommand extends Command { }); // 保存完整的对象状态,包括位置和变换信息 - this.originalObjectState = this.fabricObject.toObject(["id", "layerId", "layerName"]); + this.originalObjectState = this.fabricObject.toObject([ + "id", + "layerId", + "layerName", + ]); // // 新增:保存详细的位置和变换信息,用于重做时恢复 // this.originalPosition = { @@ -176,7 +190,10 @@ export class AddObjectToLayerCommand extends Command { async execute() { // 查找目标图层 - const { layer } = findLayerRecursively(this.layers.value, this.layerId); + const { layer, parent } = findLayerRecursively( + this.layers.value, + this.layerId + ); if (!layer) { console.error(`图层 ${this.layerId} 不存在`); @@ -193,83 +210,49 @@ export class AddObjectToLayerCommand extends Command { // 优化渲染 - 统一批处理 支持异步回调 await optimizeCanvasRendering(this.canvas, async () => { - // const positionToUse = this.isFirstExecution - // ? { - // left: this.fabricObject.left || 0, - // top: this.fabricObject.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.originalPosition; - - // if (!this.isFirstExecution) { - // fabric.util.enlivenObjects([this.originalObjectState], (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, // 设置对象可事件 - // }); - // }); - // } else { - // // 将对象添加到画布 - // this.fabricObject.set({ - // ...positionToUse, - // 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, // 设置对象可事件 - // }); - // } - - fabric.util.enlivenObjects([this.originalObjectState], (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, // 设置对象可事件 - }); - }); + 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.fabricObject?.toObject?.(["id", "layerId", "layerName"]) || + this.fabricObject ); - - await this.layerManager?.updateLayersObjectsInteractivity?.(false); // 标记为非首次执行 this.isFirstExecution = false; console.log( @@ -277,6 +260,8 @@ export class AddObjectToLayerCommand extends Command { ); }); + await this.layerManager?.updateLayersObjectsInteractivity?.(); + this.layerManager?.updateLayersObjectsInteractivity?.(); // 如果是重做,使用保存的原始位置 // this.canvas.discardActiveObject(); @@ -313,12 +298,16 @@ export class AddObjectToLayerCommand extends Command { // 从图层的fabricObjects数组中移除对象 if (layer.fabricObjects) { - layer.fabricObjects = layer.fabricObjects.filter((obj) => obj.id !== this.objectId); + 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); + const object = this.canvas + .getObjects() + .find((obj) => obj.id === this.objectId); if (object) { // 先丢弃活动对象,避免控制点渲染错误 this.canvas.discardActiveObject(); @@ -392,7 +381,9 @@ export class RemoveObjectFromLayerCommand extends Command { // 从图层的fabricObjects数组移除对象 if (layer.fabricObjects) { - layer.fabricObjects = layer.fabricObjects.filter((obj) => obj.id !== this.objectId); + layer.fabricObjects = layer.fabricObjects.filter( + (obj) => obj.id !== this.objectId + ); } // 更新画布 @@ -619,14 +610,19 @@ export class ChangeFixedImageCommand extends Command { this.retryCount = attempt; if (attempt === this.maxRetries) { - throw new Error(`图像加载失败,已重试${this.maxRetries}次: ${error.message}`); + 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); + console.warn( + `图像加载重试 ${attempt + 1}/${this.maxRetries}:`, + error.message + ); } } } @@ -634,7 +630,9 @@ export class ChangeFixedImageCommand extends Command { loadImage() { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { - reject(new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)); + reject( + new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`) + ); }, this.timeoutMs); fabric.Image.fromURL( @@ -670,9 +668,15 @@ export class ChangeFixedImageCommand extends Command { // 移除旧对象(如果存在) if (this.previousObjectId) { - const { object: oldObject } = findObjectById(this.canvas, this.previousObjectId); + const { object: oldObject } = findObjectById( + this.canvas, + this.previousObjectId + ); if (oldObject) { - const removeSuccess = removeCanvasObjectByObject(this.canvas, oldObject); + const removeSuccess = removeCanvasObjectByObject( + this.canvas, + oldObject + ); if (!removeSuccess) { console.warn("移除旧对象失败,但继续执行"); } @@ -738,75 +742,93 @@ export class ChangeFixedImageCommand extends Command { } return new Promise((resolve, reject) => { - fabric.util.enlivenObjects([this.previousImage.objectData], async (objects) => { - try { - const restoredImage = objects[0]; + 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); + 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); - } + // 恢复之前的变换 + 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, + // 设置图层属性 + 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 + ); }); - // 使用帮助函数在正确的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); + resolve(); + } catch (error) { + reject(error); + } } - }); + ); }); } async removeCurrentImage() { await optimizeCanvasRendering(this.canvas, async () => { if (this.newObjectId) { - const { object: currentObject } = findObjectById(this.canvas, this.newObjectId); + const { object: currentObject } = findObjectById( + this.canvas, + this.newObjectId + ); if (currentObject) { - const removeSuccess = removeCanvasObjectByObject(this.canvas, currentObject); + const removeSuccess = removeCanvasObjectByObject( + this.canvas, + currentObject + ); if (removeSuccess) { this.targetLayer.fabricObject = null; this.layerManager.updateLayerObject(this.targetLayer.id, null); @@ -925,7 +947,10 @@ export class AddImageToLayerCommand extends Command { this.canvas.remove(this.addedObject); // 从图层管理器中移除 - this.layerManager.removeObjectFromLayer(this.addedObject.id, this.layerId); + this.layerManager.removeObjectFromLayer( + this.addedObject.id, + this.layerId + ); this.isExecuted = false; @@ -988,14 +1013,19 @@ export class AddImageToLayerCommand extends Command { this.retryCount = attempt; if (attempt === this.maxRetries) { - throw new Error(`图像加载失败,已重试${this.maxRetries}次: ${error.message}`); + 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); + console.warn( + `图像加载重试 ${attempt + 1}/${this.maxRetries}:`, + error.message + ); } } } @@ -1003,7 +1033,9 @@ export class AddImageToLayerCommand extends Command { loadImage() { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { - reject(new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)); + reject( + new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`) + ); }, this.timeoutMs); fabric.Image.fromURL( @@ -1257,16 +1289,23 @@ export class MoveLayerToTopCommand extends Command { this.parentLayer = null; // 父图层 - const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); + 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.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.layerIndex = this.layers.value.findIndex( + (layer) => layer.id === this.layerId + ); } this.layer = layer; @@ -1348,16 +1387,23 @@ export class MoveLayerToBottomCommand extends Command { this.parentLayer = null; // 父图层 - const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); + 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.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.layerIndex = this.layers.value.findIndex( + (layer) => layer.id === this.layerId + ); } this.layer = layer; @@ -1398,7 +1444,9 @@ export class MoveLayerToBottomCommand extends Command { async undo() { if (this.originalIndex !== -1 && this.layer) { // 获取当前位置 - const currentIndex = this.layers.value.findIndex((layer) => layer.id === this.layerId); + const currentIndex = this.layers.value.findIndex( + (layer) => layer.id === this.layerId + ); if (currentIndex !== -1) { // 移除当前位置 @@ -1449,11 +1497,16 @@ export class MoveLayerToBottomCommand extends Command { if (layer.isBackground && layer.fabricObject) { // 背景图层 - const originalObj = canvasObjects.find((o) => o.id === layer.fabricObject.id); + 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) { + } else if ( + Array.isArray(layer.fabricObjects) && + layer.fabricObjects.length > 0 + ) { // 普通图层和固定图层 layer.fabricObjects.forEach((obj) => { const originalObj = canvasObjects.find((o) => o.id === obj.id);