Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix transformer resizer when draggin from top or left #602

Merged
merged 5 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ describe('tabsbar.business tests', () => {
font: { fontSize: 14, fontFamily: 'Arial' },
});

console.log({ tabs }, { containerWidth }, { minTabWidth });
console.log({ result });

const totalSum = _sum(result.widthList) + (tabs.length - 1) * tabsGap;
console.log('totalSum: ', totalSum);

// Assert
expect(result.widthList[0]).not.toBe(0);
Expand Down
31 changes: 30 additions & 1 deletion src/pods/canvas/canvas.pod.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createRef, useMemo, useRef, useState } from 'react';
import { createRef, useEffect, useMemo, useRef, useState } from 'react';
import Konva from 'konva';
import { useCanvasContext } from '@/core/providers';
import { Layer, Line, Rect, Stage, Transformer } from 'react-konva';
Expand Down Expand Up @@ -109,6 +109,35 @@ export const CanvasPod = () => {
window.__TESTING_KONVA_LAYER__ = layerRef.current;
}

// We need this trick, if the user plays hard with the transfoermer,
// resizing quite fast it mabe get out of sync wit the shape
// so once the transformer ends, we reassign the nodes to the transformer
// and redraw the layer
useEffect(() => {
const transformer = transformerRef.current;
if (!transformer) return;

const handleTransformEnd = () => {
const selectedShapes = selectedShapesRefs.current;
if (isTransfomerBeingDragged || !transformer) return;

if (selectedShapes && selectedShapes.length === 1) {
transformer.nodes([]);
transformer.getLayer()?.batchDraw();
setTimeout(() => {
transformer.nodes(selectedShapes); // Vuelve a asignar los nodos
transformer.getLayer()?.batchDraw(); // Redibuja la capa nuevamente
}, 0);
}
};

transformer.on('transformend', handleTransformEnd);

return () => {
transformer.off('transformend', handleTransformEnd);
};
}, [transformerRef.current]);

{
/* TODO: add other animation for isDraggerOver */
}
Expand Down
52 changes: 50 additions & 2 deletions src/pods/canvas/use-transform.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const useTransform = (
selectedShapesRefs,
transformerRef,
selectedShapeType,
getSelectedShapeData,
} = useCanvasContext().selectionInfo;

const setTransfomerSingleSelection = () => {
Expand Down Expand Up @@ -46,14 +47,61 @@ export const useTransform = (
}
}, [selectedShapesIds]);

// If the user isDragging from the top or left anchot we need to treat
// it as an special case, since the X,Y top position change and it may
// impact the size of the transformer (see where this is being used)
const isDraggingFromTopAnchor = () => {
const transformer = transformerRef.current;
if (!transformer) {
return false;
}

return (
transformer?.getActiveAnchor() === 'top-left' ||
transformer?.getActiveAnchor() === 'top-center' ||
transformer?.getActiveAnchor() === 'top-right'
);
};

const isDraggingFromLeftAnchor = () => {
const transformer = transformerRef.current;
if (!transformer) {
return false;
}

return (
transformer?.getActiveAnchor() === 'top-left' ||
transformer?.getActiveAnchor() === 'middle-left' ||
transformer?.getActiveAnchor() === 'bottom-left'
);
};

const updateSingleItem = (node: Node<NodeConfig>, skipHistory: boolean) => {
const scaleX = node.scaleX();
const scaleY = node.scaleY();
const position = { x: node.x(), y: node.y() };
const selectedShapeId = selectedShapesIds[0];

const newWidth = node.width() * scaleX;
const newHeight = node.height() * scaleY;
let newWidth = node.width() * scaleX;
let newHeight = node.height() * scaleY;

// Top and Left anchor, for this cases we need to do an extra calc
// to balance top of X,Y coordinates (origin) and transformer size
// if we don't to this adjustements in this case the shape may be
// up or down instead of resizing
if (isDraggingFromTopAnchor()) {
const oldShapedata = getSelectedShapeData();
const oldHeight = oldShapedata?.height ?? 0;

newHeight = oldHeight + (oldShapedata?.y ?? 0) - position.y;
}

if (isDraggingFromLeftAnchor()) {
const oldShapedata = getSelectedShapeData();
const oldWidth = oldShapedata?.width ?? 0;

newWidth = oldWidth + (oldShapedata?.x ?? 0) - position.x;
}

updateShapeSizeAndPosition(
selectedShapeId,
Expand Down
Loading