diff --git a/src/pages/editor/components/EditorCanvas.tsx b/src/pages/editor/components/EditorCanvas.tsx index e3838a2..208f580 100644 --- a/src/pages/editor/components/EditorCanvas.tsx +++ b/src/pages/editor/components/EditorCanvas.tsx @@ -227,6 +227,7 @@ const EditorCanvas = () => { const scaleX = node.scaleX(); const scaleY = node.scaleY(); + const rotation = node.rotation(); const newX = node.x(); const newY = node.y(); @@ -238,17 +239,38 @@ const EditorCanvas = () => { groupMembers.forEach((member) => { const relativeX = (member.x || 0) - oldGroupX; const relativeY = (member.y || 0) - oldGroupY; - const scaledX = relativeX * scaleX; - const scaledY = relativeY * scaleY; + + // Apply rotation + const angle = (rotation * Math.PI) / 180; + const rotatedX = relativeX * Math.cos(angle) - relativeY * Math.sin(angle); + const rotatedY = relativeX * Math.sin(angle) + relativeY * Math.cos(angle); + + // Apply scale + const scaledX = rotatedX * scaleX; + const scaledY = rotatedY * scaleY; + + const finalX = newX + scaledX; + const finalY = newY + scaledY; // Find the Konva node for this member const memberNode = layerRef.current?.findOne(`#${member.id}`) || layerRef.current?.findOne(`#masked-${member.id}`); if (memberNode) { - memberNode.x(newX + scaledX); - memberNode.y(newY + scaledY); + // برای AbstractShape و TriangleShape که از مرکز استفاده می‌کنند، باید موقعیت را تنظیم کنیم + if (member.type === "rectangle" && (member.shapeType === "triangle" || member.shapeType === "abstract")) { + // موقعیت در store گوشه بالا-چپ است، اما در render از مرکز استفاده می‌شود + const w = (member.width || 100) * scaleX; + const h = (member.height || 100) * scaleY; + memberNode.x(finalX + w / 2); + memberNode.y(finalY + h / 2); + } else { + memberNode.x(finalX); + memberNode.y(finalY); + } + memberNode.width((member.width || 100) * scaleX); memberNode.height((member.height || 100) * scaleY); + memberNode.rotation((member.rotation || 0) + rotation); memberNode.scaleX(1); memberNode.scaleY(1); } @@ -344,18 +366,30 @@ const EditorCanvas = () => { return; } - // برای مثلث و abstract، x و y مرکز است + // برای مثلث و abstract، x و y در store گوشه بالا-چپ است اما در render مرکز استفاده می‌شود if (originalMember.type === "rectangle" && (originalMember.shapeType === "triangle" || originalMember.shapeType === "abstract")) { - const cx = m.x || 0; - const cy = m.y || 0; + // محاسبه مرکز از گوشه بالا-چپ + const cx = (m.x || 0) + w / 2; + const cy = (m.y || 0) + h / 2; const rot = ((m.rotation || 0) * Math.PI) / 180; - // محاسبه چهار گوشه rectangle با rotation + // برای abstract، از radius واقعی استفاده کن (0.85 * baseRadius) + // برای triangle، از radius واقعی استفاده کن (min(width, height) / 2) + let actualRadius: number; + if (originalMember.shapeType === "abstract") { + const baseRadius = Math.min(w / 2, h / 2); + actualRadius = baseRadius * 0.85; + } else { + // triangle + actualRadius = Math.min(w / 2, h / 2); + } + + // محاسبه چهار گوشه با استفاده از radius واقعی const corners = [ - { x: -w / 2, y: -h / 2 }, - { x: w / 2, y: -h / 2 }, - { x: w / 2, y: h / 2 }, - { x: -w / 2, y: h / 2 }, + { x: -actualRadius, y: -actualRadius }, + { x: actualRadius, y: -actualRadius }, + { x: actualRadius, y: actualRadius }, + { x: -actualRadius, y: actualRadius }, ]; corners.forEach((corner) => { @@ -371,6 +405,21 @@ const EditorCanvas = () => { return; } + // برای arrow و line، x و y نقطه شروع است و width/height نقطه پایان است + if (originalMember.type === "arrow" || originalMember.type === "line") { + const startX = m.x || 0; + const startY = m.y || 0; + const endX = m.width || 0; + const endY = m.height || 0; + + // برای arrow و line، bounding box از نقطه شروع تا نقطه پایان است + minX = Math.min(minX, startX, endX); + minY = Math.min(minY, startY, endY); + maxX = Math.max(maxX, startX, endX); + maxY = Math.max(maxY, startY, endY); + return; + } + // برای سایر اشکال، x و y گوشه بالا-چپ است const cx = (m.x || 0) + w / 2; const cy = (m.y || 0) + h / 2; diff --git a/src/pages/editor/store/editorStore.ts b/src/pages/editor/store/editorStore.ts index 69528d4..d958ad1 100644 --- a/src/pages/editor/store/editorStore.ts +++ b/src/pages/editor/store/editorStore.ts @@ -771,18 +771,30 @@ export const useEditorStore = create((set, get) => { return; } - // برای مثلث و abstract، x و y مرکز است + // برای مثلث و abstract، x و y در store گوشه بالا-چپ است اما در render مرکز استفاده می‌شود if (obj.type === "rectangle" && (obj.shapeType === "triangle" || obj.shapeType === "abstract")) { - const cx = obj.x || 0; - const cy = obj.y || 0; + // محاسبه مرکز از گوشه بالا-چپ + const cx = (obj.x || 0) + w / 2; + const cy = (obj.y || 0) + h / 2; const rot = ((obj.rotation || 0) * Math.PI) / 180; - // محاسبه چهار گوشه rectangle با rotation + // برای abstract، از radius واقعی استفاده کن (0.85 * baseRadius) + // برای triangle، از radius واقعی استفاده کن (min(width, height) / 2) + let actualRadius: number; + if (obj.shapeType === "abstract") { + const baseRadius = Math.min(w / 2, h / 2); + actualRadius = baseRadius * 0.85; + } else { + // triangle + actualRadius = Math.min(w / 2, h / 2); + } + + // محاسبه چهار گوشه با استفاده از radius واقعی const corners = [ - { x: -w / 2, y: -h / 2 }, - { x: w / 2, y: -h / 2 }, - { x: w / 2, y: h / 2 }, - { x: -w / 2, y: h / 2 }, + { x: -actualRadius, y: -actualRadius }, + { x: actualRadius, y: -actualRadius }, + { x: actualRadius, y: actualRadius }, + { x: -actualRadius, y: actualRadius }, ]; corners.forEach((corner) => { @@ -798,6 +810,21 @@ export const useEditorStore = create((set, get) => { return; } + // برای arrow، x و y نقطه شروع است و width/height نقطه پایان است + if (obj.type === "arrow" || obj.type === "line") { + const startX = obj.x || 0; + const startY = obj.y || 0; + const endX = obj.width || 0; + const endY = obj.height || 0; + + // برای arrow و line، bounding box از نقطه شروع تا نقطه پایان است + minX = Math.min(minX, startX, endX); + minY = Math.min(minY, startY, endY); + maxX = Math.max(maxX, startX, endX); + maxY = Math.max(maxY, startY, endY); + return; + } + // برای سایر اشکال، x و y گوشه بالا-چپ است const cx = (obj.x || 0) + w / 2; const cy = (obj.y || 0) + h / 2;