From 1989c22562615279c631a733ce604182d7e023bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Fri, 16 Jan 2026 10:29:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=8D=B0=E8=8A=B1=E5=B9=B3?= =?UTF-8?q?=E9=93=BA=E7=9A=84=E4=BD=8D=E7=BD=AE=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commands/FillRepeatCommand.js | 11 +- .../components/SelectMenuPanel/index.vue | 2 +- .../CanvasEditor/managers/CanvasManager.js | 50 +- .../Canvas/CanvasEditor/utils/helper.js | 20 +- src/component/Canvas/OverallCanvas/demo.vue | 8 +- src/component/Canvas/OverallCanvas/index.vue | 12 +- src/component/Canvas/canvasExample.vue | 1117 +++++++++-------- 7 files changed, 636 insertions(+), 584 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/commands/FillRepeatCommand.js b/src/component/Canvas/CanvasEditor/commands/FillRepeatCommand.js index d223957e..b8e0baee 100644 --- a/src/component/Canvas/CanvasEditor/commands/FillRepeatCommand.js +++ b/src/component/Canvas/CanvasEditor/commands/FillRepeatCommand.js @@ -7,6 +7,7 @@ import { insertObjectAtZIndex, removeCanvasObjectByObject, createPatternTransform, + imageAddGapToCanvas, } from "../utils/helper"; import { restoreFabricObject } from "../utils/objectHelper"; @@ -308,16 +309,8 @@ export class FillRepeatGapChangeCommand extends Command { await image.decode(); object.fill_.width = image.width; object.fill_.height = image.height; - // 创建透明 Canvas - const tcanvas = document.createElement('canvas'); - tcanvas.width = image.width + object.fill_.gapX; - tcanvas.height = image.height + object.fill_.gapY; - const ctx = tcanvas.getContext('2d'); - ctx.clearRect(0, 0, tcanvas.width, tcanvas.height); - ctx.drawImage(image, 0, 0); - const fill = object.get("fill"); - fill.source = tcanvas; + fill.source = imageAddGapToCanvas(image, object.fill_.gapX, object.fill_.gapY); object.set("fill", new fabric.Pattern(fill)); this.canvas.renderAll(); return true; diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue index 1289e555..84659f21 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue @@ -433,7 +433,7 @@ }; changeFill(obj, pattern); }; - // 改变填充便宜 + // 改变填充偏移 const inputFillOffset = (value, obj) => { if (!obj.oldPattern) obj.oldPattern = obj.get("fill"); const pattern = new fabric.Pattern({ diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 419132e8..a07f75d6 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -34,6 +34,7 @@ import { createPatternTransform, getTransformScaleAngle, base64ToCanvas, + imageAddGapToCanvas, } from "../utils/helper"; import { ChangeFixedImageCommand } from "../commands/ObjectLayerCommands"; import { isFunction } from "lodash-es"; @@ -1630,38 +1631,57 @@ export class CanvasManager { resolve(tcanvas); }, { crossOrigin: "anonymous" }); }) - let scaleX = fixedLayerObj.width / image.width * (item.scale?.[0] || 1) / 5; - let scaleY = fixedLayerObj.height / image.height * (item.scale?.[1] || 1) / 5; - let scale = fixedLayerObj.width > fixedLayerObj.height ? scaleX : scaleY; - let left = (item.location?.[0] || 0) - image.width * scale / 2 - let top = (item.location?.[1] || 0) - image.height * scale / 2 + let scaleX_ = fixedLayerObj.width / image.width * (item.scale?.[0] || 1) / 5; + let scaleY_ = fixedLayerObj.height / image.height * (item.scale?.[1] || 1) / 5; + let scale = fixedLayerObj.width > fixedLayerObj.height ? scaleX_ : scaleY_; + let offsetX = (item.location?.[0] || 0) - image.width * scale / 2 + let offsetY = (item.location?.[1] || 0) - image.height * scale / 2 + let top = fixedLayerObj.top - fixedLayerObj.height * fixedLayerObj.scaleY / 2 + let left = fixedLayerObj.left - fixedLayerObj.width * fixedLayerObj.scaleX / 2 + let scaleX = fixedLayerObj.scaleX + let scaleY = fixedLayerObj.scaleY + let opacity = 1 + let angle = 0 + let gapX = 0 + let gapY = 0 + let fillSource = image + if(item.object){ + top += item.object.top * fixedLayerObj.scaleY + left += item.object.left * fixedLayerObj.scaleX + scaleX *= item.object.scaleX + scaleY *= item.object.scaleY + opacity = item.object.opacity + angle = item.object.angle + gapX = item.object.gapX + gapY = item.object.gapY + fillSource = imageAddGapToCanvas(image, gapX, gapY); + } let rect = new fabric.Rect({ id: id, layerId: id, layerName: name, width: fixedLayerObj.width, height: fixedLayerObj.height, - top: fixedLayerObj.top - fixedLayerObj.height * fixedLayerObj.scaleY / 2, - left: fixedLayerObj.left - fixedLayerObj.width * fixedLayerObj.scaleX / 2, - scaleX: fixedLayerObj.scaleX, - scaleY: fixedLayerObj.scaleY, + top: top, + left: left, + scaleX: scaleX, + scaleY: scaleY, globalCompositeOperation: BlendMode.MULTIPLY, fill: new fabric.Pattern({ - source: image, + source: fillSource, repeat: "repeat", patternTransform: createPatternTransform(scale, item.angle || 0), - offsetX: left, // 水平偏移 - offsetY: top, // 垂直偏移 + offsetX: offsetX, // 水平偏移 + offsetY: offsetY, // 垂直偏移 }), fill_ : { source: item.path, - gapX: 0, - gapY: 0, + gapX: gapX, + gapY: gapY, width: image.width, height: image.height, }, isPrintTrims: true, - // ...(item.object || {}), }); this.canvas.add(rect); let layer = createLayer({ diff --git a/src/component/Canvas/CanvasEditor/utils/helper.js b/src/component/Canvas/CanvasEditor/utils/helper.js index 6c4b145d..3e47cd6c 100644 --- a/src/component/Canvas/CanvasEditor/utils/helper.js +++ b/src/component/Canvas/CanvasEditor/utils/helper.js @@ -1093,4 +1093,22 @@ export function traceImageContour(canvas) { ); return contour; -} \ No newline at end of file +} + +/** + * 图片添加gap转换 + * @param {HTMLCanvasElement} image - img元素 + * @param {Number} gapX - 水平gap + * @param {Number} gapY - 垂直gap + * @returns {HTMLCanvasElement} 转换后的canvas元素 +*/ +export function imageAddGapToCanvas(image, gapX, gapY) { + // 创建透明 Canvas + const tcanvas = document.createElement('canvas'); + tcanvas.width = image.width + gapX; + tcanvas.height = image.height + gapY; + const ctx = tcanvas.getContext('2d'); + ctx.clearRect(0, 0, tcanvas.width, tcanvas.height); + ctx.drawImage(image, 0, 0); + return tcanvas; +} diff --git a/src/component/Canvas/OverallCanvas/demo.vue b/src/component/Canvas/OverallCanvas/demo.vue index 8c378d4b..9e5fd8e7 100644 --- a/src/component/Canvas/OverallCanvas/demo.vue +++ b/src/component/Canvas/OverallCanvas/demo.vue @@ -139,6 +139,8 @@ @@ -197,12 +199,12 @@ name: "Print2", priority: 1, object: { - top: 150, - left: 250, + top: 450, + left: 300, scaleX: 0.5, scaleY: 0.5, opacity: 1, - angle: 45, + angle: 0, flipX: false, flipY: false, blendMode: "multiply", diff --git a/src/component/Canvas/OverallCanvas/index.vue b/src/component/Canvas/OverallCanvas/index.vue index fdb25bb3..b8cc48a7 100644 --- a/src/component/Canvas/OverallCanvas/index.vue +++ b/src/component/Canvas/OverallCanvas/index.vue @@ -33,6 +33,8 @@ const emit = defineEmits(["change-canvas", "init-canvas"]); const props = defineProps({ list: { type: Array, default: () => [] }, + width: { type: Number, required: true }, + height: { type: Number, required: true }, }); const el = ref(null); const canvasRef = ref(null); @@ -106,13 +108,13 @@ token, action: ACTIONS.UPDATE, key: KEYS.O_TOP, - value: object.top, + value: (props.height / canvas.height) * object.top, }); list.push({ token, action: ACTIONS.UPDATE, key: KEYS.O_LEFT, - value: object.left, + value: (props.width / canvas.width) * object.left, }); if (action === "rotate") { list.push({ @@ -188,6 +190,8 @@ height: cheight, fill: pattern, ...item.object, + top: item.object.top / (props.height / canvas.height), + left: item.object.left / (props.width / canvas.width), onDelete: (v) => onDeleteItem(v), }); canvas.add(rect); @@ -237,10 +241,10 @@ let value = item.value; switch (item.key) { case KEYS.O_TOP: - object.set("top", value); + object.set("top", value / (props.height / canvas.height)); break; case KEYS.O_LEFT: - object.set("left", value); + object.set("left", value / (props.width / canvas.width)); break; case KEYS.O_OPACITY: object.set("opacity", value); diff --git a/src/component/Canvas/canvasExample.vue b/src/component/Canvas/canvasExample.vue index be04b46a..945ae303 100644 --- a/src/component/Canvas/canvasExample.vue +++ b/src/component/Canvas/canvasExample.vue @@ -1,607 +1,622 @@