diff --git a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js index ad082a9a..da61fba7 100644 --- a/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/ObjectLayerCommands.js @@ -480,6 +480,12 @@ export class ChangeFixedImageCommand extends Command { this.position.x = options.left || this.canvas.width / 2; this.position.y = options.top || this.canvas.height / 2; + this.canvasWidth = options?.canvasWidth?.value || this.canvas.width; + this.canvasHeight = options?.canvasHeight?.value || this.canvas.height; + + // 底图加载方式 1.平铺 2.拉伸 3.拉伸平铺 4.拉伸平铺并裁剪 5.包含 + this.imageMode = options?.imageMode || ""; // 默认 contains, stretch,tile, stretchTile, stretchTileCrop + // 用于回滚的状态 this.previousImage = null; this.previousTransform = null; @@ -679,6 +685,7 @@ export class ChangeFixedImageCommand extends Command { async applyImageToLayer(newImage) { await optimizeCanvasRendering(this.canvas, async () => { // 设置基本属性 + newImage.set({ id: this.targetLayer?.fabricObject?.id || this.newObjectId, layerId: this.targetLayer.id, @@ -718,6 +725,49 @@ export class ChangeFixedImageCommand extends Command { }); } + // 如果是包含 则需要根据图像模式调整大小 + switch (this.imageMode) { + case "stretch": + // 拉伸模式 - 填充整个画布 + newImage.scaleToWidth(this.canvasWidth); + newImage.scaleToHeight(this.canvasHeight); + break; + case "tile": + // 平铺模式 - 保持原始大小 + newImage.scaleX = 1; + newImage.scaleY = 1; + break; + case "stretchTile": + // 拉伸平铺模式 - 填充整个画布,但保持宽高比 + newImage.scaleToWidth(this.canvasWidth); + newImage.scaleToHeight(this.canvasHeight); + break; + case "stretchTileCrop": + // 拉伸平铺并裁剪模式 - 填充整个画布,可能 + // 会裁剪图像以适应画布 + newImage.scaleToWidth(this.canvasWidth); + newImage.scaleToHeight(this.canvasHeight); + // 这里可以添加裁剪逻辑,如果需要的话 + // 例如使用fabric.Image.clipPath来裁剪图像 + break; + case "contains": + // 包含模式 - 保证图像在画布内完整显示 + // 既要考虑画布的宽高比,也要考虑图像的宽高比 + // 图片缩放后要保证最长边能完全显示在画布内 + const canvasAspect = this.canvasWidth / this.canvasHeight; + const imageAspect = newImage.width / newImage.height; + // 保证图像在画布内完整显示 - 既要考虑画布的宽高比,也要考虑图像的宽高比 + // 图片缩放后要保证最长边能完全显示在画布内 + if (imageAspect > canvasAspect) { + // 图像更宽 + newImage.scaleToWidth(this.canvasWidth); + } else { + // 图像更高 + newImage.scaleToHeight(this.canvasHeight); + } + break; + } + // 使用帮助函数在指定z-index位置插入新图像 if (this.previousZIndex !== undefined && this.previousZIndex >= 0) { const insertSuccess = insertObjectAtZIndex( diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index d84e52f6..8aa22502 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -78,10 +78,10 @@ const imageUploadRef = ref(null); const currentZoom = ref(100); // 画布设置 -const canvasWidth = ref(CanvasConfig.width); -const canvasHeight = ref(CanvasConfig.height); -const canvasColor = ref(CanvasConfig.backgroundColor); -const layerWidth = ref(CanvasConfig.layerWidth); +const canvasWidth = ref(props.config.width); +const canvasHeight = ref(props.config.height); +const canvasColor = ref(props.config.backgroundColor); +// const layerWidth = ref(CanvasConfig.layerWidth); const brushSize = ref(CanvasConfig.brushSize); // 画笔大小 const canvasManagerLoaded = ref(false); // 画布是否加载完成 @@ -315,29 +315,26 @@ onMounted(async () => { } } - // 如果初始化有默认底图,设置底图 - 红绿图模式不通过初始化重置底图了 - if (!isRedGreenMode.value && props.clothingImageUrl) { - nextTick(() => { - setTimeout(() => { - try { - canvasManager?.changeFixedImage?.(props.clothingImageUrl, { - undoable: false, // 不可撤销操作 - ...(props?.clothingImageOpts || {}), - }); - } catch (error) { - console.error("更换底图失败:", error); - } - }, 92); // 延迟 确保更新底图完成 - }); - - this.canvasManager?.centerBackgroundLayer?.( - this.canvas.width, - this.canvas.height - ); - } - // 初始设置 handleWindowResize(); // 设置画布大小 + } else if (!isRedGreenMode.value && props.clothingImageUrl) { + nextTick(() => { + setTimeout(() => { + try { + canvasManager?.changeFixedImage?.(props.clothingImageUrl, { + undoable: false, // 不可撤销操作 + ...(props?.clothingImageOpts || {}), + }); + } catch (error) { + console.error("更换底图失败:", error); + } + }, 92); // 延迟 确保更新底图完成 + }); + + canvasManager?.centerBackgroundLayer?.( + canvasManager.canvas.width, + canvasManager.canvas.height + ); } }); diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 3cf78b26..89db592f 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -659,12 +659,15 @@ export class CanvasManager { console.error("图层管理器未设置,无法更改固定图层图片"); return; } + const command = new ChangeFixedImageCommand({ canvas: this.canvas, layerManager: this.layerManager, imageUrl: imageUrl, targetLayerType: options.targetLayerType || "fixed", // background/fixed - options: options, + canvasWidth: this.canvasWidth, + canvasHeight: this.canvasHeight, + ...options, }); command.undoable = diff --git a/src/component/DetailCopy/canvas/index.vue b/src/component/DetailCopy/canvas/index.vue index b715a5cb..0be4a02b 100644 --- a/src/component/DetailCopy/canvas/index.vue +++ b/src/component/DetailCopy/canvas/index.vue @@ -2,8 +2,8 @@
-
-
+
+ +
+
- + +
- - + --> +
@@ -35,6 +50,9 @@
-->
+
+ +
+ +
+
+ + +
+
+
+ +
+
+
+ +
+
+ + +
+
+ + +
+
+ + +
+ + + + \ No newline at end of file diff --git a/src/component/DetailCopy/detailLeft/module/selectList.vue b/src/component/DetailCopy/detailLeft/module/selectList.vue index e373daa9..07eb917b 100644 --- a/src/component/DetailCopy/detailLeft/module/selectList.vue +++ b/src/component/DetailCopy/detailLeft/module/selectList.vue @@ -25,12 +25,12 @@