Inside detection for outline binding

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2025-03-29 13:58:50 +01:00
parent 4ea534a732
commit d6d4d00f60
2 changed files with 32 additions and 30 deletions

View file

@ -275,7 +275,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
const endDragged = draggingPoints.findIndex((i) => i === endIdx) > -1;
const start = startDragged
? isBindingEnabled
? getElligibleElementForBindingElement(
? getEligibleElementForBindingElement(
selectedElement,
"start",
elementsMap,
@ -285,7 +285,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
: null // If binding is disabled and start is dragged, break all binds
: !isElbowArrow(selectedElement)
? // We have to update the focus and gap of the binding, so let's rebind
getElligibleElementForBindingElement(
getEligibleElementForBindingElement(
selectedElement,
"start",
elementsMap,
@ -295,7 +295,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
: "keep";
const end = endDragged
? isBindingEnabled
? getElligibleElementForBindingElement(
? getEligibleElementForBindingElement(
selectedElement,
"end",
elementsMap,
@ -305,7 +305,7 @@ const getBindingStrategyForDraggingArrowEndpoints = (
: null // If binding is disabled and end is dragged, break all binds
: !isElbowArrow(selectedElement)
? // We have to update the focus and gap of the binding, so let's rebind
getElligibleElementForBindingElement(
getEligibleElementForBindingElement(
selectedElement,
"end",
elementsMap,
@ -336,7 +336,7 @@ const getBindingStrategyForDraggingArrowOrJoints = (
);
const start = startIsClose
? isBindingEnabled
? getElligibleElementForBindingElement(
? getEligibleElementForBindingElement(
selectedElement,
"start",
elementsMap,
@ -347,7 +347,7 @@ const getBindingStrategyForDraggingArrowOrJoints = (
: null;
const end = endIsClose
? isBindingEnabled
? getElligibleElementForBindingElement(
? getEligibleElementForBindingElement(
selectedElement,
"end",
elementsMap,
@ -903,6 +903,13 @@ export const bindPointToSnapToElementOutline = (
);
const edgePoint = avoidRectangularCorner(bindableElement, p);
const otherPointIdx =
startOrEnd === "start" ? linearElement.points.length - 1 : 0;
const otherPoint = pointFrom<GlobalPoint>(
linearElement.x + linearElement.points[otherPointIdx][0],
linearElement.y + linearElement.points[otherPointIdx][1],
);
const adjacentPointIdx =
startOrEnd === "start" ? 1 : linearElement.points.length - 2;
const adjacentPoint =
@ -968,6 +975,14 @@ export const bindPointToSnapToElementOutline = (
return edgePoint;
}
const shape = getElementShape(bindableElement, elementsMap);
const pointInShape = isPointInShape(edgePoint, shape);
const otherPointInShape = isPointInShape(otherPoint, shape);
if (pointInShape && otherPointInShape) {
return edgePoint;
}
if (elbowed) {
const scalar =
pointDistanceSq(edgePoint, center) -
@ -1379,7 +1394,7 @@ export const calculateFixedPointForElbowArrowBinding = (
};
};
const getElligibleElementForBindingElement = (
const getEligibleElementForBindingElement = (
linearElement: NonDeleted<ExcalidrawLinearElement>,
startOrEnd: "start" | "end",
elementsMap: NonDeletedSceneElementsMap,

View file

@ -63,7 +63,6 @@ import type {
ExcalidrawBindableElement,
FixedPointBinding,
FixedSegment,
NonDeletedExcalidrawElement,
} from "./types";
type GridAddress = [number, number] & { _brand: "gridaddress" };
@ -1221,18 +1220,22 @@ const getElbowArrowData = (
if (options?.isDragging) {
const elements = Array.from(elementsMap.values());
hoveredStartElement =
getHoveredElement(
origStartGlobalPoint,
elementsMap,
getHoveredElementForBinding(
tupleToCoors(origStartGlobalPoint),
elements,
elementsMap,
options?.zoom,
true,
true,
) || null;
hoveredEndElement =
getHoveredElement(
origEndGlobalPoint,
elementsMap,
getHoveredElementForBinding(
tupleToCoors(origEndGlobalPoint),
elements,
elementsMap,
options?.zoom,
true,
true,
) || null;
} else {
hoveredStartElement = arrow.startBinding
@ -2275,22 +2278,6 @@ const getBindPointHeading = (
origPoint,
);
const getHoveredElement = (
origPoint: GlobalPoint,
elementsMap: NonDeletedSceneElementsMap,
elements: readonly NonDeletedExcalidrawElement[],
zoom?: AppState["zoom"],
) => {
return getHoveredElementForBinding(
tupleToCoors(origPoint),
elements,
elementsMap,
zoom,
true,
true,
);
};
const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean =>
a[0] === b[0] && a[1] === b[1];