diff --git a/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js b/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js index e8d09f86..60fd70f9 100644 --- a/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js @@ -22,9 +22,7 @@ export class CreateBackgroundLayerCommand extends Command { execute() { // 检查是否已经存在背景图层 - const existingBgLayer = this.layers.value.find( - (layer) => layer.isBackground - ); + const existingBgLayer = this.layers.value.find((layer) => layer.isBackground); if (existingBgLayer) { console.warn("已存在背景层,不重复创建"); return existingBgLayer.id; @@ -34,11 +32,7 @@ export class CreateBackgroundLayerCommand extends Command { const bgObject = this._createBackgroundObject(); // 将背景对象添加到图层中 - this.backgroundLayer.fabricObject = bgObject.toObject([ - "id", - "layerId", - "type", - ]); + this.backgroundLayer.fabricObject = bgObject.toObject(["id", "layerId", "type"]); // 添加图层到最底部 this.layers.value.push(this.backgroundLayer); @@ -54,9 +48,7 @@ export class CreateBackgroundLayerCommand extends Command { undo() { // 从图层列表中删除背景图层 - const bgLayerIndex = this.layers.value.findIndex( - (layer) => layer.isBackground - ); + const bgLayerIndex = this.layers.value.findIndex((layer) => layer.isBackground); if (bgLayerIndex !== -1) { this.layers.value.splice(bgLayerIndex, 1); } @@ -82,8 +74,7 @@ export class CreateBackgroundLayerCommand extends Command { // 确保背景色为白色,如果没有设置或者是透明的话 const backgroundColor = - this.backgroundLayer.backgroundColor && - this.backgroundLayer.backgroundColor !== "transparent" + this.backgroundLayer.backgroundColor && this.backgroundLayer.backgroundColor !== "transparent" ? this.backgroundLayer.backgroundColor : "#ffffff"; @@ -139,10 +130,7 @@ export class UpdateBackgroundCommand extends Command { // 查找背景图层 this.bgLayer = this.layers.value.find((layer) => layer.isBackground); this.oldBackgroundColor = this.oldColor; - this.backgroundObject = findObjectById( - this.canvas, - this.bgLayer.fabricObject.id - ).object; + this.backgroundObject = findObjectById(this.canvas, this.bgLayer.fabricObject.id).object; } execute() { @@ -163,9 +151,7 @@ export class UpdateBackgroundCommand extends Command { this.backgroundColorValue.value = this.backgroundColor; // 设置背景颜色 // 生成缩略图 - this.canvasManager?.thumbnailManager?.generateLayerThumbnail?.( - this.bgLayer.id - ); + this.canvasManager?.thumbnailManager?.generateLayerThumbnail?.(this.bgLayer.id); return true; } @@ -186,9 +172,7 @@ export class UpdateBackgroundCommand extends Command { this.backgroundColorValue.value = this.oldBackgroundColor; // 恢复背景颜色 // 生成缩略图 - this.canvasManager?.thumbnailManager?.generateLayerThumbnail?.( - this.bgLayer.id - ); + this.canvasManager?.thumbnailManager?.generateLayerThumbnail?.(this.bgLayer.id); // 如果有旧颜色,恢复到旧颜色 return true; } @@ -223,10 +207,7 @@ export class BackgroundSizeCommand extends Command { this.bgLayer = this.layers.value.find((layer) => layer.isBackground); // 记录原尺寸 - this.backgroundObject = findObjectById( - this.canvas, - this.bgLayer.fabricObject.id - ).object; + this.backgroundObject = findObjectById(this.canvas, this.bgLayer.fabricObject.id).object; this.oldWidth = this.backgroundObject.width; this.oldHeight = this.backgroundObject.height; @@ -255,8 +236,7 @@ export class BackgroundSizeCommand extends Command { // 调整背景对象大小 if (this.bgLayer && this.backgroundObject) { // 保持原有的背景颜色,如果没有设置则使用白色 - const currentFill = - this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff"; + const currentFill = this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff"; this.backgroundObject.set({ width: this.newWidth, @@ -343,10 +323,7 @@ export class BackgroundSizeWithScaleCommand extends Command { // 查找背景图层 this.bgLayer = this.layers.value.find((layer) => layer.isBackground); - this.backgroundObject = findObjectById( - this.canvas, - this.bgLayer.fabricObject.id - ).object; + this.backgroundObject = findObjectById(this.canvas, this.bgLayer.fabricObject.id).object; // 计算缩放比例 const scaleXRatio = this.newWidth / this.oldWidth; @@ -409,24 +386,21 @@ export class BackgroundSizeWithScaleCommand extends Command { // 统一缩放:使用平均值,保持相对比例的同时允许适度的形变 this.uniformScale = Math.sqrt(scaleXRatio * scaleYRatio); this.offsetX = (this.newWidth - this.oldWidth * this.uniformScale) / 2; - this.offsetY = - (this.newHeight - this.oldHeight * this.uniformScale) / 2; + this.offsetY = (this.newHeight - this.oldHeight * this.uniformScale) / 2; break; case "fit": // 适应模式:使用较小值,确保所有内容都在画布内,可能有留白 this.uniformScale = Math.min(scaleXRatio, scaleYRatio); this.offsetX = (this.newWidth - this.oldWidth * this.uniformScale) / 2; - this.offsetY = - (this.newHeight - this.oldHeight * this.uniformScale) / 2; + this.offsetY = (this.newHeight - this.oldHeight * this.uniformScale) / 2; break; case "fill": // 填充模式:使用较大值,填满画布,可能有部分内容被裁切 this.uniformScale = Math.max(scaleXRatio, scaleYRatio); this.offsetX = (this.newWidth - this.oldWidth * this.uniformScale) / 2; - this.offsetY = - (this.newHeight - this.oldHeight * this.uniformScale) / 2; + this.offsetY = (this.newHeight - this.oldHeight * this.uniformScale) / 2; break; case "stretch": @@ -441,8 +415,7 @@ export class BackgroundSizeWithScaleCommand extends Command { // 默认使用uniform模式 this.uniformScale = Math.sqrt(scaleXRatio * scaleYRatio); this.offsetX = (this.newWidth - this.oldWidth * this.uniformScale) / 2; - this.offsetY = - (this.newHeight - this.oldHeight * this.uniformScale) / 2; + this.offsetY = (this.newHeight - this.oldHeight * this.uniformScale) / 2; } } @@ -462,8 +435,7 @@ export class BackgroundSizeWithScaleCommand extends Command { // 调整背景对象大小和位置 if (this.bgLayer && this.backgroundObject) { // 保持原有的背景颜色,如果没有设置则使用白色 - const currentFill = - this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff"; + const currentFill = this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff"; this.backgroundObject.set({ width: this.newWidth, @@ -480,12 +452,10 @@ export class BackgroundSizeWithScaleCommand extends Command { // 计算基于原始画布的缩放比例 const baseScaleX = - this.newWidth / - this.objectStates[0]?.obj._originalState?.baseCanvasWidth || + this.newWidth / this.objectStates[0]?.obj._originalState?.baseCanvasWidth || this.newWidth / this.oldWidth; const baseScaleY = - this.newHeight / - this.objectStates[0]?.obj._originalState?.baseCanvasHeight || + this.newHeight / this.objectStates[0]?.obj._originalState?.baseCanvasHeight || this.newHeight / this.oldHeight; // 根据策略缩放所有非背景对象 @@ -505,13 +475,11 @@ export class BackgroundSizeWithScaleCommand extends Command { const baseUniformScale = Math.sqrt(baseScaleX * baseScaleY); const baseOffsetX = (this.newWidth - - (obj._originalState?.baseCanvasWidth || this.oldWidth) * - baseUniformScale) / + (obj._originalState?.baseCanvasWidth || this.oldWidth) * baseUniformScale) / 2; const baseOffsetY = (this.newHeight - - (obj._originalState?.baseCanvasHeight || this.oldHeight) * - baseUniformScale) / + (obj._originalState?.baseCanvasHeight || this.oldHeight) * baseUniformScale) / 2; obj.set({ @@ -537,10 +505,7 @@ export class BackgroundSizeWithScaleCommand extends Command { this.canvas.setHeight(this.oldHeight); // 如果使用 CanvasManager,通知它画布大小恢复 - if ( - this.canvasManager && - typeof this.canvasManager.updateCanvasSize === "function" - ) { + if (this.canvasManager && typeof this.canvasManager.updateCanvasSize === "function") { this.canvasManager.updateCanvasSize(this.oldWidth, this.oldHeight); } @@ -568,12 +533,9 @@ export class BackgroundSizeWithScaleCommand extends Command { const baseScaleX = this.oldWidth / originalState.baseCanvasWidth; const baseScaleY = this.oldHeight / originalState.baseCanvasHeight; const baseUniformScale = Math.sqrt(baseScaleX * baseScaleY); - const baseOffsetX = - (this.oldWidth - originalState.baseCanvasWidth * baseUniformScale) / - 2; + const baseOffsetX = (this.oldWidth - originalState.baseCanvasWidth * baseUniformScale) / 2; const baseOffsetY = - (this.oldHeight - originalState.baseCanvasHeight * baseUniformScale) / - 2; + (this.oldHeight - originalState.baseCanvasHeight * baseUniformScale) / 2; obj.set({ left: originalState.left * baseUniformScale + baseOffsetX, diff --git a/src/component/Canvas/CanvasEditor/commands/BrushCommands.js b/src/component/Canvas/CanvasEditor/commands/BrushCommands.js index 3821e660..3d3511c0 100644 --- a/src/component/Canvas/CanvasEditor/commands/BrushCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/BrushCommands.js @@ -26,9 +26,7 @@ export class BrushSizeCommand extends BaseBrushCommand { super({ ...options, name: `设置笔刷大小: ${options.size}`, - description: `将笔刷大小从 ${options.previousSize || "?"} 设为 ${ - options.size - }`, + description: `将笔刷大小从 ${options.previousSize || "?"} 设为 ${options.size}`, }); this.size = options.size; @@ -66,9 +64,7 @@ export class BrushColorCommand extends BaseBrushCommand { super({ ...options, name: `设置笔刷颜色: ${options.color}`, - description: `将笔刷颜色从 ${options.previousColor || "?"} 设为 ${ - options.color - }`, + description: `将笔刷颜色从 ${options.previousColor || "?"} 设为 ${options.color}`, }); this.color = options.color; @@ -106,14 +102,11 @@ export class BrushOpacityCommand extends BaseBrushCommand { super({ ...options, name: `设置笔刷透明度: ${options.opacity}`, - description: `将笔刷透明度从 ${options.previousOpacity || "?"} 设为 ${ - options.opacity - }`, + description: `将笔刷透明度从 ${options.previousOpacity || "?"} 设为 ${options.opacity}`, }); this.opacity = options.opacity; - this.previousOpacity = - options.previousOpacity || this.brushStore.state.opacity; + this.previousOpacity = options.previousOpacity || this.brushStore.state.opacity; } execute() { @@ -147,9 +140,7 @@ export class BrushTypeCommand extends BaseBrushCommand { super({ ...options, name: `设置笔刷类型: ${options.brushType}`, - description: `将笔刷类型从 ${options.previousType || "?"} 设为 ${ - options.brushType - }`, + description: `将笔刷类型从 ${options.previousType || "?"} 设为 ${options.brushType}`, }); this.brushType = options.brushType; @@ -192,9 +183,7 @@ export class TextureCommand extends BaseBrushCommand { super({ ...options, name: options.enabled ? "启用笔刷材质" : "禁用笔刷材质", - description: options.enabled - ? `启用材质: ${options.path || "[默认]"}` - : "禁用笔刷材质", + description: options.enabled ? `启用材质: ${options.path || "[默认]"}` : "禁用笔刷材质", }); this.enabled = options.enabled; @@ -260,9 +249,7 @@ export class BrushPresetCommand extends BaseBrushCommand { */ constructor(options = {}) { const presetName = - typeof options.preset === "object" - ? options.preset.name - : `预设 ${options.preset}`; + typeof options.preset === "object" ? options.preset.name : `预设 ${options.preset}`; super({ ...options, @@ -303,14 +290,10 @@ export class BrushPresetCommand extends BaseBrushCommand { this.brushStore.applyPreset(this.preset); } else if (typeof this.preset === "object") { // 应用自定义预设对象 - if (this.preset.size !== undefined) - this.brushStore.setBrushSize(this.preset.size); - if (this.preset.color !== undefined) - this.brushStore.setBrushColor(this.preset.color); - if (this.preset.opacity !== undefined) - this.brushStore.setBrushOpacity(this.preset.opacity); - if (this.preset.type !== undefined) - this.brushStore.setBrushType(this.preset.type); + if (this.preset.size !== undefined) this.brushStore.setBrushSize(this.preset.size); + if (this.preset.color !== undefined) this.brushStore.setBrushColor(this.preset.color); + if (this.preset.opacity !== undefined) this.brushStore.setBrushOpacity(this.preset.opacity); + if (this.preset.type !== undefined) this.brushStore.setBrushType(this.preset.type); if (this.preset.textureEnabled !== undefined) { this.brushStore.setTextureEnabled(this.preset.textureEnabled); @@ -542,8 +525,7 @@ export class TexturePresetCommand extends BaseBrushCommand { * @param {Object} options.brushManager 笔刷管理器实例 */ constructor(options = {}) { - const presetName = - typeof options.preset === "object" ? options.preset.name : options.preset; + const presetName = typeof options.preset === "object" ? options.preset.name : options.preset; super({ ...options, @@ -614,10 +596,7 @@ export class TextureUploadCommand extends BaseBrushCommand { }); this.file = options.file; - this.name = - options.name || - options.file?.name?.replace(/\.[^/.]+$/, "") || - "自定义纹理"; + this.name = options.name || options.file?.name?.replace(/\.[^/.]+$/, "") || "自定义纹理"; this.category = options.category || "自定义材质"; this.texturePresetManager = options.texturePresetManager; this.brushManager = options.brushManager; diff --git a/src/component/Canvas/CanvasEditor/commands/ClearSelectionContentCommand.js b/src/component/Canvas/CanvasEditor/commands/ClearSelectionContentCommand.js index 82bbe129..bacdcb79 100644 --- a/src/component/Canvas/CanvasEditor/commands/ClearSelectionContentCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/ClearSelectionContentCommand.js @@ -24,8 +24,7 @@ export class ClearSelectionContentCommand extends Command { this.oldLayer = [...this.layers.value]; // 获取原图层对象 - const { layer } = - findLayerRecursively(this.layers.value, this.targetLayerId) || {}; + const { layer } = findLayerRecursively(this.layers.value, this.targetLayerId) || {}; // 栅格化相关属性 this.originalLayerBackup = null; @@ -37,17 +36,10 @@ export class ClearSelectionContentCommand extends Command { // this.originalLayerObject = fabric.util.object.clone(originalLayerObject); // 获取原图层对象 - this.oldLayerObjects = originalLayerObject.toObject([ - "id", - "layerId", - "layerName", - ]); // 获取原图层的所有对象 + this.oldLayerObjects = originalLayerObject.toObject(["id", "layerId", "layerName"]); // 获取原图层的所有对象 this.rasterizedImage = null; - this.targetLayer = findLayerRecursively( - this.canvas, - this.targetLayerId - )?.layer; + this.targetLayer = findLayerRecursively(this.canvas, this.targetLayerId)?.layer; this.layerRasterized = false; @@ -88,8 +80,7 @@ export class ClearSelectionContentCommand extends Command { } // 确定目标图层 - const layerId = - this.targetLayerId || this.layerManager.getActiveLayerId(); + const layerId = this.targetLayerId || this.layerManager.getActiveLayerId(); this.targetLayer = this.layerManager.getLayerById(layerId); if (!this.targetLayer) { console.error("无法清除选区内容:目标图层无效"); @@ -107,9 +98,7 @@ export class ClearSelectionContentCommand extends Command { } // 创建反转选区(保留选区外的内容) - const invertedSelection = await this._createInvertedSelection( - this.selectionObject - ); + const invertedSelection = await this._createInvertedSelection(this.selectionObject); if (!invertedSelection) { console.error("创建反转选区失败"); return false; @@ -137,10 +126,7 @@ export class ClearSelectionContentCommand extends Command { // 恢复原图层状态 // 移除栅格化后的图像 - if ( - this.rasterizedImage && - this.canvas.getObjects().includes(this.rasterizedImage) - ) { + if (this.rasterizedImage && this.canvas.getObjects().includes(this.rasterizedImage)) { this.canvas.remove(this.rasterizedImage); } @@ -199,10 +185,7 @@ export class ClearSelectionContentCommand extends Command { let scaleFactor = this.baseResolutionScale; if (this.highResolutionEnabled) { const currentZoom = this.canvas.getZoom?.() || 1; - scaleFactor = Math.max( - scaleFactor || this.canvas?.getRetinaScaling?.(), - currentZoom - ); + scaleFactor = Math.max(scaleFactor || this.canvas?.getRetinaScaling?.(), currentZoom); scaleFactor = Math.min(scaleFactor, 3); } @@ -286,9 +269,7 @@ export class ClearSelectionContentCommand extends Command { layerBounds.left + layerBounds.width } ${layerBounds.top} L ${layerBounds.left + layerBounds.width} ${ layerBounds.top + layerBounds.height - } L ${layerBounds.left} ${layerBounds.top + layerBounds.height} Z ${ - selectionObject.path - }`; + } L ${layerBounds.left} ${layerBounds.top + layerBounds.height} Z ${selectionObject.path}`; const invertedPath = new fabric.Path(pathString, { fillRule: "evenodd", @@ -329,14 +310,8 @@ export class ClearSelectionContentCommand extends Command { if (!bounds) { bounds = { ...objBounds }; } else { - const right = Math.max( - bounds.left + bounds.width, - objBounds.left + objBounds.width - ); - const bottom = Math.max( - bounds.top + bounds.height, - objBounds.top + objBounds.height - ); + const right = Math.max(bounds.left + bounds.width, objBounds.left + objBounds.width); + const bottom = Math.max(bounds.top + bounds.height, objBounds.top + objBounds.height); bounds.left = Math.min(bounds.left, objBounds.left); bounds.top = Math.min(bounds.top, objBounds.top); @@ -370,15 +345,10 @@ export class ClearSelectionContentCommand extends Command { // 递归获取图层及其子图层的所有对象 const collectLayerObjects = (currentLayer) => { // 处理图层的fabricObjects - if ( - currentLayer.fabricObjects && - Array.isArray(currentLayer.fabricObjects) - ) { + if (currentLayer.fabricObjects && Array.isArray(currentLayer.fabricObjects)) { currentLayer.fabricObjects.forEach((fabricObj) => { if (fabricObj && fabricObj.id) { - const realObject = canvasObjects.find( - (canvasObj) => canvasObj.id === fabricObj.id - ); + const realObject = canvasObjects.find((canvasObj) => canvasObj.id === fabricObj.id); if (realObject && realObject.visible !== false) { objects.push(realObject); } @@ -420,16 +390,12 @@ export class ClearSelectionContentCommand extends Command { } // 移除栅格化后的图像 - if ( - this.rasterizedImage && - this.canvas.getObjects().includes(this.rasterizedImage) - ) { + if (this.rasterizedImage && this.canvas.getObjects().includes(this.rasterizedImage)) { this.canvas.remove(this.rasterizedImage); } // 恢复图层的fabricObjects - this.targetLayer.fabricObjects = - this.originalLayerBackup.fabricObjects || []; + this.targetLayer.fabricObjects = this.originalLayerBackup.fabricObjects || []; // 重新创建并添加对象到画布 if (this.targetLayer.fabricObjects.length > 0) { diff --git a/src/component/Canvas/CanvasEditor/commands/Command.js b/src/component/Canvas/CanvasEditor/commands/Command.js index 9f5bed8d..dfa493e9 100644 --- a/src/component/Canvas/CanvasEditor/commands/Command.js +++ b/src/component/Canvas/CanvasEditor/commands/Command.js @@ -109,10 +109,7 @@ export class CompositeCommand extends Command { console.log(`✅ 子命令执行成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令执行失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令执行失败: ${command.constructor.name}`, error); // 执行失败时,撤销已执行的命令 await this._rollbackExecutedCommands(); @@ -142,9 +139,7 @@ export class CompositeCommand extends Command { return true; } - console.log( - `↩️ 开始撤销复合命令,共 ${this.executedCommands.length} 个子命令` - ); + console.log(`↩️ 开始撤销复合命令,共 ${this.executedCommands.length} 个子命令`); try { // 逆序撤销已执行的命令 @@ -164,10 +159,7 @@ export class CompositeCommand extends Command { results.push(finalResult); console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令撤销失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error); // 撤销失败不中断整个撤销过程,但要记录错误 } } else { @@ -203,10 +195,7 @@ export class CompositeCommand extends Command { } console.log(`✅ 子命令回滚成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令回滚失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令回滚失败: ${command.constructor.name}`, error); // 回滚失败不中断整个回滚过程 } } @@ -238,9 +227,7 @@ export class CompositeCommand extends Command { commandCount: this.commands.length, executedCount: this.executedCommands.length, isExecuting: this.isExecuting, - subCommands: this.commands.map((cmd) => - cmd.getInfo ? cmd.getInfo() : cmd.constructor.name - ), + subCommands: this.commands.map((cmd) => (cmd.getInfo ? cmd.getInfo() : cmd.constructor.name)), }; } } diff --git a/src/component/Canvas/CanvasEditor/commands/CrossLevelMoveCommands.js b/src/component/Canvas/CanvasEditor/commands/CrossLevelMoveCommands.js index dc91bd91..c35bec76 100644 --- a/src/component/Canvas/CanvasEditor/commands/CrossLevelMoveCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/CrossLevelMoveCommands.js @@ -85,9 +85,7 @@ export class CrossLevelMoveCommand extends Command { this.layers.value.forEach((layer) => { if (layer.fabricObject) { states[layer.id] = { - isInCanvas: this.canvas - ? this.canvas.contains(layer.fabricObject) - : false, + isInCanvas: this.canvas ? this.canvas.contains(layer.fabricObject) : false, parentGroupId: null, visible: layer.fabricObject.visible, }; @@ -127,11 +125,7 @@ export class CrossLevelMoveCommand extends Command { * 验证移动的有效性 */ validateMove() { - const layer = this.findLayer( - this.layerId, - this.fromContainerType, - this.fromParentId - ); + const layer = this.findLayer(this.layerId, this.fromContainerType, this.fromParentId); if (!layer) { throw new Error(`找不到要移动的图层: ${this.layerId}`); @@ -153,9 +147,7 @@ export class CrossLevelMoveCommand extends Command { // 检查目标父图层是否为组 if (this.toContainerType === "child") { - const targetParent = this.layers.value.find( - (layer) => layer.id === this.toParentId - ); + const targetParent = this.layers.value.find((layer) => layer.id === this.toParentId); if (!targetParent || !isGroupLayer(targetParent)) { throw new Error("目标图层不是组图层"); } @@ -198,15 +190,9 @@ export class CrossLevelMoveCommand extends Command { try { // 根据移动类型执行对应操作 - if ( - this.fromContainerType === "root" && - this.toContainerType === "child" - ) { + if (this.fromContainerType === "root" && this.toContainerType === "child") { this.moveRootToGroup(draggedLayer); - } else if ( - this.fromContainerType === "child" && - this.toContainerType === "root" - ) { + } else if (this.fromContainerType === "child" && this.toContainerType === "root") { this.moveGroupToRoot(draggedLayer); } else if ( this.fromContainerType === "child" && @@ -228,6 +214,17 @@ export class CrossLevelMoveCommand extends Command { await this.layerManager?.updateLayersObjectsInteractivity(); this.canvas?.renderAll(); + // 生成缩略图 + this.fromParentId && + this.layerManager?.canvasManager?.thumbnailManager?.generateLayerThumbnail?.( + this.fromParentId + ); + + this.toParentId && + this.layerManager?.canvasManager?.thumbnailManager?.generateLayerThumbnail?.( + this.toParentId + ); + console.log("✅ 跨层级移动命令执行成功"); return true; } catch (error) { @@ -266,7 +263,6 @@ export class CrossLevelMoveCommand extends Command { this.restoreFabricObjectStates(this.beforeState.fabricObjects); await this.layerManager?.updateLayersObjectsInteractivity(); - this.canvas?.renderAll(); // 刷新画布 this.canvas?.renderAll(); console.log("✅ 跨层级移动命令撤销成功"); @@ -299,9 +295,7 @@ export class CrossLevelMoveCommand extends Command { // 根据图层的parentId重新放置 if (layer.parentId) { - const parentLayer = this.layers.value.find( - (l) => l.id === layer.parentId - ); + const parentLayer = this.layers.value.find((l) => l.id === layer.parentId); if ( parentLayer && parentLayer.fabricObject && @@ -396,14 +390,9 @@ export class CrossLevelMoveCommand extends Command { layer.children = layerData.children .map((childData) => { // 从原始图层数组中查找子图层 - let childLayer = originalLayers.find( - (l) => l.id === childData.id - ); + let childLayer = originalLayers.find((l) => l.id === childData.id); if (!childLayer) { - childLayer = this.findLayerInOriginalStructure( - childData.id, - originalLayers - ); + childLayer = this.findLayerInOriginalStructure(childData.id, originalLayers); } if (childLayer) { // 更新子图层属性 @@ -465,9 +454,7 @@ export class CrossLevelMoveCommand extends Command { // 根据目标状态放置对象 if (targetState.parentGroupId) { // 应该在特定组中 - const parentLayer = this.layers.value.find( - (l) => l.id === targetState.parentGroupId - ); + const parentLayer = this.layers.value.find((l) => l.id === targetState.parentGroupId); if ( parentLayer && parentLayer.fabricObject && @@ -532,12 +519,7 @@ export class CrossLevelMoveCommand extends Command { */ safeRemoveFromContainer(fabricObject, container, containerName) { return this.safeFabricOperation(() => { - if ( - container && - container.remove && - container.contains && - container.contains(fabricObject) - ) { + if (container && container.remove && container.contains && container.contains(fabricObject)) { container.remove(fabricObject); console.log(`✅ 成功从${containerName}移除对象`); return true; @@ -556,11 +538,7 @@ export class CrossLevelMoveCommand extends Command { // 从所有组中移除 this.layers.value.forEach((layer) => { if (layer.fabricObject && layer.fabricObject.type === "group") { - this.safeRemoveFromContainer( - fabricObject, - layer.fabricObject, - `组${layer.id}` - ); + this.safeRemoveFromContainer(fabricObject, layer.fabricObject, `组${layer.id}`); } }); } @@ -575,9 +553,7 @@ export class CrossLevelMoveCommand extends Command { newIndex: this.newIndex, }); - const targetParent = this.layers.value.find( - (layer) => layer.id === this.toParentId - ); + const targetParent = this.layers.value.find((layer) => layer.id === this.toParentId); if (!targetParent) { throw new Error(`找不到目标父图层: ${this.toParentId}`); } @@ -588,9 +564,7 @@ export class CrossLevelMoveCommand extends Command { } // 从顶级图层数组中移除 - const rootIndex = this.layers.value.findIndex( - (layer) => layer.id === draggedLayer.id - ); + const rootIndex = this.layers.value.findIndex((layer) => layer.id === draggedLayer.id); if (rootIndex !== -1) { this.layers.value.splice(rootIndex, 1); console.log(`🗑️ 从顶级图层数组中移除图层 ${draggedLayer.id}`); @@ -599,20 +573,14 @@ export class CrossLevelMoveCommand extends Command { // 更新图层关系 draggedLayer.parentId = this.toParentId; targetParent.children.splice(this.newIndex, 0, draggedLayer); - console.log( - `📂 将图层 ${draggedLayer.id} 添加到父图层 ${this.toParentId} 的children中` - ); + console.log(`📂 将图层 ${draggedLayer.id} 添加到父图层 ${this.toParentId} 的children中`); // 处理fabric对象的层级关系 if (draggedLayer.fabricObject && targetParent.fabricObject) { console.log(`🎨 处理fabric对象层级关系`); // 从画布中移除 - this.safeRemoveFromContainer( - draggedLayer.fabricObject, - this.canvas, - "画布" - ); + this.safeRemoveFromContainer(draggedLayer.fabricObject, this.canvas, "画布"); // 添加到父组 this.safeAddToContainer( @@ -635,22 +603,16 @@ export class CrossLevelMoveCommand extends Command { newIndex: this.newIndex, }); - const sourceParent = this.layers.value.find( - (layer) => layer.id === this.fromParentId - ); + const sourceParent = this.layers.value.find((layer) => layer.id === this.fromParentId); if (!sourceParent || !sourceParent.children) { throw new Error(`找不到源父图层或其children数组: ${this.fromParentId}`); } // 从源父图层的children中移除 - const childIndex = sourceParent.children.findIndex( - (child) => child.id === draggedLayer.id - ); + const childIndex = sourceParent.children.findIndex((child) => child.id === draggedLayer.id); if (childIndex !== -1) { sourceParent.children.splice(childIndex, 1); - console.log( - `🗑️ 从父图层 ${this.fromParentId} 的children中移除图层 ${draggedLayer.id}` - ); + console.log(`🗑️ 从父图层 ${this.fromParentId} 的children中移除图层 ${draggedLayer.id}`); } // 处理fabric对象的层级关系 @@ -675,9 +637,7 @@ export class CrossLevelMoveCommand extends Command { // 计算在顶级图层中的插入位置 const targetIndex = Math.min(this.newIndex, this.layers.value.length); this.layers.value.splice(targetIndex, 0, draggedLayer); - console.log( - `📂 将图层 ${draggedLayer.id} 添加到顶级图层数组位置 ${targetIndex}` - ); + console.log(`📂 将图层 ${draggedLayer.id} 添加到顶级图层数组位置 ${targetIndex}`); console.log("✅ 组内图层移动到顶级完成"); } @@ -693,26 +653,18 @@ export class CrossLevelMoveCommand extends Command { newIndex: this.newIndex, }); - const sourceParent = this.layers.value.find( - (layer) => layer.id === this.fromParentId - ); - const targetParent = this.layers.value.find( - (layer) => layer.id === this.toParentId - ); + const sourceParent = this.layers.value.find((layer) => layer.id === this.fromParentId); + const targetParent = this.layers.value.find((layer) => layer.id === this.toParentId); if (!sourceParent || !targetParent) { throw new Error("找不到源父图层或目标父图层"); } // 从源父图层中移除 - const childIndex = sourceParent.children.findIndex( - (child) => child.id === draggedLayer.id - ); + const childIndex = sourceParent.children.findIndex((child) => child.id === draggedLayer.id); if (childIndex !== -1) { sourceParent.children.splice(childIndex, 1); - console.log( - `🗑️ 从源父图层 ${this.fromParentId} 中移除图层 ${draggedLayer.id}` - ); + console.log(`🗑️ 从源父图层 ${this.fromParentId} 中移除图层 ${draggedLayer.id}`); // 从源父组的fabricObject中移除 if (draggedLayer.fabricObject && sourceParent.fabricObject) { @@ -726,9 +678,7 @@ export class CrossLevelMoveCommand extends Command { // 更新图层的parentId draggedLayer.parentId = this.toParentId; - console.log( - `🔗 更新图层 ${draggedLayer.id} 的parentId为 ${this.toParentId}` - ); + console.log(`🔗 更新图层 ${draggedLayer.id} 的parentId为 ${this.toParentId}`); // 确保目标父图层有children数组 if (!targetParent.children) { diff --git a/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand.js b/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand.js index d9e7b9f5..944e2fe9 100644 --- a/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand.js @@ -1,8 +1,4 @@ -import { - createLayer, - findInChildLayers, - LayerType, -} from "../utils/layerHelper.js"; +import { createLayer, findInChildLayers, LayerType } from "../utils/layerHelper.js"; import { createRasterizedImage } from "../utils/selectionToImage.js"; import { CompositeCommand, Command } from "./Command.js"; import { CreateImageLayerCommand } from "./LayerCommands.js"; @@ -56,9 +52,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { const selectionObject = this.selectionManager.getSelectionObject(); if (selectionObject) { try { - this._clonedSelectionObject = await this._cloneObject( - selectionObject - ); + this._clonedSelectionObject = await this._cloneObject(selectionObject); console.log("套索抠图:选区对象已克隆保存"); } catch (error) { console.error("套索抠图:克隆选区对象失败:", error); @@ -294,10 +288,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { await command.undo(); console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令撤销失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error); // 子命令撤销失败不中断整个撤销过程 } } @@ -361,16 +352,11 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { // 递归获取图层及其子图层的所有对象 const collectLayerObjects = (currentLayer) => { // 处理图层的fabricObjects - if ( - currentLayer.fabricObjects && - Array.isArray(currentLayer.fabricObjects) - ) { + if (currentLayer.fabricObjects && Array.isArray(currentLayer.fabricObjects)) { currentLayer.fabricObjects.forEach((fabricRef) => { if (fabricRef && fabricRef.id) { // 从画布中查找真实的对象 - const realObject = canvasObjects.find( - (obj) => obj.id === fabricRef.id - ); + const realObject = canvasObjects.find((obj) => obj.id === fabricRef.id); if (realObject && realObject.visible) { objects.push(realObject); } @@ -380,9 +366,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { // 处理单个fabricObject(背景图层等) if (currentLayer.fabricObject && currentLayer.fabricObject.id) { - const realObject = canvasObjects.find( - (obj) => obj.id === currentLayer.fabricObject.id - ); + const realObject = canvasObjects.find((obj) => obj.id === currentLayer.fabricObject.id); if (realObject && realObject.visible) { objects.push(realObject); } @@ -413,11 +397,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { * @returns {String} 抠图结果的DataURL * @private */ - async _performCutoutWithRasterized( - sourceObjects, - selectionObject, - selectionBounds - ) { + async _performCutoutWithRasterized(sourceObjects, selectionObject, selectionBounds) { try { console.log("=== 开始使用createRasterizedImage执行抠图 ==="); console.log(`源对象数量: ${sourceObjects.length}`); @@ -456,10 +436,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { // 如果createRasterizedImage失败,回退到原始方法 console.log("⚠️ 回退到原始抠图方法..."); - return await this._performCutout( - { fabricObjects: sourceObjects }, - selectionObject - ); + return await this._performCutout({ fabricObjects: sourceObjects }, selectionObject); } } @@ -490,9 +467,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { try { // 收集源图层中的可见对象 - const visibleObjects = sourceLayer.fabricObjects.filter( - (obj) => obj.visible - ); + const visibleObjects = sourceLayer.fabricObjects.filter((obj) => obj.visible); if (visibleObjects.length === 0) { throw new Error("源图层没有可见对象"); @@ -545,10 +520,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { let highResolutionScale = 1; if (this.highResolutionEnabled) { const devicePixelRatio = window.devicePixelRatio || 1; - highResolutionScale = Math.max( - this.baseResolutionScale, - devicePixelRatio * 2 - ); + highResolutionScale = Math.max(this.baseResolutionScale, devicePixelRatio * 2); } // 创建用于导出的高分辨率canvas @@ -559,12 +531,8 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { colorSpace: "srgb", }); - const actualWidth = Math.round( - renderBounds.width * highResolutionScale - ); - const actualHeight = Math.round( - renderBounds.height * highResolutionScale - ); + const actualWidth = Math.round(renderBounds.width * highResolutionScale); + const actualHeight = Math.round(renderBounds.height * highResolutionScale); exportCanvas.width = actualWidth; exportCanvas.height = actualHeight; @@ -773,17 +741,14 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { } }); } else if (objectType === "polygon") { - fabric.Polygon.fromObject( - this.serializedSelectionObject, - (polygon) => { - if (polygon) { - console.log("多边形选区对象反序列化成功"); - resolve(polygon); - } else { - reject(new Error("多边形选区对象反序列化失败")); - } + fabric.Polygon.fromObject(this.serializedSelectionObject, (polygon) => { + if (polygon) { + console.log("多边形选区对象反序列化成功"); + resolve(polygon); + } else { + reject(new Error("多边形选区对象反序列化失败")); } - ); + }); } else if (objectType === "rect") { fabric.Rect.fromObject(this.serializedSelectionObject, (rect) => { if (rect) { @@ -794,30 +759,24 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { } }); } else if (objectType === "ellipse" || objectType === "circle") { - fabric.Ellipse.fromObject( - this.serializedSelectionObject, - (ellipse) => { - if (ellipse) { - console.log("椭圆选区对象反序列化成功"); - resolve(ellipse); - } else { - reject(new Error("椭圆选区对象反序列化失败")); - } + fabric.Ellipse.fromObject(this.serializedSelectionObject, (ellipse) => { + if (ellipse) { + console.log("椭圆选区对象反序列化成功"); + resolve(ellipse); + } else { + reject(new Error("椭圆选区对象反序列化失败")); } - ); + }); } else { // 通用对象反序列化 - fabric.util.enlivenObjects( - [this.serializedSelectionObject], - (objects) => { - if (objects && objects.length > 0) { - console.log("通用选区对象反序列化成功"); - resolve(objects[0]); - } else { - reject(new Error("通用选区对象反序列化失败")); - } + fabric.util.enlivenObjects([this.serializedSelectionObject], (objects) => { + if (objects && objects.length > 0) { + console.log("通用选区对象反序列化成功"); + resolve(objects[0]); + } else { + reject(new Error("通用选区对象反序列化失败")); } - ); + }); } }); } catch (error) { diff --git a/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand_old.js b/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand_old.js index 03b38b64..64c0e60d 100644 --- a/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand_old.js +++ b/src/component/Canvas/CanvasEditor/commands/CutSelectionToNewLayerCommand_old.js @@ -1,8 +1,4 @@ -import { - createLayer, - findInChildLayers, - LayerType, -} from "../utils/layerHelper.js"; +import { createLayer, findInChildLayers, LayerType } from "../utils/layerHelper.js"; import { createRasterizedImage } from "../utils/selectionToImage.js"; import { CompositeCommand, Command } from "./Command.js"; import { CreateImageLayerCommand } from "./LayerCommands.js"; @@ -59,9 +55,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { const selectionObject = this.selectionManager.getSelectionObject(); if (selectionObject) { try { - this._clonedSelectionObject = await this._cloneObject( - selectionObject - ); + this._clonedSelectionObject = await this._cloneObject(selectionObject); console.log("剪切选区:选区对象已克隆保存"); } catch (error) { console.error("剪切选区:克隆选区对象失败:", error); @@ -132,11 +126,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { } // 步骤2: 对原图层进行栅格化处理,移除选区内容 - await this._rasterizeOriginalLayerWithCutout( - sourceLayer, - sourceObjects, - selectionObject - ); + await this._rasterizeOriginalLayerWithCutout(sourceLayer, sourceObjects, selectionObject); // 步骤3: 创建图像图层命令 const createImageLayerCmd = new CreateImageLayerCommand({ @@ -246,10 +236,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } } catch (error) { - console.error( - `❌ 子命令撤销失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error); // 子命令撤销失败不中断整个撤销过程 } } @@ -313,17 +300,14 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { await this._restoreObjectsFromBackup(sourceLayer); } else { // 备用方案:恢复原始的fabricObjects数组 - sourceLayer.fabricObjects = - this.originalLayerBackup.fabricObjects || []; + sourceLayer.fabricObjects = this.originalLayerBackup.fabricObjects || []; if (sourceLayer.fabricObjects.length > 0) { await this._restoreLayerObjects(sourceLayer); } } - console.log( - `✅ 原图层状态恢复完成,恢复了 ${sourceLayer.fabricObjects.length} 个对象` - ); + console.log(`✅ 原图层状态恢复完成,恢复了 ${sourceLayer.fabricObjects.length} 个对象`); } catch (error) { console.error("恢复原图层状态失败:", error); throw error; @@ -337,78 +321,68 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { */ async _restoreObjectsFromBackup(layer) { return new Promise((resolve, reject) => { - if ( - !this.originalLayerObjectsData || - this.originalLayerObjectsData.length === 0 - ) { + if (!this.originalLayerObjectsData || this.originalLayerObjectsData.length === 0) { console.warn("没有对象备份数据"); resolve(); return; } try { - console.log( - `开始从备份恢复 ${this.originalLayerObjectsData.length} 个对象...` - ); + console.log(`开始从备份恢复 ${this.originalLayerObjectsData.length} 个对象...`); // 使用fabric.util.enlivenObjects重建对象 - fabric.util.enlivenObjects( - this.originalLayerObjectsData, - (restoredObjects) => { - try { - let successCount = 0; + fabric.util.enlivenObjects(this.originalLayerObjectsData, (restoredObjects) => { + try { + let successCount = 0; - restoredObjects.forEach((obj, index) => { - if (obj) { - // 确保对象有正确的属性 - obj.set({ - layerId: layer.id, - layerName: layer.name, - selectable: true, - evented: true, - visible: true, - }); + restoredObjects.forEach((obj, index) => { + if (obj) { + // 确保对象有正确的属性 + obj.set({ + layerId: layer.id, + layerName: layer.name, + selectable: true, + evented: true, + visible: true, + }); - // 添加到画布 - this.canvas.add(obj); + // 添加到画布 + this.canvas.add(obj); - // 添加到图层的fabricObjects数组 - layer.fabricObjects.push( - obj.toObject([ - "id", - "layerId", - "layerName", - "parentId", - "selectable", - "evented", - "visible", - ]) - ); + // 添加到图层的fabricObjects数组 + layer.fabricObjects.push( + obj.toObject([ + "id", + "layerId", + "layerName", + "parentId", + "selectable", + "evented", + "visible", + ]) + ); - successCount++; - console.log( - `恢复对象 ${index + 1}/${restoredObjects.length}: ${ - obj.id || obj.type - }` - ); - } else { - console.warn(`对象 ${index + 1} 恢复失败`); - } - }); + successCount++; + console.log( + `恢复对象 ${index + 1}/${restoredObjects.length}: ${obj.id || obj.type}` + ); + } else { + console.warn(`对象 ${index + 1} 恢复失败`); + } + }); - // 重新渲染画布 - this.canvas.renderAll(); + // 重新渲染画布 + this.canvas.renderAll(); - console.log( - `✅ 成功恢复了 ${successCount}/${this.originalLayerObjectsData.length} 个对象` - ); - resolve(); - } catch (error) { - console.error("处理恢复的对象时出错:", error); - reject(error); - } + console.log( + `✅ 成功恢复了 ${successCount}/${this.originalLayerObjectsData.length} 个对象` + ); + resolve(); + } catch (error) { + console.error("处理恢复的对象时出错:", error); + reject(error); } - ); + }); } catch (error) { console.error("恢复对象时出错:", error); reject(error); @@ -474,11 +448,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { * @returns {fabric.Image} 抠图结果的fabric图像对象 * @private */ - async _performCutoutWithRasterized( - sourceObjects, - selectionObject, - selectionBounds - ) { + async _performCutoutWithRasterized(sourceObjects, selectionObject, selectionBounds) { try { console.log("=== 开始使用createRasterizedImage执行剪切抠图 ==="); console.log(`源对象数量: ${sourceObjects.length}`); @@ -488,10 +458,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { let scaleFactor = this.baseResolutionScale; if (this.highResolutionEnabled) { const currentZoom = this.canvas.getZoom?.() || 1; - scaleFactor = Math.max( - scaleFactor || this.canvas?.getRetinaScaling?.(), - currentZoom - ); + scaleFactor = Math.max(scaleFactor || this.canvas?.getRetinaScaling?.(), currentZoom); scaleFactor = Math.min(scaleFactor, 3); } @@ -535,15 +502,10 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { // 递归获取图层及其子图层的所有对象 const collectLayerObjects = (currentLayer) => { // 处理图层的fabricObjects - if ( - currentLayer.fabricObjects && - Array.isArray(currentLayer.fabricObjects) - ) { + if (currentLayer.fabricObjects && Array.isArray(currentLayer.fabricObjects)) { currentLayer.fabricObjects.forEach((fabricObj) => { if (fabricObj && fabricObj.id) { - const realObject = canvasObjects.find( - (canvasObj) => canvasObj.id === fabricObj.id - ); + const realObject = canvasObjects.find((canvasObj) => canvasObj.id === fabricObj.id); if (realObject && realObject.visible !== false) { objects.push(realObject); } @@ -649,17 +611,14 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { } }); } else if (objectType === "polygon") { - fabric.Polygon.fromObject( - this.serializedSelectionObject, - (polygon) => { - if (polygon) { - console.log("多边形选区对象反序列化成功"); - resolve(polygon); - } else { - reject(new Error("多边形选区对象反序列化失败")); - } + fabric.Polygon.fromObject(this.serializedSelectionObject, (polygon) => { + if (polygon) { + console.log("多边形选区对象反序列化成功"); + resolve(polygon); + } else { + reject(new Error("多边形选区对象反序列化失败")); } - ); + }); } else if (objectType === "rect") { fabric.Rect.fromObject(this.serializedSelectionObject, (rect) => { if (rect) { @@ -670,30 +629,24 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { } }); } else if (objectType === "ellipse" || objectType === "circle") { - fabric.Ellipse.fromObject( - this.serializedSelectionObject, - (ellipse) => { - if (ellipse) { - console.log("椭圆选区对象反序列化成功"); - resolve(ellipse); - } else { - reject(new Error("椭圆选区对象反序列化失败")); - } + fabric.Ellipse.fromObject(this.serializedSelectionObject, (ellipse) => { + if (ellipse) { + console.log("椭圆选区对象反序列化成功"); + resolve(ellipse); + } else { + reject(new Error("椭圆选区对象反序列化失败")); } - ); + }); } else { // 通用对象反序列化 - fabric.util.enlivenObjects( - [this.serializedSelectionObject], - (objects) => { - if (objects && objects.length > 0) { - console.log("通用选区对象反序列化成功"); - resolve(objects[0]); - } else { - reject(new Error("通用选区对象反序列化失败")); - } + fabric.util.enlivenObjects([this.serializedSelectionObject], (objects) => { + if (objects && objects.length > 0) { + console.log("通用选区对象反序列化成功"); + resolve(objects[0]); + } else { + reject(new Error("通用选区对象反序列化失败")); } - ); + }); } }); } catch (error) { @@ -761,9 +714,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { this.originalLayerRasterized = false; // 标记原图层是否已栅格化 - console.log( - `✅ 原图层状态已备份,对象数量: ${this.originalLayerObjectsData.length}` - ); + console.log(`✅ 原图层状态已备份,对象数量: ${this.originalLayerObjectsData.length}`); } catch (error) { console.error("备份原图层状态失败:", error); throw error; @@ -777,11 +728,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand { * @param {Object} selectionObject 选区对象 * @private */ - async _rasterizeOriginalLayerWithCutout( - sourceLayer, - sourceObjects, - selectionObject - ) { + async _rasterizeOriginalLayerWithCutout(sourceLayer, sourceObjects, selectionObject) { try { console.log("=== 开始对原图层进行栅格化处理,移除选区内容 ==="); diff --git a/src/component/Canvas/CanvasEditor/commands/EraserCommand.js b/src/component/Canvas/CanvasEditor/commands/EraserCommand.js index 7c746adf..e82e46c7 100644 --- a/src/component/Canvas/CanvasEditor/commands/EraserCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/EraserCommand.js @@ -92,9 +92,6 @@ export class EraserCommand extends Command { if (!this.layerManager) return; const canvasObjects = this.canvas.getObjects(); - restoreObjectLayerAssociations( - this.layerManager?.layers?.value, - canvasObjects - ); + restoreObjectLayerAssociations(this.layerManager?.layers?.value, canvasObjects); } } diff --git a/src/component/Canvas/CanvasEditor/commands/GroupCommands.js b/src/component/Canvas/CanvasEditor/commands/GroupCommands.js index c9762d09..a6e3794f 100644 --- a/src/component/Canvas/CanvasEditor/commands/GroupCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/GroupCommands.js @@ -1,10 +1,5 @@ import { generateId } from "../utils/helper"; -import { - createLayer, - findLayerRecursively, - LayerType, - OperationType, -} from "../utils/layerHelper"; +import { createLayer, findLayerRecursively, LayerType, OperationType } from "../utils/layerHelper"; import { Command } from "./Command"; import { findObjectById, @@ -33,14 +28,12 @@ export class MergeGroupLayerCommand extends Command { this.originalObjects = [...this.canvas.getObjects()]; this.flattenedLayer = null; this.flattenedLayerId = - generateId("flattened_") || - `flattened_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + generateId("flattened_") || `flattened_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.existingGroupId = null; // 用于查找现有组对象 // 组对象相关 this.newGroupId = - generateId("group") || - `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + generateId("group") || `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } async execute() { @@ -172,15 +165,11 @@ export class MergeGroupLayerCommand extends Command { }); // 获取源图层在数组中的索引 - const sourceIndex = this.layers.value.findIndex( - (l) => l.id === this.layerId - ); + const sourceIndex = this.layers.value.findIndex((l) => l.id === this.layerId); // 移除所有相关图层 const layerIdsToRemove = layersToFlatten.map((layer) => layer.id); - this.layers.value = this.layers.value.filter( - (layer) => !layerIdsToRemove.includes(layer.id) - ); + this.layers.value = this.layers.value.filter((layer) => !layerIdsToRemove.includes(layer.id)); // 在原位置插入展平后的图层 this.layers.value.splice(sourceIndex, 0, this.flattenedLayer); @@ -202,11 +191,7 @@ export class MergeGroupLayerCommand extends Command { } async undo() { - if ( - !this.flattenedLayer || - !this.originalLayers || - !this.originalObjectStates - ) { + if (!this.flattenedLayer || !this.originalLayers || !this.originalObjectStates) { console.warn("没有可撤销的数据"); return; } @@ -324,10 +309,7 @@ export class MergeGroupLayerCommand extends Command { groupObjects.forEach((obj) => { try { // 计算对象的绝对位置 - const absolutePosition = this._calculateObjectAbsolutePosition( - obj, - groupObject - ); + const absolutePosition = this._calculateObjectAbsolutePosition(obj, groupObject); // 使用removeWithUpdate移除对象,这会自动恢复对象的独立状态 groupObject.removeWithUpdate(obj); @@ -382,10 +364,7 @@ export class MergeGroupLayerCommand extends Command { const objectPoint = new fabric.Point(obj.left || 0, obj.top || 0); // 应用组的变换矩阵计算绝对位置 - const absolutePoint = fabric.util.transformPoint( - objectPoint, - groupTransform - ); + const absolutePoint = fabric.util.transformPoint(objectPoint, groupTransform); // 计算缩放比例 const totalScaleX = (group.scaleX || 1) * (obj.scaleX || 1); @@ -483,9 +462,7 @@ export class MergeGroupLayerCommand extends Command { canvasObj.layerId = layer.id; canvasObj.layerName = layer.name; - console.log( - `🔗 恢复对象 ${canvasObj.id} 与图层 ${layer.name} 的关联` - ); + console.log(`🔗 恢复对象 ${canvasObj.id} 与图层 ${layer.name} 的关联`); } } }); diff --git a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js index 09973b71..1921d41d 100644 --- a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js +++ b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.bak.js @@ -1,14 +1,7 @@ -import { - createLayer, - findInChildLayers, - LayerType, -} from "../utils/layerHelper.js"; +import { createLayer, findInChildLayers, LayerType } from "../utils/layerHelper.js"; import { createRasterizedImage } from "../utils/selectionToImage.js"; import { CompositeCommand, Command } from "./Command.js"; -import { - CreateImageLayerCommand, - RemoveLayerCommand, -} from "./LayerCommands.js"; +import { CreateImageLayerCommand, RemoveLayerCommand } from "./LayerCommands.js"; import { fabric } from "fabric-with-all"; import { generateId } from "../utils/helper.js"; @@ -65,9 +58,7 @@ export class LassoCutoutCommand extends CompositeCommand { const selectionObject = this.selectionManager.getSelectionObject(); if (selectionObject) { try { - this._clonedSelectionObject = await this._cloneObject( - selectionObject - ); + this._clonedSelectionObject = await this._cloneObject(selectionObject); console.log("套索抠图:选区对象已克隆保存"); } catch (error) { console.error("套索抠图:克隆选区对象失败:", error); @@ -103,14 +94,7 @@ export class LassoCutoutCommand extends CompositeCommand { const sourceObjects = this._getLayerObjects(activeLayer); this.originalCanvasObjects = sourceObjects; // 保存真实对象引用 this.originalFabricObjects = sourceObjects.map((obj) => - obj.toObject([ - "id", - "layerId", - "layerName", - "parentId", - "type", - "custom", - ]) + obj.toObject(["id", "layerId", "layerName", "parentId", "type", "custom"]) ); console.log( @@ -353,10 +337,7 @@ export class LassoCutoutCommand extends CompositeCommand { await command.undo(); console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令撤销失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error); // 子命令撤销失败不中断整个撤销过程 } } @@ -433,16 +414,11 @@ export class LassoCutoutCommand extends CompositeCommand { // 递归获取图层及其子图层的所有对象 const collectLayerObjects = (currentLayer) => { // 处理图层的fabricObjects - if ( - currentLayer.fabricObjects && - Array.isArray(currentLayer.fabricObjects) - ) { + if (currentLayer.fabricObjects && Array.isArray(currentLayer.fabricObjects)) { currentLayer.fabricObjects.forEach((fabricRef) => { if (fabricRef && fabricRef.id) { // 从画布中查找真实的对象 - const realObject = canvasObjects.find( - (obj) => obj.id === fabricRef.id - ); + const realObject = canvasObjects.find((obj) => obj.id === fabricRef.id); if (realObject && realObject.visible) { objects.push(realObject); } @@ -452,9 +428,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 处理单个fabricObject(背景图层等) if (currentLayer.fabricObject && currentLayer.fabricObject.id) { - const realObject = canvasObjects.find( - (obj) => obj.id === currentLayer.fabricObject.id - ); + const realObject = canvasObjects.find((obj) => obj.id === currentLayer.fabricObject.id); if (realObject && realObject.visible) { objects.push(realObject); } @@ -485,11 +459,7 @@ export class LassoCutoutCommand extends CompositeCommand { * @returns {String} 抠图结果的DataURL * @private */ - async _performCutoutWithRasterized( - sourceObjects, - selectionObject, - selectionBounds - ) { + async _performCutoutWithRasterized(sourceObjects, selectionObject, selectionBounds) { try { console.log("=== 开始使用createRasterizedImage执行抠图 ==="); console.log(`源对象数量: ${sourceObjects.length}`); @@ -528,10 +498,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 如果createRasterizedImage失败,回退到原始方法 console.log("⚠️ 回退到原始抠图方法..."); - return await this._performCutout( - { fabricObjects: sourceObjects }, - selectionObject - ); + return await this._performCutout({ fabricObjects: sourceObjects }, selectionObject); } } @@ -562,9 +529,7 @@ export class LassoCutoutCommand extends CompositeCommand { try { // 收集源图层中的可见对象 - const visibleObjects = sourceLayer.fabricObjects.filter( - (obj) => obj.visible - ); + const visibleObjects = sourceLayer.fabricObjects.filter((obj) => obj.visible); if (visibleObjects.length === 0) { throw new Error("源图层没有可见对象"); @@ -617,10 +582,7 @@ export class LassoCutoutCommand extends CompositeCommand { let highResolutionScale = 1; if (this.highResolutionEnabled) { const devicePixelRatio = window.devicePixelRatio || 1; - highResolutionScale = Math.max( - this.baseResolutionScale, - devicePixelRatio * 2 - ); + highResolutionScale = Math.max(this.baseResolutionScale, devicePixelRatio * 2); } // 创建用于导出的高分辨率canvas @@ -631,12 +593,8 @@ export class LassoCutoutCommand extends CompositeCommand { colorSpace: "srgb", }); - const actualWidth = Math.round( - renderBounds.width * highResolutionScale - ); - const actualHeight = Math.round( - renderBounds.height * highResolutionScale - ); + const actualWidth = Math.round(renderBounds.width * highResolutionScale); + const actualHeight = Math.round(renderBounds.height * highResolutionScale); exportCanvas.width = actualWidth; exportCanvas.height = actualHeight; @@ -845,17 +803,14 @@ export class LassoCutoutCommand extends CompositeCommand { } }); } else if (objectType === "polygon") { - fabric.Polygon.fromObject( - this.serializedSelectionObject, - (polygon) => { - if (polygon) { - console.log("多边形选区对象反序列化成功"); - resolve(polygon); - } else { - reject(new Error("多边形选区对象反序列化失败")); - } + fabric.Polygon.fromObject(this.serializedSelectionObject, (polygon) => { + if (polygon) { + console.log("多边形选区对象反序列化成功"); + resolve(polygon); + } else { + reject(new Error("多边形选区对象反序列化失败")); } - ); + }); } else if (objectType === "rect") { fabric.Rect.fromObject(this.serializedSelectionObject, (rect) => { if (rect) { @@ -866,30 +821,24 @@ export class LassoCutoutCommand extends CompositeCommand { } }); } else if (objectType === "ellipse" || objectType === "circle") { - fabric.Ellipse.fromObject( - this.serializedSelectionObject, - (ellipse) => { - if (ellipse) { - console.log("椭圆选区对象反序列化成功"); - resolve(ellipse); - } else { - reject(new Error("椭圆选区对象反序列化失败")); - } + fabric.Ellipse.fromObject(this.serializedSelectionObject, (ellipse) => { + if (ellipse) { + console.log("椭圆选区对象反序列化成功"); + resolve(ellipse); + } else { + reject(new Error("椭圆选区对象反序列化失败")); } - ); + }); } else { // 通用对象反序列化 - fabric.util.enlivenObjects( - [this.serializedSelectionObject], - (objects) => { - if (objects && objects.length > 0) { - console.log("通用选区对象反序列化成功"); - resolve(objects[0]); - } else { - reject(new Error("通用选区对象反序列化失败")); - } + fabric.util.enlivenObjects([this.serializedSelectionObject], (objects) => { + if (objects && objects.length > 0) { + console.log("通用选区对象反序列化成功"); + resolve(objects[0]); + } else { + reject(new Error("通用选区对象反序列化失败")); } - ); + }); } }); } catch (error) { @@ -913,11 +862,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 1. 恢复图层到原位置 if (this.originalLayerIndex !== -1) { - this.layerManager.layers.value.splice( - this.originalLayerIndex, - 0, - this.originalLayer - ); + this.layerManager.layers.value.splice(this.originalLayerIndex, 0, this.originalLayer); } else { // 如果没有保存索引,添加到末尾 this.layerManager.layers.value.push(this.originalLayer); @@ -925,9 +870,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 2. 恢复fabric对象到画布 if (this.originalFabricObjects.length > 0) { - console.log( - `↩️ 恢复 ${this.originalFabricObjects.length} 个fabric对象` - ); + console.log(`↩️ 恢复 ${this.originalFabricObjects.length} 个fabric对象`); // 使用fabric.util.enlivenObjects批量反序列化对象 await new Promise((resolve, reject) => { @@ -1076,12 +1019,7 @@ export class ClearSelectionCommand extends Command { // 序列化选区对象和相关状态 this.originalSelectionState = { // 选区对象的序列化数据 - selectionObjectData: selectionObject.toObject([ - "id", - "layerId", - "layerName", - "parentId", - ]), + selectionObjectData: selectionObject.toObject(["id", "layerId", "layerName", "parentId"]), // 选区路径数据 selectionPath: this.selectionManager.getSelectionPath(), // 羽化值 @@ -1144,13 +1082,8 @@ export class ClearSelectionCommand extends Command { return; } - const { - selectionObjectData, - featherAmount, - selectionStyle, - position, - managerState, - } = this.originalSelectionState; + const { selectionObjectData, featherAmount, selectionStyle, position, managerState } = + this.originalSelectionState; // 根据选区对象类型进行反序列化 const objectType = selectionObjectData.type; @@ -1196,9 +1129,7 @@ export class ClearSelectionCommand extends Command { // 恢复阴影(羽化效果) if (selectionStyle.shadow) { - restoredObject.shadow = new fabric.Shadow( - selectionStyle.shadow - ); + restoredObject.shadow = new fabric.Shadow(selectionStyle.shadow); } } @@ -1283,9 +1214,7 @@ export class ClearSelectionCommand extends Command { // 验证基本属性 const originalId = this.originalSelectionState.selectionId; if (currentSelection.id !== originalId) { - console.warn( - `选区ID不匹配: 期望 ${originalId}, 实际 ${currentSelection.id}` - ); + console.warn(`选区ID不匹配: 期望 ${originalId}, 实际 ${currentSelection.id}`); return false; } @@ -1293,9 +1222,7 @@ export class ClearSelectionCommand extends Command { const currentFeather = this.selectionManager.getFeatherAmount(); const originalFeather = this.originalSelectionState.featherAmount; if (currentFeather !== originalFeather) { - console.warn( - `羽化值不匹配: 期望 ${originalFeather}, 实际 ${currentFeather}` - ); + console.warn(`羽化值不匹配: 期望 ${originalFeather}, 实际 ${currentFeather}`); return false; } diff --git a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js index b7702422..e79b69df 100644 --- a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js @@ -1,15 +1,7 @@ -import { - createLayer, - findInChildLayers, - LayerType, - OperationType, -} from "../utils/layerHelper.js"; +import { createLayer, findInChildLayers, LayerType, OperationType } from "../utils/layerHelper.js"; import { createRasterizedImage } from "../utils/selectionToImage.js"; import { CompositeCommand, Command } from "./Command.js"; -import { - CreateImageLayerCommand, - RemoveLayerCommand, -} from "./LayerCommands.js"; +import { CreateImageLayerCommand, RemoveLayerCommand } from "./LayerCommands.js"; import { fabric } from "fabric-with-all"; import { generateId } from "../utils/helper.js"; import { ToolCommand } from "./ToolCommands.js"; @@ -69,9 +61,7 @@ export class LassoCutoutCommand extends CompositeCommand { const selectionObject = this.selectionManager.getSelectionObject(); if (selectionObject) { try { - this._clonedSelectionObject = await this._cloneObject( - selectionObject - ); + this._clonedSelectionObject = await this._cloneObject(selectionObject); console.log("套索抠图:选区对象已克隆保存"); } catch (error) { console.error("套索抠图:克隆选区对象失败:", error); @@ -107,14 +97,7 @@ export class LassoCutoutCommand extends CompositeCommand { const sourceObjects = this._getLayerObjects(activeLayer); this.originalCanvasObjects = sourceObjects; // 保存真实对象引用 this.originalFabricObjects = sourceObjects.map((obj) => - obj.toObject([ - "id", - "layerId", - "layerName", - "parentId", - "type", - "custom", - ]) + obj.toObject(["id", "layerId", "layerName", "parentId", "type", "custom"]) ); console.log( @@ -385,10 +368,7 @@ export class LassoCutoutCommand extends CompositeCommand { await command.undo(); console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令撤销失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error); // 子命令撤销失败不中断整个撤销过程 } } @@ -465,16 +445,11 @@ export class LassoCutoutCommand extends CompositeCommand { // 递归获取图层及其子图层的所有对象 const collectLayerObjects = (currentLayer) => { // 处理图层的fabricObjects - if ( - currentLayer.fabricObjects && - Array.isArray(currentLayer.fabricObjects) - ) { + if (currentLayer.fabricObjects && Array.isArray(currentLayer.fabricObjects)) { currentLayer.fabricObjects.forEach((fabricRef) => { if (fabricRef && fabricRef.id) { // 从画布中查找真实的对象 - const realObject = canvasObjects.find( - (obj) => obj.id === fabricRef.id - ); + const realObject = canvasObjects.find((obj) => obj.id === fabricRef.id); if (realObject && realObject.visible) { objects.push(realObject); } @@ -484,9 +459,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 处理单个fabricObject(背景图层等) if (currentLayer.fabricObject && currentLayer.fabricObject.id) { - const realObject = canvasObjects.find( - (obj) => obj.id === currentLayer.fabricObject.id - ); + const realObject = canvasObjects.find((obj) => obj.id === currentLayer.fabricObject.id); if (realObject && realObject.visible) { objects.push(realObject); } @@ -517,11 +490,7 @@ export class LassoCutoutCommand extends CompositeCommand { * @returns {String} 抠图结果的DataURL * @private */ - async _performCutoutWithRasterized( - sourceObjects, - selectionObject, - selectionBounds - ) { + async _performCutoutWithRasterized(sourceObjects, selectionObject, selectionBounds) { try { console.log("=== 开始使用createRasterizedImage执行抠图 ==="); console.log(`源对象数量: ${sourceObjects.length}`); @@ -560,10 +529,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 如果createRasterizedImage失败,回退到原始方法 console.log("⚠️ 回退到原始抠图方法..."); - return await this._performCutout( - { fabricObjects: sourceObjects }, - selectionObject - ); + return await this._performCutout({ fabricObjects: sourceObjects }, selectionObject); } } @@ -594,9 +560,7 @@ export class LassoCutoutCommand extends CompositeCommand { try { // 收集源图层中的可见对象 - const visibleObjects = sourceLayer.fabricObjects.filter( - (obj) => obj.visible - ); + const visibleObjects = sourceLayer.fabricObjects.filter((obj) => obj.visible); if (visibleObjects.length === 0) { throw new Error("源图层没有可见对象"); @@ -649,10 +613,7 @@ export class LassoCutoutCommand extends CompositeCommand { let highResolutionScale = 1; if (this.highResolutionEnabled) { const devicePixelRatio = window.devicePixelRatio || 1; - highResolutionScale = Math.max( - this.baseResolutionScale, - devicePixelRatio * 2 - ); + highResolutionScale = Math.max(this.baseResolutionScale, devicePixelRatio * 2); } // 创建用于导出的高分辨率canvas @@ -663,12 +624,8 @@ export class LassoCutoutCommand extends CompositeCommand { colorSpace: "srgb", }); - const actualWidth = Math.round( - renderBounds.width * highResolutionScale - ); - const actualHeight = Math.round( - renderBounds.height * highResolutionScale - ); + const actualWidth = Math.round(renderBounds.width * highResolutionScale); + const actualHeight = Math.round(renderBounds.height * highResolutionScale); exportCanvas.width = actualWidth; exportCanvas.height = actualHeight; @@ -877,17 +834,14 @@ export class LassoCutoutCommand extends CompositeCommand { } }); } else if (objectType === "polygon") { - fabric.Polygon.fromObject( - this.serializedSelectionObject, - (polygon) => { - if (polygon) { - console.log("多边形选区对象反序列化成功"); - resolve(polygon); - } else { - reject(new Error("多边形选区对象反序列化失败")); - } + fabric.Polygon.fromObject(this.serializedSelectionObject, (polygon) => { + if (polygon) { + console.log("多边形选区对象反序列化成功"); + resolve(polygon); + } else { + reject(new Error("多边形选区对象反序列化失败")); } - ); + }); } else if (objectType === "rect") { fabric.Rect.fromObject(this.serializedSelectionObject, (rect) => { if (rect) { @@ -898,30 +852,24 @@ export class LassoCutoutCommand extends CompositeCommand { } }); } else if (objectType === "ellipse" || objectType === "circle") { - fabric.Ellipse.fromObject( - this.serializedSelectionObject, - (ellipse) => { - if (ellipse) { - console.log("椭圆选区对象反序列化成功"); - resolve(ellipse); - } else { - reject(new Error("椭圆选区对象反序列化失败")); - } + fabric.Ellipse.fromObject(this.serializedSelectionObject, (ellipse) => { + if (ellipse) { + console.log("椭圆选区对象反序列化成功"); + resolve(ellipse); + } else { + reject(new Error("椭圆选区对象反序列化失败")); } - ); + }); } else { // 通用对象反序列化 - fabric.util.enlivenObjects( - [this.serializedSelectionObject], - (objects) => { - if (objects && objects.length > 0) { - console.log("通用选区对象反序列化成功"); - resolve(objects[0]); - } else { - reject(new Error("通用选区对象反序列化失败")); - } + fabric.util.enlivenObjects([this.serializedSelectionObject], (objects) => { + if (objects && objects.length > 0) { + console.log("通用选区对象反序列化成功"); + resolve(objects[0]); + } else { + reject(new Error("通用选区对象反序列化失败")); } - ); + }); } }); } catch (error) { @@ -945,11 +893,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 1. 恢复图层到原位置 if (this.originalLayerIndex !== -1) { - this.layerManager.layers.value.splice( - this.originalLayerIndex, - 0, - this.originalLayer - ); + this.layerManager.layers.value.splice(this.originalLayerIndex, 0, this.originalLayer); } else { // 如果没有保存索引,添加到末尾 this.layerManager.layers.value.push(this.originalLayer); @@ -957,9 +901,7 @@ export class LassoCutoutCommand extends CompositeCommand { // 2. 恢复fabric对象到画布 if (this.originalFabricObjects.length > 0) { - console.log( - `↩️ 恢复 ${this.originalFabricObjects.length} 个fabric对象` - ); + console.log(`↩️ 恢复 ${this.originalFabricObjects.length} 个fabric对象`); // 使用fabric.util.enlivenObjects批量反序列化对象 await new Promise((resolve, reject) => { @@ -1108,12 +1050,7 @@ export class ClearSelectionCommand extends Command { // 序列化选区对象和相关状态 this.originalSelectionState = { // 选区对象的序列化数据 - selectionObjectData: selectionObject.toObject([ - "id", - "layerId", - "layerName", - "parentId", - ]), + selectionObjectData: selectionObject.toObject(["id", "layerId", "layerName", "parentId"]), // 选区路径数据 selectionPath: this.selectionManager.getSelectionPath(), // 羽化值 @@ -1176,13 +1113,8 @@ export class ClearSelectionCommand extends Command { return; } - const { - selectionObjectData, - featherAmount, - selectionStyle, - position, - managerState, - } = this.originalSelectionState; + const { selectionObjectData, featherAmount, selectionStyle, position, managerState } = + this.originalSelectionState; // 根据选区对象类型进行反序列化 const objectType = selectionObjectData.type; @@ -1228,9 +1160,7 @@ export class ClearSelectionCommand extends Command { // 恢复阴影(羽化效果) if (selectionStyle.shadow) { - restoredObject.shadow = new fabric.Shadow( - selectionStyle.shadow - ); + restoredObject.shadow = new fabric.Shadow(selectionStyle.shadow); } } @@ -1315,9 +1245,7 @@ export class ClearSelectionCommand extends Command { // 验证基本属性 const originalId = this.originalSelectionState.selectionId; if (currentSelection.id !== originalId) { - console.warn( - `选区ID不匹配: 期望 ${originalId}, 实际 ${currentSelection.id}` - ); + console.warn(`选区ID不匹配: 期望 ${originalId}, 实际 ${currentSelection.id}`); return false; } @@ -1325,9 +1253,7 @@ export class ClearSelectionCommand extends Command { const currentFeather = this.selectionManager.getFeatherAmount(); const originalFeather = this.originalSelectionState.featherAmount; if (currentFeather !== originalFeather) { - console.warn( - `羽化值不匹配: 期望 ${originalFeather}, 实际 ${currentFeather}` - ); + console.warn(`羽化值不匹配: 期望 ${originalFeather}, 实际 ${currentFeather}`); return false; } diff --git a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js index 092bbf05..70ab4918 100644 --- a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js @@ -1,16 +1,13 @@ import { Command } from "./Command"; -import { - createLayer, - findLayerRecursively, - LayerType, - OperationType, -} from "../utils/layerHelper"; +import { createLayer, findLayerRecursively, LayerType, OperationType } from "../utils/layerHelper"; import { createStaticCanvas } from "../utils/canvasFactory"; import { AddObjectToLayerCommand } from "./ObjectLayerCommands"; import { ToolCommand } from "./ToolCommands"; import { findObjectById, generateId, + getObjectZIndex, + insertObjectAtZIndex, objectIsInCanvas, optimizeCanvasRendering, removeCanvasObjectByObject, @@ -112,15 +109,11 @@ export class AddLayerCommand extends Command { parentLayer.children = parentLayer.children || []; parentLayer.children.splice(insertIndex, 0, newLayer); - console.log( - `新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})` - ); + console.log(`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`); } else { // 当前激活图层是一级图层 // 在一级图层中,插入到激活图层之上 - const activeLayerIndex = layers.findIndex( - (layer) => layer.id === currentActiveLayerId - ); + const activeLayerIndex = layers.findIndex((layer) => layer.id === currentActiveLayerId); insertIndex = Math.max(0, activeLayerIndex); layers.splice(insertIndex, 0, newLayer); @@ -273,9 +266,7 @@ export class PasteLayerCommand extends Command { try { objects.forEach((obj) => { // 生成新的对象ID - const newObjId = `obj_${Date.now()}_${Math.floor( - Math.random() * 1000 - )}`; + const newObjId = `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`; obj.id = newObjId; obj.layerId = this.newLayerId; obj.layerName = this.newLayer.name; @@ -337,9 +328,7 @@ export class PasteLayerCommand extends Command { if (!this.newLayer || !this.newLayerId) return; // 从图层列表删除该图层 - const index = this.layers.value.findIndex( - (layer) => layer.id === this.newLayerId - ); + const index = this.layers.value.findIndex((layer) => layer.id === this.newLayerId); if (index !== -1) { this.layers.value.splice(index, 1); } @@ -405,9 +394,7 @@ export class RemoveLayerCommand extends Command { this.activeLayerId = options.activeLayerId; // 查找要删除的图层 - this.layerIndex = this.layers.value.findIndex( - (layer) => layer.id === this.layerId - ); + 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; @@ -474,9 +461,7 @@ export class RemoveLayerCommand extends Command { // 如果删除的是当前活动图层,需要更新活动图层 if (this.isActiveLayer) { // 查找最近的非背景层作为新的活动图层 - const newActiveLayer = this.layers.value.find( - (layer) => !layer.isBackground - ); + const newActiveLayer = this.layers.value.find((layer) => !layer.isBackground); if (newActiveLayer) { this.activeLayerId.value = newActiveLayer.id; } else { @@ -554,30 +539,22 @@ export class MoveLayerCommand 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; this.originalIndex = this.layerIndex; // 目标位置 - this.targetIndex = - options.direction === "up" ? this.layerIndex - 1 : this.layerIndex + 1; + this.targetIndex = options.direction === "up" ? this.layerIndex - 1 : this.layerIndex + 1; } async execute() { @@ -668,9 +645,7 @@ export class ToggleLayerVisibilityCommand extends Command { // 更新画布上图层对象的可见性 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.visible = this.layer.visible; }); @@ -711,10 +686,7 @@ export class ToggleChildLayerVisibilityCommand extends Command { this.layerManager = options.layerManager; // 查找父图层和子图层 - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); this.parentLayer = parent; this.childLayer = layer; @@ -731,9 +703,7 @@ export class ToggleChildLayerVisibilityCommand extends Command { // 更新画布上图层对象的可见性 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.visible = this.childLayer.visible; @@ -792,9 +762,7 @@ export class RenameLayerCommand extends Command { // 更新图层对象上的图层名称 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.layerName = this.newName; @@ -811,9 +779,7 @@ export class RenameLayerCommand extends Command { // 恢复图层对象上的图层名称 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.layerName = this.oldName; @@ -848,10 +814,7 @@ export class LayerLockCommand extends Command { // 查找图层(包括子图层) // 查找图层 - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.parentLayer = parent || null; // 父图层 this.oldLocked = this.layer ? this.layer.locked : null; @@ -869,11 +832,7 @@ export class LayerLockCommand extends Command { layer.locked = locked; // 如果是组图层,递归更新所有子图层 - if ( - layer.type === "group" && - layer.children && - Array.isArray(layer.children) - ) { + if (layer.type === "group" && layer.children && Array.isArray(layer.children)) { layer.children.forEach((child) => { this._updateLayerLockState(child, locked); }); @@ -895,11 +854,7 @@ export class LayerLockCommand extends Command { // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); - console.log( - `${newLocked ? "锁定" : "解锁"}图层: ${this.layer.name} (ID: ${ - this.layerId - })` - ); + console.log(`${newLocked ? "锁定" : "解锁"}图层: ${this.layer.name} (ID: ${this.layerId})`); return true; } @@ -911,9 +866,7 @@ export class LayerLockCommand extends Command { // 更新画布上对象的可选择状态 await this.layerManager?.updateLayersObjectsInteractivity(); - console.log( - `恢复图层锁定状态: ${this.layer.name} (锁定: ${this.oldLocked})` - ); + console.log(`恢复图层锁定状态: ${this.layer.name} (锁定: ${this.oldLocked})`); } } @@ -961,9 +914,7 @@ export class SetLayerOpacityCommand extends Command { // 更新画布上对象的不透明度 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.opacity = this.opacity; @@ -982,9 +933,7 @@ export class SetLayerOpacityCommand extends Command { // 更新画布上对象的不透明度 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.opacity = this.oldOpacity; @@ -1038,9 +987,7 @@ export class SetLayerBlendModeCommand extends Command { // 更新画布上对象的混合模式 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.globalCompositeOperation = this.blendMode; @@ -1059,9 +1006,7 @@ export class SetLayerBlendModeCommand extends Command { // 更新画布上对象的混合模式 if (this.canvas) { - const layerObjects = this.canvas - .getObjects() - .filter((obj) => obj.layerId === this.layerId); + const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId); layerObjects.forEach((obj) => { obj.globalCompositeOperation = this.oldBlendMode; @@ -1101,17 +1046,11 @@ export class MergeLayersCommand extends Command { // 备份原图层 this.originalLayers = [...this.layers.value]; // 新图层ID - this.newLayerId = `merged_layer_${Date.now()}_${Math.floor( - Math.random() * 1000 - )}`; + this.newLayerId = `merged_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } execute() { - if ( - !this.layerIds || - !Array.isArray(this.layerIds) || - this.layerIds.length < 2 - ) { + if (!this.layerIds || !Array.isArray(this.layerIds) || this.layerIds.length < 2) { console.error("合并图层至少需要两个图层"); return null; } @@ -1132,6 +1071,14 @@ export class MergeLayersCommand extends Command { 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) @@ -1164,9 +1111,7 @@ export class MergeLayersCommand extends Command { }); // 移除原图层 - this.layers.value = this.layers.value.filter( - (layer) => !this.layerIds.includes(layer.id) - ); + this.layers.value = this.layers.value.filter((layer) => !this.layerIds.includes(layer.id)); // 插入新图层 this.layers.value.splice(topLayerIndex, 0, mergedLayer); @@ -1227,18 +1172,13 @@ export class GroupLayersCommand extends Command { this.originalLayers = [...this.layers.value]; // 新组ID this.groupId = - generateId("group_layer_") || - `group_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + 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 - ) { + if (!this.layerIds || !Array.isArray(this.layerIds) || this.layerIds.length < 2) { console.error("组合图层至少需要两个图层"); return null; } @@ -1282,9 +1222,7 @@ export class GroupLayersCommand extends Command { }); // 移除原图层 - this.layers.value = this.layers.value.filter( - (layer) => !this.layerIds.includes(layer.id) - ); + this.layers.value = this.layers.value.filter((layer) => !this.layerIds.includes(layer.id)); // 插入新组图层 this.layers.value.splice(topLayerIndex, 0, groupLayer); @@ -1338,9 +1276,7 @@ export class UngroupLayersCommand extends Command { async execute() { // 查找组图层 - const groupIndex = this.layers.value.findIndex( - (layer) => layer.id === this.groupId - ); + const groupIndex = this.layers.value.findIndex((layer) => layer.id === this.groupId); if (groupIndex === -1) { console.error(`找不到组图层 ${this.groupId}`); @@ -1361,11 +1297,11 @@ export class UngroupLayersCommand extends Command { this.layers.value.splice( groupIndex, 1, - ...groupLayer.children?.map((child) => { + ...(groupLayer?.children?.map((child) => { // 为子图层添加parentId delete child.parentId; // 删除parentId属性 return { ...child }; - }) + }) || {}) ); // 更新当前活动图层为第一个子图层 if (this.childLayerIds.length > 0 && this.activeLayerId) { @@ -1411,18 +1347,14 @@ export class MergeLayerObjectsCommand extends Command { // 备份原始对象,用于撤销 if (this.activeLayer && Array.isArray(this.activeLayer.fabricObjects)) { this.originalObjects = - this.canvas - ?.getObjects() - ?.filter((fItem) => fItem.layerId === this.activeLayer.id) || []; + 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 - )}`; + this.newImageId = `merged_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } async execute() { @@ -1458,10 +1390,7 @@ export class MergeLayerObjectsCommand extends Command { // 异步处理图像合并 try { - const mergedImage = await this._createMergedImageAsync( - objectsToMerge, - bounds - ); + const mergedImage = await this._createMergedImageAsync(objectsToMerge, bounds); this._setupMergedImage(mergedImage, bounds); this._replaceObjects(mergedImage); @@ -1611,9 +1540,7 @@ export class MergeLayerObjectsCommand extends Command { }); tempCanvas.add(clonedObj); - console.log( - `添加对象 ${index + 1}/${objects.length}: ${obj.type || "unknown"}` - ); + console.log(`添加对象 ${index + 1}/${objects.length}: ${obj.type || "unknown"}`); } catch (error) { console.error(`添加对象到临时画布时发生错误:`, error); } @@ -1672,10 +1599,7 @@ export class MergeLayerObjectsCommand extends Command { }); // 如果有新的图像对象,也要移除 - if ( - this.fabricImage && - this.canvas.getObjects().includes(this.fabricImage) - ) { + if (this.fabricImage && this.canvas.getObjects().includes(this.fabricImage)) { this.canvas.remove(this.fabricImage); } @@ -1691,9 +1615,7 @@ export class MergeLayerObjectsCommand extends Command { // 更新缩略图 if (this.canvas.thumbnailManager) { setTimeout(() => { - this.canvas.thumbnailManager.generateLayerThumbnail( - this.activeLayer.id - ); + this.canvas.thumbnailManager.generateLayerThumbnail(this.activeLayer.id); }, 100); } } @@ -1737,9 +1659,7 @@ export class MergeLayerObjectsCommand extends Command { // 更新缩略图 if (this.canvas.thumbnailManager) { setTimeout(() => { - this.canvas.thumbnailManager.generateLayerThumbnail( - this.activeLayer.id - ); + this.canvas.thumbnailManager.generateLayerThumbnail(this.activeLayer.id); }, 100); } } @@ -1827,8 +1747,7 @@ export class LayerObjectsToGroupCommand extends Command { this.existingGroupId = null; this.groupObjectId = null; this.newGroupId = - generateId("group") || - `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + generateId("group") || `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.wasGroupCreated = false; // 保存原始位置信息 @@ -1889,10 +1808,7 @@ export class LayerObjectsToGroupCommand extends Command { const newObjectsToAdd = []; if (this.fabricImage) { // 如果是重做,恢复新对象的原始位置 - if ( - !this.isFirstExecution && - this.newObjectPositions.has(this.fabricImage.id) - ) { + if (!this.isFirstExecution && this.newObjectPositions.has(this.fabricImage.id)) { const savedPosition = this.newObjectPositions.get(this.fabricImage.id); this.fabricImage.set({ left: savedPosition.left, @@ -1905,9 +1821,7 @@ export class LayerObjectsToGroupCommand extends Command { flipX: savedPosition.flipX, flipY: savedPosition.flipY, }); - console.log( - `🔄 重做时恢复新对象位置: (${savedPosition.left}, ${savedPosition.top})` - ); + console.log(`🔄 重做时恢复新对象位置: (${savedPosition.left}, ${savedPosition.top})`); } newObjectsToAdd.push(this.fabricImage); @@ -1960,9 +1874,7 @@ export class LayerObjectsToGroupCommand extends Command { if (!this.existingGroupId) { const groupObjects = - this.activeLayer.fabricObjects.find( - (obj) => obj && obj.type === "group" - ) || null; + this.activeLayer.fabricObjects.find((obj) => obj && obj.type === "group") || null; this.existingGroupId = groupObjects?.id || null; } @@ -2062,9 +1974,7 @@ export class LayerObjectsToGroupCommand extends Command { // 更新图层的对象列表 // this.activeLayer.fabricObjects = [groupObject]; - this.activeLayer.fabricObjects = [ - groupObject.toObject(["id", "layerId", "layerName"]), - ]; + this.activeLayer.fabricObjects = [groupObject.toObject(["id", "layerId", "layerName"])]; } /** @@ -2150,10 +2060,7 @@ export class LayerObjectsToGroupCommand extends Command { restorePosition = { ...originalPosition }; } else { // 计算对象在画布中的当前绝对位置 - restorePosition = this._calculateObjectAbsolutePosition( - obj, - groupObject - ); + restorePosition = this._calculateObjectAbsolutePosition(obj, groupObject); } objectsToRestore.push({ @@ -2208,9 +2115,7 @@ export class LayerObjectsToGroupCommand extends Command { restoredObjects.push(obj); console.log( - `✅ 恢复原始对象 ${obj.id || obj.type} 到位置 (${position.left}, ${ - position.top - })` + `✅ 恢复原始对象 ${obj.id || obj.type} 到位置 (${position.left}, ${position.top})` ); } catch (error) { console.error(`恢复对象 ${obj.id || obj.type} 时发生错误:`, error); @@ -2270,10 +2175,7 @@ export class LayerObjectsToGroupCommand extends Command { const objectPoint = new fabric.Point(obj.left || 0, obj.top || 0); // 应用组的变换矩阵计算绝对位置 - const absolutePoint = fabric.util.transformPoint( - objectPoint, - groupTransform - ); + const absolutePoint = fabric.util.transformPoint(objectPoint, groupTransform); // 计算缩放比例 const totalScaleX = (group.scaleX || 1) * (obj.scaleX || 1); @@ -2441,8 +2343,7 @@ export class CreateImageLayerCommand extends Command { // 存储执行过程中的结果 this.newLayerId = - generateId("layer_image_") || - `layer_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + generateId("layer_image_") || `layer_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.commands = []; this.executedCommands = []; } @@ -2457,8 +2358,7 @@ export class CreateImageLayerCommand extends Command { this.executedCommands = []; // 生成图层名称 - const fileName = - this.layerName || `图片 ${new Date().toLocaleTimeString()}`; + const fileName = this.layerName || `图片 ${new Date().toLocaleTimeString()}`; this.fabricImage.set({ id: this.imageId, @@ -2529,9 +2429,7 @@ export class CreateImageLayerCommand extends Command { return true; } - console.log( - `↩️ 开始撤销创建图片图层操作,共 ${this.executedCommands.length} 个子命令` - ); + console.log(`↩️ 开始撤销创建图片图层操作,共 ${this.executedCommands.length} 个子命令`); try { // 逆序撤销已执行的命令 @@ -2547,10 +2445,7 @@ export class CreateImageLayerCommand extends Command { } console.log(`✅ 子命令撤销成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令撤销失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error); } } } @@ -2583,10 +2478,7 @@ export class CreateImageLayerCommand extends Command { } console.log(`✅ 子命令回滚成功: ${command.constructor.name}`); } catch (error) { - console.error( - `❌ 子命令回滚失败: ${command.constructor.name}`, - error - ); + console.error(`❌ 子命令回滚失败: ${command.constructor.name}`, error); } } } @@ -2721,9 +2613,7 @@ export class ReorderChildLayersCommand extends Command { async execute() { // 查找父图层 - const parentLayer = this.layers.value.find( - (layer) => layer.id === this.parentId - ); + const parentLayer = this.layers.value.find((layer) => layer.id === this.parentId); if (!parentLayer) return false; // 获取子图层 @@ -2873,15 +2763,11 @@ export class CutLayerCommand extends Command { // 生成新图层ID和名称 this.newLayerId = - generateId("layer_") || - `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + generateId("layer_") || `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } async execute() { - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); const sourceLayer = layer; const parentLayer = parent; @@ -2908,9 +2794,7 @@ export class CutLayerCommand extends Command { blendMode: sourceLayer.blendMode, fabricObjects: [], children: sourceLayer.children ? [...sourceLayer.children] : [], - layerProperties: sourceLayer.layerProperties - ? { ...sourceLayer.layerProperties } - : {}, + layerProperties: sourceLayer.layerProperties ? { ...sourceLayer.layerProperties } : {}, metadata: sourceLayer.metadata ? { ...sourceLayer.metadata } : {}, parentId: parentLayer ? parentLayer.id : undefined, // 保持父图层关系 }); @@ -2920,11 +2804,8 @@ export class CutLayerCommand extends Command { if (parentLayer) { // 处理子图层:在父图层的children数组中插入 - const sourceChildIndex = parentLayer.children.findIndex( - (child) => child.id === this.layerId - ); - insertIndex = - this.insertIndex !== null ? this.insertIndex : sourceChildIndex + 1; + 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); @@ -2933,11 +2814,8 @@ export class CutLayerCommand extends Command { this.childInsertIndex = insertIndex; } else { // 处理主图层:在主图层数组中插入 - const sourceIndex = this.layers.value.findIndex( - (l) => l.id === this.layerId - ); - insertIndex = - this.insertIndex !== null ? this.insertIndex : sourceIndex + 1; + 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); @@ -2956,9 +2834,7 @@ export class CutLayerCommand extends Command { // 重新渲染画布 await this.layerManager?.updateLayersObjectsInteractivity(false); - console.log( - `已复制图层:${newName} ${this.isChildLayer ? "(子图层)" : "(主图层)"}` - ); + console.log(`已复制图层:${newName} ${this.isChildLayer ? "(子图层)" : "(主图层)"}`); return this.newLayerId; } @@ -2975,9 +2851,7 @@ export class CutLayerCommand extends Command { } } else { // 撤销主图层:从主图层数组中删除 - const index = this.layers.value.findIndex( - (l) => l.id === this.newLayerId - ); + const index = this.layers.value.findIndex((l) => l.id === this.newLayerId); if (index !== -1) { this.layers.value.splice(index, 1); } @@ -3007,9 +2881,7 @@ export class CutLayerCommand extends Command { fabric.util.enlivenObjects(serializedObjects, (objects) => { objects.forEach((obj) => { // 生成新的对象ID - const newObjId = `obj_${Date.now()}_${Math.floor( - Math.random() * 1000 - )}`; + const newObjId = `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`; obj.id = newObjId; obj.layerId = this.newLayerId; obj.layerName = this.newLayer.name; @@ -3066,8 +2938,7 @@ export class CreateAdjustmentLayerCommand extends Command { this.newLayer = null; // 生成新图层ID this.newLayerId = - generateId("adj_layer_") || - `adj_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; + generateId("adj_layer_") || `adj_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`; } execute() { @@ -3089,9 +2960,7 @@ export class CreateAdjustmentLayerCommand extends Command { // 计算插入位置 const insertIndex = - this.insertIndex !== null - ? this.insertIndex - : this._getInsertIndexAboveActiveLayer(); + this.insertIndex !== null ? this.insertIndex : this._getInsertIndexAboveActiveLayer(); // 插入新图层 this.layers.value.splice(insertIndex, 0, this.newLayer); @@ -3155,9 +3024,7 @@ export class ApplyLayerStyleCommand extends Command { return; } this.layer = layer; - this.oldStyles = this.layer - ? { ...(this.layer.layerProperties?.styles || {}) } - : {}; + this.oldStyles = this.layer ? { ...(this.layer.layerProperties?.styles || {}) } : {}; } execute() { @@ -3296,9 +3163,7 @@ export class LayerClippingMaskCommand extends Command { if (this.maskLayerId) { // 创建剪贴蒙版 - const maskLayer = this.layers.value.find( - (l) => l.id === this.maskLayerId - ); + const maskLayer = this.layers.value.find((l) => l.id === this.maskLayerId); if (!maskLayer) { console.error(`蒙版图层 ${this.maskLayerId} 不存在`); return false; @@ -3525,19 +3390,14 @@ 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); } } } @@ -3545,9 +3405,7 @@ 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( @@ -3585,15 +3443,9 @@ 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("移除旧对象失败,但继续执行"); } @@ -3650,97 +3502,75 @@ 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, - }); - - // 使用帮助函数在正确的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 - ); + // 设置图层属性 + restoredImage.set({ + id: this.previousObjectId, + layerId: this.targetLayer.id, + layerName: this.targetLayer.name, + isBackground: this.targetLayer.isBackground, + isFixed: this.targetLayer.isFixed, }); - resolve(); - } catch (error) { - reject(error); - } + // 使用帮助函数在正确的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 - ); + 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); @@ -3797,10 +3627,7 @@ export class AddImageToLayerCommand extends Command { this.validateInputs(); // 查找目标图层 - const { layer } = findLayerRecursively( - this.layerManager?.layers?.value || [], - this.layerId - ); + const { layer } = findLayerRecursively(this.layerManager?.layers?.value || [], this.layerId); this.targetLayer = layer; @@ -3859,10 +3686,7 @@ 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; @@ -3925,19 +3749,14 @@ 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); } } } @@ -3945,9 +3764,7 @@ 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( @@ -4057,9 +3874,7 @@ export class RemoveChildLayerCommand extends Command { this.parentLayer = parent; this.childIndex = - this.parentLayer?.children?.findIndex( - (child) => child.id === this.layerId - ) ?? -1; + this.parentLayer?.children?.findIndex((child) => child.id === this.layerId) ?? -1; this.removedChild = this.parentLayer?.children?.[this.childIndex]; this.isActiveLayer = this.layerId === this.activeLayerId.value; @@ -4074,10 +3889,7 @@ export class RemoveChildLayerCommand extends Command { } // 从画布中移除子图层中的所有对象 - if ( - this.removedChild.fabricObjects && - this.removedChild.fabricObjects.length > 0 - ) { + if (this.removedChild.fabricObjects && this.removedChild.fabricObjects.length > 0) { this.removedChild.fabricObjects.forEach((obj) => { const { object } = findObjectById(this.canvas, obj.id); if (object) { @@ -4096,9 +3908,7 @@ export class RemoveChildLayerCommand extends Command { this.activeLayerId.value = this.parentLayer.children[0].id; } else { this.activeLayerId.value = - this.layers.value.find( - (layer) => !layer.isBackground || !layer.isFixed - )?.[0]?.id || null; + this.layers.value.find((layer) => !layer.isBackground || !layer.isFixed)?.[0]?.id || null; } } @@ -4233,10 +4043,7 @@ export class ChildLayerLockCommand extends Command { this.layerManager = options.layerManager; // 查找父图层和子图层 - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); this.parentLayer = parent; this.childLayer = layer; this.oldLocked = this.childLayer ? this.childLayer.locked : null; diff --git a/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js b/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js index e8ede4be..d6106c8b 100644 --- a/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LiquifyCommands.js @@ -21,9 +21,7 @@ export class LiquifyCommand extends Command { constructor(options) { super({ name: options.name || `液化操作: ${options.mode || "未知模式"}`, - description: - options.description || - `使用${options.mode || "未知模式"}模式进行液化操作`, + description: options.description || `使用${options.mode || "未知模式"}模式进行液化操作`, }); this.canvas = options.canvas; @@ -96,9 +94,7 @@ export class LiquifyCommand extends Command { // 对于图像对象,我们需要保存src和元数据 const state = { src: this.targetObject.getSrc ? this.targetObject.getSrc() : null, - element: this.targetObject._element - ? this.targetObject._element.cloneNode(true) - : null, + element: this.targetObject._element ? this.targetObject._element.cloneNode(true) : null, filters: this.targetObject.filters ? [...this.targetObject.filters] : [], originalData: this.originalData, targetLayerId: this.targetLayerId, @@ -172,10 +168,7 @@ export class LiquifyCommand extends Command { // 确保图层引用更新 const layer = this.layerManager.getLayerById(this.targetLayerId); if (layer) { - if ( - layer.type === "background" && - layer.fabricObject === this.targetObject - ) { + if (layer.type === "background" && layer.fabricObject === this.targetObject) { layer.fabricObject = img; } else if (layer.fabricObjects) { const objIndex = layer.fabricObjects.indexOf(this.targetObject); @@ -251,9 +244,7 @@ export class LiquifyDeformCommand extends LiquifyCommand { super({ ...options, name: `液化变形: ${options.mode || "未知模式"}`, - description: `在(${options.x}, ${options.y})应用${ - options.mode || "未知模式" - }变形`, + description: `在(${options.x}, ${options.y})应用${options.mode || "未知模式"}变形`, }); this.x = options.x; @@ -343,9 +334,7 @@ export class LiquifyDeformCommand extends LiquifyCommand { layer.fabricObject = img; } else if (layer.fabricObjects) { const objIndex = layer.fabricObjects.findIndex( - (obj) => - obj === this.savedState?.originalObject || - obj === this.targetObject + (obj) => obj === this.savedState?.originalObject || obj === this.targetObject ); if (objIndex !== -1) { layer.fabricObjects[objIndex] = img; @@ -374,8 +363,7 @@ export class CompositeLiquifyCommand extends Command { constructor(options) { super({ name: options.name || "液化操作组合", - description: - options.description || `包含${options.commands?.length || 0}个液化操作`, + description: options.description || `包含${options.commands?.length || 0}个液化操作`, }); this.commands = options.commands || []; @@ -551,10 +539,7 @@ export class LiquifyStateCommand extends Command { } // 通过引用管理器更新图像数据 - await this.refManager.updateObjectImageData( - this.objectRefId, - this.finalImageData - ); + await this.refManager.updateObjectImageData(this.objectRefId, this.finalImageData); // 恢复液化管理器到最终状态 if (this.liquifyManager && this.finalLiquifyState) { @@ -585,10 +570,7 @@ export class LiquifyStateCommand extends Command { } // 通过引用管理器恢复到初始快照 - await this.refManager.restoreFromSnapshot( - this.objectRefId, - this.initialSnapshotId - ); + await this.refManager.restoreFromSnapshot(this.objectRefId, this.initialSnapshotId); // 恢复液化管理器到初始状态 - 关键修复 if (this.liquifyManager) { @@ -604,18 +586,16 @@ export class LiquifyStateCommand extends Command { // 强制设置原始图像数据为初始状态 if (this.liquifyManager.enhancedManager) { - this.liquifyManager.enhancedManager.originalImageData = - this.initialImageData; - this.liquifyManager.enhancedManager.currentImageData = - this._cloneImageData(this.initialImageData); + this.liquifyManager.enhancedManager.originalImageData = this.initialImageData; + this.liquifyManager.enhancedManager.currentImageData = this._cloneImageData( + this.initialImageData + ); // 重置激活渲染器的数据 if (this.liquifyManager.enhancedManager.activeRenderer) { const renderer = this.liquifyManager.enhancedManager.activeRenderer; renderer.originalImageData = this.initialImageData; - renderer.currentImageData = this._cloneImageData( - this.initialImageData - ); + renderer.currentImageData = this._cloneImageData(this.initialImageData); // 重置CPU渲染器的网格和变形历史 if (renderer.reset) { @@ -741,8 +721,7 @@ export class LiquifyStateCommand extends Command { timestamp: Date.now(), properties: this.refManager._captureObjectState(fabricObject), imageData: this.initialImageData, - eventListeners: - this.refManager.eventListeners.get(this.objectRefId) || {}, + eventListeners: this.refManager.eventListeners.get(this.objectRefId) || {}, }; this.refManager.stateSnapshots.set(this.initialSnapshotId, snapshot); @@ -772,8 +751,7 @@ export class LiquifyStateCommand extends Command { timestamp: Date.now(), properties: this.refManager._captureObjectState(fabricObject), imageData: this.finalImageData, - eventListeners: - this.refManager.eventListeners.get(this.objectRefId) || {}, + eventListeners: this.refManager.eventListeners.get(this.objectRefId) || {}, }; this.refManager.stateSnapshots.set(this.finalSnapshotId, snapshot); @@ -804,8 +782,7 @@ export class LiquifyStateCommand extends Command { // 捕获当前渲染器状态 activeRendererState: null, // 捕获目标对象引用 - targetObjectRef: - this.liquifyManager.targetObject ?? enhancedManager.targetObject, + targetObjectRef: this.liquifyManager.targetObject ?? enhancedManager.targetObject, // 捕获初始化状态 initialized: this.liquifyManager.initialized || false, }; @@ -832,13 +809,9 @@ export class LiquifyStateCommand extends Command { params: { ...renderer.params }, currentMode: renderer.currentMode, // 对于CPU渲染器,还需要保存网格状态 - meshState: renderer.mesh - ? this._captureMeshState(renderer.mesh) - : null, + meshState: renderer.mesh ? this._captureMeshState(renderer.mesh) : null, // 保存变形历史 - deformHistory: renderer.deformHistory - ? [...renderer.deformHistory] - : [], + deformHistory: renderer.deformHistory ? [...renderer.deformHistory] : [], }; } } @@ -871,9 +844,7 @@ export class LiquifyStateCommand extends Command { this.realtimeUpdater.targetObject = this.liquifyManager.targetObject; // 如果有setTargetObject方法,调用它 if (typeof this.realtimeUpdater.setTargetObject === "function") { - this.realtimeUpdater.setTargetObject( - this.liquifyManager.targetObject - ); + this.realtimeUpdater.setTargetObject(this.liquifyManager.targetObject); } } @@ -911,10 +882,8 @@ export class LiquifyStateCommand extends Command { } else if (renderer.mesh && renderer._initMesh) { // 如果没有保存的网格状态,重新初始化网格 renderer._initMesh( - rendererState.originalImageData?.width || - renderer.originalImageData?.width, - rendererState.originalImageData?.height || - renderer.originalImageData?.height + rendererState.originalImageData?.width || renderer.originalImageData?.width, + rendererState.originalImageData?.height || renderer.originalImageData?.height ); } @@ -978,13 +947,7 @@ export class LiquifyStateCommand extends Command { * @private */ _restoreMeshState(mesh, meshState) { - if ( - !mesh || - !meshState || - !Array.isArray(mesh) || - !Array.isArray(meshState) - ) - return; + if (!mesh || !meshState || !Array.isArray(mesh) || !Array.isArray(meshState)) return; for (let i = 0; i < Math.min(mesh.length, meshState.length); i++) { for (let j = 0; j < Math.min(mesh[i].length, meshState[i].length); j++) { @@ -1043,8 +1006,7 @@ export class BatchLiquifyStateCommand extends Command { constructor(options) { super({ name: options.name || "批量液化操作", - description: - options.description || `批量液化${options.commands?.length || 0}个对象`, + description: options.description || `批量液化${options.commands?.length || 0}个对象`, }); this.commands = options.commands || []; @@ -1117,9 +1079,7 @@ export class BatchLiquifyStateCommand extends Command { * @returns {Boolean} 是否有效 */ isValid() { - return ( - this.commands.length > 0 && this.commands.every((cmd) => cmd.isValid()) - ); + return this.commands.length > 0 && this.commands.every((cmd) => cmd.isValid()); } /** diff --git a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js index 4a111c25..e52fb108 100644 --- a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js @@ -34,11 +34,7 @@ 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) { @@ -68,10 +64,7 @@ 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) @@ -153,9 +146,7 @@ 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, @@ -163,11 +154,7 @@ export class AddObjectToLayerCommand extends Command { }); // 保存完整的对象状态,包括位置和变换信息 - this.originalObjectState = this.fabricObject.toObject([ - "id", - "layerId", - "layerName", - ]); + this.originalObjectState = this.fabricObject.toObject(["id", "layerId", "layerName"]); // // 新增:保存详细的位置和变换信息,用于重做时恢复 // this.originalPosition = { @@ -279,8 +266,7 @@ export class AddObjectToLayerCommand extends Command { // 将对象添加到图层的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); @@ -327,16 +313,12 @@ 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(); @@ -410,9 +392,7 @@ 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); } // 更新画布 @@ -639,19 +619,14 @@ 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); } } } @@ -659,9 +634,7 @@ 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( @@ -697,15 +670,9 @@ 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("移除旧对象失败,但继续执行"); } @@ -771,93 +738,75 @@ 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, - }); - - // 使用帮助函数在正确的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 - ); + // 设置图层属性 + restoredImage.set({ + id: this.previousObjectId, + layerId: this.targetLayer.id, + layerName: this.targetLayer.name, + isBackground: this.targetLayer.isBackground, + isFixed: this.targetLayer.isFixed, }); - resolve(); - } catch (error) { - reject(error); - } + // 使用帮助函数在正确的z-index位置恢复对象 + if (this.previousZIndex !== undefined && this.previousZIndex >= 0) { + const insertSuccess = insertObjectAtZIndex( + this.canvas, + restoredImage, + this.previousZIndex, + false + ); + if (insertSuccess) { + console.log(`恢复图像到z-index位置: ${this.previousZIndex}`); + } else { + // 如果插入失败,回退到普通添加 + this.canvas.add(restoredImage); + console.log("z-index恢复失败,恢复图像添加到顶层"); + } + } else { + // 如果没有保存的z-index,添加到顶层 + this.canvas.add(restoredImage); + console.log("恢复图像添加到顶层"); + } + + restoredImage.setCoords(); + + // 更新引用 + this.targetLayer.fabricObject = restoredImage; + this.layerManager.updateLayerObject(this.targetLayer.id, restoredImage); + }); + + resolve(); + } catch (error) { + reject(error); } - ); + }); }); } async removeCurrentImage() { await optimizeCanvasRendering(this.canvas, async () => { if (this.newObjectId) { - const { object: currentObject } = findObjectById( - this.canvas, - this.newObjectId - ); + 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); @@ -976,10 +925,7 @@ 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; @@ -1042,19 +988,14 @@ 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); } } } @@ -1062,9 +1003,7 @@ 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( @@ -1318,23 +1257,16 @@ 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; @@ -1416,23 +1348,16 @@ 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; @@ -1473,9 +1398,7 @@ 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) { // 移除当前位置 @@ -1526,16 +1449,11 @@ 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); diff --git a/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js b/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js index 569ab999..69d2ddc8 100644 --- a/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/RasterizeLayerCommand.js @@ -1,11 +1,6 @@ import { Command } from "./Command"; import { fabric } from "fabric-with-all"; -import { - LayerType, - OperationType, - createLayer, - findLayerRecursively, -} from "../utils/layerHelper"; +import { LayerType, OperationType, createLayer, findLayerRecursively } from "../utils/layerHelper"; import { generateId, optimizeCanvasRendering, @@ -39,10 +34,7 @@ export class RasterizeLayerCommand extends Command { this.layerManager = options.layerManager; // 查找目标图层 - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.parentLayer = parent; this.isGroupLayer = this.layer?.children && this.layer.children.length > 0; @@ -102,9 +94,7 @@ export class RasterizeLayerCommand extends Command { console.log(`✅ 图层 ${this.layer.name} 栅格化完成`); - this.canvas?.thumbnailManager?.generateLayerThumbnail?.( - this.rasterizedLayerId - ); + this.canvas?.thumbnailManager?.generateLayerThumbnail?.(this.rasterizedLayerId); return this.rasterizedLayerId; } catch (error) { console.error("栅格化图层失败:", error); @@ -350,10 +340,7 @@ export class RasterizeLayerCommand extends Command { */ _replaceLayerInStructure() { // 1.当前如果是子图层,则插入到子图层的位置 - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); let insertIndex = 0; // 说明是子图层 @@ -374,11 +361,7 @@ export class RasterizeLayerCommand extends Command { if (insertIndex !== -1) { if (parent) { const pIndex = this.layers.value.findIndex((l) => l.id === parent.id); - this.layers.value[pIndex].children?.splice?.( - insertIndex, - 1, - this.rasterizedLayer - ); + this.layers.value[pIndex].children?.splice?.(insertIndex, 1, this.rasterizedLayer); } else { this.layers.value.splice(insertIndex, 1, this.rasterizedLayer); } @@ -396,14 +379,9 @@ export class RasterizeLayerCommand extends Command { async _getMaskObject() { // 如果图层有clippingMask,获取对应的fabric对象 if (this.layer?.clippingMask) { - const { object: maskObject } = findObjectById( - this.canvas, - this.layer.clippingMask.id - ); + const { object: maskObject } = findObjectById(this.canvas, this.layer.clippingMask.id); if (maskObject) { - console.log( - `📎 找到遮罩对象: ${maskObject.id}, 类型: ${maskObject.type}` - ); + console.log(`📎 找到遮罩对象: ${maskObject.id}, 类型: ${maskObject.type}`); return maskObject; } return await restoreFabricObject(this.layer.clippingMask); @@ -449,10 +427,7 @@ export class ExportLayerToImageCommand extends Command { this.layerManager = options.layerManager; // 查找目标图层 - const { layer, parent } = findLayerRecursively( - this.layers.value, - this.layerId - ); + const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.parentLayer = parent; this.isGroupLayer = this.layer?.children && this.layer.children.length > 0; diff --git a/src/component/Canvas/CanvasEditor/commands/RedGreenCommands.js b/src/component/Canvas/CanvasEditor/commands/RedGreenCommands.js index c4d60491..87dbcd70 100644 --- a/src/component/Canvas/CanvasEditor/commands/RedGreenCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/RedGreenCommands.js @@ -1,8 +1,4 @@ -import { - findObjectById, - generateId, - optimizeCanvasRendering, -} from "../utils/helper.js"; +import { findObjectById, generateId, optimizeCanvasRendering } from "../utils/helper.js"; import { imageModeHandler } from "../utils/imageHelper.js"; import { LayerType, OperationType } from "../utils/layerHelper.js"; import { Command, CompositeCommand } from "./Command.js"; @@ -58,9 +54,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { const layers = this.layerManager.layers?.value || []; const backgroundLayer = layers.find((layer) => layer.isBackground); const fixedLayer = layers.find((layer) => layer.isFixed); - const normalLayers = layers.filter( - (layer) => !layer.isBackground && !layer.isFixed - ); + const normalLayers = layers.filter((layer) => !layer.isBackground && !layer.isFixed); if (!backgroundLayer || !fixedLayer || normalLayers.length === 0) { throw new Error("缺少必要的图层结构"); @@ -76,9 +70,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { } : null; - this.originalFixedObjects = fixedLayer.fabricObject - ? [fixedLayer.fabricObject] - : []; + this.originalFixedObjects = fixedLayer.fabricObject ? [fixedLayer.fabricObject] : []; this.originalNormalObjects = normalLayer.fabricObjects ? [...normalLayer.fabricObjects] @@ -118,11 +110,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { await this._setupClothingImage(clothingImg, fixedLayer); // 7. 设置红绿图到普通图层,位置和大小与衣服底图一致 - await this._setupRedGreenImage( - redGreenImg, - normalLayer, - this.clothingImage - ); + await this._setupRedGreenImage(redGreenImg, normalLayer, this.clothingImage); // 4. 确保背景图层大小和衣服地图大小一致 const backgroundObject = await this._setupBackgroundLayer( @@ -207,13 +195,9 @@ export class BatchInitializeRedGreenModeCommand extends Command { async _createAndActivateEmptyLayer() { // 创建新的空白图层 const newLayerName = "绘制图层"; - const newLayerId = await this.layerManager.createLayer( - newLayerName, - LayerType.BITMAP, - { - undoable: false, - } - ); + const newLayerId = await this.layerManager.createLayer(newLayerName, LayerType.BITMAP, { + undoable: false, + }); // 设置为活动图层 if (newLayerId) { @@ -228,19 +212,14 @@ export class BatchInitializeRedGreenModeCommand extends Command { await optimizeCanvasRendering(this.canvas, async () => { // 1. 恢复画布背景 if (this.originalCanvasBackground !== null) { - this.canvas.setBackgroundColor( - this.originalCanvasBackground, - () => {} - ); + this.canvas.setBackgroundColor(this.originalCanvasBackground, () => {}); } // 2. 恢复图层对象 const layers = this.layerManager.layers?.value || []; const backgroundLayer = layers.find((layer) => layer.isBackground); const fixedLayer = layers.find((layer) => layer.isFixed); - const normalLayers = layers.filter( - (layer) => !layer.isBackground && !layer.isFixed - ); + const normalLayers = layers.filter((layer) => !layer.isBackground && !layer.isFixed); // 移除当前添加的对象 if (this.clothingImage) { @@ -252,9 +231,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { // 移除新创建的空白图层 if (this.newEmptyLayerId) { - const emptyLayerIndex = layers.findIndex( - (layer) => layer.id === this.newEmptyLayerId - ); + const emptyLayerIndex = layers.findIndex((layer) => layer.id === this.newEmptyLayerId); if (emptyLayerIndex !== -1) { layers.splice(emptyLayerIndex, 1); } @@ -270,9 +247,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { // 恢复固定图层 if (fixedLayer) { fixedLayer.fabricObject = - this.originalFixedObjects.length > 0 - ? this.originalFixedObjects[0] - : null; + this.originalFixedObjects.length > 0 ? this.originalFixedObjects[0] : null; if (fixedLayer.fabricObject) { this.canvas.add(fixedLayer.fabricObject); @@ -311,8 +286,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { // 4. 恢复工具状态 if (this.toolManager && this.originalToolState) { - this.toolManager.isRedGreenMode = - this.originalToolState.isRedGreenMode; + this.toolManager.isRedGreenMode = this.originalToolState.isRedGreenMode; if (this.originalToolState.currentTool) { this.toolManager.setTool(this.originalToolState.currentTool); } @@ -434,10 +408,7 @@ export class BatchInitializeRedGreenModeCommand extends Command { // 清除固定图层原有内容 if (fixedLayer.fabricObject) { - const { object } = findObjectById( - this.canvas, - fixedLayer.fabricObject.id - ); + const { object } = findObjectById(this.canvas, fixedLayer.fabricObject.id); if (object) this.canvas.remove(object); } diff --git a/src/component/Canvas/CanvasEditor/commands/SelectionCommands.js b/src/component/Canvas/CanvasEditor/commands/SelectionCommands.js index 4a3f25d2..fb0ee3a0 100644 --- a/src/component/Canvas/CanvasEditor/commands/SelectionCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/SelectionCommands.js @@ -110,9 +110,7 @@ export class AddToSelectionCommand extends Command { } // 添加到选区 - const result = await this.selectionManager.addToSelection( - this.newSelection - ); + const result = await this.selectionManager.addToSelection(this.newSelection); return result; } @@ -155,9 +153,7 @@ export class RemoveFromSelectionCommand extends Command { } // 从选区中移除 - const result = await this.selectionManager.removeFromSelection( - this.removeSelection - ); + const result = await this.selectionManager.removeFromSelection(this.removeSelection); return result; } @@ -203,9 +199,7 @@ export class FeatherSelectionCommand extends Command { } // 应用羽化 - const result = await this.selectionManager.featherSelection( - this.featherAmount - ); + const result = await this.selectionManager.featherSelection(this.featherAmount); return result; } @@ -347,8 +341,7 @@ export class CopySelectionToNewLayerCommand extends CompositeCommand { } // 确定源图层 - const sourceId = - this.sourceLayerId || this.layerManager.getActiveLayerId(); + const sourceId = this.sourceLayerId || this.layerManager.getActiveLayerId(); const sourceLayer = this.layerManager.getLayerById(sourceId); if (!sourceLayer || !sourceLayer.fabricObjects) { console.error("无法复制选区:源图层无效或为空"); @@ -356,10 +349,7 @@ export class CopySelectionToNewLayerCommand extends CompositeCommand { } // 创建新图层 - this.newLayerId = await this.layerManager.createLayer( - this.newLayerName, - LayerType.EMPTY - ); + this.newLayerId = await this.layerManager.createLayer(this.newLayerName, LayerType.EMPTY); // 获取选区内的对象 const objectsToCopy = sourceLayer.fabricObjects.filter((obj) => { diff --git a/src/component/Canvas/CanvasEditor/commands/TextCommands.js b/src/component/Canvas/CanvasEditor/commands/TextCommands.js index d21d5af4..f4d52013 100644 --- a/src/component/Canvas/CanvasEditor/commands/TextCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/TextCommands.js @@ -401,9 +401,7 @@ export class CreateTextCommand extends Command { // 更新图层的对象列表 if (layer) { layer.fabricObjects = layer.fabricObjects || []; - layer.fabricObjects.push( - this.textObject.toObject(["id", "layerId", "layerName"]) - ); + layer.fabricObjects.push(this.textObject.toObject(["id", "layerId", "layerName"])); } // 现在可以安全地设置为活动图层 @@ -416,9 +414,7 @@ export class CreateTextCommand extends Command { this.layerManager?.toolManager?.setTool?.(OperationType.SELECT); }); - console.log( - `✅ 文本对象已创建: "${finalOptions.text}",位置: (${this.x}, ${this.y})` - ); + console.log(`✅ 文本对象已创建: "${finalOptions.text}",位置: (${this.x}, ${this.y})`); return this.textObject; } catch (error) { console.error("创建文本对象失败:", error); @@ -467,15 +463,11 @@ export class CreateTextCommand extends Command { parentLayer.children = parentLayer.children || []; parentLayer.children.splice(insertIndex, 0, newLayer); - console.log( - `新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})` - ); + console.log(`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`); } else { // 当前激活图层是一级图层 // 在一级图层中,插入到激活图层之上 - const activeLayerIndex = layers.findIndex( - (layer) => layer.id === currentActiveLayerId - ); + const activeLayerIndex = layers.findIndex((layer) => layer.id === currentActiveLayerId); insertIndex = Math.max(0, activeLayerIndex); layers.splice(insertIndex, 0, newLayer); @@ -551,9 +543,7 @@ export class CreateTextCommand extends Command { // 恢复原活动图层 if (this.oldActiveLayerId && this.layerManager) { // 检查原活动图层是否还存在 - const originalLayer = this.layerManager.getLayerById( - this.oldActiveLayerId - ); + const originalLayer = this.layerManager.getLayerById(this.oldActiveLayerId); if (originalLayer) { this.layerManager.setActiveLayer(this.oldActiveLayerId); } else { @@ -603,9 +593,7 @@ export class CreateTextCommand extends Command { // 从子图层中移除 if (positionInfo.parent.children && positionInfo.index >= 0) { positionInfo.parent.children.splice(positionInfo.index, 1); - console.log( - `已从子图层移除: ${this.layerId} (父图层: ${positionInfo.parent.name})` - ); + console.log(`已从子图层移除: ${this.layerId} (父图层: ${positionInfo.parent.name})`); } } else { // 从一级图层中移除 diff --git a/src/component/Canvas/CanvasEditor/commands/UpdateGroupMaskPositionCommand.js b/src/component/Canvas/CanvasEditor/commands/UpdateGroupMaskPositionCommand.js new file mode 100644 index 00000000..cac82099 --- /dev/null +++ b/src/component/Canvas/CanvasEditor/commands/UpdateGroupMaskPositionCommand.js @@ -0,0 +1,244 @@ +import { findLayerRecursively } from "../utils/layerHelper"; +import { restoreFabricObject } from "../utils/objectHelper"; +import { Command } from "./Command"; + +/** + * 更新组图层遮罩位置命令 + * 当组图层的对象移动时,同步更新遮罩的位置 + */ +export class UpdateGroupMaskPositionCommand extends Command { + constructor(options) { + super({ + name: "更新组图层遮罩位置", + saveState: true, + }); + + this.canvas = options.canvas; + this.layers = options.layers; + this.layerManager = options.layerManager; + this.layerId = options.layerId; + this.deltaX = options.deltaX || 0; + this.deltaY = options.deltaY || 0; + this.maskInitialLeft = options.maskInitialLeft || 0; + this.maskInitialTop = options.maskInitialTop || 0; + this.isExecuteRealtime = options.isExecuteRealtime || false; + this.activeSelection = this.canvas.getActiveObject() || {}; + + this.isFristExecute = true; + + // 查找目标图层 + this.layer = findLayerRecursively(this.layers.value, this.layerId)?.layer; + + if (!this.layer || !this.layer.clippingMask) { + console.warn(`图层 ${this.layerId} 不存在或没有遮罩`); + return false; + } + + // 保存原始遮罩位置(用于撤销) + // 保存原始位置 + this.originalMaskPosition = { + left: this.maskInitialLeft || 0, + top: this.maskInitialTop || 0, + }; + + // 收集当前选择的所有对象位置 + this.originalObjectsPostion = this.activeSelection.getObjects().map((obj) => { + return { + left: obj.left || 0, + top: obj.top || 0, + id: obj.id, + }; + }); + + this.originalSelectionPosition = { + left: this.activeSelection.left || 0, + top: this.activeSelection.top || 0, + }; + + console.log( + `🛠️ 初始化更新组图层遮罩位置命令: ${this.name}, 图层ID: ${this.layerId}, 初始位置: (${this.originalMaskPosition.left}, ${this.originalMaskPosition.top})` + ); + this.newMaskPosition = null; + } + + async execute() { + try { + // 计算新位置 + const newLeft = this.maskInitialLeft + this.deltaX; + const newTop = this.maskInitialTop + this.deltaY; + + // 更新遮罩位置 + this.layer.clippingMask.left = newLeft; + this.layer.clippingMask.top = newTop; + + this.newMaskPosition = { + left: newLeft, + top: newTop, + }; + + // 更新所有使用此遮罩的子图层对象 + await this._updateChildObjectsClipPath(this.layer, false, true); + + this.isFristExecute = false; + console.log(`✅ 组图层遮罩位置已更新: (${newLeft}, ${newTop})`); + return true; + } catch (error) { + console.error("更新组图层遮罩位置失败:", error); + return false; + } + } + + async undo() { + try { + if (!this.originalMaskPosition) { + console.warn("没有原始遮罩位置数据,无法撤销"); + return false; + } + + // 查找目标图层 + const layer = this.layers.value.find((l) => l.id === this.layerId); + if (!layer || !layer.clippingMask) { + console.warn(`图层 ${this.layerId} 不存在或没有遮罩`); + return false; + } + + console.log( + `↶ 撤销更新组图层遮罩位置: ${this.originalMaskPosition.left}, 图层ID: ${this.originalMaskPosition.top}` + ); + // 恢复原始位置 + layer.clippingMask.left = this.originalMaskPosition.left; + layer.clippingMask.top = this.originalMaskPosition.top; + + // 更新所有使用此遮罩的子图层对象 + await this._updateChildObjectsClipPath(layer, true); + // await this.layerManager.updateLayersObjectsInteractivity(); + // this.canvas.renderAll(); + + console.log( + `↶ 组图层遮罩位置已恢复: (${this.originalMaskPosition.left}, ${this.originalMaskPosition.top})` + ); + return true; + } catch (error) { + console.error("撤销组图层遮罩位置更新失败:", error); + return false; + } + } + + /** + * 实时执行(不记录到历史记录) + * 用于拖拽过程中的实时更新 + */ + executeRealtime() { + try { + // 查找目标图层 + const layer = this.layers.value.find((l) => l.id === this.layerId); + if (!layer || !layer.clippingMask) { + return false; + } + + // 计算新位置 + const newLeft = this.maskInitialLeft + this.deltaX; + const newTop = this.maskInitialTop + this.deltaY; + + // 更新遮罩位置 + layer.clippingMask.left = newLeft; + layer.clippingMask.top = newTop; + + // 更新所有使用此遮罩的子图层对象(不需要等待) + this._updateChildObjectsClipPath(layer); + + return true; + } catch (error) { + console.error("实时更新组图层遮罩位置失败:", error); + return false; + } + } + + /** + * 更新子图层对象的裁剪路径 + * @param {Object} layer 组图层对象 + * @private + */ + async _updateChildObjectsClipPath(layer, isUndo = false, isExecute = false) { + if (!layer.children || layer.children.length === 0) { + return; + } + + try { + // 重新创建遮罩对象 + const clippingMaskFabricObject = await restoreFabricObject(layer.clippingMask, this.canvas); + + if (!clippingMaskFabricObject) { + console.warn("无法恢复遮罩对象"); + return; + } + + clippingMaskFabricObject.clipPath = null; + clippingMaskFabricObject.set({ + absolutePositioned: true, + }); + + clippingMaskFabricObject.dirty = true; + clippingMaskFabricObject.setCoords(); + + // 更新所有子图层对象的裁剪路径 + layer.children.forEach((childLayer) => { + // 更新 fabricObjects 中的对象 + childLayer.fabricObjects?.forEach((obj) => { + const fabricObject = this.canvas.getObjects().find((o) => o.id === obj.id); + if (fabricObject) { + fabricObject.clipPath = clippingMaskFabricObject; + fabricObject.dirty = true; + fabricObject.setCoords(); + } + }); + + // 更新单个 fabricObject + if (childLayer.fabricObject) { + const fabricObject = this.canvas + .getObjects() + .find((o) => o.id === childLayer.fabricObject.id); + if (fabricObject) { + fabricObject.clipPath = clippingMaskFabricObject; + fabricObject.dirty = true; + fabricObject.setCoords(); + } + } + }); + + if (isUndo) { + this.activeSelection.set({ + left: this.originalSelectionPosition.left - this.deltaX, + top: this.originalSelectionPosition.top - this.deltaY, + }); + this.activeSelection.dirty = true; + this.activeSelection.setCoords(); + } + + if (isExecute && !this.isFristExecute) { + this.activeSelection.set({ + left: this.activeSelection.left + this.deltaX, + top: this.activeSelection.top + this.deltaY, + }); + this.activeSelection.dirty = true; + this.activeSelection.setCoords(); + } + + // 触发画布重新渲染 + this.canvas.renderAll(); + } catch (error) { + console.error("更新子图层对象裁剪路径失败:", error); + } + } + + getInfo() { + return { + name: this.name, + layerId: this.layerId, + deltaX: this.deltaX, + deltaY: this.deltaY, + originalPosition: this.originalMaskPosition, + newPosition: this.newMaskPosition, + }; + } +} diff --git a/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue b/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue index e78a5445..00d558a3 100644 --- a/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue @@ -43,11 +43,7 @@ > + - @@ -57,16 +53,9 @@ -
+
-
- {{ Math.round(brushOpacity * 100) }}% -
+
{{ Math.round(brushOpacity * 100) }}%
-