diff --git a/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js b/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js index 9b084017..7011c361 100644 --- a/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/BackgroundCommands.js @@ -137,6 +137,10 @@ export class UpdateBackgroundCommand extends Command { // 查找背景图层 this.bgLayer = this.layers.value.find((layer) => layer.isBackground); this.oldBackgroundColor = this.bgLayer.backgroundColor; + this.backgroundObject = findObjectById( + this.canvas, + this.bgLayer.fabricObject.id + ).object; } execute() { @@ -149,12 +153,9 @@ export class UpdateBackgroundCommand extends Command { this.bgLayer.backgroundColor = this.backgroundColor; // 更新背景对象属性 - if (this.bgLayer.fabricObject) { - const { object } = findObjectById( - this.canvas, - this.bgLayer.fabricObject.id - ); - object.set("fill", this.backgroundColor); + if (this.backgroundObject) { + // const { object } = findObjectById(this.canvas, this.backgroundObject.id); + this.backgroundObject.set("fill", this.backgroundColor); this.canvas.renderAll(); } this.backgroundColorValue.value = this.backgroundColor; // 设置背景颜色 @@ -170,12 +171,9 @@ export class UpdateBackgroundCommand extends Command { this.bgLayer.backgroundColor = this.oldBackgroundColor; // 恢复背景对象属性 - if (this.bgLayer.fabricObject) { - const { object } = findObjectById( - this.canvas, - this.bgLayer.fabricObject.id - ); - object.set("fill", this.oldBackgroundColor); + if (this.backgroundObject) { + // const { object } = findObjectById(this.canvas, this.backgroundObject.id); + this.backgroundObject.set("fill", this.oldBackgroundColor); this.canvas.renderAll(); } this.backgroundColorValue.value = this.oldBackgroundColor; // 恢复背景颜色 @@ -212,8 +210,13 @@ export class BackgroundSizeCommand extends Command { this.bgLayer = this.layers.value.find((layer) => layer.isBackground); // 记录原尺寸 - this.oldWidth = this.bgLayer.fabricObject.width; - this.oldHeight = this.bgLayer.fabricObject.height; + this.backgroundObject = findObjectById( + this.canvas, + this.bgLayer.fabricObject.id + ).object; + + this.oldWidth = this.backgroundObject.width; + this.oldHeight = this.backgroundObject.height; // 查找背景图层 this.bgLayer = this.layers.value.find((layer) => layer.isBackground); @@ -221,30 +224,28 @@ export class BackgroundSizeCommand extends Command { execute() { // 调整画布大小 - this.canvas.setWidth(this.newWidth); - this.canvas.setHeight(this.newHeight); + // this.canvas.setWidth(this.newWidth); + // this.canvas.setHeight(this.newHeight); console.log( `调整画布大小:${this.oldWidth}x${this.oldHeight} -> ${this.newWidth}x${this.newHeight}` ); // 如果使用 CanvasManager,通知它画布大小变化 - if ( - this.canvasManager && - typeof this.canvasManager.updateCanvasSize === "function" - ) { - this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight); - } + // if ( + // this.canvasManager && + // typeof this.canvasManager.updateCanvasSize === "function" + // ) { + // this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight); + // } // 调整背景对象大小 - if (this.bgLayer && this.bgLayer.fabricObject) { + if (this.bgLayer && this.backgroundObject) { // 保持原有的背景颜色,如果没有设置则使用白色 const currentFill = - this.bgLayer.fabricObject.fill || - this.bgLayer.backgroundColor || - "#ffffff"; + this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff"; - this.bgLayer.fabricObject.set({ + this.backgroundObject.set({ width: this.newWidth, height: this.newHeight, fill: currentFill, // 保持原有颜色 @@ -267,16 +268,16 @@ export class BackgroundSizeCommand extends Command { this.canvas.setHeight(this.oldHeight); // 如果使用 CanvasManager,通知它画布大小恢复 - if ( - this.canvasManager && - typeof this.canvasManager.updateCanvasSize === "function" - ) { - this.canvasManager.updateCanvasSize(this.oldWidth, this.oldHeight); - } + // if ( + // this.canvasManager && + // typeof this.canvasManager.updateCanvasSize === "function" + // ) { + // this.canvasManager.updateCanvasSize(this.oldWidth, this.oldHeight); + // } // 恢复背景对象大小 - if (this.bgLayer && this.bgLayer.fabricObject) { - this.bgLayer.fabricObject.set({ + if (this.bgLayer && this.backgroundObject) { + this.backgroundObject.set({ width: this.oldWidth, height: this.oldHeight, }); @@ -329,6 +330,11 @@ export class BackgroundSizeWithScaleCommand extends Command { // 查找背景图层 this.bgLayer = this.layers.value.find((layer) => layer.isBackground); + this.backgroundObject = findObjectById( + this.canvas, + this.bgLayer.fabricObject.id + ).object; + // 计算缩放比例 const scaleXRatio = this.newWidth / this.oldWidth; const scaleYRatio = this.newHeight / this.oldHeight; @@ -433,26 +439,24 @@ export class BackgroundSizeWithScaleCommand extends Command { this.canvas.setHeight(this.newHeight); // 如果使用 CanvasManager,通知它画布大小变化 - if ( - this.canvasManager && - typeof this.canvasManager.updateCanvasSize === "function" - ) { - this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight); - } + // if ( + // this.canvasManager && + // typeof this.canvasManager.updateCanvasSize === "function" + // ) { + // this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight); + // } // 调整背景对象大小和位置 - if (this.bgLayer && this.bgLayer.fabricObject) { + if (this.bgLayer && this.backgroundObject) { // 保持原有的背景颜色,如果没有设置则使用白色 const currentFill = - this.bgLayer.fabricObject.fill || - this.bgLayer.backgroundColor || - "#ffffff"; + this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff"; - this.bgLayer.fabricObject.set({ + this.backgroundObject.set({ width: this.newWidth, height: this.newHeight, - left: this.newWidth / 2, - top: this.newHeight / 2, + left: this.canvas.width / 2, + top: this.canvas.height / 2, fill: currentFill, // 保持原有颜色 }); @@ -528,12 +532,12 @@ export class BackgroundSizeWithScaleCommand extends Command { } // 恢复背景对象大小和位置 - if (this.bgLayer && this.bgLayer.fabricObject) { - this.bgLayer.fabricObject.set({ + if (this.bgLayer && this.backgroundObject) { + this.backgroundObject.set({ width: this.oldWidth, height: this.oldHeight, - left: this.oldWidth / 2, - top: this.oldHeight / 2, + left: this.canvas.width / 2, + top: this.canvas.height / 2, }); // 恢复图层记录的尺寸 diff --git a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js index 8edc4e5d..9e77160e 100644 --- a/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/LassoCutoutCommand.js @@ -156,11 +156,18 @@ export class LassoCutoutCommand extends CompositeCommand { selectLayer.fabricObjects = [ this.fabricImage.toObject("id", "layerId", "layerName", "parentId"), ]; + this.groupLayer.clippingMask = this.fabricImage.toObject( + "id", + "layerId", + "layerName", + "parentId" + ); // 设置组图层的fabricObject为遮罩图像 + this.groupLayer.children.push(selectLayer); // 插入新组图层 this.layerManager.layers.value.splice(topLayerIndex, 1, this.groupLayer); - this.layerManager.updateLayersObjectsInteractivity(); + await this.layerManager.updateLayersObjectsInteractivity(); this.canvas.discardActiveObject(); this.canvas.setActiveObject(this.fabricImage); this.canvas.renderAll(); diff --git a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js index 685888f5..3bfe09e5 100644 --- a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js @@ -41,13 +41,15 @@ export class AddLayerCommand extends Command { this.oldActiveLayerId = this.activeLayerId.value; // 执行添加图层操作 - if (this.insertIndex !== undefined && this.insertIndex !== null) { - this.layers.value.splice(this.insertIndex, 0, this.newLayer); - } else { - this.layers.value.push(this.newLayer); - } + // 智能插入图层到合适位置 + this._insertLayerAtCorrectPosition(this.newLayer); + // if (this.insertIndex !== undefined && this.insertIndex !== null) { + // this.layers.value.splice(this.insertIndex, 0, this.newLayer); + // } else { + // this.layers.value.push(this.newLayer); + // } - // 更新活动图层 + // // 更新活动图层 if (!this.newLayer.isBackground) { this.activeLayerId.value = this.newLayer.id; } @@ -63,6 +65,104 @@ export class AddLayerCommand extends Command { this.activeLayerId.value = this.oldActiveLayerId; } + /** + * 智能插入图层到正确位置 + * 根据当前激活图层位置确定新图层插入位置 + * @param {Object} newLayer 要插入的新图层 + * @private + */ + _insertLayerAtCorrectPosition(newLayer) { + const layers = this.layers.value; + const currentActiveLayerId = this.activeLayerId?.value; + + // 如果没有当前激活图层,插入到顶部(索引0) + if (!currentActiveLayerId) { + layers.splice(0, 0, newLayer); + return; + } + + // 查找当前激活图层的位置 + const { + layer: activeLayer, + parent: parentLayer, + index: activeIndex, + } = this._findLayerPosition(currentActiveLayerId); + + if (!activeLayer) { + // 没找到激活图层,插入到顶部 + layers.splice(0, 0, newLayer); + return; + } + + // 确定插入位置 + let insertIndex = 0; + + if (parentLayer) { + // 当前激活图层是子图层 + // 在同一父图层内,插入到激活子图层之上 + insertIndex = Math.max(0, activeIndex); + parentLayer.children = parentLayer.children || []; + parentLayer.children.splice(insertIndex, 0, newLayer); + + console.log( + `新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})` + ); + } else { + // 当前激活图层是一级图层 + // 在一级图层中,插入到激活图层之上 + const activeLayerIndex = layers.findIndex( + (layer) => layer.id === currentActiveLayerId + ); + insertIndex = Math.max(0, activeLayerIndex); + layers.splice(insertIndex, 0, newLayer); + + console.log(`新图层已插入到一级图层位置: ${insertIndex}`); + } + } + + /** + * 查找图层位置信息 + * @param {String} layerId 图层ID + * @returns {Object} 包含图层、父图层和索引的对象 + * @private + */ + _findLayerPosition(layerId) { + const layers = this.layers.value; + + // 先在一级图层中查找 + for (let i = 0; i < layers.length; i++) { + const layer = layers[i]; + + if (layer.id === layerId) { + return { + layer: layer, + parent: null, + index: i, + }; + } + + // 在子图层中查找 + if (layer.children && Array.isArray(layer.children)) { + for (let j = 0; j < layer.children.length; j++) { + const childLayer = layer.children[j]; + if (childLayer.id === layerId) { + return { + layer: childLayer, + parent: layer, + index: j, + }; + } + } + } + } + + return { + layer: null, + parent: null, + index: -1, + }; + } + getInfo() { return { name: this.name, diff --git a/src/component/Canvas/CanvasEditor/commands/TextCommands.js b/src/component/Canvas/CanvasEditor/commands/TextCommands.js index 6deb2b58..d21d5af4 100644 --- a/src/component/Canvas/CanvasEditor/commands/TextCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/TextCommands.js @@ -320,7 +320,7 @@ export class CreateTextCommand extends Command { this.y = options.y; this.textOptions = options.textOptions || {}; // 生成唯一ID - this.textId = options?.textId || this.generateId("text_"); + this.textId = options?.textId || generateId("text_"); this.layerId = options?.layerId || generateId("text_layer_"); // 生成的对象和图层信息 @@ -526,14 +526,6 @@ export class CreateTextCommand extends Command { }; } - /** - * 生成唯一ID - * @returns {String} 唯一ID - */ - generateId() { - return `text_${Date.now()}_${Math.floor(Math.random() * 1000)}`; - } - getInfo() { return { name: this.name, diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js index 8f0a9ad2..cbffe1ef 100644 --- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js +++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js @@ -286,12 +286,6 @@ export class LayerManager { // 应用图层视觉属性 if (layer.opacity !== undefined) obj.opacity = layer.opacity; if (layer.blendMode) obj.globalCompositeOperation = layer.blendMode; - if (layer.clippingMask) { - const { object } = findObjectById(this.canvas, layer.clippingMask?.id); - if (object) { - obj.clipPath = object; - } - } } // 私有方法:应用交互规则 @@ -337,6 +331,42 @@ export class LayerManager { } }); }); + + // 设置裁剪对象 + layers.forEach((layer) => { + if (layer.clippingMask) { + // 如果是组图层 则给所有子对象设置裁剪对象 + if (layer.type === LayerType.GROUP || layer.children?.length > 0) { + layer.children.forEach((childLayer) => { + const { object } = findObjectById( + this.canvas, + layer.clippingMask?.id + ); + if (object) { + const tempClipPath = fabric.util.object.clone(object); + tempClipPath.set({ + // 设置绝对定位 + absolutePositioned: true, + }); + const childObj = this.canvas + .getObjects() + .find((o) => o.layerId === childLayer.id); + if (childObj) { + childObj.clipPath = tempClipPath; + } + } + }); + } else { + const { object } = findObjectById( + this.canvas, + layer.clippingMask?.id + ); + if (object) { + obj.clipPath = object; + } + } + } + }); } /** * 创建新图层 @@ -393,7 +423,7 @@ export class LayerManager { command.undoable = options.undoable; // 如果是第一个图层,或者普通图层数量小于等于3,设置为不可撤销 - if (this.layers.value.length === 3 || normalLayersCount < 1) { + if (normalLayersCount < 1) { command.undoable = false; }