From cb42dd69684dbeb40a853e1e7f23b05696e0b5a3 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 4 Jan 2026 15:08:02 +0330 Subject: [PATCH] fix mask in image --- src/pages/editor/components/EditorCanvas.tsx | 11 +++- .../components/canvas/ObjectRenderer.tsx | 65 +++++++++++++++++-- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/pages/editor/components/EditorCanvas.tsx b/src/pages/editor/components/EditorCanvas.tsx index 7944b3c..4160c07 100644 --- a/src/pages/editor/components/EditorCanvas.tsx +++ b/src/pages/editor/components/EditorCanvas.tsx @@ -56,8 +56,11 @@ const EditorCanvas = () => { setSelectedTableId(null); } setSelectedCellId(null); - if (transformerRef.current) { - transformerRef.current.nodes([node]); + if (transformerRef.current && layerRef.current) { + // اگر object با mask گروه شده، transformer را به Group متصل کن + const maskedGroup = layerRef.current.findOne(`#masked-${id}`); + const targetNode = maskedGroup || node; + transformerRef.current.nodes([targetNode]); transformerRef.current.getLayer()?.batchDraw(); } }; @@ -146,7 +149,9 @@ const EditorCanvas = () => { const timeoutId = setTimeout(() => { if (!layerRef.current || !transformerRef.current) return; - const node = layerRef.current.findOne(`#${selectedObjectId}`); + // اگر object با mask گروه شده، transformer را به Group متصل کن + const maskedGroup = layerRef.current.findOne(`#masked-${selectedObjectId}`); + const node = maskedGroup || layerRef.current.findOne(`#${selectedObjectId}`); if (node && transformerRef.current) { transformerRef.current.nodes([node]); diff --git a/src/pages/editor/components/canvas/ObjectRenderer.tsx b/src/pages/editor/components/canvas/ObjectRenderer.tsx index 1480d33..1c862ae 100644 --- a/src/pages/editor/components/canvas/ObjectRenderer.tsx +++ b/src/pages/editor/components/canvas/ObjectRenderer.tsx @@ -75,13 +75,19 @@ const ObjectRenderer = ({ return null; } + // برای objectهای با mask، یک obj جدید با موقعیت (0, 0) ایجاد کن + const shapeObj = shouldApplyMask + ? { ...obj, x: 0, y: 0 } + : obj; + const commonProps = { - obj, + obj: shapeObj, isSelected, transformerRef, onSelect, onUpdate, - draggable, + // اگر mask اعمال شده، shape را غیر draggable کن (Group drag می‌شود) + draggable: shouldApplyMask ? false : draggable, }; const renderMaskShape = (mask: EditorObject) => { @@ -93,8 +99,9 @@ const ObjectRenderer = ({ // موقعیت mask نسبت به object - برای overlap صحیح // mask در موقعیت مطلق است، پس باید آن را relative به object کنیم - const relativeX = (mask.x || 0); - const relativeY = (mask.y || 0); + // چون shape در موقعیت (0, 0) است، باید موقعیت mask را نسبت به shape محاسبه کنم + const relativeX = (mask.x || 0) - (obj.x || 0); + const relativeY = (mask.y || 0) - (obj.y || 0); if (mask.type === "rectangle" && mask.shapeType === "circle") { return ( @@ -223,11 +230,61 @@ const ObjectRenderer = ({ // Default: destination-out (overlap مخفی می‌شود) const compositeOp = obj.maskInvert === false ? "destination-in" : "destination-out"; + const handleGroupDragEnd = (e: Konva.KonvaEventObject) => { + const node = e.target; + onUpdate(obj.id, { + x: node.x(), + y: node.y(), + }); + }; + + const handleGroupDragMove = (e: Konva.KonvaEventObject) => { + const node = e.target; + onUpdate(obj.id, { + x: node.x(), + y: node.y(), + }); + // به‌روزرسانی transformer در حین drag + if (transformerRef.current && isSelected) { + transformerRef.current.nodes([node]); + transformerRef.current.getLayer()?.batchDraw(); + } + }; + + const handleGroupTransformEnd = () => { + if (!groupRef.current) return; + const node = groupRef.current; + const scaleX = node.scaleX(); + const scaleY = node.scaleY(); + + node.scaleX(1); + node.scaleY(1); + + onUpdate(obj.id, { + x: node.x(), + y: node.y(), + rotation: node.rotation(), + width: Math.max(5, (obj.width || 100) * scaleX), + height: Math.max(5, (obj.height || 100) * scaleY), + }); + }; + return ( { + if (groupRef.current) { + onSelect(obj.id, groupRef.current); + } + }} + onDragEnd={handleGroupDragEnd} + onDragMove={handleGroupDragMove} + onTransformEnd={handleGroupTransformEnd} > {shapeElement}