fix(selection): keep node positions when extent is reached closes

This commit is contained in:
moklick
2023-08-14 15:54:30 +02:00
parent 647c73cc8a
commit 9520407cf0
2 changed files with 37 additions and 6 deletions

View File

@@ -254,9 +254,10 @@ export function calcNextPosition<NodeType extends NodeBase>(
];
}
const positionAbsolute = currentExtent
? clampPosition(nextPosition, currentExtent as CoordinateExtent)
: nextPosition;
const positionAbsolute =
currentExtent && currentExtent !== 'parent'
? clampPosition(nextPosition, currentExtent as CoordinateExtent)
: nextPosition;
return {
position: {

View File

@@ -1,7 +1,15 @@
import { drag } from 'd3-drag';
import { select } from 'd3-selection';
import { calcAutoPan, getEventPosition, getPointerPosition, calcNextPosition, snapPosition } from '../utils';
import {
calcAutoPan,
getEventPosition,
getPointerPosition,
calcNextPosition,
snapPosition,
getRectOfNodes,
rectToBox,
} from '../utils';
import { getDragItems, getEventHandlerParams, hasSelector, wrapSelectionDragFunc } from './utils';
import type {
NodeBase,
@@ -18,6 +26,7 @@ import type {
OnNodeDrag,
OnSelectionDrag,
UpdateNodePositions,
Box,
} from '../types';
export type OnDrag = (event: MouseEvent, dragItems: NodeDragItem[], node: NodeBase, nodes: NodeBase[]) => void;
@@ -105,6 +114,12 @@ export function XYDrag({
lastPos = { x, y };
let hasChange = false;
let nodesBox: Box = { x: 0, y: 0, x2: 0, y2: 0 };
if (dragItems.length > 1 && nodeExtent) {
const rect = getRectOfNodes(dragItems as unknown as NodeBase[], nodeOrigin);
nodesBox = rectToBox(rect);
}
dragItems = dragItems.map((n) => {
let nextPosition = { x: x - n.distance.x, y: y - n.distance.y };
@@ -113,9 +128,24 @@ export function XYDrag({
nextPosition = snapPosition(nextPosition, snapGrid);
}
const updatedPos = calcNextPosition(n, nextPosition, nodes, nodeExtent, nodeOrigin, onError);
// if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node
// based on its position so that the node stays at it's position relative to the selection.
const adjustedNodeExtent: CoordinateExtent = [
[nodeExtent[0][0], nodeExtent[0][1]],
[nodeExtent[1][0], nodeExtent[1][1]],
];
// we want to make sure that we only fire a change event when there is a changes
if (dragItems.length > 1 && nodeExtent && !n.extent) {
adjustedNodeExtent[0][0] = n.positionAbsolute.x - nodesBox.x + nodeExtent[0][0];
adjustedNodeExtent[1][0] = n.positionAbsolute.x + (n.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];
adjustedNodeExtent[0][1] = n.positionAbsolute.y - nodesBox.y + nodeExtent[0][1];
adjustedNodeExtent[1][1] = n.positionAbsolute.y + (n.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];
}
const updatedPos = calcNextPosition(n, nextPosition, nodes, adjustedNodeExtent, nodeOrigin, onError);
// we want to make sure that we only fire a change event when there is a change
hasChange = hasChange || n.position.x !== updatedPos.position.x || n.position.y !== updatedPos.position.y;
n.position = updatedPos.position;