Skip to Content
ExamplesEdges

Floating Edges

This is an example implementation for floating edges. The source and target position of the edges are getting calculated dynamically. You can find the implementation details in the utils.js file.

import type { InternalNode } from '@xyflow/vue'; import { Position } from '@xyflow/vue'; // returns the intersection point of the line between the center of intersectionNode and the target node // https://math.stackexchange.com/questions/1724792 function getNodeIntersection(intersectionNode: InternalNode, targetNode: InternalNode) { const intersectionNodeWidth = intersectionNode.measured.width ?? 0; const intersectionNodeHeight = intersectionNode.measured.height ?? 0; const intersectionNodePosition = intersectionNode.internals.positionAbsolute; const targetPosition = targetNode.internals.positionAbsolute; const w = intersectionNodeWidth / 2; const h = intersectionNodeHeight / 2; const x2 = intersectionNodePosition.x + w; const y2 = intersectionNodePosition.y + h; const x1 = targetPosition.x + (targetNode.measured.width ?? 0) / 2; const y1 = targetPosition.y + (targetNode.measured.height ?? 0) / 2; const xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h); const yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h); const a = 1 / (Math.abs(xx1) + Math.abs(yy1) || 1); const xx3 = a * xx1; const yy3 = a * yy1; const x = w * (xx3 + yy3) + x2; const y = h * (-xx3 + yy3) + y2; return { x, y }; } // returns the position (Top, Right, Bottom or Left) of the node relative to the intersection point function getEdgePosition(node: InternalNode, intersectionPoint: { x: number; y: number }) { const pos = node.internals.positionAbsolute; const nx = Math.round(pos.x); const ny = Math.round(pos.y); const px = Math.round(intersectionPoint.x); const py = Math.round(intersectionPoint.y); const width = node.measured.width ?? 0; const height = node.measured.height ?? 0; if (px <= nx + 1) { return Position.Left; } if (px >= nx + width - 1) { return Position.Right; } if (py <= ny + 1) { return Position.Top; } if (py >= ny + height - 1) { return Position.Bottom; } return Position.Top; } // returns the params (sx, sy, tx, ty, sourcePos, targetPos) needed to draw a floating edge between two nodes export function getEdgeParams(source: InternalNode, target: InternalNode) { const sourceIntersectionPoint = getNodeIntersection(source, target); const targetIntersectionPoint = getNodeIntersection(target, source); const sourcePos = getEdgePosition(source, sourceIntersectionPoint); const targetPos = getEdgePosition(target, targetIntersectionPoint); return { sx: sourceIntersectionPoint.x, sy: sourceIntersectionPoint.y, tx: targetIntersectionPoint.x, ty: targetIntersectionPoint.y, sourcePos, targetPos, }; }
Last updated on