Easy Connect
Fed up with tiny little connection handles? Make your whole node act as one! Keep in mind though that you need to define separate drag handles in this case to still be able to drag the node.
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