Skip to content

Commit

Permalink
refactor(bezier): handle undirectional flows, use simple bezier for c…
Browse files Browse the repository at this point in the history
…onnection closes #1971
  • Loading branch information
moklick committed Mar 17, 2022
1 parent 30e83e6 commit bef6157
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 13 deletions.
4 changes: 3 additions & 1 deletion src/components/ConnectionLine/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ export default ({
};

if (connectionLineType === ConnectionLineType.Bezier) {
dAttr = getBezierPath(pathParams);
// @TODO: we need another getBezier function, that handles a connection line.
// Since we don't know the target position, we can't use the default bezier function here.
dAttr = getBezierPath({ ...pathParams, curvature: 0 });
} else if (connectionLineType === ConnectionLineType.Step) {
dAttr = getSmoothStepPath({
...pathParams,
Expand Down
62 changes: 50 additions & 12 deletions src/components/Edges/BezierEdge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface GetBezierPathParams {
centerY?: number;
}

// @TODO: refactor getBezierPath function. It's too long and hard to understand.
// We should reuse the curvature handling for top/bottom and left/right.
export function getBezierPath({
sourceX,
sourceY,
Expand All @@ -28,19 +30,36 @@ export function getBezierPath({
}: GetBezierPathParams): string {
const leftAndRight = [Position.Left, Position.Right];
const hasCurvature = curvature > 0;
let cX,
cY = 0;

const [_centerX, _centerY] = getCenter({ sourceX, sourceY, targetX, targetY });

if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
cX = typeof centerX !== 'undefined' ? centerX : _centerX;
const cX = typeof centerX !== 'undefined' ? centerX : _centerX;
const distanceX = targetX - sourceX;
const absDistanceX = Math.abs(Math.min(0, distanceX));
const absDistanceX = Math.abs(distanceX);
const amtX = (Math.sqrt(absDistanceX) / 2) * (50 * curvature);

const hx1 = hasCurvature && distanceX < 0 ? sourceX + amtX : cX;
const hx2 = hasCurvature && distanceX < 0 ? targetX - amtX : cX;
let hx1 = cX;
let hx2 = cX;

if (hasCurvature) {
const sourceAndTargetRight = sourcePosition === Position.Right && targetPosition === Position.Right;
const sourceAndTargetLeft = sourcePosition === Position.Left && targetPosition === Position.Left;

hx1 = sourceX + amtX;
hx2 = targetX - amtX;

if (sourceAndTargetLeft) {
hx1 = sourceX - amtX;
} else if (sourceAndTargetRight) {
hx2 = targetX + amtX;
} else if (sourcePosition === Position.Left && targetX <= sourceX) {
hx1 = cX;
hx2 = cX;
} else if (sourcePosition === Position.Left && targetX > sourceX) {
hx1 = sourceX - amtX;
hx2 = targetX + amtX;
}
}

return `M${sourceX},${sourceY} C${hx1},${sourceY} ${hx2},${targetY}, ${targetX},${targetY}`;
} else if (leftAndRight.includes(targetPosition)) {
Expand All @@ -49,14 +68,33 @@ export function getBezierPath({
return `M${sourceX},${sourceY} Q${targetX},${sourceY} ${targetX},${targetY}`;
}

cY = typeof centerY !== 'undefined' ? centerY : _centerY;
const cY = typeof centerY !== 'undefined' ? centerY : _centerY;
const distanceY = targetY - sourceY;

const absDistanceY = Math.abs(Math.min(0, distanceY));
const absDistanceY = Math.abs(distanceY);
const amtY = (Math.sqrt(absDistanceY) / 2) * (50 * curvature);

const hy1 = hasCurvature && distanceY < 0 ? sourceY + amtY : cY;
const hy2 = hasCurvature && distanceY < 0 ? targetY - amtY : cY;
let hy1 = cY;
let hy2 = cY;

if (hasCurvature) {
hy1 = sourceY + amtY;
hy2 = targetY - amtY;

const sourceAndTargetTop = sourcePosition === Position.Top && targetPosition === Position.Top;
const sourceAndTargetBottom = sourcePosition === Position.Bottom && targetPosition === Position.Bottom;

if (sourceAndTargetTop) {
hy1 = targetY - amtY;
} else if (sourceAndTargetBottom) {
hy2 = targetY + amtY;
} else if (sourcePosition === Position.Top && targetY <= sourceY) {
hy1 = cY;
hy2 = cY;
} else if (sourcePosition === Position.Top && targetY > sourceY) {
hy1 = sourceY - amtY;
hy2 = targetY + amtY;
}
}

return `M${sourceX},${sourceY} C${sourceX},${hy1} ${targetX},${hy2} ${targetX},${targetY}`;
}
Expand Down

0 comments on commit bef6157

Please sign in to comment.