refactor(drag): align new positions with snap grid

This commit is contained in:
moklick
2022-09-14 16:18:31 +02:00
parent e9daea7a10
commit 33d6a73dd0
+36 -13
View File
@@ -3,7 +3,6 @@ import { D3DragEvent, drag, SubjectPosition } from 'd3-drag';
import { select } from 'd3-selection'; import { select } from 'd3-selection';
import { useStoreApi } from '../../hooks/useStore'; import { useStoreApi } from '../../hooks/useStore';
import { pointToRendererPoint } from '../../utils/graph';
import { NodeDragItem, Node, SelectionDragHandler } from '../../types'; import { NodeDragItem, Node, SelectionDragHandler } from '../../types';
import { getDragItems, getEventHandlerParams, hasSelector, calcNextPosition } from './utils'; import { getDragItems, getEventHandlerParams, hasSelector, calcNextPosition } from './utils';
import { handleNodeClick } from '../../components/Nodes/utils'; import { handleNodeClick } from '../../components/Nodes/utils';
@@ -44,9 +43,18 @@ function useDrag({
const { transform, snapGrid, snapToGrid } = store.getState(); const { transform, snapGrid, snapToGrid } = store.getState();
const x = sourceEvent.touches ? sourceEvent.touches[0].clientX : sourceEvent.clientX; const x = sourceEvent.touches ? sourceEvent.touches[0].clientX : sourceEvent.clientX;
const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY; const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY;
const pointerPos = pointToRendererPoint({ x, y }, transform, snapToGrid, snapGrid);
return pointerPos; const pointerPos = {
x: (x - transform[0]) / transform[2],
y: (y - transform[1]) / transform[2],
};
// we need the snapped position in order to be able to skip unnecessary drag events
return {
xSnapped: snapToGrid ? snapGrid[0] * Math.round(pointerPos.x / snapGrid[0]) : pointerPos.x,
ySnapped: snapToGrid ? snapGrid[1] * Math.round(pointerPos.y / snapGrid[1]) : pointerPos.y,
...pointerPos,
};
}, []); }, []);
useEffect(() => { useEffect(() => {
@@ -96,19 +104,34 @@ function useDrag({
} }
}) })
.on('drag', (event: UseDragEvent) => { .on('drag', (event: UseDragEvent) => {
const { updateNodePositions, nodeInternals, nodeExtent, onNodeDrag, onSelectionDrag } = store.getState(); const {
updateNodePositions,
nodeInternals,
nodeExtent,
onNodeDrag,
onSelectionDrag,
snapGrid,
snapToGrid,
} = store.getState();
const pointerPos = getPointerPosition(event); const pointerPos = getPointerPosition(event);
// skip events without movement // skip events without movement
if ((lastPos.current.x !== pointerPos.x || lastPos.current.y !== pointerPos.y) && dragItems.current) { if (
lastPos.current = pointerPos; (lastPos.current.x !== pointerPos.xSnapped || lastPos.current.y !== pointerPos.ySnapped) &&
dragItems.current
) {
lastPos.current = {
x: pointerPos.xSnapped,
y: pointerPos.ySnapped,
};
dragItems.current = dragItems.current.map((n) => { dragItems.current = dragItems.current.map((n) => {
const updatedPos = calcNextPosition( let nextPosition = { x: pointerPos.x - n.distance.x, y: pointerPos.y - n.distance.y };
n,
{ x: pointerPos.x - n.distance.x, y: pointerPos.y - n.distance.y }, if (snapToGrid) {
nodeInternals, nextPosition.x = snapGrid[0] * Math.round(nextPosition.x / snapGrid[0]);
nodeExtent nextPosition.y = snapGrid[1] * Math.round(nextPosition.y / snapGrid[1]);
); }
const updatedPos = calcNextPosition(n, nextPosition, nodeInternals, nodeExtent);
n.position = updatedPos.position; n.position = updatedPos.position;
n.positionAbsolute = updatedPos.positionAbsolute; n.positionAbsolute = updatedPos.positionAbsolute;