feat(autoPan): add props, handle scale

This commit is contained in:
moklick
2023-01-17 16:26:04 +01:00
parent 86f7a9a43d
commit f2a4260ac9
7 changed files with 27 additions and 6 deletions
@@ -1,7 +1,7 @@
import type { MouseEvent as ReactMouseEvent } from 'react';
import { StoreApi } from 'zustand';
import { clamp, getHostForElement, getVelocity } from '../../utils';
import { getHostForElement, getVelocity } from '../../utils';
import { ConnectionMode } from '../../types';
import type { OnConnect, Connection, HandleType, ReactFlowState, XYPosition } from '../../types';
@@ -100,13 +100,13 @@ export function handleMouseDown({
}): void {
// when react-flow is used inside a shadow root we can't use document
const doc = getHostForElement(event.target as HTMLElement);
const { onConnectStart, connectionMode, domNode } = getState();
const { onConnectStart, connectionMode, domNode, autoPanOnConnect } = getState();
let connectionPosition: XYPosition | null = null;
let requestAnimationFrameId = 0;
// when the user is moving the mouse close to the edge of the canvas while connecting we move the canvas
const updateViewport = (): void => {
if (!connectionPosition || !containerBounds) {
if (!connectionPosition || !containerBounds || !autoPanOnConnect) {
return;
}
@@ -132,6 +132,7 @@ export function handleMouseDown({
const handleType = elementEdgeUpdaterType ? elementEdgeUpdaterType : elementBelowIsTarget ? 'target' : 'source';
const containerBounds = domNode.getBoundingClientRect();
let recentHoveredHandle: Element;
connectionPosition = {
x: event.clientX - containerBounds.left,
y: event.clientY - containerBounds.top,
@@ -45,6 +45,8 @@ type StoreUpdaterProps = Pick<
| 'noPanClassName'
| 'nodeOrigin'
| 'elevateNodesOnSelect'
| 'autoPanOnConnect'
| 'autoPanOnNodeDrag'
> & { rfId: string };
const selector = (s: ReactFlowState) => ({
@@ -119,6 +121,8 @@ const StoreUpdater = ({
noPanClassName,
nodeOrigin,
rfId,
autoPanOnConnect,
autoPanOnNodeDrag,
}: StoreUpdaterProps) => {
const {
setNodes,
@@ -172,6 +176,8 @@ const StoreUpdater = ({
useDirectStoreUpdater('noPanClassName', noPanClassName, store.setState);
useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState);
useDirectStoreUpdater('rfId', rfId, store.setState);
useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);
useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);
useStoreUpdater<Node[]>(nodes, setNodes);
useStoreUpdater<Edge[]>(edges, setEdges);
@@ -160,6 +160,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
elevateNodesOnSelect = true,
elevateEdgesOnSelect = false,
disableKeyboardA11y = false,
autoPanOnConnect = true,
autoPanOnNodeDrag = true,
style,
id,
...rest
@@ -287,6 +289,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
noPanClassName={noPanClassName}
nodeOrigin={nodeOrigin}
rfId={rfId}
autoPanOnConnect={autoPanOnConnect}
autoPanOnNodeDrag={autoPanOnNodeDrag}
/>
<SelectionListener onSelectionChange={onSelectionChange} />
{children}
+7 -3
View File
@@ -114,8 +114,10 @@ function useDrag({
const yMovement = getVelocity(centerPosition.current.y, 35, containerBounds.current.height - 35) * 20;
if (xMovement !== 0 || yMovement !== 0) {
lastPos.current.x = (lastPos.current.x ?? 0) + xMovement * -1;
lastPos.current.y = (lastPos.current.y ?? 0) + yMovement * -1;
const scale = store.getState().transform[2];
lastPos.current.x = (lastPos.current.x ?? 0) - xMovement / scale;
lastPos.current.y = (lastPos.current.y ?? 0) - yMovement / scale;
updateNodes(lastPos.current as XYPosition);
@@ -175,8 +177,9 @@ function useDrag({
})
.on('drag', (event: UseDragEvent) => {
const pointerPos = getPointerPosition(event);
const { autoPanOnNodeDrag } = store.getState();
if (!animationFrameStarted.current) {
if (!animationFrameStarted.current && autoPanOnNodeDrag) {
animationFrameStarted.current = true;
updateViewport();
}
@@ -199,6 +202,7 @@ function useDrag({
setDragging(false);
animationFrameStarted.current = false;
cancelAnimationFrame(requestAnimationFrameId.current);
if (dragItems.current) {
const { updateNodePositions, nodeInternals, onNodeDragStop, onSelectionDragStop } = store.getState();
const onStop = nodeId ? onNodeDragStop : wrapSelectionDragFunc(onSelectionDragStop);
+2
View File
@@ -56,6 +56,8 @@ const initialState: ReactFlowStore = {
connectOnClick: true,
ariaLiveMessage: '',
autoPanOnConnect: true,
autoPanOnNodeDrag: true,
};
export default initialState;
@@ -139,6 +139,8 @@ export type ReactFlowProps = HTMLAttributes<HTMLDivElement> & {
elevateNodesOnSelect?: boolean;
elevateEdgesOnSelect?: boolean;
disableKeyboardA11y?: boolean;
autoPanOnNodeDrag?: boolean;
autoPanOnConnect?: boolean;
};
export type ReactFlowRefType = HTMLDivElement;
+2
View File
@@ -210,6 +210,8 @@ export type ReactFlowStore = {
onSelectionChange?: OnSelectionChangeFunc;
ariaLiveMessage: string;
autoPanOnConnect: boolean;
autoPanOnNodeDrag: boolean;
};
export type ReactFlowActions = {