Unbind arrow if bound and moved at shaft of arrow key

This commit is contained in:
Mark Tolmacs 2025-06-23 17:01:12 +02:00
parent b8fac37115
commit 3ae89aba47
No known key found for this signature in database
3 changed files with 35 additions and 4 deletions

View File

@ -13,7 +13,7 @@ import type {
import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types"; import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types";
import { updateBoundElements } from "./binding"; import { bindOrUnbindLinearElement, updateBoundElements } from "./binding";
import { getCommonBounds } from "./bounds"; import { getCommonBounds } from "./bounds";
import { getPerfectElementSize } from "./sizeHelpers"; import { getPerfectElementSize } from "./sizeHelpers";
import { getBoundTextElement } from "./textElement"; import { getBoundTextElement } from "./textElement";
@ -118,9 +118,16 @@ export const dragSelectedElements = (
adjustedOffset, adjustedOffset,
); );
} }
updateBoundElements(element, scene, { updateBoundElements(element, scene, {
simultaneouslyUpdated: Array.from(elementsToUpdate), simultaneouslyUpdated: Array.from(elementsToUpdate),
}); });
} else {
// NOTE: Moving the bound arrow should unbind it, otherwise we would
// have weird situations, like 0 lenght arrow when the user moves
// the arrow outside a filled shape suddenly forcing the arrow start
// and end point to jump "outside" the shape.
bindOrUnbindLinearElement(element, null, null, scene);
} }
}); });
}; };

View File

@ -2056,14 +2056,29 @@ const pointDraggingUpdates = (
isElbowArrow(element), isElbowArrow(element),
); );
const otherBinding = const otherGlobalPoint =
element[pointIndex === 0 ? "endBinding" : "startBinding"]; LinearElementEditor.getPointAtIndexGlobalCoordinates(
element,
pointIndex === 0 ? element.points.length - 1 : 0,
elementsMap,
);
const otherHoveredElement = getHoveredElementForBinding(
{
x: otherGlobalPoint[0],
y: otherGlobalPoint[1],
},
elements,
elementsMap,
zoom,
shouldTestInside(element),
isElbowArrow(element),
);
// Allow binding inside the element if both ends are inside // Allow binding inside the element if both ends are inside
if ( if (
isArrowElement(element) && isArrowElement(element) &&
!( !(
hoveredElement?.id === otherBinding?.elementId && hoveredElement?.id === otherHoveredElement?.id &&
hoveredElement != null hoveredElement != null
) )
) { ) {

View File

@ -233,6 +233,7 @@ import {
isLineElement, isLineElement,
isSimpleArrow, isSimpleArrow,
getOutlineAvoidingPoint, getOutlineAvoidingPoint,
bindOrUnbindLinearElement,
} from "@excalidraw/element"; } from "@excalidraw/element";
import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math";
@ -4388,6 +4389,14 @@ class App extends React.Component<AppProps, AppState> {
{ informMutation: false, isDragging: false }, { informMutation: false, isDragging: false },
); );
if (isSimpleArrow(element)) {
// NOTE: Moving the bound arrow should unbind it, otherwise we would
// have weird situations, like 0 lenght arrow when the user moves
// the arrow outside a filled shape suddenly forcing the arrow start
// and end point to jump "outside" the shape.
bindOrUnbindLinearElement(element, null, null, this.scene);
}
updateBoundElements(element, this.scene, { updateBoundElements(element, this.scene, {
simultaneouslyUpdated: selectedElements, simultaneouslyUpdated: selectedElements,
}); });