From b45674cf8f9729b46eb918bb338b550e4aecbf72 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, 2 Jul 2024 11:46:03 +0800 Subject: [PATCH] =?UTF-8?q?Feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E5=90=91?= =?UTF-8?q?=E5=B7=A6=E9=80=BB=E8=BE=91=E7=BB=93=E6=9E=84=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/constants/constant.js | 6 ++ simple-mind-map/src/core/render/Render.js | 2 + .../src/layouts/LogicalStructure.js | 101 +++++++++++++----- simple-mind-map/src/plugins/Drag.js | 16 +++ 4 files changed, 99 insertions(+), 26 deletions(-) diff --git a/simple-mind-map/src/constants/constant.js b/simple-mind-map/src/constants/constant.js index 757c0c0a..dfd0ae4c 100644 --- a/simple-mind-map/src/constants/constant.js +++ b/simple-mind-map/src/constants/constant.js @@ -174,6 +174,7 @@ export const CONSTANTS = { }, LAYOUT: { LOGICAL_STRUCTURE: 'logicalStructure', + LOGICAL_STRUCTURE_LEFT: 'logicalStructureLeft', MIND_MAP: 'mindMap', ORGANIZATION_STRUCTURE: 'organizationStructure', CATALOG_ORGANIZATION: 'catalogOrganization', @@ -251,6 +252,10 @@ export const layoutList = [ name: '逻辑结构图', value: CONSTANTS.LAYOUT.LOGICAL_STRUCTURE }, + { + name: '向左逻辑结构图', + value: CONSTANTS.LAYOUT.LOGICAL_STRUCTURE_LEFT + }, { name: '思维导图', value: CONSTANTS.LAYOUT.MIND_MAP @@ -282,6 +287,7 @@ export const layoutList = [ ] export const layoutValueList = [ CONSTANTS.LAYOUT.LOGICAL_STRUCTURE, + CONSTANTS.LAYOUT.LOGICAL_STRUCTURE_LEFT, CONSTANTS.LAYOUT.MIND_MAP, CONSTANTS.LAYOUT.CATALOG_ORGANIZATION, CONSTANTS.LAYOUT.ORGANIZATION_STRUCTURE, diff --git a/simple-mind-map/src/core/render/Render.js b/simple-mind-map/src/core/render/Render.js index 347d3d63..a62d5a2c 100644 --- a/simple-mind-map/src/core/render/Render.js +++ b/simple-mind-map/src/core/render/Render.js @@ -42,6 +42,8 @@ import { Polygon } from '@svgdotjs/svg.js' const layouts = { // 逻辑结构图 [CONSTANTS.LAYOUT.LOGICAL_STRUCTURE]: LogicalStructure, + // 向左逻辑结构图 + [CONSTANTS.LAYOUT.LOGICAL_STRUCTURE_LEFT]: LogicalStructure, // 思维导图 [CONSTANTS.LAYOUT.MIND_MAP]: MindMap, // 目录组织图 diff --git a/simple-mind-map/src/layouts/LogicalStructure.js b/simple-mind-map/src/layouts/LogicalStructure.js index 26c6115c..9887e977 100644 --- a/simple-mind-map/src/layouts/LogicalStructure.js +++ b/simple-mind-map/src/layouts/LogicalStructure.js @@ -1,11 +1,13 @@ import Base from './Base' import { walk, asyncRun, getNodeIndexInNodeList } from '../utils' +import { CONSTANTS } from '../constants/constant' // 逻辑结构图 class LogicalStructure extends Base { // 构造函数 - constructor(opt = {}) { + constructor(opt = {}, layout) { super(opt) + this.isUseLeft = layout === CONSTANTS.LAYOUT.LOGICAL_STRUCTURE_LEFT } // 布局 @@ -40,8 +42,15 @@ class LogicalStructure extends Base { } else { // 非根节点 // 定位到父节点右侧 - newNode.left = - parent._node.left + parent._node.width + this.getMarginX(layerIndex) + if (this.isUseLeft) { + newNode.left = + parent._node.left - newNode.width - this.getMarginX(layerIndex) + } else { + newNode.left = + parent._node.left + + parent._node.width + + this.getMarginX(layerIndex) + } } if (!cur.data.expand) { return true @@ -167,15 +176,24 @@ class LogicalStructure extends Base { } let marginX = this.getMarginX(node.layerIndex + 1) let s1 = (marginX - expandBtnSize) * 0.6 + if (this.isUseLeft) { + s1 *= -1 + } let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle node.children.forEach((item, index) => { - let x1 = - node.layerIndex === 0 ? left + width : left + width + expandBtnSize + let x1 + if (this.isUseLeft) { + x1 = node.layerIndex === 0 ? left : left - expandBtnSize + } else { + x1 = node.layerIndex === 0 ? left + width : left + width + expandBtnSize + } let y1 = top + height / 2 - let x2 = item.left + let x2 = this.isUseLeft ? item.left + item.width : item.left let y2 = item.top + item.height / 2 // 节点使用横线风格,需要额外渲染横线 - let nodeUseLineStyleOffset = nodeUseLineStyle ? item.width : 0 + let nodeUseLineStyleOffset = nodeUseLineStyle + ? item.width * (this.isUseLeft ? -1 : 1) + : 0 y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1 y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2 let path = this.createFoldLine([ @@ -202,15 +220,17 @@ class LogicalStructure extends Base { if (node.layerIndex === 0) { expandBtnSize = 0 } - let x1 = left + width + expandBtnSize + let x1 = this.isUseLeft + ? left - expandBtnSize + : left + width + expandBtnSize let y1 = top + height / 2 - let x2 = item.left + let x2 = this.isUseLeft ? item.left + item.width : item.left let y2 = item.top + item.height / 2 y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1 y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2 // 节点使用横线风格,需要额外渲染横线 let nodeUseLineStylePath = nodeUseLineStyle - ? ` L ${item.left + item.width},${y2}` + ? ` L ${this.isUseLeft ? item.left : item.left + item.width},${y2}` : '' let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath this.setLineStyle(style, lines[index], path, item) @@ -235,20 +255,33 @@ class LogicalStructure extends Base { if (node.layerIndex === 0) { expandBtnSize = 0 } - let x1 = - node.layerIndex === 0 && !rootLineStartPositionKeepSameInCurve - ? left + width / 2 - : left + width + expandBtnSize + let x1 + if (this.isUseLeft) { + x1 = + node.layerIndex === 0 && !rootLineStartPositionKeepSameInCurve + ? left + width / 2 + : left - expandBtnSize + } else { + x1 = + node.layerIndex === 0 && !rootLineStartPositionKeepSameInCurve + ? left + width / 2 + : left + width + expandBtnSize + } let y1 = top + height / 2 - let x2 = item.left + let x2 = this.isUseLeft ? item.left + item.width : item.left let y2 = item.top + item.height / 2 let path = '' y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1 y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2 // 节点使用横线风格,需要额外渲染横线 - let nodeUseLineStylePath = nodeUseLineStyle - ? ` L ${item.left + item.width},${y2}` - : '' + let nodeUseLineStylePath + if (this.isUseLeft) { + nodeUseLineStylePath = nodeUseLineStyle ? ` L ${item.left},${y2}` : '' + } else { + nodeUseLineStylePath = nodeUseLineStyle + ? ` L ${item.left + item.width},${y2}` + : '' + } if (node.isRoot && !rootLineKeepSameInCurve) { path = this.quadraticCurvePath(x1, y1, x2, y2) + nodeUseLineStylePath } else { @@ -260,14 +293,17 @@ class LogicalStructure extends Base { // 渲染按钮 renderExpandBtn(node, btn) { - let { width, height } = node + let { width, height, expandBtnSize, layerIndex } = node + if (layerIndex === 0) { + expandBtnSize = 0 + } let { translateX, translateY } = btn.transform() // 节点使用横线风格,需要调整展开收起按钮位置 let nodeUseLineStyleOffset = this.mindMap.themeConfig.nodeUseLineStyle ? height / 2 : 0 // 位置没有变化则返回 - let _x = width + let _x = this.isUseLeft ? 0 - expandBtnSize : width let _y = height / 2 + nodeUseLineStyleOffset if (_x === translateX && _y === translateY) { return @@ -279,29 +315,42 @@ class LogicalStructure extends Base { renderGeneralization(list) { list.forEach(item => { let { + left, top, bottom, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeGeneralizationRenderBoundaries(item, 'h') - let x1 = right + generalizationLineMargin + let x = this.isUseLeft + ? left - generalizationLineMargin + : right + generalizationLineMargin + let x1 = x let y1 = top - let x2 = right + generalizationLineMargin + let x2 = x let y2 = bottom - let cx = x1 + 20 + let cx = x1 + (this.isUseLeft ? -20 : 20) let cy = y1 + (y2 - y1) / 2 let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` item.generalizationLine.plot(path) - item.generalizationNode.left = right + generalizationNodeMargin + item.generalizationNode.left = + x + + (this.isUseLeft + ? -generalizationNodeMargin + : generalizationNodeMargin) - + (this.isUseLeft ? item.generalizationNode.width : 0) item.generalizationNode.top = top + (bottom - top - item.generalizationNode.height) / 2 }) } // 渲染展开收起按钮的隐藏占位元素 - renderExpandBtnRect(rect, expandBtnSize, width, height, node) { - rect.size(expandBtnSize, height).x(width).y(0) + renderExpandBtnRect(rect, expandBtnSize, width, height) { + if (this.isUseLeft) { + rect.size(expandBtnSize, height).x(-expandBtnSize).y(0) + } else { + rect.size(expandBtnSize, height).x(width).y(0) + } } } diff --git a/simple-mind-map/src/plugins/Drag.js b/simple-mind-map/src/plugins/Drag.js index d8132c12..aed80b63 100644 --- a/simple-mind-map/src/plugins/Drag.js +++ b/simple-mind-map/src/plugins/Drag.js @@ -397,6 +397,7 @@ class Drag extends Base { } const { LOGICAL_STRUCTURE, + LOGICAL_STRUCTURE_LEFT, MIND_MAP, ORGANIZATION_STRUCTURE, CATALOG_ORGANIZATION, @@ -420,6 +421,7 @@ class Drag extends Base { } switch (this.mindMap.opt.layout) { case LOGICAL_STRUCTURE: + case LOGICAL_STRUCTURE_LEFT: this.handleLogicalStructure(node) break case MIND_MAP: @@ -457,6 +459,7 @@ class Drag extends Base { handleOverlapNode() { const { LOGICAL_STRUCTURE, + LOGICAL_STRUCTURE_LEFT, MIND_MAP, ORGANIZATION_STRUCTURE, CATALOG_ORGANIZATION, @@ -491,6 +494,10 @@ class Drag extends Base { : lastNodeRect.originLeft y = lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight break + case LOGICAL_STRUCTURE_LEFT: + x = lastNodeRect.originRight - this.placeholderWidth + y = lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight + break case ORGANIZATION_STRUCTURE: rotate = true x = lastNodeRect.originRight + this.minOffset - halfPlaceholderHeight @@ -603,6 +610,12 @@ class Drag extends Base { nodeRect.originTop + (nodeRect.originHeight - this.placeholderHeight) / 2 break + case LOGICAL_STRUCTURE_LEFT: + x = nodeRect.originLeft - this.placeholderWidth - marginX + y = + nodeRect.originTop + + (nodeRect.originHeight - this.placeholderHeight) / 2 + break case ORGANIZATION_STRUCTURE: rotate = true x = @@ -683,6 +696,7 @@ class Drag extends Base { getNewChildNodeDir(node) { const { LOGICAL_STRUCTURE, + LOGICAL_STRUCTURE_LEFT, MIND_MAP, TIMELINE2, VERTICAL_TIMELINE, @@ -691,6 +705,8 @@ class Drag extends Base { switch (this.mindMap.opt.layout) { case LOGICAL_STRUCTURE: return CONSTANTS.LAYOUT_GROW_DIR.RIGHT + case LOGICAL_STRUCTURE_LEFT: + return CONSTANTS.LAYOUT_GROW_DIR.LEFT case MIND_MAP: case TIMELINE2: case VERTICAL_TIMELINE: