From d834b76d42f07dab0333de75029ad824d1ae8a24 Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Mon, 27 Mar 2023 09:11:15 +0800 Subject: [PATCH 01/21] =?UTF-8?q?FIX=EF=BC=9A=E4=BF=AE=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E8=8A=82=E7=82=B9=E6=97=B6=E9=87=8D=E5=A4=8D=E7=9A=84?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E8=B0=83=E7=94=A8=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/layouts/Base.js | 1 - 1 file changed, 1 deletion(-) diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js index aecdfdd3..caca9bed 100644 --- a/simple-mind-map/src/layouts/Base.js +++ b/simple-mind-map/src/layouts/Base.js @@ -51,7 +51,6 @@ class Base { draw: this.draw, layerIndex }) - newNode.getSize() // 数据关联实际节点 data._node = newNode if (data.data.isActive) { From d412ae8cce98fa8d4899d5d9fe9d2f8bc7b52896 Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Tue, 28 Mar 2023 19:15:47 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=AE=9E=E4=BE=8B=E3=80=81=E6=A0=B7=E5=BC=8F=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B=E4=B8=8D=E5=86=8D=E4=BF=9D=E5=AD=98=E4=B8=BB=E9=A2=98?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E7=9B=B4=E6=8E=A5=E4=BB=8EmindMap?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E4=B8=8A=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/Node.js | 29 +++++++++-------------------- simple-mind-map/src/Style.js | 22 ++++++++-------------- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 386e9a71..9947826f 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -21,10 +21,8 @@ class Node { this.renderer = opt.renderer // 渲染器 this.draw = opt.draw || null - // 主题配置 - this.themeConfig = this.mindMap.themeConfig // 样式实例 - this.style = new Style(this, this.themeConfig) + this.style = new Style(this) // 形状实例 this.shapeInstance = new Shape(this) this.shapePadding = { @@ -110,15 +108,6 @@ class Node { this._top = val } - // 更新主题配置 - - updateThemeConfig() { - // 主题配置 - this.themeConfig = this.mindMap.themeConfig - // 样式实例 - this.style.updateThemeConfig(this.themeConfig) - } - // 复位部分布局时会重新设置的数据 reset() { @@ -342,8 +331,8 @@ class Node { return resizeImgSize( this.nodeData.data.imageSize.width, this.nodeData.data.imageSize.height, - this.themeConfig.imgMaxWidth, - this.themeConfig.imgMaxHeight + this.mindMap.themeConfig.imgMaxWidth, + this.mindMap.themeConfig.imgMaxHeight ) } @@ -354,7 +343,7 @@ class Node { if (!_data.icon || _data.icon.length <= 0) { return [] } - let iconSize = this.themeConfig.iconSize + let iconSize = this.mindMap.themeConfig.iconSize return _data.icon.map(item => { return { node: SVG(iconsSvg.getNodeIconListIcon(item)).size(iconSize, iconSize), @@ -458,7 +447,7 @@ class Node { if (!hyperlink) { return } - let iconSize = this.themeConfig.iconSize + let iconSize = this.mindMap.themeConfig.iconSize let node = new SVG() // 超链接节点 let a = new A().to(hyperlink).target('_blank') @@ -515,7 +504,7 @@ class Node { if (!this.nodeData.data.note) { return null } - let iconSize = this.themeConfig.iconSize + let iconSize = this.mindMap.themeConfig.iconSize let node = new SVG().attr('cursor', 'pointer') // 透明的层,用来作为鼠标区域 node.add(new Rect().size(iconSize, iconSize).fill({ color: 'transparent' })) @@ -571,7 +560,7 @@ class Node { getShape() { // 节点使用功能横线风格的话不支持设置形状,直接使用默认的矩形 - return this.themeConfig.nodeUseLineStyle + return this.mindMap.themeConfig.nodeUseLineStyle ? 'rectangle' : this.style.getStyle('shape', false, false) } @@ -754,7 +743,7 @@ class Node { // 更新节点 - update(layout = false) { + update(isLayout = false) { if (!this.group) { return } @@ -769,7 +758,7 @@ class Node { } this.renderGeneralization() let t = this.group.transform() - if (!layout) { + if (!isLayout) { this.group .animate(300) .translate( diff --git a/simple-mind-map/src/Style.js b/simple-mind-map/src/Style.js index 083120b2..876782e6 100644 --- a/simple-mind-map/src/Style.js +++ b/simple-mind-map/src/Style.js @@ -21,34 +21,28 @@ class Style { // 构造函数 - constructor(ctx, themeConfig) { + constructor(ctx) { this.ctx = ctx - this.themeConfig = themeConfig - } - - // 更新主题配置 - - updateThemeConfig(themeConfig) { - this.themeConfig = themeConfig } // 合并样式 merge(prop, root, isActive) { + let themeConfig = this.ctx.mindMap.themeConfig // 三级及以下节点 - let defaultConfig = this.themeConfig.node + let defaultConfig = themeConfig.node if (root || rootProp.includes(prop)) { // 直接使用最外层样式 - defaultConfig = this.themeConfig + defaultConfig = themeConfig } else if (this.ctx.isGeneralization) { // 概要节点 - defaultConfig = this.themeConfig.generalization + defaultConfig = themeConfig.generalization } else if (this.ctx.layerIndex === 0) { // 根节点 - defaultConfig = this.themeConfig.root + defaultConfig = themeConfig.root } else if (this.ctx.layerIndex === 1) { // 二级节点 - defaultConfig = this.themeConfig.second + defaultConfig = themeConfig.second } // 激活状态 if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) { @@ -96,7 +90,7 @@ class Style { if ( !this.ctx.isRoot && !this.ctx.isGeneralization && - this.themeConfig.nodeUseLineStyle && + this.ctx.mindMap.themeConfig.nodeUseLineStyle && !this.ctx.nodeData.data.isActive ) { return From fcfcb1c3d14ced3cb894c9c9f90bc6ad30371840 Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Tue, 28 Mar 2023 19:30:13 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9AgetSize?= =?UTF-8?q?=E4=BB=A5=E5=90=8E=E4=B8=8D=E9=9C=80=E8=A6=81=E8=B0=83=E7=94=A8?= =?UTF-8?q?renderNode=E6=96=B9=E6=B3=95=EF=BC=8C=E7=9B=B4=E6=8E=A5layout?= =?UTF-8?q?=E5=8D=B3=E5=8F=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/Node.js | 59 +---------------------------------- simple-mind-map/src/Render.js | 6 ++-- simple-mind-map/src/Style.js | 16 ---------- 3 files changed, 4 insertions(+), 77 deletions(-) diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 9947826f..52a4c8d5 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -9,7 +9,6 @@ import iconsSvg from './svg/icons' class Node { // 构造函数 - constructor(opt = {}) { // 节点数据 this.nodeData = this.handleData(opt.data || {}) @@ -87,7 +86,6 @@ class Node { // 初始渲染 this.initRender = true // 初始化 - // this.createNodeData() this.getSize() } @@ -109,7 +107,6 @@ class Node { } // 复位部分布局时会重新设置的数据 - reset() { this.children = [] this.parent = null @@ -120,7 +117,6 @@ class Node { } // 处理数据 - handleData(data) { data.data.expand = data.data.expand === false ? false : true data.data.isActive = data.data.isActive === true ? true : false @@ -129,13 +125,11 @@ class Node { } // 检查节点是否存在自定义数据 - hasCustomPosition() { return this.customLeft !== undefined && this.customTop !== undefined } // 检查节点是否存在自定义位置的祖先节点 - ancestorHasCustomPosition() { let node = this while (node) { @@ -148,13 +142,11 @@ class Node { } // 添加子节点 - addChildren(node) { this.children.push(node) } // 创建节点的各个内容对象数据 - createNodeData() { this._imgData = this.createImgNode() this._iconData = this.createIconNode() @@ -166,7 +158,6 @@ class Node { } // 解绑所有事件 - removeAllEvent() { if (this._noteData) { this._noteData.node.off(['mouseover', 'mouseout']) @@ -188,7 +179,6 @@ class Node { } // 移除节点内容 - removeAllNode() { // 节点内的内容 ;[ @@ -223,8 +213,8 @@ class Node { } // 计算节点的宽高 - getSize() { + this.removeAllEvent() this.removeAllNode() this.createNodeData() let { width, height } = this.getNodeRect() @@ -236,7 +226,6 @@ class Node { } // 计算节点尺寸信息 - getNodeRect() { // 宽高 let imgContentWidth = 0 @@ -304,7 +293,6 @@ class Node { } // 创建图片节点 - createImgNode() { let img = this.nodeData.data.image if (!img) { @@ -326,7 +314,6 @@ class Node { } // 获取图片显示宽高 - getImgShowSize() { return resizeImgSize( this.nodeData.data.imageSize.width, @@ -337,7 +324,6 @@ class Node { } // 创建icon节点 - createIconNode() { let _data = this.nodeData.data if (!_data.icon || _data.icon.length <= 0) { @@ -384,7 +370,6 @@ class Node { } // 创建文本节点 - createTextNode() { if (this.nodeData.data.richText) { return this.createRichTextNode() @@ -472,7 +457,6 @@ class Node { } // 创建标签节点 - createTagNode() { let tagData = this.nodeData.data.tag if (!tagData || tagData.length <= 0) { @@ -499,7 +483,6 @@ class Node { } // 创建备注节点 - createNoteNode() { if (!this.nodeData.data.note) { return null @@ -557,7 +540,6 @@ class Node { } // 获取节点形状 - getShape() { // 节点使用功能横线风格的话不支持设置形状,直接使用默认的矩形 return this.mindMap.themeConfig.nodeUseLineStyle @@ -566,7 +548,6 @@ class Node { } // 定位节点内容 - layout() { let { width, textContentItemMargin } = this let { paddingY } = this.getPaddingVale() @@ -714,7 +695,6 @@ class Node { } // 激活节点 - active(e) { if (this.mindMap.opt.readonly) { return @@ -731,7 +711,6 @@ class Node { } // 渲染节点到画布,会移除旧的,创建新的 - renderNode() { // 连线 this.renderLine() @@ -742,7 +721,6 @@ class Node { } // 更新节点 - update(isLayout = false) { if (!this.group) { return @@ -774,7 +752,6 @@ class Node { } // 递归渲染 - render(callback = () => {}) { // 节点 if (this.initRender) { @@ -818,7 +795,6 @@ class Node { } // 递归删除 - remove() { this.initRender = true this.removeAllEvent() @@ -837,7 +813,6 @@ class Node { } // 隐藏节点 - hide() { this.group.hide() this.hideGeneralization() @@ -858,7 +833,6 @@ class Node { } // 显示节点 - show() { if (!this.group) { return @@ -882,7 +856,6 @@ class Node { } // 连线 - renderLine(deep = false) { if (this.nodeData.data.expand === false) { return @@ -919,7 +892,6 @@ class Node { } // 设置连线样式 - styleLine(line, node) { let width = node.getSelfInhertStyle('lineWidth') || node.getStyle('lineWidth', true) @@ -936,7 +908,6 @@ class Node { } // 移除连线 - removeLine() { this._lines.forEach(line => { line.remove() @@ -945,13 +916,11 @@ class Node { } // 检查是否存在概要 - checkHasGeneralization() { return !!this.nodeData.data.generalization } // 创建概要节点 - createGeneralizationNode() { if (this.isGeneralization || !this.checkHasGeneralization()) { return @@ -980,14 +949,12 @@ class Node { } // 更新概要节点 - updateGeneralization() { this.removeGeneralization() this.createGeneralizationNode() } // 渲染概要节点 - renderGeneralization() { if (this.isGeneralization) { return @@ -1013,7 +980,6 @@ class Node { } // 删除概要节点 - removeGeneralization() { if (this._generalizationLine) { this._generalizationLine.remove() @@ -1034,7 +1000,6 @@ class Node { } // 隐藏概要节点 - hideGeneralization() { if (this._generalizationLine) { this._generalizationLine.hide() @@ -1045,7 +1010,6 @@ class Node { } // 显示概要节点 - showGeneralization() { if (this._generalizationLine) { this._generalizationLine.show() @@ -1056,7 +1020,6 @@ class Node { } // 创建或更新展开收缩按钮内容 - updateExpandBtnNode() { if (this._expandBtn) { this._expandBtn.clear() @@ -1076,7 +1039,6 @@ class Node { } // 更新展开收缩按钮位置 - updateExpandBtnPos() { if (!this._expandBtn) { return @@ -1085,7 +1047,6 @@ class Node { } // 展开收缩按钮 - renderExpandBtn() { if ( !this.nodeData.children || @@ -1123,7 +1084,6 @@ class Node { } // 移除展开收缩按钮 - removeExpandBtn() { if (this._expandBtn) { this._expandBtn.off(['mouseover', 'mouseout', 'click']) @@ -1134,7 +1094,6 @@ class Node { } // 检测当前节点是否是某个节点的祖先节点 - isParent(node) { if (this === node) { return false @@ -1150,7 +1109,6 @@ class Node { } // 检测当前节点是否是某个节点的兄弟节点 - isBrother(node) { if (!this.parent || this === node) { return false @@ -1161,7 +1119,6 @@ class Node { } // 获取padding值 - getPaddingVale() { return { paddingX: this.getStyle('paddingX', true, this.nodeData.data.isActive), @@ -1170,20 +1127,17 @@ class Node { } // 获取某个样式 - getStyle(prop, root, isActive) { let v = this.style.merge(prop, root, isActive) return v === undefined ? '' : v } // 获取自定义样式 - getSelfStyle(prop) { return this.style.getSelfStyle(prop) } // 获取最近一个存在自身自定义样式的祖先节点的自定义样式 - getParentSelfStyle(prop) { if (this.parent) { return ( @@ -1194,7 +1148,6 @@ class Node { } // 获取自身可继承的自定义样式 - getSelfInhertStyle(prop) { return ( this.getSelfStyle(prop) || // 自身 @@ -1203,61 +1156,51 @@ class Node { } // 修改某个样式 - setStyle(prop, value, isActive) { this.mindMap.execCommand('SET_NODE_STYLE', this, prop, value, isActive) } // 获取数据 - getData(key) { return key ? this.nodeData.data[key] || '' : this.nodeData.data } // 设置数据 - setData(data = {}) { this.mindMap.execCommand('SET_NODE_DATA', this, data) } // 设置文本 - setText(text, richText) { this.mindMap.execCommand('SET_NODE_TEXT', this, text, richText) } // 设置图片 - setImage(imgData) { this.mindMap.execCommand('SET_NODE_IMAGE', this, imgData) } // 设置图标 - setIcon(icons) { this.mindMap.execCommand('SET_NODE_ICON', this, icons) } // 设置超链接 - setHyperlink(link, title) { this.mindMap.execCommand('SET_NODE_HYPERLINK', this, link, title) } // 设置备注 - setNote(note) { this.mindMap.execCommand('SET_NODE_NOTE', this, note) } // 设置标签 - setTag(tag) { this.mindMap.execCommand('SET_NODE_TAG', this, tag) } // 设置形状 - setShape(shape) { this.mindMap.execCommand('SET_NODE_SHAPE', this, shape) } diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index 5c9a0b64..32406cc6 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -515,7 +515,7 @@ class Render { this.mindMap.render(() => { if (nodeLayerChanged) { node.getSize() - node.renderNode() + node.layout() } }) } @@ -555,7 +555,7 @@ class Render { this.mindMap.render(() => { if (nodeLayerChanged) { node.getSize() - node.renderNode() + node.layout() } }) } @@ -964,7 +964,7 @@ class Render { setNodeDataRender(node, data) { this.setNodeData(node, data) let changed = node.getSize() - node.renderNode() + node.layout() if (changed) { if (node.isGeneralization) { // 概要节点 diff --git a/simple-mind-map/src/Style.js b/simple-mind-map/src/Style.js index 876782e6..8d5f81c2 100644 --- a/simple-mind-map/src/Style.js +++ b/simple-mind-map/src/Style.js @@ -2,10 +2,8 @@ import { tagColorList } from './utils/constant' const rootProp = ['paddingX', 'paddingY'] // 样式类 - class Style { // 设置背景样式 - static setBackgroundStyle(el, themeConfig) { let { backgroundColor, backgroundImage, backgroundRepeat, backgroundPosition, backgroundSize } = themeConfig el.style.backgroundColor = backgroundColor @@ -20,13 +18,11 @@ class Style { } // 构造函数 - constructor(ctx) { this.ctx = ctx } // 合并样式 - merge(prop, root, isActive) { let themeConfig = this.ctx.mindMap.themeConfig // 三级及以下节点 @@ -62,26 +58,22 @@ class Style { } // 获取某个样式值 - getStyle(prop, root, isActive) { return this.merge(prop, root, isActive) } // 获取自身自定义样式 - getSelfStyle(prop) { return this.ctx.nodeData.data[prop] } // 矩形 - rect(node) { this.shape(node) node.radius(this.merge('borderRadius')) } // 矩形外的其他形状 - shape(node) { node.fill({ color: this.merge('fillColor') @@ -103,7 +95,6 @@ class Style { } // 文字 - text(node) { node .fill({ @@ -129,7 +120,6 @@ class Style { } // html文字节点 - domText(node, fontSizeScale = 1) { node.style.fontFamily = this.merge('fontFamily') node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px' @@ -139,7 +129,6 @@ class Style { } // 标签文字 - tagText(node, index) { node .fill({ @@ -151,7 +140,6 @@ class Style { } // 标签矩形 - tagRect(node, index) { node.fill({ color: tagColorList[index].background @@ -159,7 +147,6 @@ class Style { } // 内置图标 - iconNode(node) { node.attr({ fill: this.merge('color') @@ -167,13 +154,11 @@ class Style { } // 连线 - line(node, { width, color, dasharray } = {}) { node.stroke({ width, color, dasharray }).fill({ color: 'none' }) } // 概要连线 - generalizationLine(node) { node .stroke({ @@ -184,7 +169,6 @@ class Style { } // 按钮 - iconBtn(node, fillNode) { node.fill({ color: '#808080' }) fillNode.fill({ color: '#fff' }) From 747a781ad8bf74561b401fc16df5f85c387aa9df Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Tue, 28 Mar 2023 19:35:57 +0800 Subject: [PATCH 04/21] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E7=A9=BA=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/Drag.js | 8 - simple-mind-map/src/Render.js | 51 -- .../src/layouts/CatalogOrganization.js | 772 +++++++++--------- .../src/layouts/LogicalStructure.js | 13 - simple-mind-map/src/layouts/MindMap.js | 12 - .../src/layouts/OrganizationStructure.js | 11 - 6 files changed, 386 insertions(+), 481 deletions(-) diff --git a/simple-mind-map/src/Drag.js b/simple-mind-map/src/Drag.js index 287cb989..75ff5089 100644 --- a/simple-mind-map/src/Drag.js +++ b/simple-mind-map/src/Drag.js @@ -5,7 +5,6 @@ import Base from './layouts/Base' class Drag extends Base { // 构造函数 - constructor({ mindMap }) { super(mindMap.renderer) this.mindMap = mindMap @@ -14,7 +13,6 @@ class Drag extends Base { } // 复位 - reset() { // 当前拖拽节点 this.node = null @@ -48,7 +46,6 @@ class Drag extends Base { } // 绑定事件 - bindEvent() { this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this) this.mindMap.on('node_mousedown', (node, e) => { @@ -98,7 +95,6 @@ class Drag extends Base { } // 鼠标松开事件 - onMouseup(e) { if (!this.isMousedown) { return @@ -141,7 +137,6 @@ class Drag extends Base { } // 创建克隆节点 - createCloneNode() { if (!this.clone) { // 节点 @@ -163,7 +158,6 @@ class Drag extends Base { } // 移除克隆节点 - removeCloneNode() { if (!this.clone) { return @@ -174,7 +168,6 @@ class Drag extends Base { } // 拖动中 - onMove(x, y) { if (!this.isMousedown) { return @@ -201,7 +194,6 @@ class Drag extends Base { } // 检测重叠节点 - checkOverlapNode() { if (!this.drawTransform) { return diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index 32406cc6..85399d78 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -24,7 +24,6 @@ const layouts = { class Render { // 构造函数 - constructor(opt = {}) { this.opt = opt this.mindMap = opt.mindMap @@ -51,7 +50,6 @@ class Render { } // 设置布局结构 - setLayout() { this.layout = new ( layouts[this.mindMap.opt.layout] @@ -61,7 +59,6 @@ class Render { } // 绑定事件 - bindEvent() { // 点击事件 this.mindMap.on('draw_click', () => { @@ -73,7 +70,6 @@ class Render { } // 注册命令 - registerCommands() { // 全选 this.selectAll = this.selectAll.bind(this) @@ -175,7 +171,6 @@ class Render { } // 注册快捷键 - registerShortcutKeys() { // 插入下级节点 this.mindMap.keyCommand.addShortcut('Tab', () => { @@ -220,7 +215,6 @@ class Render { } // 开启文字编辑,会禁用回车键和删除键相关快捷键防止冲突 - startTextEdit() { this.mindMap.keyCommand.save() // this.mindMap.keyCommand.removeShortcut('Del|Backspace') @@ -229,7 +223,6 @@ class Render { } // 结束文字编辑,会恢复回车键和删除键相关快捷键 - endTextEdit() { this.mindMap.keyCommand.restore() // this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap) @@ -238,7 +231,6 @@ class Render { } // 渲染 - render(callback = () => {}) { if (this.reRender) { this.clearActive() @@ -254,7 +246,6 @@ class Render { } // 清除当前激活的节点 - clearActive() { this.activeNodeList.forEach(item => { this.setNodeActive(item, false) @@ -263,7 +254,6 @@ class Render { } // 清除当前所有激活节点,并会触发事件 - clearAllActive() { if (this.activeNodeList.length <= 0) { return @@ -273,7 +263,6 @@ class Render { } // 添加节点到激活列表里 - addActiveNode(node) { let index = this.findActiveNodeIndex(node) if (index === -1) { @@ -282,7 +271,6 @@ class Render { } // 在激活列表里移除某个节点 - removeActiveNode(node) { let index = this.findActiveNodeIndex(node) if (index === -1) { @@ -292,7 +280,6 @@ class Render { } // 检索某个节点在激活列表里的索引 - findActiveNodeIndex(node) { return this.activeNodeList.findIndex(item => { return item === node @@ -300,7 +287,6 @@ class Render { } // 获取节点在同级里的索引位置 - getNodeIndex(node) { return node.parent ? node.parent.children.findIndex(item => { @@ -310,7 +296,6 @@ class Render { } // 全选 - selectAll() { walk( this.root, @@ -332,7 +317,6 @@ class Render { } // 回退 - back(step) { this.clearAllActive() let data = this.mindMap.command.back(step) @@ -343,7 +327,6 @@ class Render { } // 前进 - forward(step) { this.clearAllActive() let data = this.mindMap.command.forward(step) @@ -360,7 +343,6 @@ class Render { } // 插入同级节点,多个节点只会操作第一个节点 - insertNode(openEdit = true, appointNodes = [], appointData = null) { appointNodes = this.formatAppointNodes(appointNodes) if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) { @@ -391,7 +373,6 @@ class Render { } // 插入子节点 - insertChildNode(openEdit = true, appointNodes = [], appointData = null) { appointNodes = this.formatAppointNodes(appointNodes) if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) { @@ -426,7 +407,6 @@ class Render { } // 上移节点,多个节点只会操作第一个节点 - upNode() { if (this.activeNodeList.length <= 0) { return @@ -454,7 +434,6 @@ class Render { } // 下移节点,多个节点只会操作第一个节点 - downNode() { if (this.activeNodeList.length <= 0) { return @@ -482,7 +461,6 @@ class Render { } // 将节点移动到另一个节点的前面 - insertBefore(node, exist) { if (node.isRoot) { return @@ -521,7 +499,6 @@ class Render { } // 将节点移动到另一个节点的后面 - insertAfter(node, exist) { if (node.isRoot) { return @@ -561,7 +538,6 @@ class Render { } // 移除节点 - removeNode(appointNodes = []) { appointNodes = this.formatAppointNodes(appointNodes) if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) { @@ -603,7 +579,6 @@ class Render { } // 移除某个指定节点 - removeOneNode(node) { let index = this.getNodeIndex(node) node.remove() @@ -612,7 +587,6 @@ class Render { } // 复制节点,多个节点只会操作第一个节点 - copyNode() { if (this.activeNodeList.length <= 0) { return @@ -621,7 +595,6 @@ class Render { } // 剪切节点,多个节点只会操作第一个节点 - cutNode(callback) { if (this.activeNodeList.length <= 0) { return @@ -641,7 +614,6 @@ class Render { } // 移动一个节点作为另一个节点的子节点 - moveNodeTo(node, toNode) { if (node.isRoot) { return @@ -658,7 +630,6 @@ class Render { } // 粘贴节点到节点 - pasteNode(data) { if (this.activeNodeList.length <= 0) { return @@ -670,7 +641,6 @@ class Render { } // 设置节点样式 - setNodeStyle(node, prop, value, isActive) { let data = {} if (isActive) { @@ -702,7 +672,6 @@ class Render { } // 设置节点是否激活 - setNodeActive(node, active) { this.setNodeData(node, { isActive: active @@ -711,7 +680,6 @@ class Render { } // 设置节点是否展开 - setNodeExpand(node, expand) { this.setNodeData(node, { expand @@ -735,7 +703,6 @@ class Render { } // 展开所有 - expandAllNode() { walk( this.renderTree, @@ -754,7 +721,6 @@ class Render { } // 收起所有 - unexpandAllNode() { walk( this.renderTree, @@ -774,7 +740,6 @@ class Render { } // 展开到指定层级 - expandToLevel(level) { walk( this.renderTree, @@ -792,7 +757,6 @@ class Render { } // 切换激活节点的展开状态 - toggleActiveExpand() { this.activeNodeList.forEach(node => { if (node.nodeData.children.length <= 0) { @@ -803,7 +767,6 @@ class Render { } // 切换节点展开状态 - toggleNodeExpand(node) { this.mindMap.execCommand( 'SET_NODE_EXPAND', @@ -813,7 +776,6 @@ class Render { } // 设置节点文本 - setNodeText(node, text, richText) { this.setNodeDataRender(node, { text, @@ -822,7 +784,6 @@ class Render { } // 设置节点图片 - setNodeImage(node, { url, title, width, height }) { this.setNodeDataRender(node, { image: url, @@ -835,7 +796,6 @@ class Render { } // 设置节点图标 - setNodeIcon(node, icons) { this.setNodeDataRender(node, { icon: icons @@ -843,7 +803,6 @@ class Render { } // 设置节点超链接 - setNodeHyperlink(node, link, title = '') { this.setNodeDataRender(node, { hyperlink: link, @@ -852,7 +811,6 @@ class Render { } // 设置节点备注 - setNodeNote(node, note) { this.setNodeDataRender(node, { note @@ -860,7 +818,6 @@ class Render { } // 设置节点标签 - setNodeTag(node, tag) { this.setNodeDataRender(node, { tag @@ -868,7 +825,6 @@ class Render { } // 添加节点概要 - addGeneralization(data) { if (this.activeNodeList.length <= 0) { return @@ -888,7 +844,6 @@ class Render { } // 删除节点概要 - removeGeneralization() { if (this.activeNodeList.length <= 0) { return @@ -906,7 +861,6 @@ class Render { } // 设置节点自定义位置 - setNodeCustomPosition(node, left = undefined, top = undefined) { let nodeList = [node] || this.activeNodeList nodeList.forEach(item => { @@ -918,7 +872,6 @@ class Render { } // 一键整理布局,即去除自定义位置 - resetLayout() { walk( this.root, @@ -940,7 +893,6 @@ class Render { } // 设置节点形状 - setNodeShape(node, shape) { if (!shape || !shapeList.includes(shape)) { return @@ -952,7 +904,6 @@ class Render { } // 更新节点数据 - setNodeData(node, data) { Object.keys(data).forEach(key => { node.nodeData.data[key] = data[key] @@ -960,7 +911,6 @@ class Render { } // 设置节点数据,并判断是否渲染 - setNodeDataRender(node, data) { this.setNodeData(node, data) let changed = node.getSize() @@ -975,7 +925,6 @@ class Render { } // 移动节点到画布中心 - moveNodeToCenter(node) { let halfWidth = this.mindMap.width / 2 let halfHeight = this.mindMap.height / 2 diff --git a/simple-mind-map/src/layouts/CatalogOrganization.js b/simple-mind-map/src/layouts/CatalogOrganization.js index 0b102655..4cf06569 100644 --- a/simple-mind-map/src/layouts/CatalogOrganization.js +++ b/simple-mind-map/src/layouts/CatalogOrganization.js @@ -1,386 +1,386 @@ -import Base from './Base' -import { walk, asyncRun } from '../utils' - -// 目录组织图 -class CatalogOrganization extends Base { - // 构造函数 - constructor(opt = {}) { - super(opt) - } - - // 布局 - doLayout(callback) { - let task = [ - () => { - this.computedBaseValue() - }, - () => { - this.computedLeftTopValue() - }, - () => { - this.adjustLeftTopValue() - }, - () => { - callback(this.root) - } - ] - asyncRun(task) - } - - // 遍历数据计算节点的left、width、height - computedBaseValue() { - walk( - this.renderer.renderTree, - null, - (cur, parent, isRoot, layerIndex) => { - let newNode = this.createNode(cur, parent, isRoot, layerIndex) - // 根节点定位在画布中心位置 - if (isRoot) { - this.setNodeCenter(newNode) - } else { - // 非根节点 - if (parent._node.isRoot) { - newNode.top = - parent._node.top + - parent._node.height + - this.getMarginX(layerIndex) - } - } - if (!cur.data.expand) { - return true - } - }, - (cur, parent, isRoot, layerIndex) => { - if (isRoot) { - let len = cur.data.expand === false ? 0 : cur._node.children.length - cur._node.childrenAreaWidth = len - ? cur._node.children.reduce((h, item) => { - return h + item.width - }, 0) + - (len + 1) * this.getMarginX(layerIndex + 1) - : 0 - } - }, - true, - 0 - ) - } - - // 遍历节点树计算节点的left、top - computedLeftTopValue() { - walk( - this.root, - null, - (node, parent, isRoot, layerIndex) => { - if ( - node.nodeData.data.expand && - node.children && - node.children.length - ) { - let marginX = this.getMarginX(layerIndex + 1) - let marginY = this.getMarginY(layerIndex + 1) - if (isRoot) { - let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 - let totalLeft = left + marginX - node.children.forEach(cur => { - cur.left = totalLeft - totalLeft += cur.width + marginX - }) - } else { - let totalTop = node.top + node.height + marginY + node.expandBtnSize - node.children.forEach(cur => { - cur.left = node.left + node.width * 0.5 - cur.top = totalTop - totalTop += cur.height + marginY + node.expandBtnSize - }) - } - } - }, - null, - true - ) - } - - // 调整节点left、top - adjustLeftTopValue() { - walk( - this.root, - null, - (node, parent, isRoot, layerIndex) => { - if (!node.nodeData.data.expand) { - return - } - // 调整left - if (parent && parent.isRoot) { - let areaWidth = this.getNodeAreaWidth(node) - let difference = areaWidth - node.width - if (difference > 0) { - this.updateBrothersLeft(node, difference / 2) - } - } - // 调整top - let len = node.children.length - if (parent && !parent.isRoot && len > 0) { - let marginY = this.getMarginY(layerIndex + 1) - let totalHeight = - node.children.reduce((h, item) => { - return h + item.height - }, 0) + - (len + 1) * marginY + - len * node.expandBtnSize - this.updateBrothersTop(node, totalHeight) - } - }, - null, - true - ) - } - - // 递归计算节点的宽度 - getNodeAreaWidth(node) { - let widthArr = [] - let loop = (node, width) => { - if (node.children.length) { - width += node.width / 2 - node.children.forEach(item => { - loop(item, width) - }) - } else { - width += node.width - widthArr.push(width) - } - } - loop(node, 0) - return Math.max(...widthArr) - } - - // 调整兄弟节点的left - updateBrothersLeft(node, addWidth) { - if (node.parent) { - let childrenList = node.parent.children - let index = childrenList.findIndex(item => { - return item === node - }) - // 存在大于一个节点时,第一个或最后一个节点自身也需要移动,否则两边不对称 - if ( - (index === 0 || index === childrenList.length - 1) && - childrenList.length > 1 - ) { - let _offset = index === 0 ? -addWidth : addWidth - node.left += _offset - if ( - node.children && - node.children.length && - !node.hasCustomPosition() - ) { - this.updateChildren(node.children, 'left', _offset) - } - } - childrenList.forEach((item, _index) => { - if (item.hasCustomPosition()) { - // 适配自定义位置 - return - } - let _offset = 0 - if (_index < index) { - // 左边的节点往左移 - _offset = -addWidth - } else if (_index > index) { - // 右边的节点往右移 - _offset = addWidth - } - item.left += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'left', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothersLeft(node.parent, addWidth) - } - } - - // 调整兄弟节点的top - updateBrothersTop(node, addHeight) { - if (node.parent && !node.parent.isRoot) { - let childrenList = node.parent.children - let index = childrenList.findIndex(item => { - return item === node - }) - childrenList.forEach((item, _index) => { - if (item.hasCustomPosition()) { - // 适配自定义位置 - return - } - let _offset = 0 - // 下面的节点往下移 - if (_index > index) { - _offset = addHeight - } - item.top += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'top', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothersTop(node.parent, addHeight) - } - } - - // 绘制连线,连接该节点到其子节点 - renderLine(node, lines, style) { - if (node.children.length <= 0) { - return [] - } - let { left, top, width, height, expandBtnSize } = node - let len = node.children.length - let marginX = this.getMarginX(node.layerIndex + 1) - if (node.isRoot) { - // 根节点 - let x1 = left + width / 2 - let y1 = top + height - let s1 = marginX * 0.7 - let minx = Infinity - let maxx = -Infinity - node.children.forEach((item, index) => { - let x2 = item.left + item.width / 2 - let y2 = item.top - if (x2 < minx) { - minx = x2 - } - if (x2 > maxx) { - maxx = x2 - } - // 节点使用横线风格,需要额外渲染横线 - let nodeUseLineStylePath = this.mindMap.themeConfig.nodeUseLineStyle - ? ` L ${item.left},${y2} L ${item.left + item.width},${y2}` - : '' - let path = - `M ${x2},${y1 + s1} L ${x2},${y1 + s1 > y2 ? y2 + item.height : y2}` + - nodeUseLineStylePath - // 竖线 - lines[index].plot(path) - style && style(lines[index], item) - }) - minx = Math.min(minx, x1) - maxx = Math.max(maxx, x1) - // 父节点的竖线 - let line1 = this.draw.path() - node.style.line(line1) - line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`) - node._lines.push(line1) - style && style(line1, node) - // 水平线 - if (len > 0) { - let lin2 = this.draw.path() - node.style.line(lin2) - lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) - node._lines.push(lin2) - style && style(lin2, node) - } - } else { - // 非根节点 - let y1 = top + height - let maxy = -Infinity - let x2 = node.left + node.width * 0.3 - node.children.forEach((item, index) => { - // 为了适配自定义位置,下面做了各种位置的兼容 - let y2 = item.top + item.height / 2 - if (y2 > maxy) { - maxy = y2 - } - // 水平线 - let path = '' - let _left = item.left - let _isLeft = item.left + item.width < x2 - let _isXCenter = false - if (_isLeft) { - // 水平位置在父节点左边 - _left = item.left + item.width - } else if (item.left < x2 && item.left + item.width > x2) { - // 水平位置在父节点之间 - _isXCenter = true - y2 = item.top - maxy = y2 - } - if (y2 > top && y2 < y1) { - // 自定义位置的情况:垂直位置节点在父节点之间 - path = `M ${ - _isLeft ? node.left : node.left + node.width - },${y2} L ${_left},${y2}` - } else if (y2 < y1) { - // 自定义位置的情况:垂直位置节点在父节点上面 - if (_isXCenter) { - y2 = item.top + item.height - _left = x2 - } - path = `M ${x2},${top} L ${x2},${y2} L ${_left},${y2}` - } else { - if (_isXCenter) { - _left = x2 - } - path = `M ${x2},${y2} L ${_left},${y2}` - } - // 节点使用横线风格,需要额外渲染横线 - let nodeUseLineStylePath = this.mindMap.themeConfig.nodeUseLineStyle - ? ` L ${_left},${y2 - item.height / 2} L ${_left},${ - y2 + item.height / 2 - }` - : '' - path += nodeUseLineStylePath - lines[index].plot(path) - style && style(lines[index], item) - }) - // 竖线 - if (len > 0) { - let lin2 = this.draw.path() - expandBtnSize = len > 0 ? expandBtnSize : 0 - node.style.line(lin2) - if (maxy < y1 + expandBtnSize) { - lin2.hide() - } else { - lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`) - lin2.show() - } - node._lines.push(lin2) - style && style(lin2, node) - } - } - } - - // 渲染按钮 - renderExpandBtn(node, btn) { - let { width, height, expandBtnSize, isRoot } = node - if (!isRoot) { - let { translateX, translateY } = btn.transform() - btn.translate( - width * 0.3 - expandBtnSize / 2 - translateX, - height + expandBtnSize / 2 - translateY - ) - } - } - - // 创建概要节点 - 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 - } -} - -export default CatalogOrganization +import Base from './Base' +import { walk, asyncRun } from '../utils' + +// 目录组织图 +class CatalogOrganization extends Base { + // 构造函数 + constructor(opt = {}) { + super(opt) + } + + // 布局 + doLayout(callback) { + let task = [ + () => { + this.computedBaseValue() + }, + () => { + this.computedLeftTopValue() + }, + () => { + this.adjustLeftTopValue() + }, + () => { + callback(this.root) + } + ] + asyncRun(task) + } + + // 遍历数据计算节点的left、width、height + computedBaseValue() { + walk( + this.renderer.renderTree, + null, + (cur, parent, isRoot, layerIndex) => { + let newNode = this.createNode(cur, parent, isRoot, layerIndex) + // 根节点定位在画布中心位置 + if (isRoot) { + this.setNodeCenter(newNode) + } else { + // 非根节点 + if (parent._node.isRoot) { + newNode.top = + parent._node.top + + parent._node.height + + this.getMarginX(layerIndex) + } + } + if (!cur.data.expand) { + return true + } + }, + (cur, parent, isRoot, layerIndex) => { + if (isRoot) { + let len = cur.data.expand === false ? 0 : cur._node.children.length + cur._node.childrenAreaWidth = len + ? cur._node.children.reduce((h, item) => { + return h + item.width + }, 0) + + (len + 1) * this.getMarginX(layerIndex + 1) + : 0 + } + }, + true, + 0 + ) + } + + // 遍历节点树计算节点的left、top + computedLeftTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if ( + node.nodeData.data.expand && + node.children && + node.children.length + ) { + let marginX = this.getMarginX(layerIndex + 1) + let marginY = this.getMarginY(layerIndex + 1) + if (isRoot) { + let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 + let totalLeft = left + marginX + node.children.forEach(cur => { + cur.left = totalLeft + totalLeft += cur.width + marginX + }) + } else { + let totalTop = node.top + node.height + marginY + node.expandBtnSize + node.children.forEach(cur => { + cur.left = node.left + node.width * 0.5 + cur.top = totalTop + totalTop += cur.height + marginY + node.expandBtnSize + }) + } + } + }, + null, + true + ) + } + + // 调整节点left、top + adjustLeftTopValue() { + walk( + this.root, + null, + (node, parent, isRoot, layerIndex) => { + if (!node.nodeData.data.expand) { + return + } + // 调整left + if (parent && parent.isRoot) { + let areaWidth = this.getNodeAreaWidth(node) + let difference = areaWidth - node.width + if (difference > 0) { + this.updateBrothersLeft(node, difference / 2) + } + } + // 调整top + let len = node.children.length + if (parent && !parent.isRoot && len > 0) { + let marginY = this.getMarginY(layerIndex + 1) + let totalHeight = + node.children.reduce((h, item) => { + return h + item.height + }, 0) + + (len + 1) * marginY + + len * node.expandBtnSize + this.updateBrothersTop(node, totalHeight) + } + }, + null, + true + ) + } + + // 递归计算节点的宽度 + getNodeAreaWidth(node) { + let widthArr = [] + let loop = (node, width) => { + if (node.children.length) { + width += node.width / 2 + node.children.forEach(item => { + loop(item, width) + }) + } else { + width += node.width + widthArr.push(width) + } + } + loop(node, 0) + return Math.max(...widthArr) + } + + // 调整兄弟节点的left + updateBrothersLeft(node, addWidth) { + if (node.parent) { + let childrenList = node.parent.children + let index = childrenList.findIndex(item => { + return item === node + }) + // 存在大于一个节点时,第一个或最后一个节点自身也需要移动,否则两边不对称 + if ( + (index === 0 || index === childrenList.length - 1) && + childrenList.length > 1 + ) { + let _offset = index === 0 ? -addWidth : addWidth + node.left += _offset + if ( + node.children && + node.children.length && + !node.hasCustomPosition() + ) { + this.updateChildren(node.children, 'left', _offset) + } + } + childrenList.forEach((item, _index) => { + if (item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + if (_index < index) { + // 左边的节点往左移 + _offset = -addWidth + } else if (_index > index) { + // 右边的节点往右移 + _offset = addWidth + } + item.left += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'left', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothersLeft(node.parent, addWidth) + } + } + + // 调整兄弟节点的top + updateBrothersTop(node, addHeight) { + if (node.parent && !node.parent.isRoot) { + let childrenList = node.parent.children + let index = childrenList.findIndex(item => { + return item === node + }) + childrenList.forEach((item, _index) => { + if (item.hasCustomPosition()) { + // 适配自定义位置 + return + } + let _offset = 0 + // 下面的节点往下移 + if (_index > index) { + _offset = addHeight + } + item.top += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'top', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothersTop(node.parent, addHeight) + } + } + + // 绘制连线,连接该节点到其子节点 + renderLine(node, lines, style) { + if (node.children.length <= 0) { + return [] + } + let { left, top, width, height, expandBtnSize } = node + let len = node.children.length + let marginX = this.getMarginX(node.layerIndex + 1) + if (node.isRoot) { + // 根节点 + let x1 = left + width / 2 + let y1 = top + height + let s1 = marginX * 0.7 + let minx = Infinity + let maxx = -Infinity + node.children.forEach((item, index) => { + let x2 = item.left + item.width / 2 + let y2 = item.top + if (x2 < minx) { + minx = x2 + } + if (x2 > maxx) { + maxx = x2 + } + // 节点使用横线风格,需要额外渲染横线 + let nodeUseLineStylePath = this.mindMap.themeConfig.nodeUseLineStyle + ? ` L ${item.left},${y2} L ${item.left + item.width},${y2}` + : '' + let path = + `M ${x2},${y1 + s1} L ${x2},${y1 + s1 > y2 ? y2 + item.height : y2}` + + nodeUseLineStylePath + // 竖线 + lines[index].plot(path) + style && style(lines[index], item) + }) + minx = Math.min(minx, x1) + maxx = Math.max(maxx, x1) + // 父节点的竖线 + let line1 = this.draw.path() + node.style.line(line1) + line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`) + node._lines.push(line1) + style && style(line1, node) + // 水平线 + if (len > 0) { + let lin2 = this.draw.path() + node.style.line(lin2) + lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) + node._lines.push(lin2) + style && style(lin2, node) + } + } else { + // 非根节点 + let y1 = top + height + let maxy = -Infinity + let x2 = node.left + node.width * 0.3 + node.children.forEach((item, index) => { + // 为了适配自定义位置,下面做了各种位置的兼容 + let y2 = item.top + item.height / 2 + if (y2 > maxy) { + maxy = y2 + } + // 水平线 + let path = '' + let _left = item.left + let _isLeft = item.left + item.width < x2 + let _isXCenter = false + if (_isLeft) { + // 水平位置在父节点左边 + _left = item.left + item.width + } else if (item.left < x2 && item.left + item.width > x2) { + // 水平位置在父节点之间 + _isXCenter = true + y2 = item.top + maxy = y2 + } + if (y2 > top && y2 < y1) { + // 自定义位置的情况:垂直位置节点在父节点之间 + path = `M ${ + _isLeft ? node.left : node.left + node.width + },${y2} L ${_left},${y2}` + } else if (y2 < y1) { + // 自定义位置的情况:垂直位置节点在父节点上面 + if (_isXCenter) { + y2 = item.top + item.height + _left = x2 + } + path = `M ${x2},${top} L ${x2},${y2} L ${_left},${y2}` + } else { + if (_isXCenter) { + _left = x2 + } + path = `M ${x2},${y2} L ${_left},${y2}` + } + // 节点使用横线风格,需要额外渲染横线 + let nodeUseLineStylePath = this.mindMap.themeConfig.nodeUseLineStyle + ? ` L ${_left},${y2 - item.height / 2} L ${_left},${ + y2 + item.height / 2 + }` + : '' + path += nodeUseLineStylePath + lines[index].plot(path) + style && style(lines[index], item) + }) + // 竖线 + if (len > 0) { + let lin2 = this.draw.path() + expandBtnSize = len > 0 ? expandBtnSize : 0 + node.style.line(lin2) + if (maxy < y1 + expandBtnSize) { + lin2.hide() + } else { + lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`) + lin2.show() + } + node._lines.push(lin2) + style && style(lin2, node) + } + } + } + + // 渲染按钮 + renderExpandBtn(node, btn) { + let { width, height, expandBtnSize, isRoot } = node + if (!isRoot) { + let { translateX, translateY } = btn.transform() + btn.translate( + width * 0.3 - expandBtnSize / 2 - translateX, + height + expandBtnSize / 2 - translateY + ) + } + } + + // 创建概要节点 + 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 + } +} + +export default CatalogOrganization diff --git a/simple-mind-map/src/layouts/LogicalStructure.js b/simple-mind-map/src/layouts/LogicalStructure.js index 5b28fa0d..a9ed8ff2 100644 --- a/simple-mind-map/src/layouts/LogicalStructure.js +++ b/simple-mind-map/src/layouts/LogicalStructure.js @@ -2,16 +2,13 @@ import Base from './Base' import { walk, asyncRun } from '../utils' // 逻辑结构图 - class LogicalStructure extends Base { // 构造函数 - constructor(opt = {}) { super(opt) } // 布局 - doLayout(callback) { let task = [ () => { @@ -31,7 +28,6 @@ class LogicalStructure extends Base { } // 遍历数据计算节点的left、width、height - computedBaseValue() { walk( this.renderer.renderTree, @@ -67,7 +63,6 @@ class LogicalStructure extends Base { } // 遍历节点树计算节点的top - computedTopValue() { walk( this.root, @@ -94,7 +89,6 @@ class LogicalStructure extends Base { } // 调整节点top - adjustTopValue() { walk( this.root, @@ -118,7 +112,6 @@ class LogicalStructure extends Base { } // 更新兄弟节点的top - updateBrothers(node, addHeight) { if (node.parent) { let childrenList = node.parent.children @@ -150,7 +143,6 @@ class LogicalStructure extends Base { } // 绘制连线,连接该节点到其子节点 - renderLine(node, lines, style, lineStyle) { if (lineStyle === 'curve') { this.renderLineCurve(node, lines, style) @@ -162,7 +154,6 @@ class LogicalStructure extends Base { } // 直线风格连线 - renderLineStraight(node, lines, style) { if (node.children.length <= 0) { return [] @@ -192,7 +183,6 @@ class LogicalStructure extends Base { } // 直连风格 - renderLineDirect(node, lines, style) { if (node.children.length <= 0) { return [] @@ -218,7 +208,6 @@ class LogicalStructure extends Base { } // 曲线风格连线 - renderLineCurve(node, lines, style) { if (node.children.length <= 0) { return [] @@ -249,7 +238,6 @@ class LogicalStructure extends Base { } // 渲染按钮 - renderExpandBtn(node, btn) { let { width, height } = node let { translateX, translateY } = btn.transform() @@ -264,7 +252,6 @@ class LogicalStructure extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { let { top, diff --git a/simple-mind-map/src/layouts/MindMap.js b/simple-mind-map/src/layouts/MindMap.js index 87e6ced3..384c301a 100644 --- a/simple-mind-map/src/layouts/MindMap.js +++ b/simple-mind-map/src/layouts/MindMap.js @@ -2,7 +2,6 @@ import Base from './Base' import { walk, asyncRun } from '../utils' // 思维导图 - class MindMap extends Base { // 构造函数 // 在逻辑结构图的基础上增加一个变量来记录生长方向,向左还是向右,同时在计算left的时候根据方向来计算、调整top时只考虑同方向的节点即可 @@ -11,7 +10,6 @@ class MindMap extends Base { } // 布局 - doLayout(callback) { let task = [ () => { @@ -31,7 +29,6 @@ class MindMap extends Base { } // 遍历数据计算节点的left、width、height - computedBaseValue() { walk( this.renderer.renderTree, @@ -96,7 +93,6 @@ class MindMap extends Base { } // 遍历节点树计算节点的top - computedTopValue() { walk( this.root, @@ -129,7 +125,6 @@ class MindMap extends Base { } // 调整节点top - adjustTopValue() { walk( this.root, @@ -152,7 +147,6 @@ class MindMap extends Base { } // 更新兄弟节点的top - updateBrothers(node, leftAddHeight, rightAddHeight) { if (node.parent) { // 过滤出和自己同方向的节点 @@ -188,7 +182,6 @@ class MindMap extends Base { } // 绘制连线,连接该节点到其子节点 - renderLine(node, lines, style, lineStyle) { if (lineStyle === 'curve') { this.renderLineCurve(node, lines, style) @@ -200,7 +193,6 @@ class MindMap extends Base { } // 直线风格连线 - renderLineStraight(node, lines, style) { if (node.children.length <= 0) { return [] @@ -238,7 +230,6 @@ class MindMap extends Base { } // 直连风格 - renderLineDirect(node, lines, style) { if (node.children.length <= 0) { return [] @@ -273,7 +264,6 @@ class MindMap extends Base { } // 曲线风格连线 - renderLineCurve(node, lines, style) { if (node.children.length <= 0) { return [] @@ -313,7 +303,6 @@ class MindMap extends Base { } // 渲染按钮 - renderExpandBtn(node, btn) { let { width, height, expandBtnSize } = node let { translateX, translateY } = btn.transform() @@ -327,7 +316,6 @@ class MindMap extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { let isLeft = node.dir === 'left' let { diff --git a/simple-mind-map/src/layouts/OrganizationStructure.js b/simple-mind-map/src/layouts/OrganizationStructure.js index 4c2dc460..36a26a84 100644 --- a/simple-mind-map/src/layouts/OrganizationStructure.js +++ b/simple-mind-map/src/layouts/OrganizationStructure.js @@ -5,13 +5,11 @@ import { walk, asyncRun } from '../utils' // 和逻辑结构图基本一样,只是方向变成向下生长,所以先计算节点的top,后计算节点的left、最后调整节点的left即可 class OrganizationStructure extends Base { // 构造函数 - constructor(opt = {}) { super(opt) } // 布局 - doLayout(callback) { let task = [ () => { @@ -31,7 +29,6 @@ class OrganizationStructure extends Base { } // 遍历数据计算节点的left、width、height - computedBaseValue() { walk( this.renderer.renderTree, @@ -67,7 +64,6 @@ class OrganizationStructure extends Base { } // 遍历节点树计算节点的left - computedLeftValue() { walk( this.root, @@ -94,7 +90,6 @@ class OrganizationStructure extends Base { } // 调整节点left - adjustLeftValue() { walk( this.root, @@ -118,7 +113,6 @@ class OrganizationStructure extends Base { } // 更新兄弟节点的left - updateBrothers(node, addWidth) { if (node.parent) { let childrenList = node.parent.children @@ -150,7 +144,6 @@ class OrganizationStructure extends Base { } // 绘制连线,连接该节点到其子节点 - renderLine(node, lines, style, lineStyle) { if (lineStyle === 'direct') { this.renderLineDirect(node, lines, style) @@ -160,7 +153,6 @@ class OrganizationStructure extends Base { } // 直连风格 - renderLineDirect(node, lines, style) { if (node.children.length <= 0) { return [] @@ -182,7 +174,6 @@ class OrganizationStructure extends Base { } // 直线风格连线 - renderLineStraight(node, lines, style) { if (node.children.length <= 0) { return [] @@ -232,7 +223,6 @@ class OrganizationStructure extends Base { } // 渲染按钮 - renderExpandBtn(node, btn) { let { width, height, expandBtnSize } = node let { translateX, translateY } = btn.transform() @@ -243,7 +233,6 @@ class OrganizationStructure extends Base { } // 创建概要节点 - renderGeneralization(node, gLine, gNode) { let { bottom, From 1795773af943b4ed3cde36e0cdf419c976f01125 Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Tue, 28 Mar 2023 20:01:52 +0800 Subject: [PATCH 05/21] =?UTF-8?q?Break=20change=EF=BC=9A=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E6=BF=80=E6=B4=BB=E6=A0=B7=E5=BC=8F=E5=8F=AA=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=BD=A2=E7=8A=B6=E7=9B=B8=E5=85=B3=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/package.json | 2 +- simple-mind-map/src/Node.js | 14 +++++++++----- simple-mind-map/src/Render.js | 4 ++-- simple-mind-map/src/themes/default.js | 6 +----- web/src/pages/Doc/en/changelog/index.md | 14 ++++++++++++++ web/src/pages/Doc/en/changelog/index.vue | 10 ++++++++++ web/src/pages/Doc/en/node/index.md | 6 ++++++ web/src/pages/Doc/en/node/index.vue | 5 +++++ web/src/pages/Doc/zh/changelog/index.md | 14 ++++++++++++++ web/src/pages/Doc/zh/changelog/index.vue | 10 ++++++++++ web/src/pages/Doc/zh/node/index.md | 6 ++++++ web/src/pages/Doc/zh/node/index.vue | 5 +++++ 12 files changed, 83 insertions(+), 13 deletions(-) diff --git a/simple-mind-map/package.json b/simple-mind-map/package.json index ccc78cac..2b1ee325 100644 --- a/simple-mind-map/package.json +++ b/simple-mind-map/package.json @@ -1,6 +1,6 @@ { "name": "simple-mind-map", - "version": "0.4.7", + "version": "0.5.0", "description": "一个简单的web在线思维导图", "authors": [ { diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 52a4c8d5..d411e056 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -55,6 +55,7 @@ class Node { this.children = opt.children || [] // 节点内容的容器 this.group = null + this.shapeNode = null// 节点形状节点 // 节点内容对象 this._imgData = null this._iconData = null @@ -426,7 +427,6 @@ class Node { } // 创建超链接节点 - createHyperlinkNode() { let { hyperlink, hyperlinkTitle } = this.nodeData.data if (!hyperlink) { @@ -561,10 +561,8 @@ class Node { this.draw.add(this.group) this.update(true) // 节点形状 - const shape = this.getShape() - this.style[shape === 'rectangle' ? 'rect' : 'shape']( - this.shapeInstance.createShape() - ) + this.shapeNode = this.shapeInstance.createShape() + this.updateNodeShape() // 图片节点 let imgHeight = 0 if (this._imgData) { @@ -751,6 +749,12 @@ class Node { } } + // 更新节点形状样式 + updateNodeShape() { + const shape = this.getShape() + this.style[shape === 'rectangle' ? 'rect' : 'shape'](this.shapeNode) + } + // 递归渲染 render(callback = () => {}) { // 节点 diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index 85399d78..64df860a 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -305,7 +305,7 @@ class Render { node.nodeData.data.isActive = true this.addActiveNode(node) setTimeout(() => { - node.renderNode() + node.updateNodeShape() }, 0) } }, @@ -676,7 +676,7 @@ class Render { this.setNodeData(node, { isActive: active }) - node.renderNode() + node.updateNodeShape() } // 设置节点是否展开 diff --git a/simple-mind-map/src/themes/default.js b/simple-mind-map/src/themes/default.js index 3436b7fa..0f2ad5ad 100644 --- a/simple-mind-map/src/themes/default.js +++ b/simple-mind-map/src/themes/default.js @@ -142,14 +142,10 @@ export default { // 简单来说,会改变节点大小的都不支持在激活时设置,为了性能考虑,节点切换激活态时不会重新计算节点大小 export const supportActiveStyle = [ 'fillColor', - 'color', - 'fontWeight', - 'fontStyle', 'borderColor', 'borderWidth', 'borderDasharray', - 'borderRadius', - 'textDecoration' + 'borderRadius' ] export const lineStyleProps = ['lineColor', 'lineDasharray', 'lineWidth'] diff --git a/web/src/pages/Doc/en/changelog/index.md b/web/src/pages/Doc/en/changelog/index.md index 9a6b402e..dbd7989e 100644 --- a/web/src/pages/Doc/en/changelog/index.md +++ b/web/src/pages/Doc/en/changelog/index.md @@ -1,5 +1,19 @@ # Changelog +## 0.5.0 + +modify: Starting from version 0.5.0, considering performance issues, the node activation state can only modify shape related styles: + +```js +[ + 'fillColor', + 'borderColor', + 'borderWidth', + 'borderDasharray', + 'borderRadius' +] +``` + ## 0.4.7 optimization: 1.During rich text editing, when initially focusing, all are no longer selected by default; 2.When editing rich text, use the node fill color as the background color to avoid being invisible when the node color is white. 3.Node activation state switching no longer triggers history. 4.Triggering history multiple times in a short time will only add the last data. 5.Optimize the addition of historical records. When there is a rollback, delete the historical data after the current pointer when adding a new record again. diff --git a/web/src/pages/Doc/en/changelog/index.vue b/web/src/pages/Doc/en/changelog/index.vue index 46210955..314bf9c8 100644 --- a/web/src/pages/Doc/en/changelog/index.vue +++ b/web/src/pages/Doc/en/changelog/index.vue @@ -1,6 +1,16 @@