feat(props): add onMoveStart and onMoveEnd #358
This commit is contained in:
@@ -11,6 +11,8 @@ const onLoad = (reactFlowInstance) => {
|
|||||||
reactFlowInstance.fitView();
|
reactFlowInstance.fitView();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onMoveEnd = (transform) => console.log('zoom/move end', transform);
|
||||||
|
|
||||||
const initialElements = [
|
const initialElements = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
@@ -116,6 +118,7 @@ const OverviewFlow = () => {
|
|||||||
onNodeDragStart={onNodeDragStart}
|
onNodeDragStart={onNodeDragStart}
|
||||||
onNodeDragStop={onNodeDragStop}
|
onNodeDragStop={onNodeDragStop}
|
||||||
onSelectionChange={onSelectionChange}
|
onSelectionChange={onSelectionChange}
|
||||||
|
onMoveEnd={onMoveEnd}
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
onLoad={onLoad}
|
onLoad={onLoad}
|
||||||
connectionLineStyle={{ stroke: '#ddd' }}
|
connectionLineStyle={{ stroke: '#ddd' }}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
Edge,
|
Edge,
|
||||||
Connection,
|
Connection,
|
||||||
ConnectionLineType,
|
ConnectionLineType,
|
||||||
|
FlowTransform,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
export interface GraphViewProps {
|
export interface GraphViewProps {
|
||||||
@@ -35,7 +36,9 @@ export interface GraphViewProps {
|
|||||||
onNodeDragStop?: (node: Node) => void;
|
onNodeDragStop?: (node: Node) => void;
|
||||||
onConnect?: (connection: Connection | Edge) => void;
|
onConnect?: (connection: Connection | Edge) => void;
|
||||||
onLoad?: OnLoadFunc;
|
onLoad?: OnLoadFunc;
|
||||||
onMove?: () => void;
|
onMove?: (flowTransform?: FlowTransform) => void;
|
||||||
|
onMoveStart?: (flowTransform?: FlowTransform) => void;
|
||||||
|
onMoveEnd?: (flowTransform?: FlowTransform) => void;
|
||||||
selectionKeyCode: number;
|
selectionKeyCode: number;
|
||||||
nodeTypes: NodeTypesType;
|
nodeTypes: NodeTypesType;
|
||||||
edgeTypes: EdgeTypesType;
|
edgeTypes: EdgeTypesType;
|
||||||
@@ -63,6 +66,8 @@ const GraphView = memo(
|
|||||||
nodeTypes,
|
nodeTypes,
|
||||||
edgeTypes,
|
edgeTypes,
|
||||||
onMove,
|
onMove,
|
||||||
|
onMoveStart,
|
||||||
|
onMoveEnd,
|
||||||
onLoad,
|
onLoad,
|
||||||
onElementClick,
|
onElementClick,
|
||||||
onNodeMouseEnter,
|
onNodeMouseEnter,
|
||||||
@@ -162,7 +167,15 @@ const GraphView = memo(
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useD3Zoom({ zoomPane, onMove, selectionKeyPressed, zoomOnScroll, zoomOnDoubleClick });
|
useD3Zoom({
|
||||||
|
zoomPane,
|
||||||
|
onMove,
|
||||||
|
onMoveStart,
|
||||||
|
onMoveEnd,
|
||||||
|
selectionKeyPressed,
|
||||||
|
zoomOnScroll,
|
||||||
|
zoomOnDoubleClick,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (d3Initialised && onLoad) {
|
if (d3Initialised && onLoad) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
Edge,
|
Edge,
|
||||||
Connection,
|
Connection,
|
||||||
ConnectionLineType,
|
ConnectionLineType,
|
||||||
|
FlowTransform,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
import '../../style.css';
|
import '../../style.css';
|
||||||
@@ -42,7 +43,9 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
|
|||||||
onNodeDragStop?: (node: Node) => void;
|
onNodeDragStop?: (node: Node) => void;
|
||||||
onConnect?: (connection: Edge | Connection) => void;
|
onConnect?: (connection: Edge | Connection) => void;
|
||||||
onLoad?: OnLoadFunc;
|
onLoad?: OnLoadFunc;
|
||||||
onMove?: () => void;
|
onMove?: (flowTransform?: FlowTransform) => void;
|
||||||
|
onMoveStart?: (flowTransform?: FlowTransform) => void;
|
||||||
|
onMoveEnd?: (flowTransform?: FlowTransform) => void;
|
||||||
onSelectionChange?: (elements: Elements | null) => void;
|
onSelectionChange?: (elements: Elements | null) => void;
|
||||||
nodeTypes: NodeTypesType;
|
nodeTypes: NodeTypesType;
|
||||||
edgeTypes: EdgeTypesType;
|
edgeTypes: EdgeTypesType;
|
||||||
@@ -76,6 +79,8 @@ const ReactFlow = ({
|
|||||||
edgeTypes,
|
edgeTypes,
|
||||||
onLoad,
|
onLoad,
|
||||||
onMove,
|
onMove,
|
||||||
|
onMoveStart,
|
||||||
|
onMoveEnd,
|
||||||
onElementsRemove,
|
onElementsRemove,
|
||||||
onConnect,
|
onConnect,
|
||||||
onNodeMouseEnter,
|
onNodeMouseEnter,
|
||||||
@@ -114,6 +119,8 @@ const ReactFlow = ({
|
|||||||
<GraphView
|
<GraphView
|
||||||
onLoad={onLoad}
|
onLoad={onLoad}
|
||||||
onMove={onMove}
|
onMove={onMove}
|
||||||
|
onMoveStart={onMoveStart}
|
||||||
|
onMoveEnd={onMoveEnd}
|
||||||
onElementClick={onElementClick}
|
onElementClick={onElementClick}
|
||||||
onNodeMouseEnter={onNodeMouseEnter}
|
onNodeMouseEnter={onNodeMouseEnter}
|
||||||
onNodeMouseMove={onNodeMouseMove}
|
onNodeMouseMove={onNodeMouseMove}
|
||||||
|
|||||||
+63
-5
@@ -1,17 +1,40 @@
|
|||||||
import { useEffect, MutableRefObject } from 'react';
|
import { useEffect, useRef, MutableRefObject } from 'react';
|
||||||
import { event } from 'd3-selection';
|
import { event } from 'd3-selection';
|
||||||
|
|
||||||
import { useStoreState, useStoreActions } from '../store/hooks';
|
import { useStoreState, useStoreActions } from '../store/hooks';
|
||||||
|
import { FlowTransform } from '../types';
|
||||||
|
|
||||||
interface UseD3ZoomParams {
|
interface UseD3ZoomParams {
|
||||||
zoomPane: MutableRefObject<Element | null>;
|
zoomPane: MutableRefObject<Element | null>;
|
||||||
selectionKeyPressed: boolean;
|
selectionKeyPressed: boolean;
|
||||||
zoomOnScroll: boolean;
|
zoomOnScroll: boolean;
|
||||||
zoomOnDoubleClick: 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 d3Zoom = useStoreState((s) => s.d3Zoom);
|
||||||
|
|
||||||
const initD3 = useStoreActions((actions) => actions.initD3);
|
const initD3 = useStoreActions((actions) => actions.initD3);
|
||||||
@@ -32,12 +55,47 @@ export default ({ zoomPane, onMove, zoomOnScroll, zoomOnDoubleClick, selectionKe
|
|||||||
updateTransform(event.transform);
|
updateTransform(event.transform);
|
||||||
|
|
||||||
if (onMove) {
|
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(() => {
|
useEffect(() => {
|
||||||
if (d3Zoom) {
|
if (d3Zoom) {
|
||||||
|
|||||||
@@ -241,3 +241,9 @@ export type NodePosUpdate = {
|
|||||||
id: ElementId;
|
id: ElementId;
|
||||||
pos: XYPosition;
|
pos: XYPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FlowTransform = {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
zoom: number;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user