refactor(fitView): use same fitView function for viewport helper and initial prop
This commit is contained in:
@@ -1,19 +1,18 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import useReactFlow from './useReactFlow';
|
||||
import { OnPaneReady } from '../types';
|
||||
import { OnInit } from '../types';
|
||||
|
||||
function useOnPaneReadyHandler(onPaneReady: OnPaneReady<any> | undefined) {
|
||||
function useOnInitHandler(onInit: OnInit<any> | undefined) {
|
||||
const ReactFlowInstance = useReactFlow();
|
||||
const isInitialized = useRef<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInitialized.current && ReactFlowInstance.viewportInitialized && onPaneReady) {
|
||||
onPaneReady(ReactFlowInstance);
|
||||
|
||||
if (!isInitialized.current && ReactFlowInstance.viewportInitialized && onInit) {
|
||||
setTimeout(() => onInit(ReactFlowInstance), 1);
|
||||
isInitialized.current = true;
|
||||
}
|
||||
}, [onPaneReady, ReactFlowInstance]);
|
||||
}, [onInit, ReactFlowInstance.viewportInitialized]);
|
||||
}
|
||||
|
||||
export default useOnPaneReadyHandler;
|
||||
export default useOnInitHandler;
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useMemo } from 'react';
|
||||
import { zoomIdentity } from 'd3-zoom';
|
||||
import shallow from 'zustand/shallow';
|
||||
import { Selection as D3Selection } from 'd3';
|
||||
|
||||
import { useStoreApi, useStore } from '../store';
|
||||
import { getRectOfNodeInternals, pointToRendererPoint, getTransformForBounds } from '../utils/graph';
|
||||
import { FitViewParams, Viewport, ViewportHelperFunctions, ReactFlowState, Rect, XYPosition } from '../types';
|
||||
import { pointToRendererPoint, getTransformForBounds, getD3Transition } from '../utils/graph';
|
||||
import { FitViewOptions, Viewport, ViewportHelperFunctions, ReactFlowState, Rect, XYPosition } from '../types';
|
||||
import { fitView as fitViewStore } from '../store/utils';
|
||||
|
||||
const DEFAULT_PADDING = 0.1;
|
||||
|
||||
@@ -16,7 +16,7 @@ const initialViewportHelper: ViewportHelperFunctions = {
|
||||
getZoom: () => 1,
|
||||
setViewport: (_: Viewport) => {},
|
||||
getViewport: () => ({ x: 0, y: 0, zoom: 1 }),
|
||||
fitView: (_: FitViewParams = { padding: DEFAULT_PADDING, includeHiddenNodes: false }) => {},
|
||||
fitView: (_: FitViewOptions = { padding: DEFAULT_PADDING, includeHiddenNodes: false }) => {},
|
||||
setCenter: (_: number, __: number) => {},
|
||||
fitBounds: (_: Rect) => {},
|
||||
project: (position: XYPosition) => position,
|
||||
@@ -28,10 +28,6 @@ const selector = (s: ReactFlowState) => ({
|
||||
d3Selection: s.d3Selection,
|
||||
});
|
||||
|
||||
const getTransition = (selection: D3Selection<Element, unknown, null, undefined>, duration: number = 0) => {
|
||||
return selection.transition().duration(duration);
|
||||
};
|
||||
|
||||
const useViewportHelper = (): ViewportHelperFunctions => {
|
||||
const store = useStoreApi();
|
||||
const { d3Zoom, d3Selection } = useStore(selector, shallow);
|
||||
@@ -39,45 +35,22 @@ const useViewportHelper = (): ViewportHelperFunctions => {
|
||||
const viewportHelperFunctions = useMemo<ViewportHelperFunctions>(() => {
|
||||
if (d3Selection && d3Zoom) {
|
||||
return {
|
||||
zoomIn: (options) => d3Zoom.scaleBy(getTransition(d3Selection, options?.duration), 1.2),
|
||||
zoomOut: (options) => d3Zoom.scaleBy(getTransition(d3Selection, options?.duration), 1 / 1.2),
|
||||
zoomTo: (zoomLevel, options) => d3Zoom.scaleTo(getTransition(d3Selection, options?.duration), zoomLevel),
|
||||
zoomIn: (options) => d3Zoom.scaleBy(getD3Transition(d3Selection, options?.duration), 1.2),
|
||||
zoomOut: (options) => d3Zoom.scaleBy(getD3Transition(d3Selection, options?.duration), 1 / 1.2),
|
||||
zoomTo: (zoomLevel, options) => d3Zoom.scaleTo(getD3Transition(d3Selection, options?.duration), zoomLevel),
|
||||
getZoom: () => {
|
||||
const [, , zoom] = store.getState().transform;
|
||||
return zoom;
|
||||
},
|
||||
setViewport: (transform, options) => {
|
||||
const nextTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.zoom);
|
||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), nextTransform);
|
||||
d3Zoom.transform(getD3Transition(d3Selection, options?.duration), nextTransform);
|
||||
},
|
||||
getViewport: () => {
|
||||
const [x, y, zoom] = store.getState().transform;
|
||||
return { x, y, zoom };
|
||||
},
|
||||
fitView: (options) => {
|
||||
const { nodeInternals, width, height, minZoom, maxZoom } = store.getState();
|
||||
// @TODO: work with nodeInternals instead of converting it to an array
|
||||
const nodes = Array.from(nodeInternals).map(([_, node]) => node);
|
||||
|
||||
if (!nodes.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bounds = getRectOfNodeInternals(
|
||||
options?.includeHiddenNodes ? nodes : nodes.filter((node) => !node.hidden)
|
||||
);
|
||||
const [x, y, zoom] = getTransformForBounds(
|
||||
bounds,
|
||||
width,
|
||||
height,
|
||||
options?.minZoom ?? minZoom,
|
||||
options?.maxZoom ?? maxZoom,
|
||||
options?.padding ?? DEFAULT_PADDING
|
||||
);
|
||||
const transform = zoomIdentity.translate(x, y).scale(zoom);
|
||||
|
||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), transform);
|
||||
},
|
||||
fitView: (options) => fitViewStore(store.getState, options),
|
||||
setCenter: (x, y, options) => {
|
||||
const { width, height, maxZoom } = store.getState();
|
||||
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;
|
||||
@@ -85,21 +58,14 @@ const useViewportHelper = (): ViewportHelperFunctions => {
|
||||
const centerY = height / 2 - y * nextZoom;
|
||||
const transform = zoomIdentity.translate(centerX, centerY).scale(nextZoom);
|
||||
|
||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), transform);
|
||||
d3Zoom.transform(getD3Transition(d3Selection, options?.duration), transform);
|
||||
},
|
||||
fitBounds: (bounds, options) => {
|
||||
const { width, height, minZoom, maxZoom } = store.getState();
|
||||
const [x, y, zoom] = getTransformForBounds(
|
||||
bounds,
|
||||
width,
|
||||
height,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
options?.padding ?? DEFAULT_PADDING
|
||||
);
|
||||
const [x, y, zoom] = getTransformForBounds(bounds, width, height, minZoom, maxZoom, options?.padding ?? 0.1);
|
||||
const transform = zoomIdentity.translate(x, y).scale(zoom);
|
||||
|
||||
d3Zoom.transform(getTransition(d3Selection, options?.duration), transform);
|
||||
d3Zoom.transform(getD3Transition(d3Selection, options?.duration), transform);
|
||||
},
|
||||
project: (position: XYPosition) => {
|
||||
const { transform, snapToGrid, snapGrid } = store.getState();
|
||||
|
||||
Reference in New Issue
Block a user