diff --git a/simple-mind-map/src/core/render/Render.js b/simple-mind-map/src/core/render/Render.js index 31913765..55b60e54 100644 --- a/simple-mind-map/src/core/render/Render.js +++ b/simple-mind-map/src/core/render/Render.js @@ -25,7 +25,7 @@ import { setDataToClipboard, getDataFromClipboard, htmlEscape, - checkHasSupSubRelation + parseAddGeneralizationNodeList } from '../../utils' import { shapeList } from './node/Shape' import { lineStyleProps } from '../../themes/default' @@ -1032,14 +1032,7 @@ class Render { let node = list[i] if (isAppointNodes) list.splice(i, 1) if (node.isGeneralization) { - // 删除概要节点 - this.mindMap.execCommand( - 'SET_NODE_DATA', - node.generalizationBelongNode, - { - generalization: null - } - ) + this.deleteNodeGeneralization(node) this.removeNodeFromActiveList(node) i-- } else { @@ -1058,6 +1051,22 @@ class Render { this.mindMap.render() } + // 删除概要节点,即从所属节点里删除该概要 + deleteNodeGeneralization(node) { + const targetNode = node.generalizationBelongNode + const index = targetNode.getGeneralizationNodeIndex(node) + let generalization = targetNode.getData('generalization') + if (Array.isArray(generalization)) { + generalization.splice(index, 1) + } else { + generalization = null + } + // 删除概要节点 + this.mindMap.execCommand('SET_NODE_DATA', targetNode, { + generalization + }) + } + // 仅删除当前节点 removeCurrentNode(appointNodes = []) { appointNodes = formatDataToArray(appointNodes) @@ -1075,13 +1084,7 @@ class Render { let node = list[i] if (node.isGeneralization) { // 删除概要节点 - this.mindMap.execCommand( - 'SET_NODE_DATA', - node.generalizationBelongNode, - { - generalization: null - } - ) + this.deleteNodeGeneralization(node) } else { const parent = node.parent const index = getNodeDataIndex(node) @@ -1403,29 +1406,41 @@ class Render { if (this.activeNodeList.length <= 0) { return } - let hasAncestorsExistGeneralization = false - this.activeNodeList.forEach(node => { - if (node.getData('generalization') || node.isRoot) { - return - } - hasAncestorsExistGeneralization = node.ancestorHasGeneralization() - this.mindMap.execCommand('SET_NODE_DATA', node, { - generalization: data || { + const nodeList = this.activeNodeList.filter(node => { + return ( + !node.isRoot && !node.isGeneralization && !node.checkHasGeneralization() + ) + }) + const list = parseAddGeneralizationNodeList(nodeList) + list.forEach(item => { + const newData = { + ...(data || { text: this.mindMap.opt.defaultGeneralizationText + }), + range: item.range || null + } + let generalization = item.node.getData('generalization') + if (generalization) { + if (Array.isArray(generalization)) { + generalization.push(newData) + } else { + generalization = [generalization, newData] } + } else { + generalization = [newData] + } + this.mindMap.execCommand('SET_NODE_DATA', item.node, { + generalization }) // 插入子节点时自动展开子节点 - node.setData({ + item.node.setData({ expand: true }) }) - const hasSupSubRelation = checkHasSupSubRelation(this.activeNodeList) this.mindMap.render(() => { // 修复祖先节点存在概要时位置未更新的问题 // 修复同时给存在上下级关系的节点添加概要时重叠的问题 - if (hasSupSubRelation || hasAncestorsExistGeneralization) { - this.mindMap.render() - } + this.mindMap.render() }) } @@ -1435,7 +1450,7 @@ class Render { return } this.activeNodeList.forEach(node => { - if (!node.getData('generalization')) { + if (!node.checkHasGeneralization()) { return } this.mindMap.execCommand('SET_NODE_DATA', node, { diff --git a/simple-mind-map/src/core/render/node/Node.js b/simple-mind-map/src/core/render/node/Node.js index f3e17f82..4421546d 100644 --- a/simple-mind-map/src/core/render/node/Node.js +++ b/simple-mind-map/src/core/render/node/Node.js @@ -83,8 +83,7 @@ class Node { this._fillExpandNode = null this._userListGroup = null this._lines = [] - this._generalizationLine = null - this._generalizationNode = null + this._generalizationList = [] this._unVisibleRectRegionNode = null this._isMouseenter = false // 尺寸信息 @@ -751,10 +750,7 @@ class Node { item.setOpacity(val) }) // 概要节点 - if (this._generalizationNode) { - this._generalizationLine.opacity(val) - this._generalizationNode.group.opacity(val) - } + this.setGeneralizationOpacity(val) } // 隐藏子节点 @@ -861,11 +857,11 @@ class Node { return false } - // 检查是否存在概要的祖先节点 + // 检查是否存在有概要的祖先节点 ancestorHasGeneralization() { let node = this.parent while (node) { - if (node.getData('generalization')) { + if (node.checkHasGeneralization()) { return true } node = node.parent @@ -939,6 +935,15 @@ class Node { }) } + // 获取该节点在兄弟节点列表中的索引 + getIndexInBrothers() { + return this.parent && this.parent.children + ? this.parent.children.findIndex(item => { + return item.uid === this.uid + }) + : -1 + } + // 获取padding值 getPaddingVale() { let { isActive } = this.getData() diff --git a/simple-mind-map/src/core/render/node/nodeGeneralization.js b/simple-mind-map/src/core/render/node/nodeGeneralization.js index 61514324..cfbd042b 100644 --- a/simple-mind-map/src/core/render/node/nodeGeneralization.js +++ b/simple-mind-map/src/core/render/node/nodeGeneralization.js @@ -1,9 +1,30 @@ import Node from './Node' import { createUid } from '../../../utils/index' +// 获取节点概要数据 +function formatGetGeneralization() { + const data = this.getData('generalization') + return Array.isArray(data) ? data : data ? [data] : [] +} + // 检查是否存在概要 function checkHasGeneralization() { - return !!this.getData('generalization') + return this.formatGetGeneralization().length > 0 +} + +// 检查是否存在自身的概要,非子节点区间 +function checkHasSelfGeneralization() { + const list = this.formatGetGeneralization() + return !!list.find(item => { + return !item.range || item.range.length <= 0 + }) +} + +// 获取概要节点所在的概要列表里的索引 +function getGeneralizationNodeIndex(node) { + return this._generalizationList.findIndex(item => { + return item.generalizationNode.uid === node.uid + }) } // 创建概要节点 @@ -11,26 +32,47 @@ function createGeneralizationNode() { if (this.isGeneralization || !this.checkHasGeneralization()) { return } - if (!this._generalizationLine) { - this._generalizationLine = this.lineDraw.path() - } - if (!this._generalizationNode) { - this._generalizationNode = new Node({ - data: { - data: this.getData('generalization') - }, - uid: createUid(), - renderer: this.renderer, - mindMap: this.mindMap, - isGeneralization: true - }) - this._generalizationNodeWidth = this._generalizationNode.width - this._generalizationNodeHeight = this._generalizationNode.height - this._generalizationNode.generalizationBelongNode = this - if (this.getData('generalization').isActive) { - this.renderer.addNodeToActiveList(this._generalizationNode) + let maxWidth = 0 + let maxHeight = 0 + const list = this.formatGetGeneralization() + list.forEach((item, index) => { + let cur = this._generalizationList[index] + if (!cur) { + cur = this._generalizationList[index] = {} } - } + // 所属节点 + cur.node = this + // 区间范围 + cur.range = item.range + // 线和节点 + if (!cur.generalizationLine) { + cur.generalizationLine = this.lineDraw.path() + } + if (!cur.generalizationNode) { + cur.generalizationNode = new Node({ + data: { + data: item + }, + uid: createUid(), + renderer: this.renderer, + mindMap: this.mindMap, + isGeneralization: true + }) + } + // 关联所属节点 + cur.generalizationNode.generalizationBelongNode = this + // 大小 + if (cur.generalizationNode.width > maxWidth) + maxWidth = cur.generalizationNode.width + if (cur.generalizationNode.height > maxHeight) + maxHeight = cur.generalizationNode.height + // 如果该概要为激活状态,那么加入激活节点列表 + if (item.isActive) { + this.renderer.addNodeToActiveList(cur.generalizationNode) + } + }) + this._generalizationNodeWidth = maxWidth + this._generalizationNodeHeight = maxHeight } // 更新概要节点 @@ -43,39 +85,64 @@ function updateGeneralization() { // 渲染概要节点 function renderGeneralization() { if (this.isGeneralization) return - if (!this.checkHasGeneralization()) { + this.updateGeneralizationData() + const list = this.formatGetGeneralization() + if (list.length <= 0 || this.getData('expand') === false) { this.removeGeneralization() - this._generalizationNodeWidth = 0 - this._generalizationNodeHeight = 0 return } - if (this.getData('expand') === false) { + if (list.length !== this._generalizationList.length) { this.removeGeneralization() - return } this.createGeneralizationNode() - this.renderer.layout.renderGeneralization( - this, - this._generalizationLine, - this._generalizationNode - ) - this.style.generalizationLine(this._generalizationLine) - this._generalizationNode.render() + this.renderer.layout.renderGeneralization(this._generalizationList) + this._generalizationList.forEach(item => { + this.style.generalizationLine(item.generalizationLine) + item.generalizationNode.render() + }) +} + +// 更新节点概要数据 +function updateGeneralizationData() { + const childrenLength = this.children.length + const list = this.formatGetGeneralization() + const newList = [] + list.forEach(item => { + if (!item.range) { + newList.push(item) + return + } + if ( + item.range.length > 0 && + item.range[0] <= childrenLength - 1 && + item.range[1] <= childrenLength - 1 + ) { + newList.push(item) + } + }) + if (newList.length !== list.length) { + this.setData({ + generalization: newList + }) + } } // 删除概要节点 function removeGeneralization() { if (this.isGeneralization) return - if (this._generalizationLine) { - this._generalizationLine.remove() - this._generalizationLine = null - } - if (this._generalizationNode) { - // 删除概要节点时要同步从激活节点里删除 - this.renderer.removeNodeFromActiveList(this._generalizationNode) - this._generalizationNode.remove() - this._generalizationNode = null - } + this._generalizationList.forEach(item => { + if (item.generalizationLine) { + item.generalizationLine.remove() + item.generalizationLine = null + } + if (item.generalizationNode) { + // 删除概要节点时要同步从激活节点里删除 + this.renderer.removeNodeFromActiveList(item.generalizationNode) + item.generalizationNode.remove() + item.generalizationNode = null + } + }) + this._generalizationList = [] // hack修复当激活一个节点时创建概要,然后立即激活创建的概要节点后会重复创建概要节点并且无法删除的问题 if (this.generalizationBelongNode) { this.nodeDraw @@ -87,31 +154,40 @@ function removeGeneralization() { // 隐藏概要节点 function hideGeneralization() { if (this.isGeneralization) return - if (this._generalizationLine) { - this._generalizationLine.hide() - } - if (this._generalizationNode) { - this._generalizationNode.hide() - } + this._generalizationList.forEach(item => { + if (item.generalizationLine) item.generalizationLine.hide() + if (item.generalizationNode) item.generalizationNode.hide() + }) } // 显示概要节点 function showGeneralization() { if (this.isGeneralization) return - if (this._generalizationLine) { - this._generalizationLine.show() - } - if (this._generalizationNode) { - this._generalizationNode.show() - } + this._generalizationList.forEach(item => { + if (item.generalizationLine) item.generalizationLine.show() + if (item.generalizationNode) item.generalizationNode.show() + }) +} + +// 设置概要节点的透明度 +function setGeneralizationOpacity(val) { + this._generalizationList.forEach(item => { + item.generalizationLine.opacity(val) + item.generalizationNode.group.opacity(val) + }) } export default { + formatGetGeneralization, checkHasGeneralization, + checkHasSelfGeneralization, + getGeneralizationNodeIndex, createGeneralizationNode, updateGeneralization, + updateGeneralizationData, renderGeneralization, removeGeneralization, hideGeneralization, - showGeneralization + showGeneralization, + setGeneralizationOpacity } diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js index f8cdc6b0..a7398e55 100644 --- a/simple-mind-map/src/layouts/Base.js +++ b/simple-mind-map/src/layouts/Base.js @@ -346,6 +346,50 @@ class Base { } } + // 获取指定索引区间的子节点的边界范围 + getChildrenBoundaries(node, dir, startIndex = 0, endIndex) { + let { generalizationLineMargin, generalizationNodeMargin } = + this.mindMap.themeConfig + const children = node.children.slice(startIndex, endIndex + 1) + let left = Infinity + let right = -Infinity + let top = Infinity + let bottom = -Infinity + children.forEach(item => { + const cur = this.getNodeBoundaries(item, dir) + left = cur.left < left ? cur.left : left + right = cur.right > right ? cur.right : right + top = cur.top < top ? cur.top : top + bottom = cur.bottom > bottom ? cur.bottom : bottom + }) + return { + left, + right, + top, + bottom, + generalizationLineMargin, + generalizationNodeMargin + } + } + + // 获取节点概要的渲染边界 + getNodeGeneralizationRenderBoundaries(item, dir) { + let res = null + // 区间 + if (item.range) { + res = this.getChildrenBoundaries( + item.node, + dir, + item.range[0], + item.range[1] + ) + } else { + // 整体概要 + res = this.getNodeBoundaries(item.node, dir) + } + return res + } + // 获取节点实际存在几个子节点 getNodeActChildrenLength(node) { return node.nodeData.children && node.nodeData.children.length diff --git a/simple-mind-map/src/layouts/CatalogOrganization.js b/simple-mind-map/src/layouts/CatalogOrganization.js index 84092778..ce6e3cd8 100644 --- a/simple-mind-map/src/layouts/CatalogOrganization.js +++ b/simple-mind-map/src/layouts/CatalogOrganization.js @@ -72,11 +72,7 @@ class CatalogOrganization extends Base { this.root, null, (node, parent, isRoot, layerIndex) => { - if ( - node.getData('expand') && - node.children && - node.children.length - ) { + if (node.getData('expand') && node.children && node.children.length) { let marginX = this.getMarginX(layerIndex + 1) let marginY = this.getMarginY(layerIndex + 1) if (isRoot) { @@ -339,24 +335,27 @@ class CatalogOrganization extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let { - top, - bottom, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'h') - let x1 = right + generalizationLineMargin - let y1 = top - let x2 = right + generalizationLineMargin - let y2 = bottom - let cx = x1 + 20 - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = right + generalizationNodeMargin - gNode.top = top + (bottom - top - gNode.height) / 2 + renderGeneralization(list) { + list.forEach(item => { + let { + top, + bottom, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'h') + let x1 = right + generalizationLineMargin + let y1 = top + let x2 = right + generalizationLineMargin + let y2 = bottom + let cx = x1 + 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.top = + top + (bottom - top - item.generalizationNode.height) / 2 + }) } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/layouts/Fishbone.js b/simple-mind-map/src/layouts/Fishbone.js index 618c9880..98f0b1fb 100644 --- a/simple-mind-map/src/layouts/Fishbone.js +++ b/simple-mind-map/src/layouts/Fishbone.js @@ -357,24 +357,27 @@ class Fishbone extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let { - top, - bottom, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'h') - let x1 = right + generalizationLineMargin - let y1 = top - let x2 = right + generalizationLineMargin - let y2 = bottom - let cx = x1 + 20 - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = right + generalizationNodeMargin - gNode.top = top + (bottom - top - gNode.height) / 2 + renderGeneralization(list) { + list.forEach(item => { + let { + top, + bottom, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'h') + let x1 = right + generalizationLineMargin + let y1 = top + let x2 = right + generalizationLineMargin + let y2 = bottom + let cx = x1 + 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.top = + top + (bottom - top - item.generalizationNode.height) / 2 + }) } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/layouts/LogicalStructure.js b/simple-mind-map/src/layouts/LogicalStructure.js index bc7bd793..572c4eb1 100644 --- a/simple-mind-map/src/layouts/LogicalStructure.js +++ b/simple-mind-map/src/layouts/LogicalStructure.js @@ -77,11 +77,7 @@ class LogicalStructure extends Base { this.root, null, (node, parent, isRoot, layerIndex) => { - if ( - node.getData('expand') && - node.children && - node.children.length - ) { + if (node.getData('expand') && node.children && node.children.length) { let marginY = this.getMarginY(layerIndex + 1) // 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半 let top = node.top + node.height / 2 - node.childrenAreaHeight / 2 @@ -269,24 +265,27 @@ class LogicalStructure extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let { - top, - bottom, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'h') - let x1 = right + generalizationLineMargin - let y1 = top - let x2 = right + generalizationLineMargin - let y2 = bottom - let cx = x1 + 20 - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = right + generalizationNodeMargin - gNode.top = top + (bottom - top - gNode.height) / 2 + renderGeneralization(list) { + list.forEach(item => { + let { + top, + bottom, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'h') + let x1 = right + generalizationLineMargin + let y1 = top + let x2 = right + generalizationLineMargin + let y2 = bottom + let cx = x1 + 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.top = + top + (bottom - top - item.generalizationNode.height) / 2 + }) } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/layouts/MindMap.js b/simple-mind-map/src/layouts/MindMap.js index 36abe5de..3641933a 100644 --- a/simple-mind-map/src/layouts/MindMap.js +++ b/simple-mind-map/src/layouts/MindMap.js @@ -358,32 +358,34 @@ class MindMap extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let isLeft = node.dir === CONSTANTS.LAYOUT_GROW_DIR.LEFT - let { - top, - bottom, - left, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'h', isLeft) - let x = isLeft - ? left - generalizationLineMargin - : right + generalizationLineMargin - let x1 = x - let y1 = top - let x2 = x - let y2 = bottom - let cx = x1 + (isLeft ? -20 : 20) - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = - x + - (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - - (isLeft ? gNode.width : 0) - gNode.top = top + (bottom - top - gNode.height) / 2 + renderGeneralization(list) { + list.forEach(item => { + let isLeft = item.node.dir === CONSTANTS.LAYOUT_GROW_DIR.LEFT + let { + top, + bottom, + left, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'h') + let x = isLeft + ? left - generalizationLineMargin + : right + generalizationLineMargin + let x1 = x + let y1 = top + let x2 = x + let y2 = bottom + let cx = x1 + (isLeft ? -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 = + x + + (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - + (isLeft ? item.generalizationNode.width : 0) + item.generalizationNode.top = top + (bottom - top - item.generalizationNode.height) / 2 + }) } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/layouts/OrganizationStructure.js b/simple-mind-map/src/layouts/OrganizationStructure.js index 93192c7a..482c0781 100644 --- a/simple-mind-map/src/layouts/OrganizationStructure.js +++ b/simple-mind-map/src/layouts/OrganizationStructure.js @@ -243,24 +243,27 @@ class OrganizationStructure extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let { - bottom, - left, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'v') - let x1 = left - let y1 = bottom + generalizationLineMargin - let x2 = right - let y2 = bottom + generalizationLineMargin - let cx = x1 + (x2 - x1) / 2 - let cy = y1 + 20 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.top = bottom + generalizationNodeMargin - gNode.left = left + (right - left - gNode.width) / 2 + renderGeneralization(list) { + list.forEach(item => { + let { + bottom, + left, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'v') + let x1 = left + let y1 = bottom + generalizationLineMargin + let x2 = right + let y2 = bottom + generalizationLineMargin + let cx = x1 + (x2 - x1) / 2 + let cy = y1 + 20 + let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` + item.generalizationLine.plot(path) + item.generalizationNode.top = bottom + generalizationNodeMargin + item.generalizationNode.left = left + (right - left - item.generalizationNode.width) / 2 + }) + } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/layouts/Timeline.js b/simple-mind-map/src/layouts/Timeline.js index 82fbc9f0..d9d51c2e 100644 --- a/simple-mind-map/src/layouts/Timeline.js +++ b/simple-mind-map/src/layouts/Timeline.js @@ -80,11 +80,7 @@ class Timeline extends Base { this.root, null, (node, parent, isRoot, layerIndex, index) => { - if ( - node.getData('expand') && - node.children && - node.children.length - ) { + if (node.getData('expand') && node.children && node.children.length) { let marginX = this.getMarginX(layerIndex + 1) let marginY = this.getMarginY(layerIndex + 1) if (isRoot) { @@ -315,24 +311,26 @@ class Timeline extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let { - top, - bottom, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'h') - let x1 = right + generalizationLineMargin - let y1 = top - let x2 = right + generalizationLineMargin - let y2 = bottom - let cx = x1 + 20 - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = right + generalizationNodeMargin - gNode.top = top + (bottom - top - gNode.height) / 2 + renderGeneralization(list) { + list.forEach(item => { + let { + top, + bottom, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'h') + let x1 = right + generalizationLineMargin + let y1 = top + let x2 = right + generalizationLineMargin + let y2 = bottom + let cx = x1 + 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.top = top + (bottom - top - item.generalizationNode.height) / 2 + }) } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/layouts/VerticalTimeline.js b/simple-mind-map/src/layouts/VerticalTimeline.js index bdd06189..7f844fb0 100644 --- a/simple-mind-map/src/layouts/VerticalTimeline.js +++ b/simple-mind-map/src/layouts/VerticalTimeline.js @@ -97,11 +97,7 @@ class VerticalTimeline extends Base { this.root, null, (node, parent, isRoot, layerIndex, index) => { - if ( - node.getData('expand') && - node.children && - node.children.length - ) { + if (node.getData('expand') && node.children && node.children.length) { let marginY = this.getMarginY(layerIndex + 1) // 定位二级节点的top if (isRoot) { @@ -386,32 +382,35 @@ class VerticalTimeline extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { - let isLeft = node.dir === CONSTANTS.LAYOUT_GROW_DIR.LEFT - let { - top, - bottom, - left, - right, - generalizationLineMargin, - generalizationNodeMargin - } = this.getNodeBoundaries(node, 'h', isLeft) - let x = isLeft - ? left - generalizationLineMargin - : right + generalizationLineMargin - let x1 = x - let y1 = top - let x2 = x - let y2 = bottom - let cx = x1 + (isLeft ? -20 : 20) - let cy = y1 + (y2 - y1) / 2 - let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}` - gLine.plot(path) - gNode.left = - x + - (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - - (isLeft ? gNode.width : 0) - gNode.top = top + (bottom - top - gNode.height) / 2 + renderGeneralization(list) { + list.forEach(item => { + let isLeft = item.node.dir === CONSTANTS.LAYOUT_GROW_DIR.LEFT + let { + top, + bottom, + left, + right, + generalizationLineMargin, + generalizationNodeMargin + } = this.getNodeGeneralizationRenderBoundaries(item, 'h') + let x = isLeft + ? left - generalizationLineMargin + : right + generalizationLineMargin + let x1 = x + let y1 = top + let x2 = x + let y2 = bottom + let cx = x1 + (isLeft ? -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 = + x + + (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - + (isLeft ? item.generalizationNode.width : 0) + item.generalizationNode.top = + top + (bottom - top - item.generalizationNode.height) / 2 + }) } // 渲染展开收起按钮的隐藏占位元素 diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index eac4b3de..917b308e 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -737,6 +737,56 @@ export const checkHasSupSubRelation = list => { return false } +// 解析要添加概要的节点实例列表 +export const parseAddGeneralizationNodeList = list => { + const cache = {} + const uidToParent = {} + list.forEach(node => { + const parent = node.parent + if (parent) { + const pUid = parent.uid + uidToParent[pUid] = parent + const index = node.getIndexInBrothers() + const data = { + node, + index + } + if (cache[pUid]) { + if ( + !cache[pUid].find(item => { + return item.index === data.index + }) + ) { + cache[pUid].push(data) + } + } else { + cache[pUid] = [data] + } + } + }) + const res = [] + Object.keys(cache).forEach(uid => { + if (cache[uid].length > 1) { + const rangeList = cache[uid] + .map(item => { + return item.index + }) + .sort((a, b) => { + return a - b + }) + res.push({ + node: uidToParent[uid], + range: [rangeList[0], rangeList[rangeList.length - 1]] + }) + } else { + res.push({ + node: cache[uid][0].node + }) + } + }) + return res +} + // 判断两个矩形是否重叠 export const checkTwoRectIsOverlap = ( minx1,