From e1b3f1517b81d37a6caa921b7e5fb88f9cd86924 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: Thu, 24 Apr 2025 17:53:29 +0800 Subject: [PATCH] =?UTF-8?q?Feat=EF=BC=9A=E5=A4=96=E6=A1=86=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=AE=BE=E7=BD=AE=E6=98=AF=E5=90=A6=E5=8C=85=E5=90=AB?= =?UTF-8?q?=E4=B8=8B=E7=BA=A7=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/plugins/OuterFrame.js | 66 +++++++++++++++-------- simple-mind-map/src/utils/index.js | 10 ++-- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/simple-mind-map/src/plugins/OuterFrame.js b/simple-mind-map/src/plugins/OuterFrame.js index 5ffc3409..121f67ba 100644 --- a/simple-mind-map/src/plugins/OuterFrame.js +++ b/simple-mind-map/src/plugins/OuterFrame.js @@ -12,6 +12,8 @@ import outerFrameTextMethods from './outerFrame/outerFrameText' // 默认外框样式 const defaultStyle = { + // 外框范围是否包含下级节点 + containsChildren: true, // 外框圆角大小 radius: 5, // 外框边框宽度 @@ -201,7 +203,8 @@ class OuterFrame { this.isNotRenderOuterFrames = true const { el, node, range } = this.activeOuterFrame let newStrokeDasharray = '' - this.getRangeNodeList(node, range).forEach(node => { + const nodeList = this.getRangeNodeList(node, range) + nodeList.forEach(node => { const outerFrame = node.getData('outerFrame') const newData = { ...outerFrame, @@ -215,6 +218,18 @@ class OuterFrame { el.cacheStyle = { dasharray: newStrokeDasharray } + // 更新是否包含下级节点,需要重新计算大小 + if (typeof config.containsChildren !== 'undefined') { + const { left, top, width, height } = getNodeListBoundingRect( + nodeList, + 0, + 0, + 0, + 0, + !config.containsChildren + ) + this.setOuterFrameElRectInfo(el, left, top, width, height) + } this.updateOuterFrameStyle() } @@ -243,6 +258,21 @@ class OuterFrame { return node.children[range[0]] } + // 设置或更新外框元素位置和大小 + setOuterFrameElRectInfo(el, left, top, width, height) { + const t = this.mindMap.draw.transform() + const { outerFramePaddingX, outerFramePaddingY } = this.mindMap.opt + const x = + (left - outerFramePaddingX - this.mindMap.elRect.left - t.translateX) / + t.scaleX + const y = + (top - outerFramePaddingY - this.mindMap.elRect.top - t.translateY) / + t.scaleY + const w = (width + outerFramePaddingX * 2) / t.scaleX + const h = (height + outerFramePaddingY * 2) / t.scaleY + el.size(w, h).x(x).y(y) + } + // 渲染外框 renderOuterFrames() { if (this.isNotRenderOuterFrames) { @@ -254,8 +284,6 @@ class OuterFrame { this.clearOuterFrameElList() let tree = this.mindMap.renderer.root if (!tree) return - const t = this.mindMap.draw.transform() - const { outerFramePaddingX, outerFramePaddingY } = this.mindMap.opt walk( tree, null, @@ -265,8 +293,15 @@ class OuterFrame { if (outerFrameList && outerFrameList.length > 0) { outerFrameList.forEach(({ nodeList, range }) => { if (range[0] === -1 || range[1] === -1) return - const { left, top, width, height } = - getNodeListBoundingRect(nodeList) + const config = this.getStyle(nodeList[0]) // 使用第一个节点的外框样式 + const { left, top, width, height } = getNodeListBoundingRect( + nodeList, + 0, + 0, + 0, + 0, + !config.containsChildren + ) if ( !Number.isFinite(left) || !Number.isFinite(top) || @@ -274,21 +309,8 @@ class OuterFrame { !Number.isFinite(height) ) return - const el = this.createOuterFrameEl( - (left - - outerFramePaddingX - - this.mindMap.elRect.left - - t.translateX) / - t.scaleX, - (top - - outerFramePaddingY - - this.mindMap.elRect.top - - t.translateY) / - t.scaleY, - (width + outerFramePaddingX * 2) / t.scaleX, - (height + outerFramePaddingY * 2) / t.scaleY, - this.getStyle(nodeList[0]) // 使用第一个节点的外框样式 - ) + const el = this.createOuterFrameEl(config) + this.setOuterFrameElRectInfo(el, left, top, width, height) // 渲染文字,如果有的话 const textNode = this.createText(el, cur, range) this.textNodeList.push(textNode) @@ -363,8 +385,8 @@ class OuterFrame { } // 创建外框元素 - createOuterFrameEl(x, y, width, height, styleConfig = {}) { - const el = this.draw.rect().size(width, height).x(x).y(y) + createOuterFrameEl(styleConfig = {}) { + const el = this.draw.rect() this.styleOuterFrame(el, styleConfig) el.cacheStyle = { dasharray: styleConfig.strokeDasharray diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index b3524ad8..a5342285 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -1457,7 +1457,8 @@ export const getNodeTreeBoundingRect = ( paddingX = 0, paddingY = 0, excludeSelf = false, - excludeGeneralization = false + excludeGeneralization = false, + onSelf = false ) => { let minX = Infinity let maxX = -Infinity @@ -1483,6 +1484,7 @@ export const getNodeTreeBoundingRect = ( } } catch (e) {} } + if (onSelf) return if (!excludeGeneralization && root._generalizationList.length > 0) { root._generalizationList.forEach(item => { walk(item.generalizationNode) @@ -1515,7 +1517,8 @@ export const getNodeListBoundingRect = ( x = 0, y = 0, paddingX = 0, - paddingY = 0 + paddingY = 0, + onSelf = false ) => { let minX = Infinity let maxX = -Infinity @@ -1529,7 +1532,8 @@ export const getNodeListBoundingRect = ( paddingX, paddingY, false, - true + true, + onSelf ) if (left < minX) { minX = left