From 57b7f8bd427120a0ecdddf3562e0e796ecf01f93 Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Sat, 30 Aug 2025 21:54:25 +0200 Subject: [PATCH] Small positional fixes --- packages/element/src/binding.ts | 93 +++++++++------------ packages/element/src/linearElementEditor.ts | 91 +++++++++++++------- packages/excalidraw/components/App.tsx | 10 ++- 3 files changed, 108 insertions(+), 86 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index abc23c34bf..cb6038a940 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -221,6 +221,13 @@ export const getStartGlobalEndLocalPointsForSimpleArrowBinding = ( elementsMap, ); endLocalPoint = newEndLocalPoint ?? endLocalPoint; + if (end.focusPoint[0] === 0.5001 && end.focusPoint[1] === 0.5001) { + endLocalPoint = LinearElementEditor.pointFromAbsoluteCoords( + arrow, + elementCenterPoint(arrow, elementsMap), + elementsMap, + ); + } } if (start.mode) { @@ -250,6 +257,9 @@ export const getStartGlobalEndLocalPointsForSimpleArrowBinding = ( elementsMap, ) : startGlobalPoint; + if (start.focusPoint[0] === 0.5001 && start.focusPoint[1] === 0.5001) { + startGlobalPoint = elementCenterPoint(arrow, elementsMap); + } } return [ @@ -1045,51 +1055,6 @@ export const bindPointToSnapToElementOutline = ( return intersection; }; -export const getOutlineAvoidingPoint = ( - element: NonDeleted, - hoveredElement: ExcalidrawBindableElement | null, - coords: GlobalPoint, - pointIndex: number, - elementsMap: ElementsMap, - customIntersector?: LineSegment, -): GlobalPoint => { - if (hoveredElement) { - return bindPointToSnapToElementOutline( - { - ...element, - x: pointIndex === 0 ? coords[0] : element.x, - y: pointIndex === 0 ? coords[1] : element.y, - points: - pointIndex === 0 - ? [ - pointFrom(0, 0), - ...element.points - .slice(1) - .map((p) => - pointFrom( - p[0] - (coords[0] - element.x), - p[1] - (coords[1] - element.y), - ), - ), - ] - : [ - ...element.points.slice(0, -1), - pointFrom( - coords[0] - element.x, - coords[1] - element.y, - ), - ], - }, - hoveredElement, - pointIndex === 0 ? "start" : "end", - elementsMap, - customIntersector, - ); - } - - return coords; -}; - export const avoidRectangularCorner = ( element: ExcalidrawBindableElement, elementsMap: ElementsMap, @@ -1336,20 +1301,44 @@ export const updateBoundPoint = ( return null; } - const fixedPoint = normalizeFixedPoint(binding.fixedPoint); const global = getGlobalFixedPointForBindableElement( - fixedPoint, + normalizeFixedPoint(binding.fixedPoint), bindableElement, elementsMap, ); + const pointIndex = + startOrEnd === "startBinding" ? 0 : arrow.points.length - 1; const maybeOutlineGlobal = - binding.mode === "orbit" - ? getOutlineAvoidingPoint( - arrow, + binding.mode === "orbit" && bindableElement + ? bindPointToSnapToElementOutline( + { + ...arrow, + x: pointIndex === 0 ? global[0] : arrow.x, + y: pointIndex === 0 ? global[1] : arrow.y, + points: + pointIndex === 0 + ? [ + pointFrom(0, 0), + ...arrow.points + .slice(1) + .map((p) => + pointFrom( + p[0] - (global[0] - arrow.x), + p[1] - (global[1] - arrow.y), + ), + ), + ] + : [ + ...arrow.points.slice(0, -1), + pointFrom( + global[0] - arrow.x, + global[1] - arrow.y, + ), + ], + }, bindableElement, - global, - startOrEnd === "startBinding" ? 0 : arrow.points.length - 1, + pointIndex === 0 ? "start" : "end", elementsMap, ) : global; diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 129ecd9586..4ef4dc7193 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -344,6 +344,21 @@ export class LinearElementEditor { ); LinearElementEditor.movePoints(element, app.scene, positions, updates); + + // Move the arrow over the bindable object in terms of z-index + if (isBindingElement(element)) { + moveArrowAboveBindable( + LinearElementEditor.getPointGlobalCoordinates( + element, + element.points[element.points.length - 1], + elementsMap, + ), + element, + elements, + elementsMap, + app.scene, + ); + } } // Suggest bindings for first and last point if selected @@ -481,6 +496,23 @@ export class LinearElementEditor { ); LinearElementEditor.movePoints(element, app.scene, positions, updates); + + // Move the arrow over the bindable object in terms of z-index + if (isBindingElement(element) && startIsSelected !== endIsSelected) { + moveArrowAboveBindable( + LinearElementEditor.getPointGlobalCoordinates( + element, + startIsSelected + ? element.points[0] + : element.points[element.points.length - 1], + elementsMap, + ), + element, + elements, + elementsMap, + app.scene, + ); + } } // Attached text might need to update if arrow dimensions change @@ -2097,41 +2129,40 @@ const pointDraggingUpdates = ( endLocalPoint[1] + (startGlobalPoint[1] - element.y), ); - if (startIsDragged !== endIsDragged) { - moveArrowAboveBindable( - startIsDragged - ? startGlobalPoint - : LinearElementEditor.getPointGlobalCoordinates( - element, - finalEndLocalPoint, - elementsMap, - ), - element, - elements, - elementsMap, - app.scene, - ); - } - const indices = Array.from( new Set([0, element.points.length - 1, ...selectedPointsIndices]), ); + const updates: PointMoveOtherUpdates = {}; + if (start.mode) { + updates.startBinding = { + elementId: start.element.id, + mode: start.mode, + ...calculateFixedPointForNonElbowArrowBinding( + element, + start.element, + "start", + elementsMap, + start.focusPoint, + ), + }; + } + if (end.mode) { + updates.endBinding = { + elementId: end.element.id, + mode: end.mode, + ...calculateFixedPointForNonElbowArrowBinding( + element, + end.element, + "end", + elementsMap, + end.focusPoint, + ), + }; + } + return { - updates: start.mode - ? { - startBinding: { - elementId: start.element.id, - mode: start.mode, - ...calculateFixedPointForNonElbowArrowBinding( - element, - start.element, - "start", - elementsMap, - ), - }, - } - : undefined, + updates: start.mode || end.mode ? updates : undefined, positions: new Map( indices.map((idx) => { return [ diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index debc67cc24..aa93e4d8b8 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -969,19 +969,21 @@ class App extends React.Component { const event = this.lastPointerMoveEvent ?? this.lastPointerDownEvent?.nativeEvent; invariant(event, "Last event must exist"); + const deltaX = x - this.state.selectedLinearElement.pointerOffset.x; + const deltaY = y - this.state.selectedLinearElement.pointerOffset.y; const newState = this.state.multiElement ? LinearElementEditor.handlePointerMove( event, this, - x - this.state.selectedLinearElement.pointerOffset.x, - y - this.state.selectedLinearElement.pointerOffset.y, + deltaX, + deltaY, this.state.selectedLinearElement, ) : LinearElementEditor.handlePointDragging( event, this, - x - this.state.selectedLinearElement.pointerOffset.x, - y - this.state.selectedLinearElement.pointerOffset.y, + deltaX, + deltaY, this.state.selectedLinearElement, ); this.setState(newState);