From db468770ce7f067d2dac48d1b4bdbd6081c9d306 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, 14 Jan 2025 18:34:49 +0800 Subject: [PATCH] =?UTF-8?q?Feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=BF=AB=E6=8D=B7=E5=88=9B=E5=BB=BA=E5=AD=90=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/constants/defaultOptions.js | 12 +++ .../src/core/render/node/MindMapNode.js | 40 ++++++++- .../core/render/node/QuickCreateChildBtn.js | 84 +++++++++++++++++++ .../src/core/render/node/nodeExpandBtn.js | 8 +- .../node/nodeExpandBtnPlaceholderRect.js | 8 +- .../core/render/node/nodeGeneralization.js | 2 +- simple-mind-map/src/svg/btns.js | 6 +- 7 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 simple-mind-map/src/core/render/node/QuickCreateChildBtn.js diff --git a/simple-mind-map/src/constants/defaultOptions.js b/simple-mind-map/src/constants/defaultOptions.js index 01aa0244..9b3d5d26 100644 --- a/simple-mind-map/src/constants/defaultOptions.js +++ b/simple-mind-map/src/constants/defaultOptions.js @@ -292,6 +292,18 @@ export const defaultOpt = { // color: '',// 图标颜色,不手动设置则会使用节点文本的颜色 } }, + // 是否显示快捷创建子节点按钮 + isShowCreateChildBtnIcon: true, + // 自定义快捷创建子节点按钮图标 + quickCreateChildBtnIcon: { + icon: '', // svg字符串,如果不是确定要使用svg自带的样式,否则请去除其中的fill等样式属性 + style: { + // 图标大小使用的是expandBtnSize选项 + // color: '',// 图标颜色,不手动设置则会使用expandBtnStyle选项的color字段 + } + }, + // 自定义快捷创建子节点按钮的点击操作, + customQuickCreateChildBtnClick: null, // 【Select插件】 // 多选节点时鼠标移动到边缘时的画布移动偏移量 diff --git a/simple-mind-map/src/core/render/node/MindMapNode.js b/simple-mind-map/src/core/render/node/MindMapNode.js index 3bd5d4a0..d2fa60fb 100644 --- a/simple-mind-map/src/core/render/node/MindMapNode.js +++ b/simple-mind-map/src/core/render/node/MindMapNode.js @@ -8,6 +8,7 @@ import nodeCreateContentsMethods from './nodeCreateContents' import nodeExpandBtnPlaceholderRectMethods from './nodeExpandBtnPlaceholderRect' import nodeModifyWidthMethods from './nodeModifyWidth' import nodeCooperateMethods from './nodeCooperate' +import QuickCreateChildBtnMethods from './QuickCreateChildBtn' import { CONSTANTS } from '../../../constants/constant' import { copyNodeTree, @@ -156,6 +157,13 @@ class MindMapNode { Object.keys(nodeModifyWidthMethods).forEach(item => { proto[item] = nodeModifyWidthMethods[item] }) + // 快捷创建子节点按钮 + if (this.mindMap.opt.isShowCreateChildBtnIcon) { + Object.keys(QuickCreateChildBtnMethods).forEach(item => { + proto[item] = QuickCreateChildBtnMethods[item] + }) + this.initQuickCreateChildBtn() + } proto.bindEvent = true } // 初始化 @@ -782,10 +790,11 @@ class MindMapNode { return } this.updateNodeActiveClass() - const { alwaysShowExpandBtn, notShowExpandBtn } = this.mindMap.opt + const { alwaysShowExpandBtn, notShowExpandBtn, isShowCreateChildBtnIcon } = + this.mindMap.opt + const childrenLength = this.getChildrenLength() // 不显示展开收起按钮则不需要处理 if (!notShowExpandBtn) { - const childrenLength = this.nodeData.children.length if (alwaysShowExpandBtn) { // 需要移除展开收缩按钮 if (this._expandBtn && childrenLength <= 0) { @@ -806,6 +815,19 @@ class MindMapNode { } } } + // 更新快速创建子节点按钮 + if (isShowCreateChildBtnIcon) { + if (childrenLength > 0) { + this.removeQuickCreateChildBtn() + } else { + const { isActive } = this.getData() + if (isActive) { + this.showQuickCreateChildBtn() + } else { + this.hideQuickCreateChildBtn() + } + } + } // 更新拖拽手柄的显示与否 this.updateDragHandle() // 更新概要 @@ -863,11 +885,18 @@ class MindMapNode { // 根据是否激活更新节点 updateNodeByActive(active) { if (this.group) { + const { isShowCreateChildBtnIcon } = this.mindMap.opt // 切换激活状态,需要切换展开收起按钮的显隐 if (active) { this.showExpandBtn() + if (isShowCreateChildBtnIcon) { + this.showQuickCreateChildBtn() + } } else { this.hideExpandBtn() + if (isShowCreateChildBtnIcon) { + this.hideQuickCreateChildBtn() + } } this.updateNodeActiveClass() this.updateDragHandle() @@ -1090,7 +1119,7 @@ class MindMapNode { if (this.getData('expand') === false) { return } - let childrenLen = this.nodeData.children.length + let childrenLen = this.getChildrenLength() // 切换为鱼骨结构时,清空根节点和二级节点的连线 if ( this.mindMap.opt.layout === CONSTANTS.LAYOUT.FISHBONE && @@ -1407,6 +1436,11 @@ class MindMapNode { this.customTextWidth !== undefined ) } + + // 获取子节点的数量 + getChildrenLength() { + return this.nodeData.children ? this.nodeData.children.length : 0 + } } export default MindMapNode diff --git a/simple-mind-map/src/core/render/node/QuickCreateChildBtn.js b/simple-mind-map/src/core/render/node/QuickCreateChildBtn.js new file mode 100644 index 00000000..ed21d346 --- /dev/null +++ b/simple-mind-map/src/core/render/node/QuickCreateChildBtn.js @@ -0,0 +1,84 @@ +import btnsSvg from '../../../svg/btns' +import { SVG, Circle, G } from '@svgdotjs/svg.js' + +function initQuickCreateChildBtn() { + this._quickCreateChildBtn = null + this._showQuickCreateChildBtn = false +} + +// 显示按钮 +function showQuickCreateChildBtn() { + if (this.getChildrenLength() > 0) return + // 创建按钮 + if (this._quickCreateChildBtn) { + this.group.add(this._quickCreateChildBtn) + } else { + const { quickCreateChildBtnIcon, expandBtnStyle } = this.mindMap.opt + const { icon, style } = quickCreateChildBtnIcon + let { color, fill } = expandBtnStyle || { + color: '#808080', + fill: '#fff' + } + color = style.color || color + // 图标节点 + const iconNode = SVG(icon || btnsSvg.quickCreateChild).size( + this.expandBtnSize, + this.expandBtnSize + ) + iconNode.css({ + cursor: 'pointer' + }) + iconNode.x(0).y(-this.expandBtnSize / 2) + this.style.iconNode(iconNode, color) + // 填充节点 + const fillNode = new Circle().size(this.expandBtnSize) + fillNode.x(0).y(-this.expandBtnSize / 2) + fillNode.fill({ color: fill }).css({ + cursor: 'pointer' + }) + // 容器节点 + this._quickCreateChildBtn = new G() + this._quickCreateChildBtn.add(fillNode).add(iconNode) + this._quickCreateChildBtn.on('click', e => { + e.stopPropagation() + this.mindMap.emit('quick_create_btn_click', this) + const { customQuickCreateChildBtnClick } = this.mindMap.opt + if (typeof customQuickCreateChildBtnClick === 'function') { + customQuickCreateChildBtnClick(this) + return + } + this.mindMap.execCommand('INSERT_CHILD_NODE', true, [this]) + }) + this._quickCreateChildBtn.on('dblclick', e => { + e.stopPropagation() + }) + this._quickCreateChildBtn.addClass('smm-quick-create-child-btn') + this.group.add(this._quickCreateChildBtn) + } + this._showQuickCreateChildBtn = true + // 更新按钮 + this.renderer.layout.renderExpandBtn(this, this._quickCreateChildBtn) +} + +// 移除按钮 +function removeQuickCreateChildBtn() { + if (this._quickCreateChildBtn && this._showQuickCreateChildBtn) { + this._quickCreateChildBtn.remove() + this._showQuickCreateChildBtn = false + } +} + +// 隐藏按钮 +function hideQuickCreateChildBtn() { + const { isActive } = this.getData() + if (!isActive) { + this.removeQuickCreateChildBtn() + } +} + +export default { + initQuickCreateChildBtn, + showQuickCreateChildBtn, + removeQuickCreateChildBtn, + hideQuickCreateChildBtn +} diff --git a/simple-mind-map/src/core/render/node/nodeExpandBtn.js b/simple-mind-map/src/core/render/node/nodeExpandBtn.js index 65f540d4..7d6aa380 100644 --- a/simple-mind-map/src/core/render/node/nodeExpandBtn.js +++ b/simple-mind-map/src/core/render/node/nodeExpandBtn.js @@ -79,7 +79,7 @@ function updateExpandBtnNode() { color: expandBtnStyle.strokeColor }) // 计算子节点数量 - let count = this.sumNode(this.nodeData.children) + let count = this.sumNode(this.nodeData.children || []) if (typeof expandBtnNumHandler === 'function') { const res = expandBtnNumHandler(count, this) if (!isUndef(res)) { @@ -105,11 +105,7 @@ function updateExpandBtnPos() { // 创建展开收缩按钮 function renderExpandBtn() { - if ( - !this.nodeData.children || - this.nodeData.children.length <= 0 || - this.isRoot - ) { + if (this.getChildrenLength() <= 0 || this.isRoot) { return } if (this._expandBtn) { diff --git a/simple-mind-map/src/core/render/node/nodeExpandBtnPlaceholderRect.js b/simple-mind-map/src/core/render/node/nodeExpandBtnPlaceholderRect.js index da6410a5..7a11e55f 100644 --- a/simple-mind-map/src/core/render/node/nodeExpandBtnPlaceholderRect.js +++ b/simple-mind-map/src/core/render/node/nodeExpandBtnPlaceholderRect.js @@ -3,11 +3,7 @@ import { Rect } from '@svgdotjs/svg.js' // 渲染展开收起按钮的隐藏占位元素 function renderExpandBtnPlaceholderRect() { // 根节点或没有子节点不需要渲染 - if ( - !this.nodeData.children || - this.nodeData.children.length <= 0 || - this.isRoot - ) { + if (this.getChildrenLength() <= 0 || this.isRoot) { return } // 默认显示展开按钮的情况下或不显示展开收起按钮的情况下不需要渲染 @@ -48,7 +44,7 @@ function updateExpandBtnPlaceholderRect() { this.renderExpandBtnPlaceholderRect() } // 没有子节点到有子节点需要渲染 - if (this.nodeData.children && this.nodeData.children.length > 0) { + if (this.getChildrenLength() > 0) { if (!this._unVisibleRectRegionNode) { this.renderExpandBtnPlaceholderRect() } diff --git a/simple-mind-map/src/core/render/node/nodeGeneralization.js b/simple-mind-map/src/core/render/node/nodeGeneralization.js index 3bc735d5..f1f27410 100644 --- a/simple-mind-map/src/core/render/node/nodeGeneralization.js +++ b/simple-mind-map/src/core/render/node/nodeGeneralization.js @@ -106,7 +106,7 @@ function renderGeneralization(forceRender) { // 更新节点概要数据 function updateGeneralizationData() { - const childrenLength = this.nodeData.children.length + const childrenLength = this.getChildrenLength() const list = this.formatGetGeneralization() const newList = [] list.forEach(item => { diff --git a/simple-mind-map/src/svg/btns.js b/simple-mind-map/src/svg/btns.js index a4b67ed0..25e06904 100644 --- a/simple-mind-map/src/svg/btns.js +++ b/simple-mind-map/src/svg/btns.js @@ -10,9 +10,13 @@ const remove = `` +// 快捷创建子节点按钮 +const quickCreateChild = `` + export default { open, close, remove, - imgAdjust + imgAdjust, + quickCreateChild }