Feat:优化创建关联线时初始端点位置的计算逻辑

This commit is contained in:
街角小林 2024-01-16 10:10:32 +08:00
parent 3f9c3e9fb1
commit bbb21d4e76
2 changed files with 110 additions and 30 deletions

View File

@ -1,3 +1,5 @@
import { getRectRelativePosition } from '../../utils/index'
// 获取目标节点在起始节点的目标数组中的索引
export const getAssociativeLineTargetIndex = (node, toNode) => {
return node.getData('associativeLineTargets').findIndex(item => {
@ -7,14 +9,21 @@ export const getAssociativeLineTargetIndex = (node, toNode) => {
// 计算贝塞尔曲线的控制点
export const computeCubicBezierPathPoints = (x1, y1, x2, y2) => {
const min = 5
let cx1 = x1 + (x2 - x1) / 2
let cy1 = y1
let cx2 = cx1
let cy2 = y2
if (Math.abs(x1 - x2) <= 5) {
if (Math.abs(x1 - x2) <= min) {
cx1 = x1 + (y2 - y1) / 2
cx2 = cx1
}
if (Math.abs(y1 - y2) <= min) {
cx1 = x1
cy1 = y1 - (x2 - x1) / 2
cx2 = x2
cy2 = cy1
}
return [
{
x: cx1,
@ -39,7 +48,9 @@ const getNodeRect = node => {
right: left + width,
bottom: top + height,
left,
top
top,
width,
height
}
}
@ -197,34 +208,64 @@ export const getNodePoint = (node, dir = 'right', range = 0, e = null) => {
// 根据两个节点的位置计算节点的连接点
export const computeNodePoints = (fromNode, toNode) => {
let fromRect = getNodeRect(fromNode)
let fromCx = (fromRect.right + fromRect.left) / 2
let fromCy = (fromRect.bottom + fromRect.top) / 2
let toRect = getNodeRect(toNode)
let toCx = (toRect.right + toRect.left) / 2
let toCy = (toRect.bottom + toRect.top) / 2
// 中心点坐标的差值
let offsetX = toCx - fromCx
let offsetY = toCy - fromCy
if (offsetX === 0 && offsetY === 0) return []
const fromRect = getNodeRect(fromNode)
const toRect = getNodeRect(toNode)
let fromDir = ''
let toDir = ''
if (offsetX <= 0 && offsetX <= offsetY && offsetX <= -offsetY) {
// left
fromDir = 'left'
toDir = 'right'
} else if (offsetX > 0 && offsetX >= -offsetY && offsetX >= offsetY) {
// right
fromDir = 'right'
toDir = 'left'
} else if (offsetY <= 0 && offsetY < offsetX && offsetY < -offsetX) {
// up
fromDir = 'top'
toDir = 'bottom'
} else if (offsetY > 0 && -offsetY < offsetX && offsetY > offsetX) {
// down
fromDir = 'bottom'
toDir = 'top'
const dir = getRectRelativePosition(
{
x: fromRect.left,
y: fromRect.top,
width: fromRect.width,
height: fromRect.height
},
{
x: toRect.left,
y: toRect.top,
width: toRect.width,
height: toRect.height
}
)
// 起始矩形在结束矩形的什么方向
switch (dir) {
case 'left-top':
fromDir = 'right'
toDir = 'top'
break
case 'right-top':
fromDir = 'left'
toDir = 'top'
break
case 'right-bottom':
fromDir = 'left'
toDir = 'bottom'
break
case 'left-bottom':
fromDir = 'right'
toDir = 'bottom'
break
case 'left':
fromDir = 'right'
toDir = 'left'
break
case 'right':
fromDir = 'left'
toDir = 'right'
break
case 'top':
fromDir = 'right'
toDir = 'right'
break
case 'bottom':
fromDir = 'left'
toDir = 'left'
break
case 'overlap':
fromDir = 'right'
toDir = 'right'
break
default:
break
}
return [getNodePoint(fromNode, fromDir), getNodePoint(toNode, toDir)]
}
@ -234,8 +275,9 @@ export const getNodeLinePath = (startPoint, endPoint, node, toNode) => {
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
// 控制点
let controlPoints = []
let associativeLineTargetControlOffsets =
node.getData('associativeLineTargetControlOffsets')
let associativeLineTargetControlOffsets = node.getData(
'associativeLineTargetControlOffsets'
)
if (
associativeLineTargetControlOffsets &&
associativeLineTargetControlOffsets[targetIndex]

View File

@ -1198,3 +1198,41 @@ export const transformObjectToTreeData = data => {
})
return res
}
// 计算两个点的直线距离
export const getTwoPointDistance = (x1, y1, x2, y2) => {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
}
// 判断两个矩形的相对位置
// 第一个矩形在第二个矩形的什么方向
export const getRectRelativePosition = (rect1, rect2) => {
// 获取第一个矩形的中心点坐标
const rect1CenterX = rect1.x + rect1.width / 2
const rect1CenterY = rect1.y + rect1.height / 2
// 获取第二个矩形的中心点坐标
const rect2CenterX = rect2.x + rect2.width / 2
const rect2CenterY = rect2.y + rect2.height / 2
// 判断第一个矩形在第二个矩形的哪个方向
if (rect1CenterX < rect2CenterX && rect1CenterY < rect2CenterY) {
return 'left-top'
} else if (rect1CenterX > rect2CenterX && rect1CenterY < rect2CenterY) {
return 'right-top'
} else if (rect1CenterX > rect2CenterX && rect1CenterY > rect2CenterY) {
return 'right-bottom'
} else if (rect1CenterX < rect2CenterX && rect1CenterY > rect2CenterY) {
return 'left-bottom'
} else if (rect1CenterX < rect2CenterX && rect1CenterY === rect2CenterY) {
return 'left'
} else if (rect1CenterX > rect2CenterX && rect1CenterY === rect2CenterY) {
return 'right'
} else if (rect1CenterX === rect2CenterX && rect1CenterY < rect2CenterY) {
return 'top'
} else if (rect1CenterX === rect2CenterX && rect1CenterY > rect2CenterY) {
return 'bottom'
} else {
return 'overlap'
}
}