From 2532538bb0d712a0577ba73ab9df601279df0205 Mon Sep 17 00:00:00 2001 From: r00gm Date: Tue, 10 Sep 2024 13:24:30 +0200 Subject: [PATCH] fix: collision avoidance --- .../edges/CanvasConnectionLine.spec.ts | 21 +++++++++++++++++++ .../canvas/elements/edges/utils/edgePath.ts | 17 +++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts index 876cde7ca642c..7591a86668d55 100644 --- a/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts +++ b/packages/editor-ui/src/components/canvas/elements/edges/CanvasConnectionLine.spec.ts @@ -53,4 +53,25 @@ describe('CanvasConnectionLine', () => { 'M0 0L 32,0Q 40,0 40,8L 40,132Q 40,140 32,140L1 140L0 140M0 140L-40 140L -132,140Q -140,140 -140,132L -140,-92Q -140,-100 -132,-100L-100 -100', ); }); + + it('should only avoid obstacles when the edge intersects the nodes ', () => { + const { container } = renderComponent({ + props: { + ...DEFAULT_PROPS, + sourceX: -72, + sourceY: -290, + sourcePosition: Position.Right, + targetX: -344, + targetY: -30, + targetPosition: Position.Left, + }, + }); + + const edge = container.querySelector('.vue-flow__edge-path'); + + expect(edge).toHaveAttribute( + 'd', + 'M-72 -290L -57,-290Q -52,-290 -52,-285L -52,-165Q -52,-160 -57,-160L -359,-160Q -364,-160 -364,-155L -364,-35Q -364,-30 -359,-30L-344 -30', + ); + }); }); diff --git a/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts b/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts index 348a0283b8026..8975641a1a7d8 100644 --- a/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts +++ b/packages/editor-ui/src/components/canvas/elements/edges/utils/edgePath.ts @@ -5,7 +5,13 @@ const EDGE_PADDING_Y = 140; const EDGE_PADDING_Y_TOP = 80; const EDGE_BORDER_RADIUS = 8; const EDGE_OFFSET = 40; -const HANDLE_SIZE = 16; +// const HANDLE_SIZE = 16; + +const isTargetHandlePositionedLeftOfSourceTarget = (sourceX: number, targetX: number) => + sourceX > targetX; + +const pathIntersectsNodes = (targetY: number, sourceY: number) => + Math.abs(targetY - sourceY) < EDGE_PADDING_Y; export function getCustomPath( props: Pick< @@ -14,12 +20,15 @@ export function getCustomPath( >, ) { const { targetX, targetY, sourceX, sourceY, sourcePosition, targetPosition } = props; - const xDiff = targetX - sourceX; const yDiff = targetY - sourceY; + if (!isTargetHandlePositionedLeftOfSourceTarget(sourceX, targetX)) { + return getBezierPath(props); + } + // Connection is backwards and the source is on the right side // -> We need to avoid overlapping the source node - if (xDiff < -HANDLE_SIZE && sourcePosition === Position.Right) { + if (pathIntersectsNodes(targetY, sourceY)) { const direction = yDiff < -EDGE_PADDING_Y || yDiff > 0 ? 'up' : 'down'; const firstSegmentTargetX = sourceX; const firstSegmentTargetY = @@ -49,5 +58,5 @@ export function getCustomPath( return path; } - return getBezierPath(props); + return getSmoothStepPath(props); }