feat(props): add onMoveStart and onMoveEnd #358

This commit is contained in:
moklick
2020-07-24 17:39:35 +02:00
parent d73105df61
commit b77977997b
5 changed files with 95 additions and 8 deletions
+3
View File
@@ -11,6 +11,8 @@ const onLoad = (reactFlowInstance) => {
reactFlowInstance.fitView();
};
const onMoveEnd = (transform) => console.log('zoom/move end', transform);
const initialElements = [
{
id: '1',
@@ -116,6 +118,7 @@ const OverviewFlow = () => {
onNodeDragStart={onNodeDragStart}
onNodeDragStop={onNodeDragStop}
onSelectionChange={onSelectionChange}
onMoveEnd={onMoveEnd}
style={{ width: '100%', height: '100%' }}
onLoad={onLoad}
connectionLineStyle={{ stroke: '#ddd' }}
+15 -2
View File
@@ -21,6 +21,7 @@ import {
Edge,
Connection,
ConnectionLineType,
FlowTransform,
} from '../../types';
export interface GraphViewProps {
@@ -35,7 +36,9 @@ export interface GraphViewProps {
onNodeDragStop?: (node: Node) => void;
onConnect?: (connection: Connection | Edge) => void;
onLoad?: OnLoadFunc;
onMove?: () => void;
onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void;
onMoveEnd?: (flowTransform?: FlowTransform) => void;
selectionKeyCode: number;
nodeTypes: NodeTypesType;
edgeTypes: EdgeTypesType;
@@ -63,6 +66,8 @@ const GraphView = memo(
nodeTypes,
edgeTypes,
onMove,
onMoveStart,
onMoveEnd,
onLoad,
onElementClick,
onNodeMouseEnter,
@@ -162,7 +167,15 @@ const GraphView = memo(
};
}, []);
useD3Zoom({ zoomPane, onMove, selectionKeyPressed, zoomOnScroll, zoomOnDoubleClick });
useD3Zoom({
zoomPane,
onMove,
onMoveStart,
onMoveEnd,
selectionKeyPressed,
zoomOnScroll,
zoomOnDoubleClick,
});
useEffect(() => {
if (d3Initialised && onLoad) {
+8 -1
View File
@@ -26,6 +26,7 @@ import {
Edge,
Connection,
ConnectionLineType,
FlowTransform,
} from '../../types';
import '../../style.css';
@@ -42,7 +43,9 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
onNodeDragStop?: (node: Node) => void;
onConnect?: (connection: Edge | Connection) => void;
onLoad?: OnLoadFunc;
onMove?: () => void;
onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void;
onMoveEnd?: (flowTransform?: FlowTransform) => void;
onSelectionChange?: (elements: Elements | null) => void;
nodeTypes: NodeTypesType;
edgeTypes: EdgeTypesType;
@@ -76,6 +79,8 @@ const ReactFlow = ({
edgeTypes,
onLoad,
onMove,
onMoveStart,
onMoveEnd,
onElementsRemove,
onConnect,
onNodeMouseEnter,
@@ -114,6 +119,8 @@ const ReactFlow = ({
<GraphView
onLoad={onLoad}
onMove={onMove}
onMoveStart={onMoveStart}
onMoveEnd={onMoveEnd}
onElementClick={onElementClick}
onNodeMouseEnter={onNodeMouseEnter}
onNodeMouseMove={onNodeMouseMove}
+63 -5
View File
@@ -1,17 +1,40 @@
import { useEffect, MutableRefObject } from 'react';
import { useEffect, useRef, MutableRefObject } from 'react';
import { event } from 'd3-selection';
import { useStoreState, useStoreActions } from '../store/hooks';
import { FlowTransform } from '../types';
interface UseD3ZoomParams {
zoomPane: MutableRefObject<Element | null>;
selectionKeyPressed: boolean;
zoomOnScroll: boolean;
zoomOnDoubleClick: boolean;
onMove?: () => void;
onMove?: (flowTransform?: FlowTransform) => void;
onMoveStart?: (flowTransform?: FlowTransform) => void;
onMoveEnd?: (flowTransform?: FlowTransform) => void;
}
export default ({ zoomPane, onMove, zoomOnScroll, zoomOnDoubleClick, selectionKeyPressed }: UseD3ZoomParams): void => {
const viewChanged = (prevTransform: FlowTransform, eventTransform: any): boolean =>
prevTransform.x !== eventTransform.x ||
prevTransform.y !== eventTransform.y ||
prevTransform.zoom !== eventTransform.k;
const eventToFlowTransform = (eventTransform: any): FlowTransform => ({
x: eventTransform.x,
y: eventTransform.y,
zoom: eventTransform.k,
});
export default ({
zoomPane,
onMove,
onMoveStart,
onMoveEnd,
zoomOnScroll,
zoomOnDoubleClick,
selectionKeyPressed,
}: UseD3ZoomParams): void => {
const prevTransform = useRef<FlowTransform>({ x: 0, y: 0, zoom: 0 });
const d3Zoom = useStoreState((s) => s.d3Zoom);
const initD3 = useStoreActions((actions) => actions.initD3);
@@ -32,12 +55,47 @@ export default ({ zoomPane, onMove, zoomOnScroll, zoomOnDoubleClick, selectionKe
updateTransform(event.transform);
if (onMove) {
onMove();
const flowTransform = eventToFlowTransform(event.transform);
onMove(flowTransform);
}
});
}
}
}, [selectionKeyPressed, d3Zoom]);
}, [selectionKeyPressed, d3Zoom, updateTransform, onMove]);
useEffect(() => {
if (d3Zoom) {
if (onMoveStart) {
d3Zoom.on('start', () => {
if (viewChanged(prevTransform.current, event.transform)) {
const flowTransform = eventToFlowTransform(event.transform);
prevTransform.current = flowTransform;
onMoveStart(flowTransform);
}
});
} else {
d3Zoom.on('start', null);
}
}
}, [d3Zoom, onMoveStart]);
useEffect(() => {
if (d3Zoom) {
if (onMoveEnd) {
d3Zoom.on('end', () => {
if (viewChanged(prevTransform.current, event.transform)) {
const flowTransform = eventToFlowTransform(event.transform);
prevTransform.current = flowTransform;
onMoveEnd(flowTransform);
}
});
} else {
d3Zoom.on('end', null);
}
}
}, [d3Zoom, onMoveEnd]);
useEffect(() => {
if (d3Zoom) {
+6
View File
@@ -241,3 +241,9 @@ export type NodePosUpdate = {
id: ElementId;
pos: XYPosition;
};
export type FlowTransform = {
x: number;
y: number;
zoom: number;
};