From e459ea0cc7db71d60fe5125660b1ef47b44f0771 Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Sun, 2 Mar 2025 11:37:35 +0100 Subject: [PATCH] Apply outline tracking to simple arrows as well Signed-off-by: Mark Tolmacs --- packages/element/src/binding.ts | 27 +++++++++++- packages/element/src/linearElementEditor.ts | 49 ++++++++++++++++++--- packages/excalidraw/components/App.tsx | 1 - 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index 55b4ba6ce8..332cf57eb0 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -966,6 +966,7 @@ export const bindPointToSnapToElementOutline = ( ), otherPoint, ), + adjacentPoint, ), ).sort( (g, h) => @@ -1017,7 +1018,31 @@ export const bindPointToSnapToElementOutline = ( ); } - return edgePoint; + const currentDistance = pointDistance(edgePoint, center); + const fullDistance = Math.max( + pointDistance(intersection ?? edgePoint, center), + 1e-5, // Avoid division by zero + ); + const ratio = round(currentDistance / fullDistance); + + switch (true) { + case ratio > 0.5: + return pointFromVector( + vectorScale( + vectorNormalize( + vectorFromPoint(intersection ?? center, adjacentPoint), + ), + -FIXED_BINDING_DISTANCE, + ), + intersection ?? edgePoint, + ); + default: + if (elbowed) { + return headingToMidBindPoint(edgePoint, bindableElement, aabb); + } + + return edgePoint; + } }; export const avoidRectangularCorner = ( diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 8a9117bf88..10bc71733d 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -258,7 +258,7 @@ export class LinearElementEditor { return null; } const { elementId } = linearElementEditor; - const elementsMap = scene.getNonDeletedElementsMap(); + const elementsMap = app.scene.getNonDeletedElementsMap(); const element = LinearElementEditor.getElement(elementId, elementsMap); if (!element) { return null; @@ -334,19 +334,54 @@ export class LinearElementEditor { LinearElementEditor.movePoints( element, selectedPointsIndices.map((pointIndex) => { + let p = pointFrom( + element.x + element.points[pointIndex][0] + deltaX, + element.y + element.points[pointIndex][1] + deltaY, + ); + if ( + pointIndex === lastClickedPoint && + (pointIndex === 0 || pointIndex === element.points.length - 1) + ) { + const hoveredElement = getHoveredElementForBinding( + { + x: scenePointerX, + y: scenePointerY, + }, + app.scene.getNonDeletedElements(), + app.scene.getNonDeletedElementsMap(), + app.state.zoom, + isElbowArrow(element), + isElbowArrow(element), + ); + if (hoveredElement) { + const newPoints = Array.from(element.points); + newPoints[pointIndex] = pointFrom( + element.points[pointIndex][0] + deltaX, + element.points[pointIndex][1] + deltaY, + ); + p = bindPointToSnapToElementOutline( + { + ...element, + points: newPoints, + }, + hoveredElement, + pointIndex === 0 ? "start" : "end", + ); + } + } + const newPointPosition: LocalPoint = pointIndex === lastClickedPoint ? LinearElementEditor.createPointAt( element, elementsMap, - scenePointerX - linearElementEditor.pointerOffset.x, - scenePointerY - linearElementEditor.pointerOffset.y, + p[0], + p[1], + // p[0] - linearElementEditor.pointerOffset.x, + // p[1] - linearElementEditor.pointerOffset.y, event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(), ) - : pointFrom( - element.points[pointIndex][0] + deltaX, - element.points[pointIndex][1] + deltaY, - ); + : pointFrom(p[0] - element.x, p[1] - element.y); return { index: pointIndex, point: newPointPosition, diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 276cde0274..e50e02978f 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -8273,7 +8273,6 @@ class App extends React.Component { ); }, linearElementEditor, - this.scene, ); if (newLinearElementEditor) { pointerDownState.lastCoords.x = pointerCoords.x;