From 8c565e4a27410fa46992a9cee8eaa3911d15754f Mon Sep 17 00:00:00 2001 From: moklick Date: Fri, 24 Jul 2020 17:54:12 +0200 Subject: [PATCH] feat(props): add defaultPosition prop #358 --- README.md | 5 ++++- src/container/GraphView/index.tsx | 20 +++++++++++++++----- src/container/ReactFlow/index.tsx | 4 ++++ src/store/index.ts | 14 ++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a1d06b9c..9fee03ef 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ const BasicFlow = () => ; - `minZoom`: default: `0.5` - `maxZoom`: default: `2` - `defaultZoom`: default: `1` +- `defaultPosition`: default: `[0, 0]` - `snapToGrid`: default: `false` - `snapGrid`: [x, y] array - default: `[16, 16]` - `onlyRenderVisibleNodes`: default: `true` @@ -88,7 +89,9 @@ const BasicFlow = () => ; - `onNodeContextMenu(evt: MouseEvent, node: Node)`: node context menu - `onConnect({ source, target })`: called when user connects two nodes - `onLoad(reactFlowInstance)`: called after flow is initialized -- `onMove()`: called when user pans or zooms +- `onMove()`: called when user is panning or zooming +- `onMoveStart()`: called when user starts panning or zooming +- `onMoveEnd()`: called when user ends panning or zooming - `onSelectionChange(elements: Elements)`: called when user selects one or multiple elements #### Interaction diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index f174600d..080d3921 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -55,6 +55,7 @@ export interface GraphViewProps { minZoom: number; maxZoom: number; defaultZoom: number; + defaultPosition: [number, number]; arrowHeadColor: string; markerEndId?: string; zoomOnScroll: boolean; @@ -93,6 +94,7 @@ const GraphView = memo( minZoom, maxZoom, defaultZoom, + defaultPosition, arrowHeadColor, markerEndId, zoomOnScroll, @@ -111,7 +113,7 @@ const GraphView = memo( const setNodesDraggable = useStoreActions((actions) => actions.setNodesDraggable); const setNodesConnectable = useStoreActions((actions) => actions.setNodesConnectable); const setElementsSelectable = useStoreActions((actions) => actions.setElementsSelectable); - const updateTransform = useStoreActions((actions) => actions.updateTransform); + const setInitTransform = useStoreActions((actions) => actions.setInitTransform); const setMinMaxZoom = useStoreActions((actions) => actions.setMinMaxZoom); const fitView = useStoreActions((actions) => actions.fitView); const zoom = useStoreActions((actions) => actions.zoom); @@ -144,10 +146,6 @@ const GraphView = memo( setOnConnect(onConnect); } - if (defaultZoom !== 1) { - updateTransform({ x: 0, y: 0, k: defaultZoom }); - } - if (rendererNode.current) { resizeObserver = new ResizeObserver((entries) => { for (let _ of entries) { @@ -187,6 +185,18 @@ const GraphView = memo( getElements, }); } + + if (d3Initialised) { + const initialTransform = { + x: defaultPosition[0], + y: defaultPosition[1], + k: defaultZoom, + }; + + if (initialTransform.x !== 0 || initialTransform.y !== 0 || initialTransform.k !== 1) { + setInitTransform(initialTransform); + } + } }, [d3Initialised, onLoad]); useEffect(() => { diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index d4a7f6fb..c69b4a69 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -63,6 +63,7 @@ export interface ReactFlowProps extends Omit, 'on minZoom: number; maxZoom: number; defaultZoom: number; + defaultPosition: [number, number]; arrowHeadColor: string; markerEndId?: string; zoomOnScroll: boolean; @@ -104,6 +105,7 @@ const ReactFlow = ({ minZoom, maxZoom, defaultZoom, + defaultPosition, arrowHeadColor, markerEndId, zoomOnScroll, @@ -147,6 +149,7 @@ const ReactFlow = ({ minZoom={minZoom} maxZoom={maxZoom} defaultZoom={defaultZoom} + defaultPosition={defaultPosition} arrowHeadColor={arrowHeadColor} markerEndId={markerEndId} zoomOnScroll={zoomOnScroll} @@ -186,6 +189,7 @@ ReactFlow.defaultProps = { minZoom: 0.5, maxZoom: 2, defaultZoom: 1, + defaultPosition: [0, 0], arrowHeadColor: '#bbb', zoomOnScroll: true, zoomOnDoubleClick: true, diff --git a/src/store/index.ts b/src/store/index.ts index 0f42280f..7729f9cd 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -105,6 +105,8 @@ export interface StoreModel { updateTransform: Action; + setInitTransform: Action; + updateSize: Action; initD3: Action; @@ -342,6 +344,18 @@ export const storeModel: StoreModel = { state.transform[2] = transform.k; }), + setInitTransform: action((state, transform) => { + state.transform[0] = transform.x; + state.transform[1] = transform.y; + state.transform[2] = transform.k; + + if (state.d3Selection) { + const updatedTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.k); + // we need to sync the d3 zoom transform with the updated transform + state.d3Selection.property('__zoom', updatedTransform); + } + }), + updateSize: action((state, size) => { state.width = size.width; state.height = size.height;