feat(edges): Add & export bezierCenter function
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { GetBezierPathParams, GetCenterParams, GetSmoothStepPathParams, Position } from '~/types'
|
||||
import { GetBezierPathParams, GetCenterParams, GetControlWithCurvatureParams, GetSmoothStepPathParams, Position } from '~/types'
|
||||
|
||||
const LeftOrRight = [Position.Left, Position.Right]
|
||||
|
||||
@@ -36,6 +36,37 @@ export const getCenter = ({
|
||||
return [centerX, centerY, xOffset, yOffset]
|
||||
}
|
||||
|
||||
function calculateControlOffset(distance: number, curvature: number): number {
|
||||
if (distance >= 0) {
|
||||
return 0.5 * distance
|
||||
} else {
|
||||
return curvature * 25 * Math.sqrt(-distance)
|
||||
}
|
||||
}
|
||||
|
||||
function getControlWithCurvature({ pos, x1, y1, x2, y2, c }: GetControlWithCurvatureParams): [number, number] {
|
||||
let ctX: number, ctY: number
|
||||
switch (pos) {
|
||||
case Position.Left:
|
||||
ctX = x1 - calculateControlOffset(x1 - x2, c)
|
||||
ctY = y1
|
||||
break
|
||||
case Position.Right:
|
||||
ctX = x1 + calculateControlOffset(x2 - x1, c)
|
||||
ctY = y1
|
||||
break
|
||||
case Position.Top:
|
||||
ctX = x1
|
||||
ctY = y1 - calculateControlOffset(y1 - y2, c)
|
||||
break
|
||||
case Position.Bottom:
|
||||
ctX = x1
|
||||
ctY = y1 + calculateControlOffset(y2 - y1, c)
|
||||
break
|
||||
}
|
||||
return [ctX, ctY]
|
||||
}
|
||||
|
||||
export function getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
@@ -44,78 +75,58 @@ export function getBezierPath({
|
||||
targetY,
|
||||
targetPosition = Position.Top,
|
||||
curvature = 0.25,
|
||||
centerX,
|
||||
centerY,
|
||||
}: GetBezierPathParams): string {
|
||||
const leftAndRight = [Position.Left, Position.Right]
|
||||
const hasCurvature = curvature > 0
|
||||
const [_centerX, _centerY] = getCenter({ sourceX, sourceY, targetX, targetY })
|
||||
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,
|
||||
})
|
||||
return `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`
|
||||
}
|
||||
|
||||
if (leftAndRight.includes(sourcePosition) && leftAndRight.includes(targetPosition)) {
|
||||
const cX = typeof centerX !== 'undefined' ? centerX : _centerX
|
||||
const distanceX = targetX - sourceX
|
||||
const absDistanceX = Math.abs(distanceX)
|
||||
const amtX = (Math.sqrt(absDistanceX) / 2) * (50 * curvature)
|
||||
|
||||
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)) {
|
||||
return `M${sourceX},${sourceY} Q${sourceX},${targetY} ${targetX},${targetY}`
|
||||
} else if (leftAndRight.includes(sourcePosition)) {
|
||||
return `M${sourceX},${sourceY} Q${targetX},${sourceY} ${targetX},${targetY}`
|
||||
}
|
||||
|
||||
const cY = typeof centerY !== 'undefined' ? centerY : _centerY
|
||||
const distanceY = targetY - sourceY
|
||||
const absDistanceY = Math.abs(distanceY)
|
||||
const amtY = (Math.sqrt(absDistanceY) / 2) * (50 * curvature)
|
||||
|
||||
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}`
|
||||
export function getBezierCenter({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourcePosition = Position.Bottom,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition = Position.Top,
|
||||
curvature = 0.25,
|
||||
}: GetBezierPathParams): [number, number, number, 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,
|
||||
})
|
||||
// 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 xOffset = Math.abs(centerX - sourceX)
|
||||
const yOffset = Math.abs(centerY - sourceY)
|
||||
return [centerX, centerY, xOffset, yOffset]
|
||||
}
|
||||
|
||||
// These are some helper methods for drawing the round corners
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
export { default as VueFlow } from './container/VueFlow/VueFlow.vue'
|
||||
export { default as Handle } from './components/Handle/Handle.vue'
|
||||
export { getBezierPath, getSmoothStepPath, getCenter as getEdgeCenter } from './components/Edges/utils'
|
||||
export { getBezierPath, getSmoothStepPath, getCenter as getEdgeCenter, getBezierCenter } from './components/Edges/utils'
|
||||
|
||||
export {
|
||||
isNode,
|
||||
|
||||
Reference in New Issue
Block a user