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