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:
Moritz Klack
2022-06-01 12:55:36 +02:00
committed by GitHub
parent 17df2ab078
commit 26795be7fb
7 changed files with 29 additions and 40 deletions

View File

@@ -141,7 +141,7 @@ const initialEdges: Edge[] = [
];
const connectionLineStyle: CSSProperties = { stroke: '#ddd' };
const snapGrid: SnapGrid = [16, 16];
const snapGrid: SnapGrid = [25, 25];
const nodeStrokeColor = (n: Node): string => {
if (n.style?.background) return n.style.background as string;
@@ -203,7 +203,7 @@ const OverviewFlow = () => {
>
<MiniMap nodeStrokeColor={nodeStrokeColor} nodeColor={nodeColor} nodeBorderRadius={2} />
<Controls />
<Background color="#aaa" gap={20} />
<Background color="#aaa" gap={25} />
</ReactFlow>
);
};

View File

@@ -4,8 +4,8 @@ import { select } from 'd3-selection';
import { useStoreApi } from '../../store';
import { pointToRendererPoint } from '../../utils/graph';
import { NodeDragItem, NodeDragHandler, XYPosition } from '../../types';
import { getDragItems, getEventHandlerParams, getParentNodePosition, hasSelector, updatePosition } from './utils';
import { NodeDragItem, NodeDragHandler } from '../../types';
import { getDragItems, getEventHandlerParams, hasSelector, updatePosition } from './utils';
import { handleNodeClick } from '../../components/Nodes/utils';
export type UseDragEvent = D3DragEvent<HTMLDivElement, null, SubjectPosition>;
@@ -40,7 +40,6 @@ function useDrag({
const store = useStoreApi();
const dragItems = useRef<NodeDragItem[]>();
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
const getPointerPosition = useCallback(({ sourceEvent }: UseDragEvent) => {
@@ -49,9 +48,6 @@ function useDrag({
const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY;
const pointerPos = pointToRendererPoint({ x, y }, transform, snapToGrid, snapGrid);
pointerPos.x -= parentPos.current.x;
pointerPos.y -= parentPos.current.y;
return pointerPos;
}, []);
@@ -65,7 +61,6 @@ function useDrag({
const dragHandler = drag()
.on('start', (event: UseDragEvent) => {
const { nodeInternals, multiSelectionActive, unselectNodesAndEdges } = store.getState();
parentPos.current = getParentNodePosition(nodeInternals, nodeId);
if (!selectNodesOnDrag && !multiSelectionActive && nodeId) {
if (!nodeInternals.get(nodeId)?.selected) {

View File

@@ -21,16 +21,6 @@ export function isParentSelected(node: Node, nodeInternals: NodeInternals): bool
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 {
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)))
.map((n) => ({
id: n.id,
position: n.position,
position: n.positionAbsolute || { x: 0, y: 0 },
distance: {
x: mousePos.x - n.position.x,
y: mousePos.y - n.position.y,
x: mousePos.x - (n.positionAbsolute?.x ?? 0),
y: mousePos.y - (n.positionAbsolute?.y ?? 0),
},
delta: {
x: 0,
@@ -72,16 +62,19 @@ export function updatePosition(
nodeExtent?: CoordinateExtent
): NodeDragItem {
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.parentNode && dragItem.width && dragItem.height) {
const parent = nodeInternals.get(dragItem.parentNode);
currentExtent =
parent?.width && parent?.height
parent?.positionAbsolute && parent?.width && parent?.height
? [
[0, 0],
[parent.width - dragItem.width, parent.height - dragItem.height],
[parent.positionAbsolute.x, parent.positionAbsolute.y],
[
parent.positionAbsolute.x + parent.width - dragItem.width,
parent.positionAbsolute.y + parent.height - dragItem.height,
],
]
: currentExtent;
} else {
@@ -93,13 +86,7 @@ export function updatePosition(
}
}
nextPosition = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition;
dragItem.delta = {
x: nextPosition.x - dragItem.position.x,
y: nextPosition.y - dragItem.position.y,
};
dragItem.position = nextPosition;
dragItem.position = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition;
return dragItem;
}
@@ -121,11 +108,6 @@ export function getEventHandlerParams({
return {
...node,
position: n.position,
positionAbsolute: {
x: (node.positionAbsolute?.x || 0) + n.delta.x,
y: (node.positionAbsolute?.y || 0) + n.delta.y,
},
};
});

View File

@@ -99,7 +99,16 @@ const createStore = () =>
};
if (positionChanged) {
change.positionAbsolute = 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;

View File

@@ -12,6 +12,7 @@ export type NodePositionChange = {
id: string;
type: 'position';
position?: XYPosition;
positionAbsolute?: XYPosition;
dragging?: boolean;
};

View File

@@ -115,8 +115,6 @@ export type NodeDragItem = {
position: XYPosition;
// distance from the mouse cursor to the node when start dragging
distance: XYPosition;
// delta to previous position
delta: XYPosition;
width?: number | null;
height?: number | null;
extent?: 'parent' | CoordinateExtent;

View File

@@ -67,6 +67,10 @@ function applyChanges(changes: any[], elements: any[]): any[] {
updateItem.position = currentChange.position;
}
if (typeof currentChange.positionAbsolute !== 'undefined') {
updateItem.positionAbsolute = currentChange.positionAbsolute;
}
if (typeof currentChange.dragging !== 'undefined') {
updateItem.dragging = currentChange.dragging;
}