From fdb6a87ab483e386917884966d6f11d9d4a83495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Mon, 2 Feb 2026 09:47:10 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8D=B0=E8=8A=B1?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E6=8E=92=E5=BA=8Fpriority?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanvasEditor/commands/LayerCommands.js | 2 +- .../components/SelectMenuPanel/index.vue | 4 +- src/component/Canvas/CanvasEditor/index.vue | 2 +- .../CanvasEditor/managers/CanvasManager.js | 46 +++++++------ src/component/Canvas/canvasExample.vue | 69 ++++++++++--------- 5 files changed, 64 insertions(+), 59 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js index 88f9afb1..9c79d9ce 100644 --- a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js @@ -283,7 +283,7 @@ export class PasteLayerCommand extends Command { if(this.newLayer.isPrintTrims){ this.layers.value.forEach((layer) => { if (layer.isPrintTrimsGroup) { - layer.children.push(this.newLayer); + layer.children.unshift(this.newLayer); } }) }else if (this.insertIndex !== undefined && this.insertIndex !== null) { diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue index 447bd6b7..26a16fa2 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue @@ -126,8 +126,8 @@ :options="selectOptions" @change="(e) => changeFillRepeat(e, v)" :disabled=" - v.layer?.metadata?.level2Type === - 'Embroidery' + v.layer?.metadata?.sourceData?.type === + 'trims' " /> diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index d1b21f2c..53f4455b 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -991,7 +991,7 @@ defineExpose({ }, updateOtherLayers: async (otherData) => { await new Promise((resolve) => optimizeCanvasRendering(canvasManager.canvas, resolve)); - await canvasManager?.createOtherLayers?.(otherData, true); + await canvasManager?.createOtherLayers?.(otherData); layerManager.activeLayerId.value = "" layerManager?.sortLayers(); await layerManager?.updateLayersObjectsInteractivity?.(true); diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 75c547dd..77ee63ed 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -1160,7 +1160,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') const flScaleY = fixedLayerObj.scaleY const prints = []; const trims = []; - objects.forEach((v) => { + objects.forEach((v, i) => { const label = glayer.children.find((v_) => (v_.id === v.layerId || v_.id === v.id)); const sourceData = label?.metadata?.sourceData; if(!sourceData) return; @@ -1174,7 +1174,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') scale: [0, 0], angle: v.angle, name: sourceData.name, - priority: sourceData.priority, + priority: i + 1, object:{ top: 0, left: 0, @@ -1240,8 +1240,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') } }) // prints.sort((a, b) => a.ifSingle ? 1 : -1); - prints.forEach((v, i) => v.priority = i + 1); - trims.forEach((v, i) => v.priority = i + 1); + // prints.forEach((v, i) => v.priority = i + 1); + // trims.forEach((v, i) => v.priority = i + 1); return {prints, trims}; } @@ -1507,7 +1507,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') * 创建其他图层:印花、颜色、元素... * @param {Object} otherData - 其他图层数据 */ - async createOtherLayers(otherData, isUpdate = false) { + async createOtherLayers(otherData) { if (!otherData) return console.warn("otherData 为空不需要添加"); this.canvas.loading.value = true; let resolve = ()=>{}; @@ -1515,17 +1515,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') const otherData_ = JSON.parse(JSON.stringify(otherData)); console.log("==========创建其他图层", otherData_); - const updateColor = !!otherData_.color; - const updateSpecialGroup = !!otherData_.printObject || !!otherData_.trims; // 删除颜色图层和特殊组图层 - const ids = []; - if(isUpdate){ - updateColor && ids.push(SpecialLayerId.COLOR) - updateSpecialGroup && ids.push(SpecialLayerId.SPECIAL_GROUP) - }else{ - ids.push(SpecialLayerId.COLOR) - ids.push(SpecialLayerId.SPECIAL_GROUP) - } + const ids = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP]; this.layers.value = this.layers.value.filter((layer) => { if(ids.includes(layer.id)){ ids.push(...layer.children?.map((child) => child.id)); @@ -1533,11 +1524,15 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') } return true; }) - this.canvas.getObjects().forEach((v) => ids.includes(v.id) && this.canvas.remove(v)) + this.canvas.getObjects().forEach((v) => { + if(ids.includes(v.id) || ids.includes(v.layerId)){ + this.canvas.remove(v) + } + }) // 创建颜色图层 - otherData_.color && await this.createColorLayer(otherData_.color); + await this.createColorLayer(otherData_.color); const printTrimsLayers = [];// 印花和元素图层 const singleLayers = [];// 平铺图层 @@ -1555,7 +1550,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') trims.type = "trims"; printTrimsLayers.unshift({...trims}); }) - if(isUpdate ? updateSpecialGroup : true){ + if(printTrimsLayers.length || singleLayers.length){ await this.createPrintTrimsLayers(printTrimsLayers, singleLayers); } await this.changeCanvas(); @@ -1686,7 +1681,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') let opacity = 1 let flipX = false; let flipY = false; - let blendMode = BlendMode.MULTIPLY; + let blendMode = BlendMode.NORMAL; // if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常 if(item.object){ opacity = item.object.opacity @@ -1712,7 +1707,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') hasBorders: true, isPrintTrims: true, }); - this.canvas.add(image); + // this.canvas.add(image); let layer = createLayer({ id: id, name: name, @@ -1723,7 +1718,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') isPrintTrims: true, blendMode: blendMode, fabricObjects: [image.toObject(["id", "layerId", "layerName"])], - metadata: {sourceData: item, level2Type: item.level2Type}, + metadata: {sourceData: item}, + object: image, }) children.push(layer); }; @@ -1808,7 +1804,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') }, isPrintTrims: true, }); - this.canvas.add(rect); + // this.canvas.add(rect); let layer = createLayer({ id: id, name: name, @@ -1820,6 +1816,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') blendMode: blendMode, fabricObjects: [rect.toObject(["id", "layerId", "layerName"])], metadata: {sourceData: item}, + object: rect, }) children.push(layer); }; @@ -1836,6 +1833,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') // children.push(layer); // } if(children.length === 0) return; + // 印花元素排序 + children.sort((a, b) => b.metadata.sourceData.priority - a.metadata.sourceData.priority); + children.forEach(layer => { + this.canvas.add(layer.object); + }); const groupRect = new fabric.Rect({}); await this.setObjecCliptInfo(groupRect); // 插入组图层 diff --git a/src/component/Canvas/canvasExample.vue b/src/component/Canvas/canvasExample.vue index 19efe42a..7a961666 100644 --- a/src/component/Canvas/canvasExample.vue +++ b/src/component/Canvas/canvasExample.vue @@ -337,46 +337,49 @@ color: { rgba: { r: 255, g: 0, b: 0, a: 1 } }, printObject: { prints: [ - // { - // ifSingle: false, - // level2Type: "Pattern", - // designType: "Library", - // path: "/src/assets/images/canvas/yinhua1.jpg", - // location: [800, 600], - // scale: [1, 1], - // angle: 0, - // object: { - // top: 300, - // left: 400, - // scaleX: 0.5, - // scaleY: 0.5, - // opacity: 1, - // angle: 0, - // flipX: false, - // flipY: false, - // blendMode: "multiply", - // gapX: 0, - // gapY: 0, - // }, - // }, - // { - // ifSingle: true, - // level2Type: "Pattern", - // designType: "Library", - // path: "/src/assets/images/canvas/yinhua1.jpg", - // location: [550, 650], - // scale: [0.15, 0.2], - // angle: 0, - // }, + { + ifSingle: false, + level2Type: "Pattern", + designType: "Library", + path: "/src/assets/images/canvas/yinhua1.jpg", + location: [800, 600], + scale: [1, 1], + angle: 0, + priority: 1, + object: { + top: 300, + left: 400, + scaleX: 0.5, + scaleY: 0.5, + opacity: 1, + angle: 0, + flipX: false, + flipY: false, + // blendMode: "multiply", + gapX: 0, + gapY: 0, + }, + }, { ifSingle: true, level2Type: "Pattern", designType: "Library", path: "/src/assets/images/canvas/yinhua1.jpg", - location: [700, 400], - scale: [0.1, 0.133], + location: [550, 650], + scale: [0.15, 0.2], angle: 0, + priority: 2, }, + // { + // ifSingle: true, + // level2Type: "Pattern", + // designType: "Library", + // path: "/src/assets/images/canvas/yinhua1.jpg", + // location: [700, 400], + // scale: [0.1, 0.133], + // angle: 0, + // priority: 3, + // }, ], }, }); From 56916c8d109e5ca0c0ee2d8679b6a1e0f288a698 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Mon, 2 Feb 2026 10:31:37 +0800 Subject: [PATCH 2/8] fix --- .../Detail/detailRight/editPrintElement.vue | 6 +- src/component/Detail/model/modelPosition.vue | 263 ++++++++++++------ src/store/Detail/designDetail.ts | 2 +- 3 files changed, 183 insertions(+), 88 deletions(-) diff --git a/src/component/Detail/detailRight/editPrintElement.vue b/src/component/Detail/detailRight/editPrintElement.vue index 21472da3..2e51f2ea 100644 --- a/src/component/Detail/detailRight/editPrintElement.vue +++ b/src/component/Detail/detailRight/editPrintElement.vue @@ -804,7 +804,8 @@ export default defineComponent({ }; } }; - elList[item.index].sort = moveIndex; + let index = elList.findIndex((elListItem:any)=>item.id == elListItem.id) + elList[index].sort = moveIndex; moveItem(); } } @@ -866,7 +867,8 @@ export default defineComponent({ el: elArr[i], // sort: elArr.length - i -1, sort: sortMap[arr[i].priority], - index: i, + id: `${arr[i].priority}_${Date.now() + i}`, + // index: i, uniqueId:arr[i]?.uniqueId || 99999, }); } diff --git a/src/component/Detail/model/modelPosition.vue b/src/component/Detail/model/modelPosition.vue index 3646962d..ad20795d 100644 --- a/src/component/Detail/model/modelPosition.vue +++ b/src/component/Detail/model/modelPosition.vue @@ -8,8 +8,8 @@ -
- +
+
@@ -165,6 +165,30 @@ export default defineComponent({ if(moveableInstance.value)moveableInstance.value.updateRect() }, 200); } + function getTransformValues(transformStr) { + let scaleX = 1; + let scaleY = 1; + let rotate = 0; + if (!transformStr || transformStr === 'none') { + return { scaleX, scaleY, rotate }; + } + const scaleXMatch = transformStr.match(/scaleX\(([-\d.]+)\)/); + if (scaleXMatch) { + scaleX = parseFloat(scaleXMatch[1]); + } + const scaleYMatch = transformStr.match(/scaleY\(([-\d.]+)\)/); + if (scaleYMatch) { + scaleY = parseFloat(scaleYMatch[1]); + } + const rotateMatch = transformStr.match(/rotate\(([-\d.]+)(deg|rad)?\)/); + if (rotateMatch) { + rotate = parseFloat(rotateMatch[1]); + if (rotateMatch[2] === 'rad') { + rotate = rotate * (180 / Math.PI); + } + } + return { scaleX, scaleY, rotate }; + } const initMoveableForSelected = () => { // 销毁旧的实例 if(selectItem.imgDomIndex == -1)return @@ -185,6 +209,90 @@ export default defineComponent({ snapThreshold: 5, edge: false, }); + const createCustomButtons = () => { + const flipX = document.createElement('div'); + const flipY = document.createElement('div'); + flipX.className = 'custom-btn'; + flipX.innerHTML = ` + + + + + + + + + + + + + + + `; + flipY.className = 'custom-btn'; + flipY.innerHTML = ` + + + + + + + + + + + + + + + `; + let moveableControlBox = getDetailListDom.moveableContainer.querySelector('.moveable-control-box') + // 添加到 Moveable 容器或目标元素 + moveableControlBox.appendChild(flipX); + moveableControlBox.appendChild(flipY); + + // 绑定事件 + moveableControlBox.addEventListener('click', (e:any) => { + e.stopPropagation(); + const btn = e.target.closest('.btn'); + if (!btn) return; + + handleCustomButtonClick(btn.className?.animVal); + }); + }; + + const handleCustomButtonClick = (btnClass:any) => { + const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; + let transform = getTransformValues(frontStyle.style.transform) + switch (btnClass) { + case 'btn flip-x': + transform.scaleX = transform.scaleX == -1?1:-1 + frontStyle.style.transform = `rotate(${transform.rotate}deg) scaleX(${transform.scaleX}) scaleY(${transform.scaleY})`; + break; + case 'btn flip-y': + transform.scaleY = transform.scaleY == -1?1:-1 + frontStyle.style.transform = `rotate(${transform.rotate}deg) scaleX(${transform.scaleX}) scaleY(${transform.scaleY})`; + break; + } + }; + const updateTransform = () => { + let leftClass = '.moveable-control-box .moveable-w' + let bottomClass = '.moveable-control-box .moveable-s' + + const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; + let transform = getTransformValues(frontStyle.style.transform) + // leftClass = transform.scaleX == -1?'.moveable-control-box .moveable-e':leftClass + // bottomClass = transform.scaleY == -1?'.moveable-control-box .moveable-n':bottomClass + + let customFlipX = getDetailListDom.moveableContainer.querySelector('.moveable-control-box .flip-x') + let customFlipY = getDetailListDom.moveableContainer.querySelector('.moveable-control-box .flip-y') + let leftBorder = getDetailListDom.moveableContainer.querySelector(leftClass) + let bottomBorder = getDetailListDom.moveableContainer.querySelector(bottomClass) + customFlipX.parentNode.style.transform = leftBorder.style.transform + customFlipY.parentNode.style.transform = bottomBorder.style.transform + } + createCustomButtons() + updateTransform() let startPosition = {//记录初始位置 left: 0, top: 0, @@ -195,11 +303,11 @@ export default defineComponent({ } moveableInstance.value.on('scaleStart', ({ target, direction }) => { const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; - if (!frontStyle?.mirror){ - let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/); - let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/); - frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false }; - } + // let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/); + // let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/); + let scaleX = ['1','1'] + let scaleY = ['1','1'] + frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false }; startSize.width = Number(parseInt(target.style.width)) startSize.height = Number(parseInt(target.style.height)) startPosition.left = Number(parseInt(target.style.left)) @@ -207,11 +315,11 @@ export default defineComponent({ }); moveableInstance.value.on('rotateStart', ({ target, direction }) => { const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; - if (!frontStyle?.mirror){ - let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/); - let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/); - frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false }; - } + // let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/); + // let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/); + let scaleX = ['1','1'] + let scaleY = ['1','1'] + frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false }; }); moveableInstance.value.on('dragStart', ({ target, clientX, clientY }) => { startPosition = { @@ -229,22 +337,41 @@ export default defineComponent({ const updateElementTransform = (element, rotateDeg = null) => { const currentTransform = element.style?.transform || ''; const currentRotates = (currentTransform.match(/rotate[XYZ]?\([^)]+\)/g) || []); + const scaleXMatch = currentTransform.match(/scaleX\(([^)]+)\)/); + const scaleYMatch = currentTransform.match(/scaleY\(([^)]+)\)/); + // 移除所有需要单独处理的变换 let otherTransforms = currentTransform - .replace(/scaleX\([^)]*\)/g, '') // 移除所有 scaleX(...) - .replace(/scaleY\([^)]*\)/g, '') // 移除所有 scaleY(...) .replace(/rotate[XYZ]?\([^)]+\)/g, '') + .replace(/scaleX\([^)]+\)/g, '') + .replace(/scaleY\([^)]+\)/g, '') .replace(/\s+/g, ' ') .trim(); const transforms = []; - if (element.mirror && element.mirror.x) transforms.push('scaleX(-1)'); - if (element.mirror && element.mirror.y) transforms.push('scaleY(-1)'); - if (otherTransforms) transforms.push(otherTransforms); + // 处理旋转 if (rotateDeg !== null) { transforms.push(`rotate(${rotateDeg}deg)`); } else if (currentRotates.length > 0) { transforms.push(...currentRotates); } + // 处理scaleX + if (element.mirror && element.mirror.x) { + transforms.push('scaleX(-1)'); + } else if (scaleXMatch) { + // 保留原有的scaleX + transforms.push(`scaleX(${scaleXMatch[1]})`); + } + // 处理scaleY + if (element.mirror && element.mirror.y) { + transforms.push('scaleY(-1)'); + } else if (scaleYMatch) { + // 保留原有的scaleY + transforms.push(`scaleY(${scaleYMatch[1]})`); + } + // 添加其他变换 + if (otherTransforms) { + transforms.push(otherTransforms); + } element.style.transform = transforms.join(' ').trim(); }; @@ -254,18 +381,9 @@ export default defineComponent({ // console.log('scaleStart', e); const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; - // 确保 mirror 对象存在并正确初始化 - if (!frontStyle.mirror) { - frontStyle.mirror = { x: false, y: false }; - } - // 清除可能存在的重复镜像变换 - updateElementTransform(frontStyle); + // updateElementTransform(frontStyle); - // let width = parseFloat(frontStyle.style.width); - // let height = parseFloat(frontStyle.style.height); - // let left = parseFloat(frontStyle.style.left) || 0; - // let top = parseFloat(frontStyle.style.top) || 0; let width = startSize.width let height = startSize.height let left = startPosition.left; @@ -273,29 +391,10 @@ export default defineComponent({ let rotation = 0; const originalRatio = width / height; - - // 提取当前旋转角度 if (frontStyle.style.transform) { const match = frontStyle.style.transform.match(/rotate\(([-\d.]+)deg\)/); if (match) rotation = parseFloat(match[1]); } - - const getAdjustedCorner = (corner, rot) => { - const rad = rot * (Math.PI / 180); - const x = corner.x * Math.cos(rad) - corner.y * Math.sin(rad); - const y = corner.x * Math.sin(rad) + corner.y * Math.cos(rad); - const threshold = 0.5; - return { - x: Math.abs(x) > threshold ? (x > 0 ? 1 : -1) : 0, - y: Math.abs(y) > threshold ? (y > 0 ? 1 : -1) : 0 - }; - }; - - // 根据旋转角度调整方向 - // if (rotation !== 0) { - // direction = getAdjustedCorner({ x: direction[0], y: direction[1] }, rotation); - // direction = [direction.x, direction.y]; - // } const isDiagonal = Math.abs(direction[0]) === 1 && Math.abs(direction[1]) === 1; const processAxis = (axis, val, distVal, dir, pos, keepRatio = false, otherAxisResult = null) => { @@ -303,46 +402,19 @@ export default defineComponent({ const isWidth = axis === 'width'; let newVal = val * distVal; - // 翻转处理 - 只在值真正变为负值时触发镜像 - // if (newVal < 0) { - // frontStyle.mirror[mirrorKey] = !frontStyle.mirror[mirrorKey]; - // newVal = Math.abs(newVal); - // } else if (newVal === 0) { - // // 防止值变为0 - // newVal = 1; - // } + if(newVal < 10) newVal = 10; // 位置调整 const shouldMove = (!frontStyle.mirror[mirrorKey] && dir === -1) || (frontStyle.mirror[mirrorKey] && dir === 1); // 保持宽高比 - // if (keepRatio && otherAxisResult) { - // newVal = isWidth ? otherAxisResult.newVal * originalRatio : otherAxisResult.newVal / originalRatio; - // } - const adjustPos = shouldMove ? pos - (newVal - val) : pos; return { newVal, adjustPos }; }; - // 处理缩放 if (isDiagonal) { - // const mainAxis = Math.abs(dist[0] - 1) > Math.abs(dist[1] - 1) ? 'width' : 'height'; - // const crossAxis = mainAxis === 'width' ? 'height' : 'width'; - - // const mainDir = mainAxis === 'width' ? dist[0] : dist[1]; - // const crossDir = crossAxis === 'width' ? dist[0] : dist[1]; - - // const mainDelta = mainAxis === 'width' ? dist[0] : dist[1]; - - // const mainResult = processAxis(mainAxis, mainAxis === 'width' ? width : height, mainDelta, mainDir, mainAxis === 'width' ? left : top); - // const crossResult = processAxis(crossAxis, crossAxis === 'width' ? width : height, 1, crossDir, crossAxis === 'width' ? left : top, true, mainResult); - - // frontStyle.style.width = mainAxis === 'width' ? mainResult.newVal + 'px' : crossResult.newVal + 'px'; - // frontStyle.style.height = mainAxis === 'height' ? mainResult.newVal + 'px' : crossResult.newVal + 'px'; - // frontStyle.style.left = mainAxis === 'width' ? mainResult.adjustPos + 'px' : crossResult.adjustPos + 'px'; - // frontStyle.style.top = mainAxis === 'height' ? mainResult.adjustPos + 'px' : crossResult.adjustPos + 'px'; const scale = (dist[0] < 0 && dist[1] < 0) ? -Math.sqrt(dist[0] * dist[1]) : Math.sqrt(dist[0] * dist[1]); const widthResult = processAxis('width', width, scale, direction[0], left); const heightResult = processAxis('height', height, scale, direction[1], top); @@ -363,13 +435,12 @@ export default defineComponent({ // 更新变换,确保正确的顺序 updateElementTransform(frontStyle); + //更新自定义按钮 + updateTransform() }); moveableInstance.value.on('rotate', ({ target, beforeRotate }) => { let frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; - if (!frontStyle.mirror) { - frontStyle.mirror = { x: false, y: false }; - } - const { x: isMirroredX, y: isMirroredY } = frontStyle.mirror; + // 获取当前旋转角度 const currentTransform = frontStyle.style?.transform || ''; const rotateMatch = currentTransform.match(/rotate\(([-\d.]+)deg\)/); let currentAngle = 0; @@ -379,6 +450,7 @@ export default defineComponent({ currentAngle = parsed; } } + // 计算新角度 const newBeforeRotate = parseFloat(beforeRotate) || 0; if (!window._lastRotateData) { window._lastRotateData = { @@ -387,17 +459,16 @@ export default defineComponent({ }; } const delta = newBeforeRotate - window._lastRotateData.beforeRotate; - const shouldReverse = (isMirroredX && !isMirroredY) || (!isMirroredX && isMirroredY); - let newAngle; - if (shouldReverse) { - newAngle = window._lastRotateData.angle - delta; - } else { - newAngle = window._lastRotateData.angle + delta; - } + let newAngle = window._lastRotateData.angle + delta; + // 规范化角度到 0-360 范围 newAngle = ((newAngle % 360) + 360) % 360; + window._lastRotateData.beforeRotate = newBeforeRotate; window._lastRotateData.angle = newAngle; + // 更新元素变换 updateElementTransform(frontStyle, newAngle); + // 更新自定义按钮 + updateTransform(); }); // 可选:在rotateStart时重置 @@ -602,6 +673,7 @@ export default defineComponent({ updataPosition, updateRect, initMoveableForSelected, + getTransformValues, } }, @@ -701,6 +773,27 @@ export default defineComponent({ background-color: #ffff; } } + :deep(.custom-btn){ + width: 2.8rem; + height: 2.8rem; + margin: .5rem; + border-radius: 50%; + position: absolute; + left: 0; + top: 0; + will-change: transform; + margin-left: -1.4rem; + margin-top: -1.4rem; + > svg{ + cursor: pointer; + } + .flip-y{ + transform: translateY(100%); + } + .flip-x{ + transform: translateX(-100%); + } + } :deep(.moveable-rotation-control){ border-radius: 50%; } diff --git a/src/store/Detail/designDetail.ts b/src/store/Detail/designDetail.ts index 8547783a..6e6f94ba 100644 --- a/src/store/Detail/designDetail.ts +++ b/src/store/Detail/designDetail.ts @@ -81,7 +81,7 @@ const DesignDetail : Module = { left:v.layersObject[i].position?.[1], width:v.layersObject[i].imageSize?.[0], height:v.layersObject[i].imageSize?.[1], - transform:`scaleX(${v.layersObject[i].transpose?.[0] || 1}) scaleY(${v.layersObject[i].transpose?.[1] || 1}) rotate(${v.layersObject?.[i]?.rotate || 0}deg)`, + transform:`rotate(${v.layersObject?.[i]?.rotate || 0}deg) scaleX(${v.layersObject[i].transpose?.[0] || 1}) scaleY(${v.layersObject[i].transpose?.[1] || 1})`, } v.layersObject[i].centers={ left:0, From 4913d02c937bfdf0906c3ce3cb1a87759851b4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Mon, 2 Feb 2026 10:37:13 +0800 Subject: [PATCH 3/8] fix --- src/component/Canvas/CanvasEditor/managers/CanvasManager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 77ee63ed..b7583264 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -1834,7 +1834,9 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') // } if(children.length === 0) return; // 印花元素排序 - children.sort((a, b) => b.metadata.sourceData.priority - a.metadata.sourceData.priority); + if(new Set(children.map(v => v.metadata.sourceData.priority)).size === children.length){ + children.sort((a, b) => b.metadata.sourceData.priority - a.metadata.sourceData.priority); + } children.forEach(layer => { this.canvas.add(layer.object); }); From 73d912d3cd3bf44b563356c425159501bb354712 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Mon, 2 Feb 2026 11:08:20 +0800 Subject: [PATCH 4/8] =?UTF-8?q?detail=E8=AE=BE=E7=BD=AE=E5=8D=B0=E8=8A=B1?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Detail/detailRight/editPrintElement.vue | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/component/Detail/detailRight/editPrintElement.vue b/src/component/Detail/detailRight/editPrintElement.vue index 2e51f2ea..7c319f06 100644 --- a/src/component/Detail/detailRight/editPrintElement.vue +++ b/src/component/Detail/detailRight/editPrintElement.vue @@ -174,7 +174,6 @@ export default defineComponent({ type:props.type, imgDomIndex:-1, direction:'',//判断点的那条边 - printZIndex:2,//印花优先级 sketchWH:{ width:0, height:0, @@ -247,6 +246,11 @@ export default defineComponent({ const addPrintELement = async (data:any)=>{ if(!editPrintElementData.isSketchLoad)return let {scale,location} = await setScaleLocation(data) + let allElementPrint = [ + ...(editPrintElementData.selectDetail.printObject.prints || []), + ...(editPrintElementData.selectDetail.trims.prints || []), + ] + let printIndex = Math.max(...allElementPrint.map(item => item.priority)) + 1 let item = { angle:0, designType:data.designType, @@ -255,7 +259,7 @@ export default defineComponent({ location:editPrintElementData.stateOverallSingle == 'single'?location:[0,0], minIOPath:data.minIOPath || data.originalUrl, path:data.url, - priority:editPrintElementData.printZIndex, + priority:printIndex, scale, globalCompositeOperation:'', } @@ -286,7 +290,7 @@ export default defineComponent({ angle : item.pattern.transform.rotateZ, // angle : !this.overallSingle ? 0:item.pattern.transform.rotateZ, location : location, - priority:index, + priority:item.priority, scale: scale, designType:item.designType, level2Type:item.level2Type, @@ -301,10 +305,14 @@ export default defineComponent({ if(editPrintElementData.printStyleList[props.type].single.length>0){ sort(editPrintElementData.printStyleList[props.type].single) } + if(editPrintElementData.printStyleList[props.type].overall.length>0){ + sort(editPrintElementData.printStyleList[props.type].overall) + } editPrintElementData.printStyleList[props.type].overall.forEach((item:any)=>{ data.push(setData(item,index)) index++ }) + console.log(editPrintElementData.printStyleList[props.type].single) editPrintElementData.printStyleList[props.type].single.forEach((item:any)=>{ data.push(setData(item,index)) index++ @@ -357,7 +365,6 @@ export default defineComponent({ }, designOpenrtionBtn:false } - editPrintElementData.printZIndex++ item.pattern = pattern if(item.object){ @@ -518,7 +525,6 @@ export default defineComponent({ let scale = Number(editPrintElementDom.imgDom.children[0].style.transform?.split('scale(')[1]?.split(')')[0]) let rotateZ = Number(editPrintElementDom.imgDom.children[0].style.transform?.split('rotateZ(')[1]?.split('deg')[0]) editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle][index].pattern.designOpenrtionBtn = true - // editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle][index].pattern.style.zIndex = editPrintElementData.printZIndex++ editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle][index].pattern.transform = { scale:scale, rotateZ:rotateZ?rotateZ:0, @@ -652,7 +658,6 @@ export default defineComponent({ top:editPrintElementDom.imgDom.offsetTop+'px', height:editPrintElementDom.imgDom.offsetHeight+'px', width:editPrintElementDom.imgDom.offsetWidth+'px', - // zIndex:editPrintElementData.printZIndex } document.removeEventListener('mousemove',sizeMouseMove) document.removeEventListener('touchmove',sizeTouchmove) @@ -836,6 +841,7 @@ export default defineComponent({ collItemSize.elList.forEach((elItem:any)=>{ let clothesIndex = arr.findIndex((item:any)=>item.uniqueId == elItem.uniqueId) arr[clothesIndex].pattern.style.zIndex = elItem.sort + arr[clothesIndex].priority = elItem.id.split('_')[0] // let clothesId = editPrintElementData.designDetail.clothes[clothesIndex].id // editPrintElementData.designDetail.clothes[clothesIndex].priority = elItem.sort // let frontIndex = editPrintElementData.frontBack_.front.findIndex((item:any)=>item.id == clothesId) @@ -856,7 +862,7 @@ export default defineComponent({ let arr:any = editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle] arr.forEach((item,index) => {item.uniqueId = `${Date.now()}_${index}`}); - + console.log(arr) const sortedArray = [...arr].sort((a, b) => a.priority - b.priority); const sortMap = {} as any; sortedArray.forEach((item, index) => { From fe72df0c07e43837ade19d8df99d6ed1a4ae9df6 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Mon, 2 Feb 2026 11:30:26 +0800 Subject: [PATCH 5/8] fix --- src/component/Detail/detailRight/editPrintElement.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/Detail/detailRight/editPrintElement.vue b/src/component/Detail/detailRight/editPrintElement.vue index 7c319f06..05805d3f 100644 --- a/src/component/Detail/detailRight/editPrintElement.vue +++ b/src/component/Detail/detailRight/editPrintElement.vue @@ -89,8 +89,8 @@ - - + +
- +
@@ -160,7 +160,6 @@ export default defineComponent({ selectDetail:computed(()=>store.state.DesignDetail.selectDetail), currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType), currentPrintElement:computed(()=>store.state.DesignDetail.currentPrintElement), - systemDesignerPercentage:0, printStyleList:{ print:{ single:[], @@ -344,10 +343,9 @@ export default defineComponent({ top = item.location[1] / editPrintElementData.sketchWH.scale[1] }else{ //overall - editPrintElementData.systemDesignerPercentage = item.scale[0]*1000 left = item.location[0] / editPrintElementData.sketchWH.scale[0] top = item.location[1] / editPrintElementData.sketchWH.scale[1] - editPrintElementData.systemDesignerPercentage = item.scale?.[0]?item.scale[0]*100:30 + item.scale = [1,1] } let pattern = { centers:{left:0,top:0}, From 4bd7740753a95b6b57cbd4445903f1b5724bc9dc Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Mon, 2 Feb 2026 13:30:43 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddetail=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8D=B0=E8=8A=B1sort=E5=80=BC=E8=AE=BE=E7=BD=AE=E4=B8=8D?= =?UTF-8?q?=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Detail/detailRight/editPrintElement.vue | 118 ++++++++++-------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/src/component/Detail/detailRight/editPrintElement.vue b/src/component/Detail/detailRight/editPrintElement.vue index dd145724..c55f9219 100644 --- a/src/component/Detail/detailRight/editPrintElement.vue +++ b/src/component/Detail/detailRight/editPrintElement.vue @@ -89,8 +89,8 @@
- - + +