From d7abb6a309c06616dd1e4aad86e6e8cf6278c34b Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Wed, 18 Mar 2026 20:25:19 +0000 Subject: [PATCH] fix: Diamonds and ellipses Signed-off-by: Mark Tolmacs --- packages/element/src/binding.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index cd9a1e5d12..1fbd5d66e5 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -818,6 +818,11 @@ const getBindingStrategyForDraggingBindingElementEndpoints_simple = ( elementsMap, appState.gridSize as NullableGridSize, arrow, + LinearElementEditor.getPointAtIndexGlobalCoordinates( + arrow, + startDragged ? 1 : -2, + elementsMap, + ), ) : globalPoint, hit, @@ -1768,17 +1773,21 @@ const snapBoundPointToGrid = ( elementsMap: ElementsMap, gridSize: NullableGridSize, arrowElement: ExcalidrawArrowElement, + adjacentPoint?: GlobalPoint, ): GlobalPoint => { if (!gridSize) { return outlinePoint; } const aabb = aabbForElement(bindableElement, elementsMap); - const heading = headingForPointFromElement( - bindableElement, - aabb, - outlinePoint, - ); + // For ellipses and diamonds use the arrow's incoming direction instead of + // the position-based heading, which can give the wrong axis when the + // outline point is near a cardinal zone or an angled diamond face. + const heading = + adjacentPoint && + (bindableElement.type === "ellipse" || bindableElement.type === "diamond") + ? vectorToHeading(vectorFromPoint(adjacentPoint, outlinePoint)) + : headingForPointFromElement(bindableElement, aabb, outlinePoint); const normalLocal = pointFrom(heading[0], heading[1]); const normalGlobal = pointRotateRads(