From 493e6c2961b6864ca0b6d6e4e9a8a62a057e8e94 Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Sun, 31 Aug 2025 11:49:20 +0200 Subject: [PATCH] Fix jiggly arrows Signed-off-by: Mark Tolmacs --- packages/element/src/binding.ts | 105 +++++++------------- packages/element/src/linearElementEditor.ts | 85 +++++++++------- 2 files changed, 85 insertions(+), 105 deletions(-) diff --git a/packages/element/src/binding.ts b/packages/element/src/binding.ts index cb6038a940..e62771419b 100644 --- a/packages/element/src/binding.ts +++ b/packages/element/src/binding.ts @@ -193,82 +193,49 @@ export const getStartGlobalEndLocalPointsForSimpleArrowBinding = ( arrow: NonDeleted, start: BindingStrategy, end: BindingStrategy, - startPoint: GlobalPoint, - endPoint: LocalPoint, elementsMap: ElementsMap, -): [GlobalPoint, LocalPoint] => { - let startGlobalPoint = startPoint; - let endLocalPoint = endPoint; +): [GlobalPoint, GlobalPoint] => { + let startGlobalPoint = pointFrom(arrow.x, arrow.y); + let endGlobalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates( + arrow, + -1, + elementsMap, + ); - if (end.mode) { - const newEndLocalPoint = updateBoundPoint( - arrow, - "endBinding", - end.mode - ? { - ...calculateFixedPointForNonElbowArrowBinding( - arrow, - end.element, - "end", - elementsMap, - end.focusPoint, - ), - elementId: end.element.id, - mode: end.mode, - } - : null, - end.element, - 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.focusPoint) { + startGlobalPoint = start.focusPoint; + } + if (end.focusPoint) { + endGlobalPoint = end.focusPoint; } if (start.mode) { - const newStartLocalPoint = updateBoundPoint( - arrow, - "startBinding", - start.mode - ? { - ...calculateFixedPointForNonElbowArrowBinding( - arrow, - start.element, - "start", - elementsMap, - start.focusPoint, - ), - elementId: start.element.id, - mode: start.mode, - } - : null, - start.element, - elementsMap, - ); - startGlobalPoint = newStartLocalPoint - ? LinearElementEditor.getPointGlobalCoordinates( - arrow, - newStartLocalPoint, - elementsMap, - ) - : startGlobalPoint; - if (start.focusPoint[0] === 0.5001 && start.focusPoint[1] === 0.5001) { - startGlobalPoint = elementCenterPoint(arrow, elementsMap); - } + startGlobalPoint = + start.mode === "orbit" + ? bindPointToSnapToElementOutline( + arrow, + start.element, + "start", + elementsMap, + lineSegment(startGlobalPoint, endGlobalPoint), + ) + : startGlobalPoint; } - return [ - startGlobalPoint, - pointFrom( - endLocalPoint[0] - (startGlobalPoint[0] - arrow.x), - endLocalPoint[1] - (startGlobalPoint[1] - arrow.y), - ), - ]; + if (end.mode) { + endGlobalPoint = + end.mode === "orbit" + ? bindPointToSnapToElementOutline( + arrow, + end.element, + "end", + elementsMap, + lineSegment(startGlobalPoint, endGlobalPoint), + ) + : endGlobalPoint; + } + + return [startGlobalPoint, endGlobalPoint]; }; const bindingStrategyForNewSimpleArrowEndpointDragging = ( diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 4ef4dc7193..01dc043e2c 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -2073,9 +2073,49 @@ const pointDraggingUpdates = ( }; } - const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints( + const s = startIsDragged + ? pointFrom(element.x + deltaX, element.y + deltaY) + : pointFrom(element.x, element.y); + const preE = LinearElementEditor.getPointAtIndexGlobalCoordinates( element, - naiveDraggingPoints, + -1, + elementsMap, + ); + const e = endIsDragged + ? pointFrom(preE[0] + deltaX, preE[1] + deltaY) + : preE; + + const nextArrow = { + ...element, + x: s[0], + y: s[1], + points: [ + ...element.points + .slice(0, -1) + .map((p) => + pointFrom( + p[0] + (s[0] - element.x), + p[1] + (s[1] - element.y), + ), + ), + pointFrom(e[0] - s[0], e[1] - s[1]), + ], + }; + + const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints( + nextArrow, + new Map( + Array.from(naiveDraggingPoints).map(([idx, { point }]) => [ + idx, + { + point: pointFrom( + point[0] + (s[0] - element.x), + point[1] + (s[1] - element.y), + ), + isDragging: true, + }, + ]), + ), elementsMap, elements, app.state, @@ -2084,39 +2124,11 @@ const pointDraggingUpdates = ( }, ); - const originalStartGlobalPoint = - LinearElementEditor.getPointGlobalCoordinates( - element, - element.points[0], - elementsMap, - ); - const originalEndGlobalPoint = LinearElementEditor.getPointGlobalCoordinates( - element, - element.points[element.points.length - 1], - elementsMap, - ); - const offsetStartGlobalPoint = startIsDragged - ? pointFrom( - originalStartGlobalPoint[0] + deltaX, - originalStartGlobalPoint[1] + deltaY, - ) - : originalStartGlobalPoint; - const offsetEndGlobalPoint = pointFrom( - originalEndGlobalPoint[0] + deltaX, - originalEndGlobalPoint[1] + deltaY, - ); - const offsetEndLocalPoint = pointFrom( - offsetEndGlobalPoint[0] - offsetStartGlobalPoint[0], - offsetEndGlobalPoint[1] - offsetStartGlobalPoint[1], - ); - - const [startGlobalPoint, endLocalPoint] = + const [startGlobalPoint, endGlobalPoint] = getStartGlobalEndLocalPointsForSimpleArrowBinding( - element, + nextArrow, start, end, - offsetStartGlobalPoint, - offsetEndLocalPoint, elementsMap, ); const startLocalPoint = LinearElementEditor.pointFromAbsoluteCoords( @@ -2124,9 +2136,10 @@ const pointDraggingUpdates = ( startGlobalPoint, elementsMap, ); - const finalEndLocalPoint = pointFrom( - endLocalPoint[0] + (startGlobalPoint[0] - element.x), - endLocalPoint[1] + (startGlobalPoint[1] - element.y), + const endLocalPoint = LinearElementEditor.pointFromAbsoluteCoords( + element, + endGlobalPoint, + elementsMap, ); const indices = Array.from( @@ -2170,7 +2183,7 @@ const pointDraggingUpdates = ( idx === 0 ? { point: startLocalPoint, isDragging: true } : idx === element.points.length - 1 - ? { point: finalEndLocalPoint, isDragging: true } + ? { point: endLocalPoint, isDragging: true } : naiveDraggingPoints.get(idx)!, ]; }),