feat(packages): add edge-utils
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { Position } from '@reactflow/system';
|
||||
|
||||
export type GetBezierPathParams = {
|
||||
sourceX: number;
|
||||
sourceY: number;
|
||||
sourcePosition?: Position;
|
||||
targetX: number;
|
||||
targetY: number;
|
||||
targetPosition?: Position;
|
||||
curvature?: number;
|
||||
};
|
||||
|
||||
export type GetControlWithCurvatureParams = {
|
||||
pos: Position;
|
||||
x1: number;
|
||||
y1: number;
|
||||
x2: number;
|
||||
y2: number;
|
||||
c: number;
|
||||
};
|
||||
|
||||
export function getBezierEdgeCenter({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
sourceControlX,
|
||||
sourceControlY,
|
||||
targetControlX,
|
||||
targetControlY,
|
||||
}: {
|
||||
sourceX: number;
|
||||
sourceY: number;
|
||||
targetX: number;
|
||||
targetY: number;
|
||||
sourceControlX: number;
|
||||
sourceControlY: number;
|
||||
targetControlX: number;
|
||||
targetControlY: number;
|
||||
}): [number, number, number, number] {
|
||||
// cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate
|
||||
// https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve
|
||||
const centerX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125;
|
||||
const centerY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125;
|
||||
const offsetX = Math.abs(centerX - sourceX);
|
||||
const offsetY = Math.abs(centerY - sourceY);
|
||||
|
||||
return [centerX, centerY, offsetX, offsetY];
|
||||
}
|
||||
|
||||
function calculateControlOffset(distance: number, curvature: number): number {
|
||||
if (distance >= 0) {
|
||||
return 0.5 * distance;
|
||||
}
|
||||
|
||||
return curvature * 25 * Math.sqrt(-distance);
|
||||
}
|
||||
|
||||
function getControlWithCurvature({ pos, x1, y1, x2, y2, c }: GetControlWithCurvatureParams): [number, number] {
|
||||
switch (pos) {
|
||||
case Position.Left:
|
||||
return [x1 - calculateControlOffset(x1 - x2, c), y1];
|
||||
case Position.Right:
|
||||
return [x1 + calculateControlOffset(x2 - x1, c), y1];
|
||||
case Position.Top:
|
||||
return [x1, y1 - calculateControlOffset(y1 - y2, c)];
|
||||
case Position.Bottom:
|
||||
return [x1, y1 + calculateControlOffset(y2 - y1, c)];
|
||||
}
|
||||
}
|
||||
|
||||
export function getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition = Position.Bottom,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition = Position.Top,
|
||||
curvature = 0.25,
|
||||
}: GetBezierPathParams): [path: string, labelX: number, labelY: number, offsetX: number, offsetY: number] {
|
||||
const [sourceControlX, sourceControlY] = getControlWithCurvature({
|
||||
pos: sourcePosition,
|
||||
x1: sourceX,
|
||||
y1: sourceY,
|
||||
x2: targetX,
|
||||
y2: targetY,
|
||||
c: curvature,
|
||||
});
|
||||
const [targetControlX, targetControlY] = getControlWithCurvature({
|
||||
pos: targetPosition,
|
||||
x1: targetX,
|
||||
y1: targetY,
|
||||
x2: sourceX,
|
||||
y2: sourceY,
|
||||
c: curvature,
|
||||
});
|
||||
const [labelX, labelY, offsetX, offsetY] = getBezierEdgeCenter({
|
||||
sourceX,
|
||||
sourceY,
|
||||
targetX,
|
||||
targetY,
|
||||
sourceControlX,
|
||||
sourceControlY,
|
||||
targetControlX,
|
||||
targetControlY,
|
||||
});
|
||||
|
||||
return [
|
||||
`M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,
|
||||
labelX,
|
||||
labelY,
|
||||
offsetX,
|
||||
offsetY,
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user