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,