fix(subflows): use abs positions for internal calculations (#2189)
* refactor(dragging): only use absolute positions * refactor(drag): handle node extent * refactor(drag-handler): return latest data * refactor(use-drag): cleanup fixes #2181
This commit is contained in:
@@ -141,7 +141,7 @@ const initialEdges: Edge[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const connectionLineStyle: CSSProperties = { stroke: '#ddd' };
|
const connectionLineStyle: CSSProperties = { stroke: '#ddd' };
|
||||||
const snapGrid: SnapGrid = [16, 16];
|
const snapGrid: SnapGrid = [25, 25];
|
||||||
|
|
||||||
const nodeStrokeColor = (n: Node): string => {
|
const nodeStrokeColor = (n: Node): string => {
|
||||||
if (n.style?.background) return n.style.background as string;
|
if (n.style?.background) return n.style.background as string;
|
||||||
@@ -203,7 +203,7 @@ const OverviewFlow = () => {
|
|||||||
>
|
>
|
||||||
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
|
||||||
<Controls />
|
<Controls />
|
||||||
<Background color="#aaa" gap={20} />
|
<Background color="#aaa" gap={25} />
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { select } from 'd3-selection';
|
|||||||
|
|
||||||
import { useStoreApi } from '../../store';
|
import { useStoreApi } from '../../store';
|
||||||
import { pointToRendererPoint } from '../../utils/graph';
|
import { pointToRendererPoint } from '../../utils/graph';
|
||||||
import { NodeDragItem, NodeDragHandler, XYPosition } from '../../types';
|
import { NodeDragItem, NodeDragHandler } from '../../types';
|
||||||
import { getDragItems, getEventHandlerParams, getParentNodePosition, hasSelector, updatePosition } from './utils';
|
import { getDragItems, getEventHandlerParams, hasSelector, updatePosition } from './utils';
|
||||||
import { handleNodeClick } from '../../components/Nodes/utils';
|
import { handleNodeClick } from '../../components/Nodes/utils';
|
||||||
|
|
||||||
export type UseDragEvent = D3DragEvent<HTMLDivElement, null, SubjectPosition>;
|
export type UseDragEvent = D3DragEvent<HTMLDivElement, null, SubjectPosition>;
|
||||||
@@ -40,7 +40,6 @@ function useDrag({
|
|||||||
const store = useStoreApi();
|
const store = useStoreApi();
|
||||||
const dragItems = useRef<NodeDragItem[]>();
|
const dragItems = useRef<NodeDragItem[]>();
|
||||||
const lastPos = useRef<{ x: number | null; y: number | null }>({ x: null, y: null });
|
const lastPos = useRef<{ x: number | null; y: number | null }>({ x: null, y: null });
|
||||||
const parentPos = useRef<XYPosition>({ x: 0, y: 0 });
|
|
||||||
|
|
||||||
// returns the pointer position projected to the RF coordinate system
|
// returns the pointer position projected to the RF coordinate system
|
||||||
const getPointerPosition = useCallback(({ sourceEvent }: UseDragEvent) => {
|
const getPointerPosition = useCallback(({ sourceEvent }: UseDragEvent) => {
|
||||||
@@ -49,9 +48,6 @@ function useDrag({
|
|||||||
const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY;
|
const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY;
|
||||||
const pointerPos = pointToRendererPoint({ x, y }, transform, snapToGrid, snapGrid);
|
const pointerPos = pointToRendererPoint({ x, y }, transform, snapToGrid, snapGrid);
|
||||||
|
|
||||||
pointerPos.x -= parentPos.current.x;
|
|
||||||
pointerPos.y -= parentPos.current.y;
|
|
||||||
|
|
||||||
return pointerPos;
|
return pointerPos;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -65,7 +61,6 @@ function useDrag({
|
|||||||
const dragHandler = drag()
|
const dragHandler = drag()
|
||||||
.on('start', (event: UseDragEvent) => {
|
.on('start', (event: UseDragEvent) => {
|
||||||
const { nodeInternals, multiSelectionActive, unselectNodesAndEdges } = store.getState();
|
const { nodeInternals, multiSelectionActive, unselectNodesAndEdges } = store.getState();
|
||||||
parentPos.current = getParentNodePosition(nodeInternals, nodeId);
|
|
||||||
|
|
||||||
if (!selectNodesOnDrag && !multiSelectionActive && nodeId) {
|
if (!selectNodesOnDrag && !multiSelectionActive && nodeId) {
|
||||||
if (!nodeInternals.get(nodeId)?.selected) {
|
if (!nodeInternals.get(nodeId)?.selected) {
|
||||||
|
|||||||
+11
-29
@@ -21,16 +21,6 @@ export function isParentSelected(node: Node, nodeInternals: NodeInternals): bool
|
|||||||
return isParentSelected(parentNode, nodeInternals);
|
return isParentSelected(parentNode, nodeInternals);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getParentNodePosition(nodeInternals: NodeInternals, nodeId?: string): XYPosition {
|
|
||||||
const parentNodeId = nodeId ? nodeInternals.get(nodeId)?.parentNode : null;
|
|
||||||
const parentNode = parentNodeId ? nodeInternals.get(parentNodeId) : null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: parentNode?.positionAbsolute?.x || 0,
|
|
||||||
y: parentNode?.positionAbsolute?.y || 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hasSelector(target: Element, selector: string, nodeRef: RefObject<Element>): boolean {
|
export function hasSelector(target: Element, selector: string, nodeRef: RefObject<Element>): boolean {
|
||||||
let current = target;
|
let current = target;
|
||||||
|
|
||||||
@@ -49,10 +39,10 @@ export function getDragItems(nodeInternals: NodeInternals, mousePos: XYPosition,
|
|||||||
.filter((n) => (n.selected || n.id === nodeId) && (!n.parentNode || !isParentSelected(n, nodeInternals)))
|
.filter((n) => (n.selected || n.id === nodeId) && (!n.parentNode || !isParentSelected(n, nodeInternals)))
|
||||||
.map((n) => ({
|
.map((n) => ({
|
||||||
id: n.id,
|
id: n.id,
|
||||||
position: n.position,
|
position: n.positionAbsolute || { x: 0, y: 0 },
|
||||||
distance: {
|
distance: {
|
||||||
x: mousePos.x - n.position.x,
|
x: mousePos.x - (n.positionAbsolute?.x ?? 0),
|
||||||
y: mousePos.y - n.position.y,
|
y: mousePos.y - (n.positionAbsolute?.y ?? 0),
|
||||||
},
|
},
|
||||||
delta: {
|
delta: {
|
||||||
x: 0,
|
x: 0,
|
||||||
@@ -72,16 +62,19 @@ export function updatePosition(
|
|||||||
nodeExtent?: CoordinateExtent
|
nodeExtent?: CoordinateExtent
|
||||||
): NodeDragItem {
|
): NodeDragItem {
|
||||||
let currentExtent = dragItem.extent || nodeExtent;
|
let currentExtent = dragItem.extent || nodeExtent;
|
||||||
let nextPosition = { x: mousePos.x - dragItem.distance.x, y: mousePos.y - dragItem.distance.y };
|
const nextPosition = { x: mousePos.x - dragItem.distance.x, y: mousePos.y - dragItem.distance.y };
|
||||||
|
|
||||||
if (dragItem.extent === 'parent') {
|
if (dragItem.extent === 'parent') {
|
||||||
if (dragItem.parentNode && dragItem.width && dragItem.height) {
|
if (dragItem.parentNode && dragItem.width && dragItem.height) {
|
||||||
const parent = nodeInternals.get(dragItem.parentNode);
|
const parent = nodeInternals.get(dragItem.parentNode);
|
||||||
currentExtent =
|
currentExtent =
|
||||||
parent?.width && parent?.height
|
parent?.positionAbsolute && parent?.width && parent?.height
|
||||||
? [
|
? [
|
||||||
[0, 0],
|
[parent.positionAbsolute.x, parent.positionAbsolute.y],
|
||||||
[parent.width - dragItem.width, parent.height - dragItem.height],
|
[
|
||||||
|
parent.positionAbsolute.x + parent.width - dragItem.width,
|
||||||
|
parent.positionAbsolute.y + parent.height - dragItem.height,
|
||||||
|
],
|
||||||
]
|
]
|
||||||
: currentExtent;
|
: currentExtent;
|
||||||
} else {
|
} else {
|
||||||
@@ -93,13 +86,7 @@ export function updatePosition(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextPosition = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition;
|
dragItem.position = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition;
|
||||||
|
|
||||||
dragItem.delta = {
|
|
||||||
x: nextPosition.x - dragItem.position.x,
|
|
||||||
y: nextPosition.y - dragItem.position.y,
|
|
||||||
};
|
|
||||||
dragItem.position = nextPosition;
|
|
||||||
|
|
||||||
return dragItem;
|
return dragItem;
|
||||||
}
|
}
|
||||||
@@ -121,11 +108,6 @@ export function getEventHandlerParams({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
position: n.position,
|
|
||||||
positionAbsolute: {
|
|
||||||
x: (node.positionAbsolute?.x || 0) + n.delta.x,
|
|
||||||
y: (node.positionAbsolute?.y || 0) + n.delta.y,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,16 @@ const createStore = () =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (positionChanged) {
|
if (positionChanged) {
|
||||||
|
change.positionAbsolute = node.position;
|
||||||
change.position = node.position;
|
change.position = node.position;
|
||||||
|
|
||||||
|
if (node.parentNode) {
|
||||||
|
const parentNode = nodeInternals.get(node.parentNode);
|
||||||
|
change.position = {
|
||||||
|
x: change.position.x - (parentNode?.positionAbsolute?.x ?? 0),
|
||||||
|
y: change.position.y - (parentNode?.positionAbsolute?.y ?? 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return change;
|
return change;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type NodePositionChange = {
|
|||||||
id: string;
|
id: string;
|
||||||
type: 'position';
|
type: 'position';
|
||||||
position?: XYPosition;
|
position?: XYPosition;
|
||||||
|
positionAbsolute?: XYPosition;
|
||||||
dragging?: boolean;
|
dragging?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ export type NodeDragItem = {
|
|||||||
position: XYPosition;
|
position: XYPosition;
|
||||||
// distance from the mouse cursor to the node when start dragging
|
// distance from the mouse cursor to the node when start dragging
|
||||||
distance: XYPosition;
|
distance: XYPosition;
|
||||||
// delta to previous position
|
|
||||||
delta: XYPosition;
|
|
||||||
width?: number | null;
|
width?: number | null;
|
||||||
height?: number | null;
|
height?: number | null;
|
||||||
extent?: 'parent' | CoordinateExtent;
|
extent?: 'parent' | CoordinateExtent;
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ function applyChanges(changes: any[], elements: any[]): any[] {
|
|||||||
updateItem.position = currentChange.position;
|
updateItem.position = currentChange.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof currentChange.positionAbsolute !== 'undefined') {
|
||||||
|
updateItem.positionAbsolute = currentChange.positionAbsolute;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof currentChange.dragging !== 'undefined') {
|
if (typeof currentChange.dragging !== 'undefined') {
|
||||||
updateItem.dragging = currentChange.dragging;
|
updateItem.dragging = currentChange.dragging;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user