61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { zoomIdentity } from 'd3-zoom';
|
|
|
|
import { useStoreState, useStore } from '../store/hooks';
|
|
import { clamp } from '../utils';
|
|
import { getRectOfNodes } from '../utils/graph';
|
|
import { FitViewParams, FlowTransform } from '../types';
|
|
|
|
const initialZoomPanHelper = {
|
|
zoomIn: null,
|
|
zoomOut: null,
|
|
zoomTo: null,
|
|
transform: null,
|
|
fitView: null,
|
|
};
|
|
|
|
export default () => {
|
|
const store = useStore();
|
|
const d3Zoom = useStoreState((s) => s.d3Zoom);
|
|
const d3Selection = useStoreState((s) => s.d3Selection);
|
|
|
|
const zoomPanHelperFunctions = useMemo(() => {
|
|
if (d3Selection && d3Zoom) {
|
|
return {
|
|
zoomIn: () => d3Zoom.scaleBy(d3Selection, 1.2),
|
|
zoomOut: () => d3Zoom.scaleBy(d3Selection, 1 / 1.2),
|
|
zoomTo: (zoomLevel: number) => d3Zoom.scaleTo(d3Selection, zoomLevel),
|
|
transform: (transform: FlowTransform) => {
|
|
const nextTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.zoom);
|
|
|
|
d3Zoom.transform(d3Selection, nextTransform);
|
|
},
|
|
fitView: (options: FitViewParams = { padding: 0.1 }) => {
|
|
const { nodes, width, height, minZoom, maxZoom } = store.getState();
|
|
|
|
if (!nodes.length) {
|
|
return;
|
|
}
|
|
|
|
const bounds = getRectOfNodes(nodes);
|
|
const xZoom = width / (bounds.width * (1 + options.padding));
|
|
const yZoom = height / (bounds.height * (1 + options.padding));
|
|
const zoom = Math.min(xZoom, yZoom);
|
|
const clampedZoom = clamp(zoom, minZoom, maxZoom);
|
|
const boundsCenterX = bounds.x + bounds.width / 2;
|
|
const boundsCenterY = bounds.y + bounds.height / 2;
|
|
const x = width / 2 - boundsCenterX * clampedZoom;
|
|
const y = height / 2 - boundsCenterY * clampedZoom;
|
|
const transform = zoomIdentity.translate(x, y).scale(clampedZoom);
|
|
|
|
d3Zoom.transform(d3Selection, transform);
|
|
},
|
|
};
|
|
}
|
|
|
|
return initialZoomPanHelper;
|
|
}, [d3Zoom, d3Selection]);
|
|
|
|
return zoomPanHelperFunctions;
|
|
};
|