From 534da13a607e6349e3c89e3c8ce9046d02e8b60b Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Tue, 18 Nov 2025 12:50:11 +0100 Subject: [PATCH] fix: Center point for linears Signed-off-by: Mark Tolmacs --- packages/element/src/binding.ts | 29 +++++++-------------- packages/element/src/bounds.ts | 10 ++++++- packages/element/src/linearElementEditor.ts | 9 ++++++- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index ce21b582fb..7126f2e6e7 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -4,6 +4,7 @@ import { getFeatureFlag, invariant, isTransparent, + randomId, } from "@excalidraw/common"; import { @@ -1200,16 +1201,12 @@ export const bindPointToSnapToElementOutline = ( startOrEnd: "start" | "end", elementsMap: ElementsMap, customIntersector?: LineSegment, - ignoreFrameCutouts?: boolean, ): GlobalPoint => { const aabb = aabbForElement(bindableElement, elementsMap); - const localPoint = - arrowElement.points[ - startOrEnd === "start" ? 0 : arrowElement.points.length - 1 - ]; - const point = pointFrom( - arrowElement.x + localPoint[0], - arrowElement.y + localPoint[1], + const point = LinearElementEditor.getPointAtIndexGlobalCoordinates( + arrowElement, + startOrEnd === "start" ? 0 : -1, + elementsMap, ); if (arrowElement.points.length < 2) { @@ -1222,17 +1219,11 @@ export const bindPointToSnapToElementOutline = ( : point; const elbowed = isElbowArrow(arrowElement); const center = getCenterForBounds(aabb); - const adjacentPointIdx = - startOrEnd === "start" ? 1 : arrowElement.points.length - 2; - const adjacentPoint = pointRotateRads( - pointFrom( - arrowElement.x + arrowElement.points[adjacentPointIdx][0], - arrowElement.y + arrowElement.points[adjacentPointIdx][1], - ), - center, - arrowElement.angle ?? 0, + const adjacentPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates( + arrowElement, + startOrEnd === "start" ? 1 : -2, + elementsMap, ); - const bindingGap = getBindingGap(bindableElement, arrowElement); let intersection: GlobalPoint | null = null; @@ -1624,7 +1615,6 @@ export const updateBoundPoint = ( } const isNested = (arrowTooShort || isOverlapping) && isLargerThanOther; - const maybeOutlineGlobal = binding.mode === "orbit" && bindableElement ? isNested @@ -1632,6 +1622,7 @@ export const updateBoundPoint = ( : bindPointToSnapToElementOutline( { ...arrow, + id: randomId(), x: pointIndex === 0 ? global[0] : arrow.x, y: pointIndex === 0 ? global[1] : arrow.y, points: diff --git a/packages/element/src/bounds.ts b/packages/element/src/bounds.ts index 0f3970db80..25127f1803 100644 --- a/packages/element/src/bounds.ts +++ b/packages/element/src/bounds.ts @@ -1276,7 +1276,15 @@ export const elementCenterPoint = ( xOffset: number = 0, yOffset: number = 0, ) => { - const [x, y] = getCenterForBounds(getElementBounds(element, elementsMap)); + if (isLinearElement(element)) { + const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap); + const [x, y] = pointFrom((x1 + x2) / 2, (y1 + y2) / 2); + + return pointFrom(x + xOffset, y + yOffset); + } + + const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap); + const [x, y] = pointFrom((x1 + x2) / 2, (y1 + y2) / 2); return pointFrom(x + xOffset, y + yOffset); }; diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 75d0d3dc9d..c17b67df50 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -22,6 +22,9 @@ import { invariant, isShallowEqual, getFeatureFlag, + debugDrawPoint, + debugDrawLine, + randomId, } from "@excalidraw/common"; import { @@ -51,6 +54,7 @@ import { updateBoundPoint, } from "./binding"; import { + elementCenterPoint, getElementAbsoluteCoords, getElementPointsCoords, getMinMaxXYFromCurvePathOps, @@ -2275,9 +2279,12 @@ const pointDraggingUpdates = ( element.points[element.points.length - 1][1] + deltaY, ) : element.points[element.points.length - 1]; - + debugDrawPoint(pointFrom(element.x, element.y)); const nextArrow = { ...element, + id: randomId(), + x: 0, + y: 0, points: [ offsetStartLocalPoint, ...element.points