Merge pull request #4790 from xyflow/fix/node-drag

Fix node drag while zooming
This commit is contained in:
Peter Kogo
2024-11-08 11:21:51 +01:00
committed by GitHub
6 changed files with 39 additions and 12 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@xyflow/system': patch
'@xyflow/react': patch
'@xyflow/svelte': patch
---
Fix node dragging & resizing while zooming on flow that does not cover whole browser window.
@@ -56,13 +56,14 @@ function ResizeControl({
domNode: resizeControlRef.current,
nodeId: id,
getStoreItems: () => {
const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin } = store.getState();
const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin, domNode } = store.getState();
return {
nodeLookup,
transform,
snapGrid,
snapToGrid,
nodeOrigin,
paneDomNode: domNode,
};
},
onChange: (change: XYResizerChange, childChanges: XYResizerChildChange[]) => {
@@ -35,7 +35,7 @@
let className: $$Props['class'] = '';
export { className as class };
const { nodeLookup, snapGrid, viewport, nodes, nodeOrigin } = useStore();
const { nodeLookup, snapGrid, viewport, nodes, nodeOrigin, domNode } = useStore();
const contextNodeId = getContext<string>('svelteflow__node_id');
$: id = typeof nodeId === 'string' ? nodeId : contextNodeId;
@@ -65,7 +65,8 @@
transform: [$viewport.x, $viewport.y, $viewport.zoom],
snapGrid: $snapGrid ?? undefined,
snapToGrid: !!$snapGrid,
nodeOrigin: $nodeOrigin
nodeOrigin: $nodeOrigin,
paneDomNode: $domNode
};
},
onChange: (change: XYResizerChange, childChanges: XYResizerChildChange[]) => {
+6 -2
View File
@@ -5,14 +5,18 @@ export type GetPointerPositionParams = {
transform: Transform;
snapGrid?: SnapGrid;
snapToGrid?: boolean;
containerBounds: DOMRect | null;
};
export function getPointerPosition(
event: MouseEvent | TouchEvent,
{ snapGrid = [0, 0], snapToGrid = false, transform }: GetPointerPositionParams
{ snapGrid = [0, 0], snapToGrid = false, transform, containerBounds }: GetPointerPositionParams
): XYPosition & { xSnapped: number; ySnapped: number } {
const { x, y } = getEventPosition(event);
const pointerPos = pointToRendererPoint({ x, y }, transform);
const pointerPos = pointToRendererPoint(
{ x: x - (containerBounds?.left ?? 0), y: y - (containerBounds?.top ?? 0) },
transform
);
const { x: xSnapped, y: ySnapped } = snapToGrid ? snapPosition(pointerPos, snapGrid) : pointerPos;
// we need the snapped position in order to be able to skip unnecessary drag events
+4 -4
View File
@@ -257,7 +257,7 @@ export function XYDrag<OnNodeDrag extends (e: any, nodes: any, node: any) => voi
onNodeMouseDown?.(nodeId);
}
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
lastPos = pointerPos;
dragItems = getDragItems(nodeLookup, nodesDraggable, pointerPos, nodeId);
@@ -281,6 +281,7 @@ export function XYDrag<OnNodeDrag extends (e: any, nodes: any, node: any) => voi
.clickDistance(nodeClickDistance)
.on('start', (event: UseDragEvent) => {
const { domNode, nodeDragThreshold, transform, snapGrid, snapToGrid } = getStoreItems();
containerBounds = domNode?.getBoundingClientRect() || null;
abortDrag = false;
@@ -288,14 +289,13 @@ export function XYDrag<OnNodeDrag extends (e: any, nodes: any, node: any) => voi
startDrag(event);
}
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
lastPos = pointerPos;
containerBounds = domNode?.getBoundingClientRect() || null;
mousePosition = getEventPosition(event.sourceEvent, containerBounds!);
})
.on('drag', (event: UseDragEvent) => {
const { autoPanOnNodeDrag, transform, snapGrid, snapToGrid, nodeDragThreshold, nodeLookup } = getStoreItems();
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
if (
(event.sourceEvent.type === 'touchmove' && event.sourceEvent.touches.length > 1) ||
+17 -3
View File
@@ -45,6 +45,7 @@ type XYResizerParams = {
snapGrid?: [number, number];
snapToGrid: boolean;
nodeOrigin: NodeOrigin;
paneDomNode: HTMLDivElement | null;
};
onChange: (changes: XYResizerChange, childChanges: XYResizerChildChange[]) => void;
onEnd?: () => void;
@@ -109,6 +110,7 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
const controlDirection = getControlDirection(controlPosition);
let node: InternalNodeBase | undefined = undefined;
let containerBounds: DOMRect | null = null;
let childNodes: XYResizerChildChange[] = [];
let parentNode: InternalNodeBase | undefined = undefined; // Needed to fix expandParent
let parentExtent: CoordinateExtent | undefined = undefined;
@@ -116,14 +118,20 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
const dragHandler = drag<HTMLDivElement, unknown>()
.on('start', (event: ResizeDragEvent) => {
const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin } = getStoreItems();
const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin, paneDomNode } = getStoreItems();
node = nodeLookup.get(nodeId);
if (!node) {
return;
}
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
containerBounds = paneDomNode?.getBoundingClientRect() ?? null;
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, {
transform,
snapGrid,
snapToGrid,
containerBounds,
});
prevValues = {
width: node.measured.width ?? 0,
@@ -178,7 +186,13 @@ export function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }: X
})
.on('drag', (event: ResizeDragEvent) => {
const { transform, snapGrid, snapToGrid, nodeOrigin: storeNodeOrigin } = getStoreItems();
const pointerPosition = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
const pointerPosition = getPointerPosition(event.sourceEvent, {
transform,
snapGrid,
snapToGrid,
containerBounds,
});
const childChanges: XYResizerChildChange[] = [];
if (!node) {