|
19 | 19 | </script> |
20 | 20 |
|
21 | 21 | <script lang="ts"> |
22 | | - import { BaseEdge, type EdgeProps, Position } from '@xyflow/svelte'; |
| 22 | + import { BaseEdge, getSmoothStepPath, type EdgeProps, Position } from '@xyflow/svelte'; |
23 | 23 | import { hoveredHandle, selectedNodeHighlight } from '$lib/stores/hoveredHandle'; |
24 | 24 | import { routingStore, type PortInfo } from '$lib/stores/routing'; |
25 | 25 | import { historyStore } from '$lib/stores/history'; |
|
294 | 294 | } |
295 | 295 | }); |
296 | 296 |
|
297 | | - // Always use the cached path - never show fallback routes |
| 297 | + // Smooth-step fallback when no valid orthogonal path exists |
| 298 | + const smoothStepFallback = $derived(() => { |
| 299 | + const src = adjustedSource(); |
| 300 | + const tgt = adjustedTarget(); |
| 301 | + const [edgePath] = getSmoothStepPath({ |
| 302 | + sourceX: src.x, |
| 303 | + sourceY: src.y, |
| 304 | + sourcePosition, |
| 305 | + targetX: tgt.x, |
| 306 | + targetY: tgt.y, |
| 307 | + targetPosition, |
| 308 | + borderRadius: 8 |
| 309 | + }); |
| 310 | + return edgePath; |
| 311 | + }); |
| 312 | +
|
| 313 | + // Use cached orthogonal path, or fall back to smooth-step |
298 | 314 | const pathInfo = $derived(() => { |
299 | | - return { path: cachedPath, isFallback: !cachedPath }; |
| 315 | + if (cachedPath) return { path: cachedPath, isFallback: false }; |
| 316 | + return { path: smoothStepFallback(), isFallback: true }; |
300 | 317 | }); |
301 | 318 |
|
302 | 319 | // Get user waypoints from route result or data |
|
488 | 505 | return { x: endPoint.x, y: endPoint.y, angle }; |
489 | 506 | } |
490 | 507 |
|
491 | | - // Fallback (smoothstep): arrow based on target position, use unadjusted target |
492 | | - let angle = 0; |
493 | | - if (targetPosition === 'left') angle = 180; |
494 | | - else if (targetPosition === 'top') angle = -90; |
495 | | - else if (targetPosition === 'bottom') angle = 90; |
| 508 | + // Fallback (smoothstep): derive arrow position and angle from SVG path geometry |
| 509 | + const { path } = pathInfo(); |
| 510 | + if (path) { |
| 511 | + const svgPath = document.createElementNS('http://www.w3.org/2000/svg', 'path'); |
| 512 | + svgPath.setAttribute('d', path); |
| 513 | + const totalLength = svgPath.getTotalLength(); |
| 514 | + const endPoint = svgPath.getPointAtLength(totalLength); |
| 515 | + const nearEnd = svgPath.getPointAtLength(totalLength - 5); |
| 516 | + const angle = Math.atan2(endPoint.y - nearEnd.y, endPoint.x - nearEnd.x) * (180 / Math.PI); |
| 517 | + return { x: endPoint.x, y: endPoint.y, angle }; |
| 518 | + } |
496 | 519 |
|
497 | | - return { x: targetX, y: targetY, angle }; |
| 520 | + return { x: tgt.x, y: tgt.y, angle: 0 }; |
498 | 521 | }); |
499 | 522 | </script> |
500 | 523 |
|
|
0 commit comments