From 3f259e96622b0c2272c4d90476e28bda7413a285 Mon Sep 17 00:00:00 2001 From: peterkogo Date: Thu, 4 Jul 2024 16:33:45 +0200 Subject: [PATCH] variable autoPanSpeed --- .../react/src/components/Handle/index.tsx | 1 + .../src/components/StoreUpdater/index.tsx | 1 + .../react/src/container/ReactFlow/index.tsx | 2 ++ packages/react/src/store/initialState.ts | 1 + packages/react/src/types/component-props.ts | 4 ++++ packages/react/src/types/store.ts | 1 + packages/system/src/utils/general.ts | 24 ++++++++++++++----- packages/system/src/xydrag/XYDrag.ts | 8 ++++--- packages/system/src/xyhandle/XYHandle.ts | 4 +++- packages/system/src/xyhandle/types.ts | 1 + 10 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/react/src/components/Handle/index.tsx b/packages/react/src/components/Handle/index.tsx index 02ba9ced..10f34731 100644 --- a/packages/react/src/components/Handle/index.tsx +++ b/packages/react/src/components/Handle/index.tsx @@ -139,6 +139,7 @@ function HandleComponent( isValidConnection: isValidConnection || currentStore.isValidConnection, getTransform: () => store.getState().transform, getFromHandle: () => store.getState().connection.fromHandle, + autoPanSpeed: currentStore.autoPanSpeed, }); } diff --git a/packages/react/src/components/StoreUpdater/index.tsx b/packages/react/src/components/StoreUpdater/index.tsx index 56a37134..674eebd1 100644 --- a/packages/react/src/components/StoreUpdater/index.tsx +++ b/packages/react/src/components/StoreUpdater/index.tsx @@ -66,6 +66,7 @@ const reactFlowFieldsToTrack = [ 'nodeDragThreshold', 'onBeforeDelete', 'debug', + 'autoPanSpeed', ] as const; type ReactFlowFieldsToTrack = (typeof reactFlowFieldsToTrack)[number]; diff --git a/packages/react/src/container/ReactFlow/index.tsx b/packages/react/src/container/ReactFlow/index.tsx index c301d9d4..d8933d8e 100644 --- a/packages/react/src/container/ReactFlow/index.tsx +++ b/packages/react/src/container/ReactFlow/index.tsx @@ -129,6 +129,7 @@ function ReactFlow( disableKeyboardA11y = false, autoPanOnConnect, autoPanOnNodeDrag, + autoPanSpeed, connectionRadius, isValidConnection, onError, @@ -269,6 +270,7 @@ function ReactFlow( rfId={rfId} autoPanOnConnect={autoPanOnConnect} autoPanOnNodeDrag={autoPanOnNodeDrag} + autoPanSpeed={autoPanSpeed} onError={onError} connectionRadius={connectionRadius} isValidConnection={isValidConnection} diff --git a/packages/react/src/store/initialState.ts b/packages/react/src/store/initialState.ts index 7d2789a2..279506ba 100644 --- a/packages/react/src/store/initialState.ts +++ b/packages/react/src/store/initialState.ts @@ -112,6 +112,7 @@ const getInitialState = ({ ariaLiveMessage: '', autoPanOnConnect: true, autoPanOnNodeDrag: true, + autoPanSpeed: 15, connectionRadius: 20, onError: devWarn, isValidConnection: undefined, diff --git a/packages/react/src/types/component-props.ts b/packages/react/src/types/component-props.ts index 5dd6d57e..cd46ac22 100644 --- a/packages/react/src/types/component-props.ts +++ b/packages/react/src/types/component-props.ts @@ -471,6 +471,10 @@ export interface ReactFlowProps; diff --git a/packages/system/src/utils/general.ts b/packages/system/src/utils/general.ts index 0513f562..00097fa6 100644 --- a/packages/system/src/utils/general.ts +++ b/packages/system/src/utils/general.ts @@ -21,6 +21,10 @@ export const clampPosition = (position: XYPosition = { x: 0, y: 0 }, extent: Coo y: clamp(position.y, extent[0][1], extent[1][1]), }); +function easeInOutSine(x: number): number { + return -(Math.cos(Math.PI * x) - 1) / 2; +} + /** * Calculates the velocity of panning when the mouse is close to the edge of the canvas * @internal @@ -29,19 +33,27 @@ export const clampPosition = (position: XYPosition = { x: 0, y: 0 }, extent: Coo * @param max - Maximal position on canvas before panning starts * @returns - A number between 0 and 1 that represents the velocity of panning */ -const calcAutoPanVelocity = (value: number, min: number, max: number): number => { +const calcAutoPanVelocity = (value: number, min: number, max: number, zoom: number): number => { + clamp(zoom, 0, 1); if (value < min) { - return clamp(Math.abs(value - min), 1, 50) / 50; + return clamp(Math.abs(value - min), 1, min) / min; } else if (value > max) { - return -clamp(Math.abs(value - max), 1, 50) / 50; + return -clamp(Math.abs(value - max), 1, min) / min; } return 0; }; -export const calcAutoPan = (pos: XYPosition, bounds: Dimensions): number[] => { - const xMovement = calcAutoPanVelocity(pos.x, 35, bounds.width - 35) * 20; - const yMovement = calcAutoPanVelocity(pos.y, 35, bounds.height - 35) * 20; +export const calcAutoPan = ( + pos: XYPosition, + bounds: Dimensions, + transform: Transform, + speed: number = 15, + distance: number = 50 +): number[] => { + const zoomFactor = clamp(transform[2] * 10, 0.01, 1); + const xMovement = calcAutoPanVelocity(pos.x, distance, bounds.width - distance, transform[2]) * speed * zoomFactor; + const yMovement = calcAutoPanVelocity(pos.y, distance, bounds.height - distance, transform[2]) * speed * zoomFactor; return [xMovement, yMovement]; }; diff --git a/packages/system/src/xydrag/XYDrag.ts b/packages/system/src/xydrag/XYDrag.ts index 0e89c1c6..02387ff4 100644 --- a/packages/system/src/xydrag/XYDrag.ts +++ b/packages/system/src/xydrag/XYDrag.ts @@ -61,6 +61,7 @@ type StoreItems = { onSelectionDrag?: OnSelectionDrag; onSelectionDragStop?: OnSelectionDrag; updateNodePositions: UpdateNodePositions; + autoPanSpeed?: number; }; export type XYDragParams = { @@ -69,6 +70,7 @@ export type XYDragParams = { onDrag?: OnDrag; onDragStop?: OnDrag; onNodeMouseDown?: (id: string) => void; + autoPanSpeed?: number; }; export type XYDragInstance = { @@ -198,11 +200,11 @@ export function XYDrag voi return; } - const [xMovement, yMovement] = calcAutoPan(mousePosition, containerBounds); + const { transform, panBy, autoPanSpeed } = getStoreItems(); + + const [xMovement, yMovement] = calcAutoPan(mousePosition, containerBounds, transform, autoPanSpeed); if (xMovement !== 0 || yMovement !== 0) { - const { transform, panBy } = getStoreItems(); - lastPos.x = (lastPos.x ?? 0) - xMovement / transform[2]; lastPos.y = (lastPos.y ?? 0) - yMovement / transform[2]; diff --git a/packages/system/src/xyhandle/XYHandle.ts b/packages/system/src/xyhandle/XYHandle.ts index fcc1391b..db0dafd2 100644 --- a/packages/system/src/xyhandle/XYHandle.ts +++ b/packages/system/src/xyhandle/XYHandle.ts @@ -44,6 +44,7 @@ function onPointerDown( updateConnection, getTransform, getFromHandle, + autoPanSpeed, }: OnPointerDownParams ) { // when xyflow is used inside a shadow root we can't use document @@ -78,7 +79,8 @@ function onPointerDown( if (!autoPanOnConnect || !containerBounds) { return; } - const [x, y] = calcAutoPan(position, containerBounds); + const transform = getTransform(); + const [x, y] = calcAutoPan(position, containerBounds, transform, autoPanSpeed); panBy({ x, y }); autoPanId = requestAnimationFrame(autoPan); diff --git a/packages/system/src/xyhandle/types.ts b/packages/system/src/xyhandle/types.ts index 7c7543a1..299fbc8f 100644 --- a/packages/system/src/xyhandle/types.ts +++ b/packages/system/src/xyhandle/types.ts @@ -35,6 +35,7 @@ export type OnPointerDownParams = { onReconnectEnd?: (evt: MouseEvent | TouchEvent) => void; getTransform: () => Transform; getFromHandle: () => Handle | null; + autoPanSpeed?: number; }; export type IsValidParams = {