From bbb21d4e765b609193d3c90d58901e50238823fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A1=97=E8=A7=92=E5=B0=8F=E6=9E=97?= <1013335014@qq.com> Date: Tue, 16 Jan 2024 10:10:32 +0800 Subject: [PATCH] =?UTF-8?q?Feat=EF=BC=9A=E4=BC=98=E5=8C=96=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=85=B3=E8=81=94=E7=BA=BF=E6=97=B6=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E7=AB=AF=E7=82=B9=E4=BD=8D=E7=BD=AE=E7=9A=84=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../associativeLine/associativeLineUtils.js | 102 ++++++++++++------ simple-mind-map/src/utils/index.js | 38 +++++++ 2 files changed, 110 insertions(+), 30 deletions(-) diff --git a/simple-mind-map/src/plugins/associativeLine/associativeLineUtils.js b/simple-mind-map/src/plugins/associativeLine/associativeLineUtils.js index 3c97cbae..b1626b3f 100644 --- a/simple-mind-map/src/plugins/associativeLine/associativeLineUtils.js +++ b/simple-mind-map/src/plugins/associativeLine/associativeLineUtils.js @@ -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] diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index 2b5bfe31..6bd64d58 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -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' + } +}