From e36a4082750a42cd7542008a2d9041028b389058 Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Wed, 19 Apr 2023 15:45:51 +0800 Subject: [PATCH 01/12] =?UTF-8?q?Fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E5=BF=AB?= =?UTF-8?q?=E9=80=9F=E5=A4=9A=E6=AC=A1=E6=B8=B2=E6=9F=93=E6=97=B6=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E4=BD=8D=E7=BD=AE=E9=94=99=E4=B9=B1=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/index.js | 4 ++-- simple-mind-map/src/Render.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index fb5f002c..ec5aa9be 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -183,11 +183,11 @@ class MindMap { // 渲染,部分渲染 render(callback, source = '') { - this.batchExecution.push('render', () => { + // this.batchExecution.push('render', () => { this.initTheme() this.renderer.reRender = false this.renderer.render(callback, source) - }) + // }) } // 重新渲染 diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index aac78ecd..74eb4f53 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -251,6 +251,7 @@ class Render { // 渲染 render(callback = () => {}, source) { // 如果当前还没有渲染完毕,不再触发渲染 + console.log('this.isRendering', this.isRendering); if (this.isRendering) { // 等待当前渲染完毕后再进行一次渲染 this.hasWaitRendering = true From 6eacfab9c27831f1bbac700fc92034dc319667ef Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Wed, 19 Apr 2023 16:07:52 +0800 Subject: [PATCH 02/12] =?UTF-8?q?Demo=EF=BC=9A=E6=94=AF=E6=8C=81=E5=8F=B3?= =?UTF-8?q?=E9=94=AE=E5=88=A0=E9=99=A4=E6=A6=82=E8=A6=81=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/index.js | 4 ++-- simple-mind-map/src/Node.js | 2 +- simple-mind-map/src/Render.js | 1 - web/src/pages/Edit/components/Contextmenu.vue | 15 +++++++++------ web/src/pages/Edit/components/Edit.vue | 3 ++- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index ec5aa9be..fb5f002c 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -183,11 +183,11 @@ class MindMap { // 渲染,部分渲染 render(callback, source = '') { - // this.batchExecution.push('render', () => { + this.batchExecution.push('render', () => { this.initTheme() this.renderer.reRender = false this.renderer.render(callback, source) - // }) + }) } // 重新渲染 diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 528f1635..3a787edc 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -389,7 +389,7 @@ class Node { // 右键菜单事件 this.group.on('contextmenu', e => { // 按住ctrl键点击鼠标左键不知为何触发的是contextmenu事件 - if (this.mindMap.opt.readonly || this.isGeneralization || e.ctrlKey) { + if (this.mindMap.opt.readonly || e.ctrlKey) {// || this.isGeneralization return } e.stopPropagation() diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index 74eb4f53..aac78ecd 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -251,7 +251,6 @@ class Render { // 渲染 render(callback = () => {}, source) { // 如果当前还没有渲染完毕,不再触发渲染 - console.log('this.isRendering', this.isRendering); if (this.isRendering) { // 等待当前渲染完毕后再进行一次渲染 this.hasWaitRendering = true diff --git a/web/src/pages/Edit/components/Contextmenu.vue b/web/src/pages/Edit/components/Contextmenu.vue index efc16f47..552fb0d9 100644 --- a/web/src/pages/Edit/components/Contextmenu.vue +++ b/web/src/pages/Edit/components/Contextmenu.vue @@ -13,7 +13,7 @@ {{ $t('contextmenu.insertSiblingNode') }} Enter -
${text}
` - this.textEditNode.innerHTML = html + this.textEditNode.innerHTML = this.cacheEditingText || html } else { - this.textEditNode.innerHTML = node.nodeData.data.text + this.textEditNode.innerHTML = this.cacheEditingText || node.nodeData.data.text } this.initQuillEditor() document.querySelector('.ql-editor').style.minHeight = originHeight + 'px' @@ -172,6 +173,7 @@ class RichText { // 如果是非富文本的情况,需要手动应用文本样式 this.setTextStyleIfNotRichText(node) } + this.cacheEditingText = '' } // 如果是非富文本的情况,需要手动应用文本样式 @@ -188,14 +190,19 @@ class RichText { this.formatAllText(style) } + // 获取当前正在编辑的内容 + getEditText() { + let html = this.quill.container.firstChild.innerHTML + // 去除最后的空行 + return html.replace(/
<\/p>$/, '')
+ }
+
// 隐藏文本编辑控件,即完成编辑
hideEditText(nodes) {
if (!this.showTextEdit) {
return
}
- let html = this.quill.container.firstChild.innerHTML
- // 去除最后的空行
- html = html.replace(/
Fix: 1.Fix the issue of node position disorder during fast and multiple renderings in a short period of time. 2.Fix the issue of dragging the canvas while the node is being edited, causing the edit box and node to separate. New: 1.Add a maximum history limit. Fix: 1.Fix the issue where the edit box is also outside the canvas when editing nodes outside the canvas. 2.After modifying the structure, reset the transformation to prevent the problem of sudden position changes during the first drag after switching the structure during scaling. optimization: 1.When multiple nodes are selected, as long as there is a cross between the node and the selection area, it is considered selected. Fix: 1.Fix mini map error. New: 1.Supports configuring the padding when exporting to PNG, SVG, or PDF. 2.Support the configuration of z-index for node text editing boxes and node comment floating layer elements. 3.Support clicking on areas outside the canvas to end node editing status. 修复:1.修复短时间快速多次渲染时节点位置错乱的问题。 2.修复节点正在编辑中时拖动画布导致编辑框和节点分离的问题。 新增:1.添加最大历史记录数限制。 新增:1.支持配置导出为png、svg、pdf时的内边距。 2.支持配置节点文本编辑框、节点备注浮层元素的z-index。 3.支持点击画布外的区域结束节点编辑状态。 修复:1.修复节点在画布外编辑时编辑框也在画布外的问题。 2.修改结构后复位变换,防止存在缩放时切换结构后第一次拖动时会发生位置突变的问题。 优化:1.节点多选时只要节点和选区存在交叉即认为被选中。 修复:1.修复小地图报错。 新增:1.添加新主题。 2.新增时间轴和鱼骨结构。 修复:1.修复节点右键和画布右键的冲突问题。 2.修复组织结构图、目录组织图等节点拖拽时存在线段未隐藏的bug。 Parsing the Parsing the Convert 可以在实例化 要支持节点富文本编辑需要使用富文本插件 如果开启了节点富文本编辑,那么可以对节点内的部分文本应用样式,一般当选中文本时上方会出现一个工具栏,有加粗、斜体、改变颜色等等的按钮。 首先要监听 可以通过 计算出来的是相对于浏览器窗口左上角的位置,所以你的工具栏元素最好是添加在body元素下面,并且使用固定定位或相对定位,另外 编写中。。。 要使用导出功能需要使用导出插件。 目前支持导出为 导出直接调用 这两种文件的导出是一样的: 如果传 示例: 导出这两种文件很简单: 如果开启了节点富文本编辑,那么导出会非常慢,因为需要挨个转换节点,所以如果导出操作很频繁的话建议关闭节点非文本编辑功能。 导出为 如果开启了节点富文本编辑功能,那么可以通过 如果 导出为 目前支持从 这两个文件导入很简单,直接读取文件内容,转成对象,然后调用相关方法渲染到画布即可。 因为导出这两种类型时可以选择是否包含配置数据,所以导入的时候调用的方法也是不一样的: 要导入 如果使用的是 如果你是通过 另外如果导入的是 这个文件的导入没有内置方法,需要你自己开发,以下是一个使用 要导入 如果使用的是umd格式的文件,那么可以通过如下方式获取: 获取到 编写中。。。 在线 保存数据,一般有两种做法,一是让用户手动保存,二是当画布上的数据改变后自动保存,显然,第二中体验更好一点。 要获取画布的数据,可以使用 包含配置的完整数据结构: 你可以直接把获取到的数据保存起来即可。 如果要自动保存,那么肯定需要监听相关事件: 主题和结构的改变一般是开发者提供一个ui界面让用户选择,所以可以自行触发保存。 当从数据库获取到了保存的数据,那么怎么渲染到画布上呢,首先可以直接在 其次如果是包含配置的完整数据也可以调用 如果是纯节点数据可以调用 修改结构可以调用 设置主题可以调用 设置主题配置可以调用 设置视图数据可以调用 解析 解析 转换 转换
<\/p>$/, '')
+ let html = this.getEditText()
let list = nodes && nodes.length > 0 ? nodes : this.mindMap.renderer.activeNodeList
list.forEach(node => {
this.mindMap.execCommand('SET_NODE_TEXT', node, html, true)
diff --git a/simple-mind-map/src/TextEdit.js b/simple-mind-map/src/TextEdit.js
index b371f658..adb2c9de 100644
--- a/simple-mind-map/src/TextEdit.js
+++ b/simple-mind-map/src/TextEdit.js
@@ -6,16 +6,21 @@ export default class TextEdit {
constructor(renderer) {
this.renderer = renderer
this.mindMap = renderer.mindMap
+ // 当前编辑的节点
+ this.currentNode = null
// 文本编辑框
this.textEditNode = null
// 文本编辑框是否显示
this.showTextEdit = false
+ // 如果编辑过程中缩放画布了,那么缓存当前编辑的内容
+ this.cacheEditingText = ''
this.bindEvent()
}
// 事件
bindEvent() {
this.show = this.show.bind(this)
+ this.onScale = this.onScale.bind(this)
// 节点双击事件
this.mindMap.on('node_dblclick', this.show)
// 点击事件
@@ -48,6 +53,7 @@ export default class TextEdit {
}
this.show(this.renderer.activeNodeList[0])
})
+ this.mindMap.on('scale', this.onScale)
}
// 注册临时快捷键
@@ -60,6 +66,7 @@ export default class TextEdit {
// 显示文本编辑框
show(node) {
+ this.currentNode = node
let { offsetLeft, offsetTop } = checkNodeOuter(this.mindMap, node)
this.mindMap.view.translateXY(offsetLeft, offsetTop)
let rect = node._textData.node.node.getBoundingClientRect()
@@ -70,6 +77,19 @@ export default class TextEdit {
this.showEditTextBox(node, rect)
}
+ // 处理画布缩放
+ onScale() {
+ if (!this.currentNode) return
+ if (this.mindMap.richText) {
+ this.mindMap.richText.cacheEditingText = this.mindMap.richText.getEditText()
+ this.mindMap.richText.showTextEdit = false
+ } else {
+ this.cacheEditingText = this.getEditText()
+ this.showTextEdit = false
+ }
+ this.show(this.currentNode)
+ }
+
// 显示文本编辑框
showEditTextBox(node, rect) {
this.mindMap.emit('before_show_text_edit')
@@ -89,7 +109,7 @@ export default class TextEdit {
let scale = this.mindMap.view.scale
let lineHeight = node.style.merge('lineHeight')
let fontSize = node.style.merge('fontSize')
- let textLines = node.nodeData.data.text.split(/\n/gim)
+ let textLines = (this.cacheEditingText || node.nodeData.data.text).split(/\n/gim)
node.style.domText(this.textEditNode, scale, textLines.length)
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
this.textEditNode.innerHTML = textLines.join('
')
@@ -104,7 +124,10 @@ export default class TextEdit {
}
this.showTextEdit = true
// 选中文本
- this.selectNodeText()
+ if (!this.cacheEditingText) {
+ this.selectNodeText()
+ }
+ this.cacheEditingText = ''
}
// 选中文本
@@ -116,8 +139,14 @@ export default class TextEdit {
selection.addRange(range)
}
+ // 获取当前正在编辑的内容
+ getEditText() {
+ return getStrWithBrFromHtml(this.textEditNode.innerHTML)
+ }
+
// 隐藏文本编辑框
hideEditTextBox() {
+ this.currentNode = null
if (this.mindMap.richText) {
return this.mindMap.richText.hideEditText()
}
@@ -125,7 +154,7 @@ export default class TextEdit {
return
}
this.renderer.activeNodeList.forEach(node => {
- let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
+ let str = this.getEditText()
this.mindMap.execCommand('SET_NODE_TEXT', node, str)
if (node.isGeneralization) {
// 概要节点
From 077478d654cefe7b5044b5e85efa551d5e7262c2 Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Thu, 20 Apr 2023 16:10:25 +0800
Subject: [PATCH 06/12] =?UTF-8?q?Feature=EF=BC=9A=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E6=9C=80=E5=A4=A7=E5=8E=86=E5=8F=B2=E8=AE=B0=E5=BD=95=E6=95=B0?=
=?UTF-8?q?=E9=99=90=E5=88=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
simple-mind-map/index.js | 4 +++-
simple-mind-map/src/Command.js | 4 ++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js
index fb5f002c..da5beaaa 100644
--- a/simple-mind-map/index.js
+++ b/simple-mind-map/index.js
@@ -101,7 +101,9 @@ const defaultOpt = {
// 节点备注浮层的z-index
nodeNoteTooltipZIndex: 3000,
// 是否在点击了画布外的区域时结束节点文本的编辑状态
- isEndNodeTextEditOnClickOuter: true
+ isEndNodeTextEditOnClickOuter: true,
+ // 最大历史记录数
+ maxHistoryCount: 1000
}
// 思维导图
diff --git a/simple-mind-map/src/Command.js b/simple-mind-map/src/Command.js
index 7b49ef0d..b1c35c57 100644
--- a/simple-mind-map/src/Command.js
+++ b/simple-mind-map/src/Command.js
@@ -84,6 +84,10 @@ class Command {
// 删除当前历史指针后面的数据
this.history = this.history.slice(0, this.activeHistoryIndex + 1)
this.history.push(simpleDeepClone(data))
+ // 历史记录数超过最大数量
+ if (this.history.length > this.mindMap.opt.maxHistoryCount) {
+ this.history.shift()
+ }
this.activeHistoryIndex = this.history.length - 1
this.mindMap.emit('data_change', this.removeDataUid(data))
this.mindMap.emit(
From b91dde8084407ab2b6e8567648572308f879a762 Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Thu, 20 Apr 2023 16:31:28 +0800
Subject: [PATCH 07/12] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
simple-mind-map/package.json | 2 +-
web/src/pages/Doc/en/changelog/index.md | 10 ++++++++++
web/src/pages/Doc/en/changelog/index.vue | 5 +++++
web/src/pages/Doc/en/constructor/index.md | 1 +
web/src/pages/Doc/en/constructor/index.vue | 7 +++++++
web/src/pages/Doc/zh/changelog/index.md | 10 ++++++++++
web/src/pages/Doc/zh/changelog/index.vue | 5 +++++
web/src/pages/Doc/zh/constructor/index.md | 1 +
web/src/pages/Doc/zh/constructor/index.vue | 7 +++++++
9 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/simple-mind-map/package.json b/simple-mind-map/package.json
index fab46370..d37349b2 100644
--- a/simple-mind-map/package.json
+++ b/simple-mind-map/package.json
@@ -1,6 +1,6 @@
{
"name": "simple-mind-map",
- "version": "0.5.5-fix.2",
+ "version": "0.5.6",
"description": "一个简单的web在线思维导图",
"authors": [
{
diff --git a/web/src/pages/Doc/en/changelog/index.md b/web/src/pages/Doc/en/changelog/index.md
index f4f6088a..15b6fa44 100644
--- a/web/src/pages/Doc/en/changelog/index.md
+++ b/web/src/pages/Doc/en/changelog/index.md
@@ -1,11 +1,21 @@
# Changelog
+## 0.5.6
+
+Fix: 1.Fix the issue of node position disorder during fast and multiple renderings in a short period of time. 2.Fix the issue of dragging the canvas while the node is being edited, causing the edit box and node to separate.
+
+New: 1.Add a maximum history limit.
+
## 0.5.5-fix.1
Fix: 1.Fix the issue where the edit box is also outside the canvas when editing nodes outside the canvas. 2.After modifying the structure, reset the transformation to prevent the problem of sudden position changes during the first drag after switching the structure during scaling.
optimization: 1.When multiple nodes are selected, as long as there is a cross between the node and the selection area, it is considered selected.
+## 0.5.5-fix.2
+
+Fix: 1.Fix mini map error.
+
## 0.5.5
New: 1.Supports configuring the padding when exporting to PNG, SVG, or PDF. 2.Support the configuration of z-index for node text editing boxes and node comment floating layer elements. 3.Support clicking on areas outside the canvas to end node editing status.
diff --git a/web/src/pages/Doc/en/changelog/index.vue b/web/src/pages/Doc/en/changelog/index.vue
index c7e18164..8fc39958 100644
--- a/web/src/pages/Doc/en/changelog/index.vue
+++ b/web/src/pages/Doc/en/changelog/index.vue
@@ -1,9 +1,14 @@
Changelog
+0.5.6
+0.5.5-fix.1
0.5.5-fix.2
+0.5.5
0.5.4
diff --git a/web/src/pages/Doc/en/constructor/index.md b/web/src/pages/Doc/en/constructor/index.md
index 96694a32..3a3ea03e 100644
--- a/web/src/pages/Doc/en/constructor/index.md
+++ b/web/src/pages/Doc/en/constructor/index.md
@@ -58,6 +58,7 @@ const mindMap = new MindMap({
| nodeTextEditZIndex(v0.5.5+) | Number | 3000 | | z-index of node text edit box elements |
| nodeNoteTooltipZIndex(v0.5.5+) | Number | 3000 | z-index of floating layer elements in node comments | |
| isEndNodeTextEditOnClickOuter(v0.5.5+) | Boolean | true | Whether to end the editing status of node text when clicking on an area outside the canvas | |
+| maxHistoryCount(v0.5.6+) | Number | 1000 | | Maximum number of history records |
### Watermark config
diff --git a/web/src/pages/Doc/en/constructor/index.vue b/web/src/pages/Doc/en/constructor/index.vue
index 7d2b1a02..c5bfb63f 100644
--- a/web/src/pages/Doc/en/constructor/index.vue
+++ b/web/src/pages/Doc/en/constructor/index.vue
@@ -266,6 +266,13 @@
Whether to end the editing status of node text when clicking on an area outside the canvas
+
+
maxHistoryCount(v0.5.6+)
+Number
+1000
+
+ Maximum number of history records
+Watermark config
diff --git a/web/src/pages/Doc/zh/changelog/index.md b/web/src/pages/Doc/zh/changelog/index.md
index 5084cfad..f3273f66 100644
--- a/web/src/pages/Doc/zh/changelog/index.md
+++ b/web/src/pages/Doc/zh/changelog/index.md
@@ -1,5 +1,11 @@
# Changelog
+## 0.5.6
+
+修复:1.修复短时间快速多次渲染时节点位置错乱的问题。 2.修复节点正在编辑中时拖动画布导致编辑框和节点分离的问题。
+
+新增:1.添加最大历史记录数限制。
+
## 0.5.5
新增:1.支持配置导出为png、svg、pdf时的内边距。 2.支持配置节点文本编辑框、节点备注浮层元素的z-index。 3.支持点击画布外的区域结束节点编辑状态。
@@ -10,6 +16,10 @@
优化:1.节点多选时只要节点和选区存在交叉即认为被选中。
+## 0.5.5-fix.2
+
+修复:1.修复小地图报错。
+
## 0.5.4
新增:1.添加新主题。 2.新增时间轴和鱼骨结构。
diff --git a/web/src/pages/Doc/zh/changelog/index.vue b/web/src/pages/Doc/zh/changelog/index.vue
index 25fb3698..65d5ad30 100644
--- a/web/src/pages/Doc/zh/changelog/index.vue
+++ b/web/src/pages/Doc/zh/changelog/index.vue
@@ -1,11 +1,16 @@
Changelog
+0.5.6
+0.5.5
0.5.5-fix.1
0.5.5-fix.2
+0.5.4
是否在点击了画布外的区域时结束节点文本的编辑状态
+
+
maxHistoryCount(v0.5.6+)
+Number
+1000
+最大历史记录数
+
+ 水印配置
From e584081b417c1bcfe3ee773e0dd9a9fb9dd32560 Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Fri, 21 Apr 2023 09:32:36 +0800
Subject: [PATCH 08/12] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/pages/Doc/en/xmind/index.md | 10 +-
web/src/pages/Doc/en/xmind/index.vue | 10 +-
web/src/pages/Doc/zh/course11/index.md | 2 +-
web/src/pages/Doc/zh/course11/index.vue | 2 +-
web/src/pages/Doc/zh/course16/index.md | 100 +++++++++-
web/src/pages/Doc/zh/course16/index.vue | 61 +++++-
web/src/pages/Doc/zh/course17/index.md | 244 ++++++++++++++++++++++-
web/src/pages/Doc/zh/course17/index.vue | 176 +++++++++++++++-
web/src/pages/Doc/zh/course18/index.md | 101 +++++++++-
web/src/pages/Doc/zh/course18/index.vue | 65 +++++-
web/src/pages/Doc/zh/xmind/index.md | 4 +-
web/src/pages/Doc/zh/xmind/index.vue | 4 +-
web/src/pages/Edit/components/Import.vue | 1 +
13 files changed, 755 insertions(+), 25 deletions(-)
diff --git a/web/src/pages/Doc/en/xmind/index.md b/web/src/pages/Doc/en/xmind/index.md
index e4d9274e..b26a54a7 100644
--- a/web/src/pages/Doc/en/xmind/index.md
+++ b/web/src/pages/Doc/en/xmind/index.md
@@ -24,9 +24,8 @@ MindMap.xmind
### xmind.parseXmindFile(file)
-Parsing the `.xmind` file and returning the parsed data. Note that this is
-complete data, including the node tree, theme, and structure. You can use
-`mindMap.setFullData(data)` to render the returned data to the canvas.
+Parsing the `.xmind` file and returning the parsed data. You can use
+`mindMap.setData(data)` to render the returned data to the canvas.
`file`: `File` object
@@ -35,9 +34,8 @@ complete data, including the node tree, theme, and structure. You can use
Convert `xmind` data. The `.xmind` file is essentially a `zip` file that can be
decompressed by changing the suffix to zip. Inside, there is a `content.json`
file. If you have parsed this file yourself, you can pass the contents of this
-file to this method for conversion. The converted data is the complete data,
-including the node tree, theme, structure, etc. You can use
-`mindMap.setFullData(data)` to render the returned data to the canvas.
+file to this method for conversion. You can use
+`mindMap.setData(data)` to render the returned data to the canvas.
`content`: the contents of the `content.json` file within the `.xmind` zip
package
diff --git a/web/src/pages/Doc/en/xmind/index.vue b/web/src/pages/Doc/en/xmind/index.vue
index a2c3af24..323a9990 100644
--- a/web/src/pages/Doc/en/xmind/index.vue
+++ b/web/src/pages/Doc/en/xmind/index.vue
@@ -15,17 +15,15 @@
Methods
xmind.parseXmindFile(file)
-.xmind file and returning the parsed data. Note that this is
-complete data, including the node tree, theme, and structure. You can use
-mindMap.setFullData(data) to render the returned data to the canvas..xmind file and returning the parsed data. You can use
+mindMap.setData(data) to render the returned data to the canvas.file: File objectxmind.transformXmind(content)
xmind data. The .xmind file is essentially a zip file that can be
decompressed by changing the suffix to zip. Inside, there is a content.json
file. If you have parsed this file yourself, you can pass the contents of this
-file to this method for conversion. The converted data is the complete data,
-including the node tree, theme, structure, etc. You can use
-mindMap.setFullData(data) to render the returned data to the canvas.mindMap.setData(data) to render the returned data to the canvas.
content: the contents of the content.json file within the .xmind zip
packagexmind.transformOldXmind(content)
diff --git a/web/src/pages/Doc/zh/course11/index.md b/web/src/pages/Doc/zh/course11/index.md
index bc705990..462f19de 100644
--- a/web/src/pages/Doc/zh/course11/index.md
+++ b/web/src/pages/Doc/zh/course11/index.md
@@ -1,6 +1,6 @@
# 结构
-`simple-mind-map`目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)。
+`simple-mind-map`目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)。
可以在实例化`simple-mind-map`时通过选项指定使用的结构:
diff --git a/web/src/pages/Doc/zh/course11/index.vue b/web/src/pages/Doc/zh/course11/index.vue
index 6319e743..94b1db73 100644
--- a/web/src/pages/Doc/zh/course11/index.vue
+++ b/web/src/pages/Doc/zh/course11/index.vue
@@ -1,7 +1,7 @@
结构
-simple-mind-map目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)。simple-mind-map目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)。simple-mind-map时通过选项指定使用的结构:new MindMap({
// ...
diff --git a/web/src/pages/Doc/zh/course16/index.md b/web/src/pages/Doc/zh/course16/index.md
index 6354013c..26d07840 100644
--- a/web/src/pages/Doc/zh/course16/index.md
+++ b/web/src/pages/Doc/zh/course16/index.md
@@ -1,3 +1,101 @@
# 如何渲染富文本的悬浮工具栏
-> 要支持节点富文本编辑需要使用富文本插件
\ No newline at end of file
+> 要支持节点富文本编辑需要使用富文本插件
+
+如果开启了节点富文本编辑,那么可以对节点内的部分文本应用样式,一般当选中文本时上方会出现一个工具栏,有加粗、斜体、改变颜色等等的按钮。
+
+首先要监听`rich_text_selection_change`事件,也就是选中文本的事件:
+
+```js
+mindMap.on('rich_text_selection_change', (hasRange, rect, formatInfo) => {
+ // hasRange(是否存在选区)
+ // rectInfo(选区的尺寸和位置信息)
+ // formatInfo(选区的文本格式化信息)
+ // 显示你的工具栏
+})
+```
+
+可以通过`hasRange`来判断是否显示工具栏,工具栏的位置可以通过`rectInfo`获取,通过`formatInfo`可以获取当前选中文本的样式信息,比如已经被加粗了,那么你的加粗按钮就可以渲染为激活状态。
+
+### 工具栏定位
+
+```js
+let left = rect.left + rect.width / 2 + 'px'
+let top = rect.top - 60 + 'px'
+```
+
+计算出来的是相对于浏览器窗口左上角的位置,所以你的工具栏元素最好是添加在body元素下面,并且使用固定定位或相对定位,另外`z-index`的属性最好也设置的高一点,否则在弹窗等场景下可能会被挡住。
+
+### 加粗/取消加粗
+
+```js
+mindMap.richText.formatText({
+ bold: true/false
+})
+```
+
+### 斜体/取消斜体
+
+```js
+mindMap.richText.formatText({
+ italic: true/false
+})
+```
+
+### 下划线/取消下划线
+
+```js
+mindMap.richText.formatText({
+ underline: true/false
+})
+```
+
+### 删除线/取消删除线
+
+```js
+mindMap.richText.formatText({
+ strike: true/false
+})
+```
+
+### 设置字体
+
+```js
+mindMap.richText.formatText({
+ font: '宋体, SimSun, Songti SC'
+})
+```
+
+### 设置字号
+
+```js
+mindMap.richText.formatText({
+ font: 16 + 'px'
+})
+```
+
+### 设置文字颜色
+
+```js
+mindMap.richText.formatText({
+ color: '#fff'
+})
+```
+
+### 设置文字背景颜色
+
+```js
+mindMap.richText.formatText({
+ background: '#fff'
+})
+```
+
+### 清除样式
+
+```js
+mindMap.richText.removeFormat()
+```
+
+## 完整示例
+
+
\ No newline at end of file
diff --git a/web/src/pages/Doc/zh/course16/index.vue b/web/src/pages/Doc/zh/course16/index.vue
index 24547b16..90e80f11 100644
--- a/web/src/pages/Doc/zh/course16/index.vue
+++ b/web/src/pages/Doc/zh/course16/index.vue
@@ -4,7 +4,66 @@
-
+rich_text_selection_change事件,也就是选中文本的事件:
+mindMap.on('rich_text_selection_change', (hasRange, rect, formatInfo) => {
+ // hasRange(是否存在选区)
+ // rectInfo(选区的尺寸和位置信息)
+ // formatInfo(选区的文本格式化信息)
+ // 显示你的工具栏
+})
+hasRange来判断是否显示工具栏,工具栏的位置可以通过rectInfo获取,通过formatInfo可以获取当前选中文本的样式信息,比如已经被加粗了,那么你的加粗按钮就可以渲染为激活状态。工具栏定位
+
+let left = rect.left + rect.width / 2 + 'px'
+let top = rect.top - 60 + 'px'
+z-index的属性最好也设置的高一点,否则在弹窗等场景下可能会被挡住。加粗/取消加粗
+
+mindMap.richText.formatText({
+ bold: true/false
+})
+斜体/取消斜体
+
+mindMap.richText.formatText({
+ italic: true/false
+})
+下划线/取消下划线
+
+mindMap.richText.formatText({
+ underline: true/false
+})
+删除线/取消删除线
+
+mindMap.richText.formatText({
+ strike: true/false
+})
+设置字体
+
+mindMap.richText.formatText({
+ font: '宋体, SimSun, Songti SC'
+})
+设置字号
+
+mindMap.richText.formatText({
+ font: 16 + 'px'
+})
+设置文字颜色
+
+mindMap.richText.formatText({
+ color: '#fff'
+})
+设置文字背景颜色
+
+mindMap.richText.formatText({
+ background: '#fff'
+})
+清除样式
+
+mindMap.richText.removeFormat()
+完整示例
+
导入和导出
-导出
+
+
+.smm、.json、.svg、.png、.pdf、.md文件。.smm是simple-mind-map自己定义的一种文件,其实就是json文件,换了一个扩展名而已。export方法即可。导出为smm、json
+
+mindMap.export(type, isDownload, fileName, withConfig)
+withConfig指定导出的数据中是否要包含节点数据外的配置数据,比如使用的布局、主题等,传true,导出的结构如下:
+{
+ layout,
+ root,
+ theme: {
+ template,
+ config
+ },
+ view
+}
+false,导出的数据只有root部分,也就是纯节点树。
+mindMap.export('smm', true, '文件名', true)
+mindMap.export('json', true, '文件名', false)
+导出为png、pdf
+
+mindMap.export('png', true, '文件名')
+mindMap.export('pdf', true, '文件名')
+导出为svg
+svg可以传递的参数如下:
+mindMap.export(type, isDownload, fileName, domToImage = false, plusCssText = '')
+domToImage参数控制导出的svg中是否保留html结构,还是转换成图片形式,同样,如果传了true,导出会非常耗时,建议导出为svg时domToImage传false。domToImage传的是false,也就是svg中会保留节点的html结构,这就又存在一个问题,因为浏览器对每个元素默认会设置一些样式,影响最大的就是margin和padding,这就有可能会导致节点中的文字错位,所以可以通过plusCssText参数传入css样式:
+mindMap.export(
+ 'svg',
+ true,
+ '文件名',
+ false,
+ `* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }`
+)
+导出为md
+markdown文件只要传递默认的三个参数即可:
+mindMap.export('md', true, '文件名')
+导入
+.smm、.json、.xmind、.xlsx、.md格式的文件导入。导入smm、json
+
+let data = JSON.parse('json数据')
+// 如果数据中存在root属性,那么代表是包含配置的完整数据,则使用setFullData方法导入数据
+if (data.root) {
+ mindMap.setFullData(data)
+} else {
+// 否则使用setData方法导入
+ mindMap.setData(data)
+}
+// 导入数据后有可能新数据渲染在可视区域外了,所以为了更好的体验,可以复位一下视图的变换
+mindMap.view.reset()
+导入xmind
+xmind文件,需要引入xmind的解析方法:
+import xmind from 'simple-mind-map/src/parse/xmind.js'
+umd文件,可以这样获取:
+MindMap.xmind
+input type=file等方式获取到的File文件对象,那么可以直接传递给parseXmindFile方法解析,注意返回的是一个Promise实例,会返回解析后的节点树数据,使用setData方法渲染到画布即可。
+let data = await xmind.parseXmindFile(file)
+mindMap.setData(data)
+.xmind文件本质上是一个压缩包,改成zip后缀可以解压缩,里面存在一个content.json文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个transformXmind方法进行转换:
+let data = await xmind.transformXmind(fileContent)
+mindMap.setData(data)
+xmind8版本的数据,需要使用transformOldXmind方法。导入xlsx
+xlsx库的方式:
+import { read, utils } from 'xlsx'
+// 文件转buffer
+export const fileToBuffer = file => {
+ return new Promise(r => {
+ const reader = new FileReader()
+ reader.onload = () => {
+ r(reader.result)
+ }
+ reader.readAsArrayBuffer(file)
+ })
+}
+
+// File文件对象
+const transformXLSXToJson = async (file) => {
+ const wb = read(await fileToBuffer(file))
+ const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {
+ header: 1
+ })
+ if (data.length <= 0) {
+ return
+ }
+ let max = 0
+ data.forEach(arr => {
+ if (arr.length > max) {
+ max = arr.length
+ }
+ })
+ let layers = []
+ let walk = layer => {
+ if (!layers[layer]) {
+ layers[layer] = []
+ }
+ for (let i = 0; i < data.length; i++) {
+ if (data[i][layer]) {
+ let node = {
+ data: {
+ text: data[i][layer]
+ },
+ children: [],
+ _row: i
+ }
+ layers[layer].push(node)
+ }
+ }
+ if (layer < max - 1) {
+ walk(layer + 1)
+ }
+ }
+ walk(0)
+ let getParent = (arr, row) => {
+ for (let i = arr.length - 1; i >= 0; i--) {
+ if (row >= arr[i]._row) {
+ return arr[i]
+ }
+ }
+ }
+ for (let i = 1; i < layers.length; i++) {
+ let arr = layers[i]
+ for (let j = 0; j < arr.length; j++) {
+ let item = arr[j]
+ let parent = getParent(layers[i - 1], item._row)
+ if (parent) {
+ parent.children.push(item)
+ }
+ }
+ }
+
+ return layers[0][0]
+}
+
+let data = transformXLSXToJson('xlsx文件对象')
+mindMap.setData(data)
+导入md
+markdown文件需要引入相应的解析方法:
+import markdown from 'simple-mind-map/src/parse/markdown.js'
+
+MindMap.markdown
+md文件的内容后调用transformMarkdownTo方法转换即可,返回一个Promise实例:
+let data = await markdown.transformMarkdownTo('md文件内容')
+mindMap.setData(data)
+完整示例
+
如何持久化数据
-demo的数据是存储在电脑本地的,也就是localStorage里,当然,你也可以存储到数据库中。保存数据
+getData方法,可以传递一个参数,true指定返回的数据中包含配置数据,false指定只返回节点树数据。
+const data = mindMap.getData(true)
+
+{
+ layout,
+ root,
+ theme: {
+ template,
+ config
+ },
+ view
+}
+
+this.$bus.$on('data_change', data => {
+ // 节点树数据改变
+ // data即完整数据中的root部分
+})
+this.$bus.$on('view_data_change', data => {
+ // 视图数据改变
+ // data即完整数据中的view部分
+})
+回显数据
+new一个MindMap实例时直接传入:
+// 从数据中取出各个部分
+let { root, layout, theme, view } = storeData
+let mindMap = new MindMap({
+ el: container,
+ data: root,
+ layout: layout,
+ theme: theme.template,
+ themeConfig: theme.config,
+ viewData: view,
+ // ...
+})
+setFullData方法:
+mindMap.setFullData(data)
+setData方法:
+mindMap.setData(data)
+setLayout方法:
+mindMap.setLayout(layout)
+setTheme方法:
+mindMap.setTheme(theme)
+setThemeConfig方法:
+mindMap.setThemeConfig(themeConfig)
+view.setTransformData方法:
+mindMap.view.setTransformData(view)
+完整示例
+
方法
xmind.parseXmindFile(file)
-.xmind文件,返回解析后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用mindMap.setFullData(data)来将返回的数据渲染到画布上.xmind文件,返回解析后的数据,可以使用mindMap.setData(data)来将返回的数据渲染到画布上file:File对象xmind.transformXmind(content)
-xmind数据,.xmind文件本质上是一个压缩包,改成zip后缀可以解压缩,里面存在一个content.json文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用mindMap.setFullData(data)来将返回的数据渲染到画布上xmind数据,.xmind文件本质上是一个压缩包,改成zip后缀可以解压缩,里面存在一个content.json文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,可以使用mindMap.setData(data)来将返回的数据渲染到画布上content:.xmind压缩包内的content.json文件内容xmind.transformOldXmind(content)
diff --git a/web/src/pages/Edit/components/Import.vue b/web/src/pages/Edit/components/Import.vue
index e936066d..e79cdd84 100644
--- a/web/src/pages/Edit/components/Import.vue
+++ b/web/src/pages/Edit/components/Import.vue
@@ -150,6 +150,7 @@ export default {
async handleXmind(file) {
try {
let data = await xmind.parseXmindFile(file.raw)
+ console.log(data);
this.$bus.$emit('setData', data)
this.$message.success('导入成功')
} catch (error) {
From a6fff7f7a3224b6207ad9c832af79c0d70f175fe Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Fri, 21 Apr 2023 09:37:49 +0800
Subject: [PATCH 09/12] =?UTF-8?q?Demo=EF=BC=9A=E4=BF=AE=E5=A4=8D=E8=8A=82?=
=?UTF-8?q?=E7=82=B9=E6=96=87=E5=AD=97=E6=95=B0=E9=87=8F=E8=AE=A1=E6=95=B0?=
=?UTF-8?q?=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/pages/Edit/components/Count.vue | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/web/src/pages/Edit/components/Count.vue b/web/src/pages/Edit/components/Count.vue
index b7fb3755..26bdf34a 100644
--- a/web/src/pages/Edit/components/Count.vue
+++ b/web/src/pages/Edit/components/Count.vue
@@ -17,11 +17,14 @@
* @Date: 2021-06-24 22:53:10
* @Desc: 字数及节点数量统计
*/
+
+let countEl = document.createElement('div')
export default {
name: 'Count',
props: {},
data() {
return {
+ textStr: '',
words: 0,
num: 0
}
@@ -39,9 +42,12 @@ export default {
* @Desc: 监听数据变化
*/
onDataChange(data) {
+ this.textStr = ''
this.words = 0
this.num = 0
this.walk(data)
+ countEl.innerHTML = this.textStr
+ this.words = countEl.textContent.length
},
/**
@@ -51,7 +57,7 @@ export default {
*/
walk(data) {
this.num++
- this.words += (String(data.data.text) || '').length
+ this.textStr += String(data.data.text) || ''
if (data.children && data.children.length > 0) {
data.children.forEach(item => {
this.walk(item)
From e39a94c5e275fb03bd10c150f415b8d0da7cd8e3 Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Fri, 21 Apr 2023 09:55:29 +0800
Subject: [PATCH 10/12] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9?=
=?UTF-8?q?=E5=AF=8C=E6=96=87=E6=9C=AC=E7=BC=96=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
simple-mind-map/src/RichText.js | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/simple-mind-map/src/RichText.js b/simple-mind-map/src/RichText.js
index e29fb748..f419f151 100644
--- a/simple-mind-map/src/RichText.js
+++ b/simple-mind-map/src/RichText.js
@@ -61,15 +61,18 @@ class RichText {
height: auto;
font-size: inherit;
}
-
- .smm-richtext-node-wrap p {
- display: flex;
- }
-
- .smm-richtext-node-edit-wrap p {
- display: flex;
+
+ .ql-container.ql-snow {
+ border: none;
}
`
+ // .smm-richtext-node-wrap p {
+ // display: flex;
+ // }
+
+ // .smm-richtext-node-edit-wrap p {
+ // display: flex;
+ // }
this.styleEl = document.createElement('style')
this.styleEl.type = 'text/css'
this.styleEl.innerHTML = cssText
From 2abff3e21b11f6adedea585ec2818cc6492089c8 Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Fri, 21 Apr 2023 09:56:14 +0800
Subject: [PATCH 11/12] =?UTF-8?q?Demo=EF=BC=9A=E5=85=B3=E9=97=AD=E6=96=B0?=
=?UTF-8?q?=E7=89=B9=E6=80=A7=E6=8F=90=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/pages/Edit/components/Edit.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/src/pages/Edit/components/Edit.vue b/web/src/pages/Edit/components/Edit.vue
index 40873d10..b5b0003c 100644
--- a/web/src/pages/Edit/components/Edit.vue
+++ b/web/src/pages/Edit/components/Edit.vue
@@ -111,7 +111,7 @@ export default {
}
},
mounted() {
- this.showNewFeatureInfo()
+ // this.showNewFeatureInfo()
this.getData()
this.init()
this.$bus.$on('execCommand', this.execCommand)
From c3393abed6640b40268dee0210b0c9a6a847ac16 Mon Sep 17 00:00:00 2001
From: wanglin2 <1013335014@qq.com>
Date: Fri, 21 Apr 2023 10:07:08 +0800
Subject: [PATCH 12/12] =?UTF-8?q?=E6=89=93=E5=8C=850.5.6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.html b/index.html
index ad7a6fcf..2e49ce9e 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-