Improve UE-style Bezier Edge calculation

This commit is contained in:
Joey Ballentine
2022-03-14 12:52:18 -04:00
parent 3b8756316b
commit 6f51af2074
2 changed files with 27 additions and 32 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ const sourceTargetPositions = [
{ source: Position.Right, target: Position.Left }, { source: Position.Right, target: Position.Left },
]; ];
const nodeColors = [ const nodeColors = [
['#1e9e99', '#4cb3ac', '#6ec9c0', '#8ddfd4', '#c4fff7'], ['#0c5956', '#1e9e99', '#4cb3ac', '#6ec9c0', '#8ddfd4'],
['#0f4c75', '#1b5d8b', '#276fa1', '#3282b8', '#4fa6e0'], ['#0f4c75', '#1b5d8b', '#276fa1', '#3282b8', '#4fa6e0'],
]; ];
const edgeTypes = ['default', 'step', 'smoothstep', 'straight', 'simplebezier']; const edgeTypes = ['default', 'step', 'smoothstep', 'straight', 'simplebezier'];
+26 -31
View File
@@ -1,8 +1,8 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import { EdgeProps, Position } from '../../types';
import BaseEdge from './BaseEdge'; import BaseEdge from './BaseEdge';
import { getCenter } from './utils'; import { getCenter } from './utils';
import { EdgeProps, Position } from '../../types';
export interface GetBezierPathParams { export interface GetBezierPathParams {
sourceX: number; sourceX: number;
@@ -23,7 +23,7 @@ export function getBezierPath({
targetX, targetX,
targetY, targetY,
targetPosition = Position.Top, targetPosition = Position.Top,
curvature = 0.5, curvature = 0.4,
centerX, centerX,
centerY, centerY,
}: GetBezierPathParams): string { }: GetBezierPathParams): string {
@@ -32,40 +32,35 @@ export function getBezierPath({
let cX, let cX,
cY = 0; cY = 0;
if (!hasCurvature) { const [_centerX, _centerY] = getCenter({ sourceX, sourceY, targetX, targetY });
const [_centerX, _centerY] = getCenter({ sourceX, sourceY, targetX, targetY });
cX = typeof centerX !== 'undefined' ? centerX : _centerX;
cY = typeof centerY !== 'undefined' ? centerY : _centerY;
}
const distanceX = sourceX - targetX;
const distanceY = sourceY - targetY;
// A scalar value to fix the curve size getting larger
const scalarX = Math.min(curvature, Math.max(0, distanceX / 10000));
const scalarY = Math.min(curvature, Math.max(0, distanceY / 10000));
const hx1 = sourceX + Math.abs(targetX - sourceX) * (curvature - scalarX);
const hx2 = targetX - Math.abs(targetX - sourceX) * (curvature - scalarX);
const hy1 = sourceY + Math.abs(targetY - sourceY) * (curvature - scalarY);
const hy2 = targetY - Math.abs(targetY - sourceY) * (curvature - scalarY);
let path = hasCurvature
? `M${sourceX},${sourceY} C${sourceX},${hy1} ${targetX},${hy2} ${targetX},${targetY}`
: `M${sourceX},${sourceY} C${sourceX},${cY} ${targetX},${cY} ${targetX},${targetY}`;
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) { if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
path = hasCurvature cX = typeof centerX !== 'undefined' ? centerX : _centerX;
? `M${sourceX},${sourceY} C${hx1},${sourceY} ${hx2},${targetY}, ${targetX},${targetY}` const distanceX = targetX - sourceX;
: `M${sourceX},${sourceY} C${cX},${sourceY} ${cX},${targetY} ${targetX},${targetY}`; const absDistanceX = Math.abs(Math.min(0, 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;
return `M${sourceX},${sourceY} C${hx1},${sourceY} ${hx2},${targetY}, ${targetX},${targetY}`
} else if (leftAndRight.includes(targetPosition)) { } else if (leftAndRight.includes(targetPosition)) {
path = `M${sourceX},${sourceY} Q${sourceX},${targetY} ${targetX},${targetY}`; return `M${sourceX},${sourceY} Q${sourceX},${targetY} ${targetX},${targetY}`;
} else if (leftAndRight.includes(sourcePosition)) { } else if (leftAndRight.includes(sourcePosition)) {
path = `M${sourceX},${sourceY} Q${targetX},${sourceY} ${targetX},${targetY}`; return `M${sourceX},${sourceY} Q${targetX},${sourceY} ${targetX},${targetY}`;
} }
return path; cY = typeof centerY !== 'undefined' ? centerY : _centerY;
const distanceY = targetY - sourceY;
const absDistanceY = Math.abs(Math.min(0, 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;
return `M${sourceX},${sourceY} C${sourceX},${hy1} ${targetX},${hy2} ${targetX},${targetY}`
} }
export default memo( export default memo(