Compare commits

..

45 Commits

Author SHA1 Message Date
街角小林
cc62f98a9f 打包0.9.11 2024-04-19 14:34:56 +08:00
街角小林
244f2755a1 Doc: update 2024-04-19 14:18:59 +08:00
街角小林
23d38d9301 Doc: update 2024-04-19 14:18:24 +08:00
街角小林
73a61f81f8 Demo:新增演示模式 2024-04-19 09:30:32 +08:00
街角小林
6539a87cb2 Feat:新增演示插件 2024-04-19 09:29:48 +08:00
街角小林
75635ef2bb Doc: update 2024-04-17 17:50:18 +08:00
街角小林
20fae6270d Demo:优化鼠标在窗口边缘点击右键时菜单显示不全的问题 2024-04-17 09:14:58 +08:00
街角小林
6b40358f65 Demo:节点右键菜单新增导出为图片按钮 2024-04-16 19:02:57 +08:00
街角小林
e072dcb170 Feat:支持导出某个节点为图片 2024-04-16 19:02:35 +08:00
街角小林
6878d92ebe Fix:修复拖拽节点到边缘时画布自动移动无法停止的问题 2024-04-16 17:32:04 +08:00
街角小林
e9352a4f6c Fix:修复删除非当前激活的节点时,当前激活节点的激活状态无法取消的问题 2024-04-15 18:50:05 +08:00
wanglin2
6b9eee7fc6 Fix:修复删除当前激活的节点的所有子节点后,展开收起按钮没有消失的问题 2024-04-13 19:31:07 +08:00
wanglin2
c1217f1532 Feat:支持按住Command键和Win键多选节点 2024-04-13 15:28:56 +08:00
wanglin2
d73225f787 Doc: update 2024-04-13 14:17:59 +08:00
wanglin2
11b3270314 Doc: update 2024-04-12 23:08:33 +08:00
街角小林
5730a7aed5 Doc: update 2024-04-12 17:41:45 +08:00
街角小林
aeda3924a0 Fix:修复Dockerfile错误 2024-04-12 17:36:54 +08:00
街角小林
d9300395ff 新增docker文件及文档 2024-04-11 09:39:42 +08:00
街角小林
5bff885c00 Doc: update 2024-04-09 18:47:40 +08:00
街角小林
088fd398a9 Fix:修复同时创建多个实例时,文本编辑后节点宽高丢失的问题 2024-04-08 19:27:51 +08:00
街角小林
487aa38216 Fix:修复概要节点文本编辑中按回车结束时,相应的节点高亮框会错位显示 2024-04-08 18:20:23 +08:00
街角小林
e2403ae433 Fix:修复富文本插件转换节点数据时没有处理节点概要的问题 2024-04-08 18:07:37 +08:00
街角小林
7f0202e16e Fix:1.修复一键去除所有节点自定义样式命令不支持不为数组的概要的问题;2.修复富文本模式下创建的概要节点不是富文本的问题;Feat:插入概要时支持默认聚焦和进入编辑状态 2024-04-08 18:06:34 +08:00
街角小林
2b8d4ae225 Fix:修复点击概要会触发data_change_detail事件的问题 2024-04-08 18:02:59 +08:00
街角小林
513a1c342c Feat:复制知犀数据时,概要数据创建为数组形式 2024-04-08 18:01:59 +08:00
街角小林
d641b7e2ef Doc: update 2024-04-08 09:40:06 +08:00
街角小林
c769d4d203 Doc: update 2024-04-07 18:37:11 +08:00
街角小林
a36b9085bf 打包0.9.10 2024-04-02 18:14:01 +08:00
街角小林
42c934cb6d Doc: update 2024-04-02 13:57:57 +08:00
街角小林
728b1e1503 Doc: update 2024-04-02 11:53:30 +08:00
街角小林
1949d86abb Demo:支持拖拽文件到页面进行导入 2024-04-02 11:51:32 +08:00
街角小林
a7c68816f9 Doc: update 2024-04-02 09:01:45 +08:00
街角小林
ac3ad1681f Fix:修复节点文本存在svg不支持的实体字符时小地图无法渲染的问题 2024-04-02 09:00:09 +08:00
街角小林
92894d0341 Demo: update 2024-04-01 20:08:15 +08:00
街角小林
58dc232ebf Doc: update 2024-04-01 20:04:06 +08:00
街角小林
5abf09b560 Doc: update 2024-04-01 17:49:57 +08:00
街角小林
6694dffa06 update 2024-04-01 14:51:49 +08:00
街角小林
3673c6aafe Demo:支持添加附件内容(在线Demo不开放) 2024-04-01 13:53:09 +08:00
街角小林
979299f2e2 Feat:节点内容支持设置附件 2024-04-01 13:51:05 +08:00
街角小林
c0f69e038a Feat:节点内容支持设置附件 2024-04-01 13:50:20 +08:00
街角小林
80727b759d Fix:修复搜索时全部替换操作报错的问题 2024-03-29 18:02:02 +08:00
街角小林
57fe315345 打包0.9.9-fix.2 2024-03-29 16:16:08 +08:00
街角小林
231dbc00bc Demo:修复侧边栏大纲点击全屏编辑时打开的是源码编辑模式的问题 2024-03-29 16:02:09 +08:00
街角小林
02957e1fcf Fix:修复开启彩虹线条时切换结构会报错的问题 2024-03-29 15:51:32 +08:00
街角小林
38576a4860 Fix:修复插入父节点操作时原节点样式为更新的问题 2024-03-29 15:44:02 +08:00
132 changed files with 2816 additions and 427 deletions

5
Dockerfile Normal file
View File

@@ -0,0 +1,5 @@
FROM nginx
RUN mkdir /app
COPY ./index.html /app/
COPY ./dist /app/dist/
COPY nginx.conf /etc/nginx/nginx.conf

View File

@@ -38,6 +38,7 @@ Github[releases](https://github.com/wanglin2/mind-map/releases)。百度云
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条
- [x] 提供丰富的配置,满足各种场景各种使用习惯
- [x] 支持协同编辑
- [x] 支持演示模式
# 安装
@@ -92,7 +93,7 @@ const mindMap = new MindMap({
# star
如果喜欢本项目欢迎点个star这对我们很重要。
如果喜欢本项目,欢迎点个 star这对我们很重要。
[![Star History Chart](https://api.star-history.com/svg?repos=wanglin2/mind-map&type=Date)](https://star-history.com/#wanglin2/mind-map&Date)
@@ -316,4 +317,16 @@ const mindMap = new MindMap({
<img src="./web/src/assets/avatar/L.jpg" style="width: 50px;height: 50px;" />
<span>L</span>
</span>
<span>
<img src="./web/src/assets/avatar/default.png" style="width: 50px;height: 50px;" />
<span>sunniberg</span>
</span>
<span>
<img src="./web/src/assets/avatar/在下青铜五.jpg" style="width: 50px;height: 50px;" />
<span>在下青铜五</span>
</span>
<span>
<img src="./web/src/assets/avatar/木星二号.jpg" style="width: 50px;height: 50px;" />
<span>木星二号</span>
</span>
</p>

2
dist/css/app.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
dist/img/在下青铜五.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
dist/img/木星二号.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

2
dist/js/app.js vendored

File diff suppressed because one or more lines are too long

1
dist/js/chunk-2d0a4b03.js vendored Normal file
View File

@@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0a4b03"],{"0805":function(t,s,_){"use strict";_.r(s);var a=function(){var t=this;t._self._c;return t._m(0)},v=[function(){var t=this,s=t._self._c;return s("div",[s("h1",[t._v("快捷键操作如何传递自定义参数")]),s("p",[t._v("库提供了很多命令,比如插入子节点的"),s("code",[t._v("INSERT_CHILD_NODE")]),t._v("等这些命令大多可以接收一定参数比如在插入节点时我想指定初始文本和节点uid那么可以这样调用")]),s("pre",{staticClass:"hljs"},[s("code",[t._v("mindMap.execCommand("),s("span",{staticClass:"hljs-string"},[t._v("'INSERT_CHILD_NODE'")]),t._v(", "),s("span",{staticClass:"hljs-literal"},[t._v("true")]),t._v(", [], {\n "),s("span",{staticClass:"hljs-attr"},[t._v("text")]),t._v(": "),s("span",{staticClass:"hljs-string"},[t._v("'初始文本'")]),t._v(",\n "),s("span",{staticClass:"hljs-attr"},[t._v("uid")]),t._v(": "),s("span",{staticClass:"hljs-string"},[t._v("'xxx'")]),t._v("\n})\n")])]),s("p",[t._v("但是同时库内部也默认注册了很多快捷键,比如插入下级节点的"),s("code",[t._v("Tab")]),t._v("快捷键,很遗憾,目前快捷键操作无法让你传入自定义的参数,那么该怎么办呢,可以这样处理,首先确定你要给什么快捷键传入参数,比如"),s("code",[t._v("Tab")]),t._v(",那么首先可以调用如下方法删除库默认注册的快捷键:")]),s("pre",{staticClass:"hljs"},[s("code",[s("span",{staticClass:"hljs-keyword"},[t._v("const")]),t._v(" keyName = "),s("span",{staticClass:"hljs-string"},[t._v("'Tab'")]),t._v("\nmindMap.keyCommand.removeShortcut(keyName)\n")])]),s("p",[t._v("然后再重新注册即可:")]),s("pre",{staticClass:"hljs"},[s("code",[t._v("mindMap.keyCommand.addShortcut(keyName, "),s("span",{staticClass:"hljs-function"},[t._v("() =>")]),t._v(" {\n mindMap.execCommand("),s("span",{staticClass:"hljs-string"},[t._v("'INSERT_CHILD_NODE'")]),t._v(", "),s("span",{staticClass:"hljs-literal"},[t._v("true")]),t._v(", [], {\n "),s("span",{staticClass:"hljs-attr"},[t._v("text")]),t._v(": "),s("span",{staticClass:"hljs-string"},[t._v("'初始文本'")]),t._v(",\n "),s("span",{staticClass:"hljs-attr"},[t._v("uid")]),t._v(": "),s("span",{staticClass:"hljs-string"},[t._v("'xxx'")]),t._v("\n })\n})\n")])]),s("p",[t._v("库内部默认注册的快捷键对应的命令一览:")]),s("table",[s("thead",[s("tr",[s("th",[t._v("快捷键")]),s("th",[t._v("命令")])])]),s("tbody",[s("tr",[s("td",[t._v("Control+z")]),s("td",[t._v("BACK")])]),s("tr",[s("td",[t._v("Control+y")]),s("td",[t._v("FORWARD")])]),s("tr",[s("td",[t._v("Tab")]),s("td",[t._v("INSERT_CHILD_NODE")])]),s("tr",[s("td",[t._v("Insert")]),s("td",[t._v("INSERT_CHILD_NODE")])]),s("tr",[s("td",[t._v("Enter")]),s("td",[t._v("INSERT_NODE")])]),s("tr",[s("td",[t._v("Shift+Tab")]),s("td",[t._v("INSERT_PARENT_NODE")])]),s("tr",[s("td",[t._v("Control+g")]),s("td",[t._v("ADD_GENERALIZATION")])]),s("tr",[s("td",[t._v("Del或Backspace")]),s("td",[t._v("REMOVE_NODE")])]),s("tr",[s("td",[t._v("Shift+Backspace")]),s("td",[t._v("REMOVE_CURRENT_NODE")])]),s("tr",[s("td",[t._v("Control+a")]),s("td",[t._v("SELECT_ALL")])]),s("tr",[s("td",[t._v("Control+l")]),s("td",[t._v("RESET_LAYOUT")])]),s("tr",[s("td",[t._v("Control+Up")]),s("td",[t._v("UP_NODE")])]),s("tr",[s("td",[t._v("Control+Down")]),s("td",[t._v("DOWN_NODE")])])])])])}],n={},l=n,r=_("2877"),d=Object(r["a"])(l,a,v,!1,null,null,null);s["default"]=d.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/js/chunk-2d0d36df.js vendored Normal file
View File

@@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0d36df"],{"5d71":function(e,t,n){"use strict";n.r(t);var i=function(){var e=this;e._self._c;return e._m(0)},o=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("Demonstrate plugin")]),t("blockquote",[t("p",[e._v("v0.9.11+")])]),t("p",[e._v("The "),t("code",[e._v("Demonstrate")]),e._v(" plugin provides demonstration functionality.")]),t("p",[e._v("When entering demonstration mode, the container elements will be automatically displayed in full screen, and then default to the root node. You can switch between the previous and next steps by pressing the left and right arrow keys on the keyboard, and exit demonstration mode by pressing the 'Esc' key.")]),t("p",[e._v("After entering demonstration mode, all shortcut keys on the mind map will be unavailable, and the mouse will not be able to operate the mind map.")]),t("h2",[e._v("Register")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[e._v("import")]),e._v(" MindMap "),t("span",{staticClass:"hljs-keyword"},[e._v("from")]),e._v(" "),t("span",{staticClass:"hljs-string"},[e._v("'simple-mind-map'")]),e._v("\n"),t("span",{staticClass:"hljs-keyword"},[e._v("import")]),e._v(" Demonstrate "),t("span",{staticClass:"hljs-keyword"},[e._v("from")]),e._v(" "),t("span",{staticClass:"hljs-string"},[e._v("'simple-mind-map/src/plugins/Demonstrate.js'")]),e._v("\n\nMindMap.usePlugin(Demonstrate)\n")])]),t("p",[e._v("After registration and instantiation of "),t("code",[e._v("MindMap")]),e._v(", the instance can be obtained through "),t("code",[e._v("mindMap.demonstrate")]),e._v(".")]),t("h3",[e._v("Config")]),t("p",[e._v("This plugin provides some configuration items for configuration, which can be configured through the instantiation option 'demonstrateConfig'. Please refer to the 【Instantiation options】 section in the 【Constructor】 section for details.")]),t("h3",[e._v("Event")]),t("p",[e._v("The plugin will dispatch the following events:")]),t("p",[t("code",[e._v("exit_demonstrate")]),e._v("Triggered when exiting the demonstration.")]),t("p",[t("code",[e._v("demonstrate_jump")]),e._v("Triggered when jumping.")]),t("p",[e._v("Please refer to the 'on' function in the 【Instance methods】 section of the 【Constructor】 chapter for details.")]),t("h2",[e._v("Props")]),t("h3",[e._v("stepList")]),t("p",[e._v("List of all steps demonstrated. Available when the 'enter' method is called.")]),t("h3",[e._v("currentStepIndex")]),t("p",[e._v("The index of the steps currently played, counting from 0.")]),t("h3",[e._v("config")]),t("p",[e._v("The current configuration of the plugin.")]),t("h2",[e._v("Methods")]),t("h3",[e._v("enter()")]),t("p",[e._v("Entering demonstration mode will automatically display the container elements in full screen.")]),t("h3",[e._v("exit()")]),t("p",[e._v("Exit demonstration mode, which can also be exited by pressing the 'Esc' key.")]),t("h3",[e._v("prev()")]),t("p",[e._v("Previous step.")]),t("h3",[e._v("next()")]),t("p",[e._v("Next step.")]),t("h3",[e._v("jump(index)")]),t("ul",[t("li",[t("code",[e._v("index")]),e._v("NumberTo jump to a certain step, count from 0.")])]),t("p",[e._v("Jump to a certain step.")])])}],s={},a=s,r=n("2877"),l=Object(r["a"])(a,i,o,!1,null,null,null);t["default"]=l.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0db0f2"],{"6df4":function(n,v,_){"use strict";_.r(v);var e=function(){var n=this;n._self._c;return n._m(0)},o=[function(){var n=this,v=n._self._c;return v("div",[v("h1",[n._v("Command实例")]),v("p",[v("code",[n._v("command")]),n._v("实例负责命令的添加及执行,内置了很多命令,也可以自行添加,命令指需要在历史堆栈数据里添加副本的操作。可通过"),v("code",[n._v("mindMap.command")]),n._v("获取到该实例")]),v("h2",[n._v("方法")]),v("h3",[n._v("add(name, fn)")]),v("p",[n._v("添加命令。")]),v("p",[v("code",[n._v("name")]),n._v(":命令名称")]),v("p",[v("code",[n._v("fn")]),n._v(":命令要执行的方法")]),v("h3",[n._v("remove(name, fn)")]),v("p",[n._v("移除命令。")]),v("p",[v("code",[n._v("name")]),n._v(":要移除的命令名称")]),v("p",[v("code",[n._v("fn")]),n._v(":要移除的方法,不传的话移除该命令所有的方法")]),v("h3",[n._v("getCopyData()")]),v("p",[n._v("获取渲染树数据副本")]),v("h3",[n._v("clearHistory()")]),v("p",[n._v("清空历史堆栈数据")])])}],a={},c=a,d=_("2877"),p=Object(d["a"])(c,e,o,!1,null,null,null);v["default"]=p.exports}}]);
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0db0f2"],{"6df4":function(v,_,e){"use strict";e.r(_);var n=function(){var v=this;v._self._c;return v._m(0)},o=[function(){var v=this,_=v._self._c;return _("div",[_("h1",[v._v("Command 实例")]),_("p",[_("code",[v._v("command")]),v._v("实例负责命令的添加及执行,内置了很多命令,也可以自行添加,命令指需要在历史堆栈数据里添加副本的操作。可通过"),_("code",[v._v("mindMap.command")]),v._v("获取到该实例")]),_("h2",[v._v("方法")]),_("h3",[v._v("pause()")]),_("blockquote",[_("p",[v._v("v0.9.11+")])]),_("p",[v._v("暂停收集历史数据。")]),_("h3",[v._v("recovery()")]),_("blockquote",[_("p",[v._v("v0.9.11+")])]),_("p",[v._v("恢复收集历史数据。")]),_("h3",[v._v("add(name, fn)")]),_("p",[v._v("添加命令。")]),_("p",[_("code",[v._v("name")]),v._v(":命令名称")]),_("p",[_("code",[v._v("fn")]),v._v(":命令要执行的方法")]),_("h3",[v._v("remove(name, fn)")]),_("p",[v._v("移除命令。")]),_("p",[_("code",[v._v("name")]),v._v(":要移除的命令名称")]),_("p",[_("code",[v._v("fn")]),v._v(":要移除的方法,不传的话移除该命令所有的方法")]),_("h3",[v._v("getCopyData()")]),_("p",[v._v("获取渲染树数据副本")]),_("h3",[v._v("clearHistory()")]),_("p",[v._v("清空历史堆栈数据")])])}],c={},p=c,a=e("2877"),d=Object(a["a"])(p,n,o,!1,null,null,null);_["default"]=d.exports}}]);

View File

@@ -1 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0e5089"],{9381:function(e,a,n){"use strict";n.r(a);var o=function(){var e=this;e._self._c;return e._m(0)},d=[function(){var e=this,a=e._self._c;return a("div",[a("h1",[e._v("command instance")]),a("p",[e._v("The "),a("code",[e._v("command")]),e._v(" instance is responsible for adding and executing commands. It includes many built-in commands and can also be added manually. A command refers to an operation that needs to add a copy to the history stack data. The "),a("code",[e._v("mindMap.command")]),e._v(' instance can be obtained through this."')]),a("h2",[e._v("Methods")]),a("h3",[e._v("add(name, fn)")]),a("p",[e._v("Add a command.")]),a("p",[a("code",[e._v("name")]),e._v(": Command name")]),a("p",[a("code",[e._v("fn")]),e._v(": Method to be executed by the command")]),a("h3",[e._v("remove(name, fn)")]),a("p",[e._v("Remove a command.")]),a("p",[a("code",[e._v("name")]),e._v(": Name of the command to be removed")]),a("p",[a("code",[e._v("fn")]),e._v(": Method to be removed, if not provided all methods for the command will be removed")]),a("h3",[e._v("getCopyData()")]),a("p",[e._v("Get a copy of the rendering tree data")]),a("h3",[e._v("clearHistory()")]),a("p",[e._v("Clear the history stack data")])])}],t={},c=t,m=n("2877"),v=Object(m["a"])(c,o,d,!1,null,null,null);a["default"]=v.exports}}]);
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0e5089"],{9381:function(e,o,a){"use strict";a.r(o);var n=function(){var e=this;e._self._c;return e._m(0)},t=[function(){var e=this,o=e._self._c;return o("div",[o("h1",[e._v("command instance")]),o("p",[e._v("The "),o("code",[e._v("command")]),e._v(" instance is responsible for adding and executing commands. It includes many built-in commands and can also be added manually. A command refers to an operation that needs to add a copy to the history stack data. The "),o("code",[e._v("mindMap.command")]),e._v(' instance can be obtained through this."')]),o("h2",[e._v("Methods")]),o("h3",[e._v("pause()")]),o("blockquote",[o("p",[e._v("v0.9.11+")])]),o("p",[e._v("Pause collecting historical data.")]),o("h3",[e._v("recovery()")]),o("blockquote",[o("p",[e._v("v0.9.11+")])]),o("p",[e._v("Restore the collection of historical data.")]),o("h3",[e._v("add(name, fn)")]),o("p",[e._v("Add a command.")]),o("p",[o("code",[e._v("name")]),e._v(": Command name")]),o("p",[o("code",[e._v("fn")]),e._v(": Method to be executed by the command")]),o("h3",[e._v("remove(name, fn)")]),o("p",[e._v("Remove a command.")]),o("p",[o("code",[e._v("name")]),e._v(": Name of the command to be removed")]),o("p",[o("code",[e._v("fn")]),e._v(": Method to be removed, if not provided all methods for the command will be removed")]),o("h3",[e._v("getCopyData()")]),o("p",[e._v("Get a copy of the rendering tree data")]),o("h3",[e._v("clearHistory()")]),o("p",[e._v("Clear the history stack data")])])}],d={},c=d,v=a("2877"),m=Object(v["a"])(c,n,t,!1,null,null,null);o["default"]=m.exports}}]);

1
dist/js/chunk-2d0e96e3.js vendored Normal file
View File

@@ -0,0 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0e96e3"],{"8e00":function(_,v,e){"use strict";e.r(v);var s=function(){var _=this;_._self._c;return _._m(0)},t=[function(){var _=this,v=_._self._c;return v("div",[v("h1",[_._v("Demonstrate 插件")]),v("blockquote",[v("p",[_._v("v0.9.11+")])]),v("p",[v("code",[_._v("Demonstrate")]),_._v("插件提供演示功能。")]),v("p",[_._v("进入演示模式时会自动将容器元素全屏,然后默认聚焦到根节点,可通过键盘方向键的左右来切换上一步和下一步,可通过"),v("code",[_._v("Esc")]),_._v("键退出演示模式。")]),v("p",[_._v("进入演示模式后思维导图所有的快捷键都将无法使用,鼠标也无法操作思维导图。")]),v("h2",[_._v("注册")]),v("pre",{staticClass:"hljs"},[v("code",[v("span",{staticClass:"hljs-keyword"},[_._v("import")]),_._v(" MindMap "),v("span",{staticClass:"hljs-keyword"},[_._v("from")]),_._v(" "),v("span",{staticClass:"hljs-string"},[_._v("'simple-mind-map'")]),_._v("\n"),v("span",{staticClass:"hljs-keyword"},[_._v("import")]),_._v(" Demonstrate "),v("span",{staticClass:"hljs-keyword"},[_._v("from")]),_._v(" "),v("span",{staticClass:"hljs-string"},[_._v("'simple-mind-map/src/plugins/Demonstrate.js'")]),_._v("\n\nMindMap.usePlugin(Demonstrate)\n")])]),v("p",[_._v("注册完且实例化"),v("code",[_._v("MindMap")]),_._v("后可通过"),v("code",[_._v("mindMap.demonstrate")]),_._v("获取到该实例。")]),v("h3",[_._v("配置")]),v("p",[_._v("该插件提供了一些配置项可供配置,可以通过实例化选项"),v("code",[_._v("demonstrateConfig")]),_._v("进行配置。详见【构造函数】篇章的【实例化选项】小节。")]),v("h3",[_._v("事件")]),v("p",[_._v("该插件会派发如下事件:")]),v("p",[v("code",[_._v("exit_demonstrate")]),_._v(":退出演示时触发。")]),v("p",[v("code",[_._v("demonstrate_jump")]),_._v(":跳转时触发。")]),v("p",[_._v("详见【构造函数】篇章的【实例方法】小节"),v("code",[_._v("on")]),_._v("函数。")]),v("h2",[_._v("属性")]),v("h3",[_._v("stepList")]),v("p",[_._v("演示的所有步骤列表。当调用了"),v("code",[_._v("enter")]),_._v("方法后可用。")]),v("h3",[_._v("currentStepIndex")]),v("p",[_._v("当前播放到的步骤索引从0开始计数。")]),v("h3",[_._v("config")]),v("p",[_._v("插件当前的配置。")]),v("h2",[_._v("方法")]),v("h3",[_._v("enter()")]),v("p",[_._v("进入演示模式,会自动将容器元素全屏。")]),v("h3",[_._v("exit()")]),v("p",[_._v("退出演示模式,通过"),v("code",[_._v("Esc")]),_._v("键也可退出。")]),v("h3",[_._v("prev()")]),v("p",[_._v("上一步。")]),v("h3",[_._v("next()")]),v("p",[_._v("下一步。")]),v("h3",[_._v("jump(index)")]),v("ul",[v("li",[v("code",[_._v("index")]),_._v("Number要跳转到的某一步从0开始计数。")])]),v("p",[_._v("跳转到某一步。")])])}],n={},p=n,a=e("2877"),o=Object(a["a"])(p,s,t,!1,null,null,null);v["default"]=o.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216037"],{c13f:function(s,t,n){"use strict";n.r(t);var a=function(){var s=this;s._self._c;return s._m(0)},e=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("开启节点自由拖拽")]),t("blockquote",[t("p",[s._v("节点自由拖拽的连线可能不会符合你的预期,这个问题基本上不会改,所以自由拖拽功能不建议使用。")])]),t("p",[s._v("节点支持自由拖拽,也就是可以把它拖动到你指定的位置,默认是不开启的,如果需要开启可以在实例化"),t("code",[s._v("simple-mind-map")]),s._v("时传入开启的选项:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v("\n})\n")])]),t("p",[s._v("也可以动态切换是否开启:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.updateConfig({\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),t("span",{staticClass:"hljs-comment"},[s._v("// false")]),s._v("\n})\n")])]),t("p",[s._v("自由拖拽很容器将节点拖的乱七八糟,所以也可以通过命令回到默认的位置:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.execCommand("),t("span",{staticClass:"hljs-string"},[s._v("'RESET_LAYOUT'")]),s._v(")\n")])]),t("p",[s._v("也可以使用快捷键"),t("code",[s._v("Ctrl + L")]),s._v("来恢复。")]),t("h2",[s._v("完整示例")]),t("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVd1uG0UUfpVhEVoH2buuxJVxSksbJKSEolAuUDeqxrtje8rszLIzm8SyVgoF1EKIFASiFdxAVQFCQFWBEE2oeJmsnb4FZ3b2L44veldLa82c853znZnzM1PrchQ52wmxelZf+jGNFJJEJdFFj9MwErFCUxSTYRsJviESrkjQRnKMGRM7m2SIUjSMRYhs8GBXFhuUBxs4MirPkiBmpBOCtBPiyLM8jpDHGVFIyzRyFfGEMSN3XZQ9/Tr7/GD2397sr+P5d5+efnF7fvtJdvfe6Y+/eNwXXCqEfUW3yTsiIBKs64haN7ZWPF6iqLwWEf5WTMjVGI8ACEdpDTGTJAdpqrt3ZgcPZvcfZYc/Zf/uZYePTu/8Ov/m8Wz/29n+09KPEqMRIw0/rRW0ehFNdcRnOZxtzBICiJeWyTW+OLOTRAFW5IrgQzpq5Z4QIhwPap7eUt8QuEoh/LQ4wezjB9nDg2fH90//eJj980n2eK+MOiaQynU8EYk6G3IZAtkl/hURhpgHLXtz7b216zfXL39w7f3rdum/ynrrvLnOGtkps10dgfVQIPwkJFw5I6LWGNHLNydvA0dhCYdWmHIS2yttYwVXgXvGu/55lhZ4VkNkxIrsKi32rNkPT0xdmHrSv7RwpoH+mLIgJlyDb9Q+FtwtZVlkOjn6cn708yLZWcIlpFu1rol7QRGUy0JW2lFO1aYQSjfSu0JSRQUHS5uRobLbyPYhdZCmrQK+WJ95K2lVuvK66V6EoCTn33+VHf5m4jVdfHK0f3L8d7P2BG/ZHFhvmk4GspbetpH+X6dS1fWGmt1eNViJM/RQr/D1XTPDYHrBRhEYPNBjsEOoH9Bt5DMs5apnFUFcJaHwrFxdAGhQa6sqBUjfBW0TWHpSQrAB1hCj9FR/kCglOLrkM+p/mEOawwOQ0+niYHoD2dlnfz6793tz+NioB+JzM8lGadp3DUlBCjEtkjZ6HxjPz4gFD/X5ylXfbVwfbKWaMHOTl4ox71mOa2Z7MQIcIkPHl9KzqmJwGjddJnOHBmrcQxe63VdyHEJRVXkxAUZIda7Ii1Z/Ly9mpHRVG+KBFCxRxhAhXb891C12SkT15jz9mNDRGOCvdbvRbsm8nPfVkjnE8YgCb+k1wkFAObSEEVShO0WBPGfEF8oIiqCrPTiE4s5zYLUtkwH9mjq3pODweOfuvUIBGagmimfB22zGiOPC0olhntOQ6GR1BrHYkSQGJ55VtPiS91rbjpWKZM912e5HXE6kI6Ts+LwzIPQWHNvBjE4S7kvHF6ELnUGUXFIbmqY4TGql/wPpBfrv"}})])}],l={},r=l,i=n("2877"),p=Object(i["a"])(r,a,e,!1,null,null,null);t["default"]=p.exports}}]);
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216037"],{c13f:function(s,t,a){"use strict";a.r(t);var n=function(){var s=this;s._self._c;return s._m(0)},e=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("开启节点自由拖拽")]),t("blockquote",[t("p",[s._v("节点自由拖拽的连线可能不会符合你的预期,这个问题基本上不会改,所以自由拖拽功能不建议使用。")])]),t("blockquote",[t("p",[s._v("另外不要把节点拖拽和自由拖拽搞混,节点拖拽指拖动节点到其他节点上成为其子节点或兄弟节点,自由拖拽只是可以把节点放置在你拖动到的画布位置,并不能改变节点的层级。")])]),t("blockquote",[t("p",[s._v("最后要注意这两个功能都需要先注册Drag插件。")])]),t("p",[s._v("节点支持自由拖拽,也就是可以把它拖动到你指定的位置,默认是不开启的,如果需要开启可以在实例化"),t("code",[s._v("simple-mind-map")]),s._v("时传入开启的选项:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v("\n})\n")])]),t("p",[s._v("也可以动态切换是否开启:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.updateConfig({\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),t("span",{staticClass:"hljs-comment"},[s._v("// false")]),s._v("\n})\n")])]),t("p",[s._v("自由拖拽很容器将节点拖的乱七八糟,所以也可以通过命令回到默认的位置:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.execCommand("),t("span",{staticClass:"hljs-string"},[s._v("'RESET_LAYOUT'")]),s._v(")\n")])]),t("p",[s._v("也可以使用快捷键"),t("code",[s._v("Ctrl + L")]),s._v("来恢复。")]),t("h2",[s._v("完整示例")]),t("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVd1uG0UUfpVhEVoH2buuxJVxSksbJKSEolAuUDeqxrtje8rszLIzm8SyVgoF1EKIFASiFdxAVQFCQFWBEE2oeJmsnb4FZ3b2L44veldLa82c853znZnzM1PrchQ52wmxelZf+jGNFJJEJdFFj9MwErFCUxSTYRsJviESrkjQRnKMGRM7m2SIUjSMRYhs8GBXFhuUBxs4MirPkiBmpBOCtBPiyLM8jpDHGVFIyzRyFfGEMSN3XZQ9/Tr7/GD2397sr+P5d5+efnF7fvtJdvfe6Y+/eNwXXCqEfUW3yTsiIBKs64haN7ZWPF6iqLwWEf5WTMjVGI8ACEdpDTGTJAdpqrt3ZgcPZvcfZYc/Zf/uZYePTu/8Ov/m8Wz/29n+09KPEqMRIw0/rRW0ehFNdcRnOZxtzBICiJeWyTW+OLOTRAFW5IrgQzpq5Z4QIhwPap7eUt8QuEoh/LQ4wezjB9nDg2fH90//eJj980n2eK+MOiaQynU8EYk6G3IZAtkl/hURhpgHLXtz7b216zfXL39w7f3rdum/ynrrvLnOGtkps10dgfVQIPwkJFw5I6LWGNHLNydvA0dhCYdWmHIS2yttYwVXgXvGu/55lhZ4VkNkxIrsKi32rNkPT0xdmHrSv7RwpoH+mLIgJlyDb9Q+FtwtZVlkOjn6cn708yLZWcIlpFu1rol7QRGUy0JW2lFO1aYQSjfSu0JSRQUHS5uRobLbyPYhdZCmrQK+WJ95K2lVuvK66V6EoCTn33+VHf5m4jVdfHK0f3L8d7P2BG/ZHFhvmk4GspbetpH+X6dS1fWGmt1eNViJM/RQr/D1XTPDYHrBRhEYPNBjsEOoH9Bt5DMs5apnFUFcJaHwrFxdAGhQa6sqBUjfBW0TWHpSQrAB1hCj9FR/kCglOLrkM+p/mEOawwOQ0+niYHoD2dlnfz6793tz+NioB+JzM8lGadp3DUlBCjEtkjZ6HxjPz4gFD/X5ylXfbVwfbKWaMHOTl4ox71mOa2Z7MQIcIkPHl9KzqmJwGjddJnOHBmrcQxe63VdyHEJRVXkxAUZIda7Ii1Z/Ly9mpHRVG+KBFCxRxhAhXb891C12SkT15jz9mNDRGOCvdbvRbsm8nPfVkjnE8YgCb+k1wkFAObSEEVShO0WBPGfEF8oIiqCrPTiE4s5zYLUtkwH9mjq3pODweOfuvUIBGagmimfB22zGiOPC0olhntOQ6GR1BrHYkSQGJ55VtPiS91rbjpWKZM912e5HXE6kI6Ts+LwzIPQWHNvBjE4S7kvHF6ELnUGUXFIbmqY4TGql/wPpBfrv"}})])}],l={},r=l,i=a("2877"),p=Object(i["a"])(r,n,e,!1,null,null,null);t["default"]=p.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/js/chunk-2fb39b1c.js vendored Normal file

File diff suppressed because one or more lines are too long

76
dist/js/chunk-50d4139a.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="icon" href="dist/logo.ico"><title>思绪思维导图</title><script>// 自定义静态资源的路径
window.externalPublicPath = './dist/'
// 接管应用
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?beeb148b8a9b236eb3f3" rel="stylesheet"><link href="dist/css/app.css?beeb148b8a9b236eb3f3" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?389be1da0a7a3dbc051c" rel="stylesheet"><link href="dist/css/app.css?389be1da0a7a3dbc051c" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
@@ -66,4 +66,4 @@
// 可以通过window.$bus.$on()来监听应用的一些事件
// 实例化页面
window.initApp()
}</script><script src="dist/js/chunk-vendors.js?beeb148b8a9b236eb3f3"></script><script src="dist/js/app.js?beeb148b8a9b236eb3f3"></script></body></html>
}</script><script src="dist/js/chunk-vendors.js?389be1da0a7a3dbc051c"></script><script src="dist/js/app.js?389be1da0a7a3dbc051c"></script></body></html>

30
nginx.conf Normal file
View File

@@ -0,0 +1,30 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /app;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}

View File

@@ -29,7 +29,7 @@ MindMap.iconList = icons.nodeIconList
MindMap.constants = constants
MindMap.themes = themes
MindMap.defaultTheme = defaultTheme
MindMap.version = '0.9.9-fix.1'
MindMap.version = '0.9.11'
MindMap.usePlugin(MiniMap)
.usePlugin(Watermark)

View File

@@ -10,17 +10,16 @@ import BatchExecution from './src/utils/BatchExecution'
import {
layoutValueList,
CONSTANTS,
commonCaches,
ERROR_TYPES,
cssContent
} from './src/constants/constant'
import { SVG } from '@svgdotjs/svg.js'
import {
simpleDeepClone,
getType,
getObjectChangedProps,
isUndef,
handleGetSvgDataExtraContent
handleGetSvgDataExtraContent,
getNodeTreeBoundingRect
} from './src/utils'
import defaultTheme, {
checkIsNodeSizeIndependenceConfig
@@ -228,19 +227,10 @@ class MindMap {
// 初始化缓存数据
initCache() {
Object.keys(commonCaches).forEach(key => {
let type = getType(commonCaches[key])
let value = ''
switch (type) {
case 'Boolean':
value = false
break
default:
value = null
break
}
commonCaches[key] = value
})
this.commonCaches = {
measureCustomNodeContentSizeEl: null,
measureRichtextNodeTextSizeEl: null
}
}
// 设置主题
@@ -420,7 +410,8 @@ class MindMap {
paddingY = 0,
ignoreWatermark = false,
addContentToHeader,
addContentToFooter
addContentToFooter,
node
} = {}) {
const { cssTextList, header, headerHeight, footer, footerHeight } =
handleGetSvgDataExtraContent({
@@ -438,6 +429,11 @@ class MindMap {
draw.scale(1 / origTransform.scaleX, 1 / origTransform.scaleY)
// 获取变换后的位置尺寸信息其实是getBoundingClientRect方法的包装方法
const rect = draw.rbox()
// 需要裁减的区域
let clipData = null
if (node) {
clipData = getNodeTreeBoundingRect(node, rect.x, rect.y, paddingX, paddingY)
}
// 内边距
const fixHeight = 0
rect.width += paddingX * 2
@@ -517,6 +513,7 @@ class MindMap {
return {
svg: clone, // 思维导图图形的整体svg元素包括svg画布容器、g实际的思维导图组
svgHTML: clone.svg(), // svg字符串
clipData,
rect: {
...rect, // 思维导图图形未缩放时的位置尺寸等信息
ratio: rect.width / rect.height // 思维导图图形的宽高比

View File

@@ -1,6 +1,6 @@
{
"name": "simple-mind-map",
"version": "0.9.9-fix.1",
"version": "0.9.11",
"description": "一个简单的web在线思维导图",
"authors": [
{

View File

@@ -312,15 +312,11 @@ export const nodeDataNoStylePropList = [
'associativeLineTargets',
'associativeLineTargetControlOffsets',
'associativeLinePoint',
'associativeLineText'
'associativeLineText',
'attachmentUrl',
'attachmentName'
]
// 数据缓存
export const commonCaches = {
measureCustomNodeContentSizeEl: null,
measureRichtextNodeTextSizeEl: null
}
// 错误类型
export const ERROR_TYPES = {
READ_CLIPBOARD_ERROR: 'read_clipboard_error',

View File

@@ -318,5 +318,7 @@ export const defaultOpt = {
}
*/
addContentToHeader: null,
addContentToFooter: null
addContentToFooter: null,
// 演示插件配置
demonstrateConfig: null
}

View File

@@ -23,6 +23,18 @@ class Command {
this.mindMap.opt.addHistoryTime,
this
)
// 是否暂停收集历史数据
this.isPause = false
}
// 暂停收集历史数据
pause() {
this.isPause = true
}
// 恢复收集历史数据
recovery() {
this.isPause = false
}
// 清空历史数据
@@ -88,7 +100,7 @@ class Command {
// 添加回退数据
addHistory() {
if (this.mindMap.opt.readonly) {
if (this.mindMap.opt.readonly || this.isPause) {
return
}
const lastData =

View File

@@ -65,7 +65,9 @@ class Render {
this.mindMap = opt.mindMap
this.themeConfig = this.mindMap.themeConfig
// 渲染树,操作过程中修改的都是这里的数据
this.renderTree = this.mindMap.opt.data ? merge({}, this.mindMap.opt.data) : null
this.renderTree = this.mindMap.opt.data
? merge({}, this.mindMap.opt.data)
: null
// 是否重新渲染
this.reRender = false
// 是否正在渲染中
@@ -246,6 +248,9 @@ class Render {
// 设置节点备注
this.setNodeNote = this.setNodeNote.bind(this)
this.mindMap.command.add('SET_NODE_NOTE', this.setNodeNote)
// 设置节点附件
this.setNodeAttachment = this.setNodeAttachment.bind(this)
this.mindMap.command.add('SET_NODE_ATTACHMENT', this.setNodeAttachment)
// 设置节点标签
this.setNodeTag = this.setNodeTag.bind(this)
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
@@ -330,7 +335,7 @@ class Render {
})
// 一键整理布局
this.mindMap.keyCommand.addShortcut('Control+l', () => {
this.mindMap.execCommand('RESET_LAYOUT', this.resetLayout)
this.mindMap.execCommand('RESET_LAYOUT')
})
// 上移节点
this.mindMap.keyCommand.addShortcut('Control+Up', () => {
@@ -856,6 +861,9 @@ class Render {
},
children: [node.nodeData]
}
node.setData({
resetRichText: true
})
const parent = node.parent
// 获取当前节点所在位置
const index = getNodeDataIndex(node)
@@ -981,12 +989,18 @@ class Render {
const _hasCustomStyles = this._handleRemoveCustomStyles(node.data)
if (_hasCustomStyles) hasCustomStyles = true
// 不要忘记概要节点
if (node.data.generalization && node.data.generalization.length > 0) {
node.data.generalization.forEach(generalizationData => {
const _hasCustomStyles =
this._handleRemoveCustomStyles(generalizationData)
if (_hasCustomStyles) hasCustomStyles = true
})
let generalization = node.data.generalization
if (generalization) {
generalization = Array.isArray(generalization)
? generalization
: [generalization]
if (generalization.length > 0) {
generalization.forEach(generalizationData => {
const _hasCustomStyles =
this._handleRemoveCustomStyles(generalizationData)
if (_hasCustomStyles) hasCustomStyles = true
})
}
}
})
}
@@ -1228,7 +1242,7 @@ class Render {
root.nodeData.children = []
} else {
// 如果只选中了一个节点,删除后激活其兄弟节点或者父节点
needActiveNode = this.getNextActiveNode()
needActiveNode = this.getNextActiveNode(list)
for (let i = 0; i < list.length; i++) {
const node = list[i]
const currentEditNode = this.textEdit.getCurrentEditNode()
@@ -1283,13 +1297,13 @@ class Render {
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
return
}
// 删除节点后需要激活的节点,如果只选中了一个节点,删除后激活其兄弟节点或者父节点
let needActiveNode = this.getNextActiveNode()
let isAppointNodes = appointNodes.length > 0
let list = isAppointNodes ? appointNodes : this.activeNodeList
list = list.filter(node => {
return !node.isRoot
})
// 删除节点后需要激活的节点,如果只选中了一个节点,删除后激活其兄弟节点或者父节点
let needActiveNode = this.getNextActiveNode(list)
for (let i = 0; i < list.length; i++) {
let node = list[i]
if (node.isGeneralization) {
@@ -1315,7 +1329,11 @@ class Render {
}
// 计算下一个可激活的节点
getNextActiveNode() {
getNextActiveNode(deleteList) {
// 删除多个节点不自动激活相邻节点
if (deleteList.length !== 1) return null
// 被删除的节点不在当前激活的节点列表里,不激活相邻节点
if (this.findActiveNodeIndex(deleteList[0]) === -1) return null
let needActiveNode = null
if (
this.activeNodeList.length === 1 &&
@@ -1488,7 +1506,7 @@ class Render {
}
// 收起所有
unexpandAllNode() {
unexpandAllNode(isSetRootNodeCenter = true) {
if (!this.renderTree) return
walk(
this.renderTree,
@@ -1504,7 +1522,9 @@ class Render {
0
)
this.mindMap.render(() => {
this.setRootNodeCenter()
if (isSetRootNodeCenter) {
this.setRootNodeCenter()
}
})
}
@@ -1597,6 +1617,14 @@ class Render {
})
}
// 设置节点附件
setNodeAttachment(node, url, name = '') {
this.setNodeDataRender(node, {
attachmentUrl: url,
attachmentName: name
})
}
// 设置节点标签
setNodeTag(node, tag) {
this.setNodeDataRender(node, {
@@ -1616,7 +1644,7 @@ class Render {
}
// 添加节点概要
addGeneralization(data) {
addGeneralization(data, openEdit = true) {
if (this.activeNodeList.length <= 0) {
return
}
@@ -1628,13 +1656,22 @@ class Render {
)
})
const list = parseAddGeneralizationNodeList(nodeList)
const isRichText = !!this.mindMap.richText
const { focusNewNode, inserting } = this.getNewNodeBehavior(
openEdit,
list.length > 1
)
list.forEach(item => {
const newData = {
inserting,
...(data || {
text: this.mindMap.opt.defaultGeneralizationText
}),
range: item.range || null,
uid: createUid()
uid: createUid(),
richText: isRichText,
resetRichText: isRichText,
isActive: focusNewNode
}
let generalization = item.node.getData('generalization')
if (generalization) {
@@ -1654,6 +1691,10 @@ class Render {
expand: true
})
})
// 需要清除原来激活的节点
if (focusNewNode) {
this.clearActiveNodeList()
}
this.mindMap.render(() => {
// 修复祖先节点存在概要时位置未更新的问题
// 修复同时给存在上下级关系的节点添加概要时重叠的问题
@@ -1824,6 +1865,8 @@ class Render {
// 高亮节点或子节点
highlightNode(node, range) {
// 如果当前正在渲染,那么不进行高亮,因为节点位置可能不正确
if (this.isRendering) return
const { highlightNodeBoxStyle = {} } = this.mindMap.opt
if (!this.highlightBoxNode) {
this.highlightBoxNode = new Polygon()

View File

@@ -75,6 +75,7 @@ class Node {
this._noteData = null
this.noteEl = null
this.noteContentIsShow = false
this._attachmentData = null
this._expandBtn = null
this._lastExpandBtnType = null
this._showExpandBtn = false
@@ -199,6 +200,7 @@ class Node {
this._hyperlinkData = this.createHyperlinkNode()
this._tagData = this.createTagNode()
this._noteData = this.createNoteNode()
this._attachmentData = this.createAttachmentNode()
}
// 计算节点的宽高
@@ -267,6 +269,14 @@ class Node {
textContentWidth += this._noteData.width
textContentHeight = Math.max(textContentHeight, this._noteData.height)
}
// 附件
if (this._attachmentData) {
textContentWidth += this._attachmentData.width
textContentHeight = Math.max(
textContentHeight,
this._attachmentData.height
)
}
// 文字内容部分的尺寸
this._rectInfo.textContentWidth = textContentWidth
this._rectInfo.textContentHeight = textContentHeight
@@ -399,6 +409,14 @@ class Node {
textContentNested.add(this._noteData.node)
textContentOffsetX += this._noteData.width
}
// 附件
if (this._attachmentData) {
this._attachmentData.node
.x(textContentOffsetX)
.y((this._rectInfo.textContentHeight - this._attachmentData.height) / 2)
textContentNested.add(this._attachmentData.node)
textContentOffsetX += this._attachmentData.width
}
// 文字内容整体
textContentNested.translate(
width / 2 - textContentNested.bbox().width / 2,
@@ -451,7 +469,7 @@ class Node {
}
}
// 多选和取消多选
if (e.ctrlKey && enableCtrlKeyNodeSelection) {
if ((e.ctrlKey || e.metaKey) && enableCtrlKeyNodeSelection) {
this.isMultipleChoice = true
let isActive = this.getData('isActive')
if (!isActive)
@@ -495,7 +513,7 @@ class Node {
// 双击事件
this.group.on('dblclick', e => {
const { readonly, onlyOneEnableActiveNodeOnCooperate } = this.mindMap.opt
if (readonly || e.ctrlKey) {
if (readonly || e.ctrlKey || e.metaKey) {
return
}
e.stopPropagation()
@@ -547,6 +565,12 @@ class Node {
this.renderer.emitNodeActiveEvent(this)
}
// 取消激活该节点
deactivate() {
this.mindMap.renderer.removeNodeFromActiveList(this)
this.mindMap.renderer.emitNodeActiveEvent()
}
// 更新节点
update() {
if (!this.group) {
@@ -554,9 +578,10 @@ class Node {
}
this.updateNodeActiveClass()
let { alwaysShowExpandBtn } = this.mindMap.opt
const childrenLength = this.nodeData.children.length
if (alwaysShowExpandBtn) {
// 需要移除展开收缩按钮
if (this._expandBtn && this.nodeData.children.length <= 0) {
if (this._expandBtn && childrenLength <= 0) {
this.removeExpandBtn()
} else {
// 更新展开收起按钮
@@ -565,7 +590,9 @@ class Node {
} else {
let { isActive, expand } = this.getData()
// 展开状态且非激活状态,且当前鼠标不在它上面,才隐藏
if (expand && !isActive && !this._isMouseenter) {
if (childrenLength <= 0) {
this.removeExpandBtn()
} else if (expand && !isActive && !this._isMouseenter) {
this.hideExpandBtn()
} else {
this.showExpandBtn()

View File

@@ -28,6 +28,11 @@ function setNote(note) {
this.mindMap.execCommand('SET_NODE_NOTE', this, note)
}
// 设置附件
function setAttachment(url, name) {
this.mindMap.execCommand('SET_NODE_ATTACHMENT', this, url, name)
}
// 设置标签
function setTag(tag) {
this.mindMap.execCommand('SET_NODE_TAG', this, tag)
@@ -55,6 +60,7 @@ export default {
setIcon,
setHyperlink,
setNote,
setAttachment,
setTag,
setShape,
setStyle,

View File

@@ -16,7 +16,7 @@ import {
ForeignObject
} from '@svgdotjs/svg.js'
import iconsSvg from '../../../svg/icons'
import { CONSTANTS, commonCaches } from '../../../constants/constant'
import { CONSTANTS } from '../../../constants/constant'
// 创建图片节点
function createImgNode() {
@@ -149,13 +149,13 @@ function createRichTextNode() {
})
}
let html = `<div>${this.getData('text')}</div>`
if (!commonCaches.measureRichtextNodeTextSizeEl) {
commonCaches.measureRichtextNodeTextSizeEl = document.createElement('div')
commonCaches.measureRichtextNodeTextSizeEl.style.position = 'fixed'
commonCaches.measureRichtextNodeTextSizeEl.style.left = '-999999px'
this.mindMap.el.appendChild(commonCaches.measureRichtextNodeTextSizeEl)
if (!this.mindMap.commonCaches.measureRichtextNodeTextSizeEl) {
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl = document.createElement('div')
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl.style.position = 'fixed'
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl.style.left = '-999999px'
this.mindMap.el.appendChild(this.mindMap.commonCaches.measureRichtextNodeTextSizeEl)
}
let div = commonCaches.measureRichtextNodeTextSizeEl
let div = this.mindMap.commonCaches.measureRichtextNodeTextSizeEl
div.innerHTML = html
let el = div.children[0]
el.classList.add('smm-richtext-node-wrap')
@@ -262,7 +262,7 @@ function createHyperlinkNode() {
e.stopPropagation()
})
if (hyperlinkTitle) {
a.attr('title', hyperlinkTitle)
node.add(SVG(`<title>${hyperlinkTitle}</title>`))
}
// 添加一个透明的层,作为鼠标区域
a.rect(iconSize, iconSize).fill({ color: 'transparent' })
@@ -368,6 +368,36 @@ function createNoteNode() {
}
}
// 创建附件节点
function createAttachmentNode() {
const { attachmentUrl, attachmentName } = this.getData()
if (!attachmentUrl) {
return
}
const iconSize = this.mindMap.themeConfig.iconSize
const node = new SVG().attr('cursor', 'pointer').size(iconSize, iconSize)
if (attachmentName) {
node.add(SVG(`<title>${attachmentName}</title>`))
}
// 透明的层,用来作为鼠标区域
node.add(new Rect().size(iconSize, iconSize).fill({ color: 'transparent' }))
// 备注图标
const iconNode = SVG(iconsSvg.attachment).size(iconSize, iconSize)
this.style.iconNode(iconNode)
node.add(iconNode)
node.on('click', e => {
this.mindMap.emit('node_attachmentClick', this, e, node)
})
node.on('contextmenu', e => {
this.mindMap.emit('node_attachmentContextmenu', this, e, node)
})
return {
node,
width: iconSize,
height: iconSize
}
}
// 获取节点备注显示位置
function getNoteContentPosition() {
const iconSize = this.mindMap.themeConfig.iconSize
@@ -383,18 +413,18 @@ function getNoteContentPosition() {
// 测量自定义节点内容元素的宽高
function measureCustomNodeContentSize(content) {
if (!commonCaches.measureCustomNodeContentSizeEl) {
commonCaches.measureCustomNodeContentSizeEl = document.createElement('div')
commonCaches.measureCustomNodeContentSizeEl.style.cssText = `
if (!this.mindMap.commonCaches.measureCustomNodeContentSizeEl) {
this.mindMap.commonCaches.measureCustomNodeContentSizeEl = document.createElement('div')
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.style.cssText = `
position: fixed;
left: -99999px;
top: -99999px;
`
this.mindMap.el.appendChild(commonCaches.measureCustomNodeContentSizeEl)
this.mindMap.el.appendChild(this.mindMap.commonCaches.measureCustomNodeContentSizeEl)
}
commonCaches.measureCustomNodeContentSizeEl.innerHTML = ''
commonCaches.measureCustomNodeContentSizeEl.appendChild(content)
let rect = commonCaches.measureCustomNodeContentSizeEl.getBoundingClientRect()
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.innerHTML = ''
this.mindMap.commonCaches.measureCustomNodeContentSizeEl.appendChild(content)
let rect = this.mindMap.commonCaches.measureCustomNodeContentSizeEl.getBoundingClientRect()
return {
width: rect.width,
height: rect.height
@@ -415,6 +445,7 @@ export default {
createHyperlinkNode,
createTagNode,
createNoteNode,
createAttachmentNode,
getNoteContentPosition,
measureCustomNodeContentSize,
isUseCustomNodeContent

View File

@@ -51,6 +51,7 @@ function createGeneralizationNode() {
if (!cur.generalizationNode) {
cur.generalizationNode = new Node({
data: {
inserting: item.inserting,
data: item
},
uid: createUid(),
@@ -59,6 +60,7 @@ function createGeneralizationNode() {
isGeneralization: true
})
}
delete item.inserting
// 关联所属节点
cur.generalizationNode.generalizationBelongNode = this
// 大小

View File

@@ -37,7 +37,7 @@ class View {
this.mindMap.event.on('drag', (e, event) => {
// 按住ctrl键拖动为多选
// 禁用拖拽
if (e.ctrlKey || this.mindMap.opt.isDisableDrag) {
if (e.ctrlKey || e.metaKey || this.mindMap.opt.isDisableDrag) {
return
}
if (this.firstDrag) {
@@ -72,7 +72,11 @@ class View {
return customHandleMousewheel(e)
}
// 1.鼠标滚轮事件控制缩放
if (mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM || e.ctrlKey) {
if (
mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM ||
e.ctrlKey ||
e.metaKey
) {
if (disableMouseWheelZoom) return
const { x: clientX, y: clientY } = this.mindMap.toPos(
e.clientX,
@@ -158,7 +162,8 @@ class View {
...viewData.transform
})
this.mindMap.emit('view_data_change', this.getTransformData())
this.mindMap.emit('scale', this.scale)
this.emitEvent('scale')
this.emitEvent('translate')
}
}
@@ -168,6 +173,7 @@ class View {
this.x += x
this.y += y
this.transform()
this.emitEvent('translate')
}
// 平移x方向
@@ -175,12 +181,14 @@ class View {
if (step === 0) return
this.x += step
this.transform()
this.emitEvent('translate')
}
// 平移x方式到
translateXTo(x) {
this.x = x
this.transform()
this.emitEvent('translate')
}
// 平移y方向
@@ -188,12 +196,14 @@ class View {
if (step === 0) return
this.y += step
this.transform()
this.emitEvent('translate')
}
// 平移y方向到
translateYTo(y) {
this.y = y
this.transform()
this.emitEvent('translate')
}
// 应用变换
@@ -211,13 +221,17 @@ class View {
// 恢复
reset() {
let scaleChange = this.scale !== 1
const scaleChange = this.scale !== 1
const translateChange = this.x !== 0 || this.y !== 0
this.scale = 1
this.x = 0
this.y = 0
this.transform()
if (scaleChange) {
this.mindMap.emit('scale', this.scale)
this.emitEvent('scale')
}
if (translateChange) {
this.emitEvent('translate')
}
}
@@ -227,7 +241,7 @@ class View {
const scale = Math.max(this.scale - scaleRatio, 0.1)
this.scaleInCenter(scale, cx, cy)
this.transform()
this.mindMap.emit('scale', this.scale)
this.emitEvent('scale')
}
// 放大
@@ -236,7 +250,7 @@ class View {
const scale = this.scale + scaleRatio
this.scaleInCenter(scale, cx, cy)
this.transform()
this.mindMap.emit('scale', this.scale)
this.emitEvent('scale')
}
// 基于指定中心进行缩放cxcy 可不指定,此时会使用画布中心点
@@ -262,15 +276,16 @@ class View {
this.scale = scale
}
this.transform()
this.mindMap.emit('scale', this.scale)
this.emitEvent('scale')
}
// 适应画布大小
fit() {
const { fitPadding } = this.mindMap.opt
fit(getRbox = () => {}, enlarge = false, fitPadding) {
fitPadding =
fitPadding === undefined ? this.mindMap.opt.fitPadding : fitPadding
const draw = this.mindMap.draw
const origTransform = draw.transform()
const rect = draw.rbox()
const rect = getRbox() || draw.rbox()
const drawWidth = rect.width / origTransform.scaleX
const drawHeight = rect.height / origTransform.scaleY
const drawRatio = drawWidth / drawHeight
@@ -280,7 +295,7 @@ class View {
const elRatio = elWidth / elHeight
let newScale = 0
let flag = ''
if (drawWidth <= elWidth && drawHeight <= elHeight) {
if (drawWidth <= elWidth && drawHeight <= elHeight && !enlarge) {
newScale = 1
flag = 1
} else {
@@ -298,7 +313,7 @@ class View {
newScale = newWidth / drawWidth
}
this.setScale(newScale)
const newRect = draw.rbox()
const newRect = getRbox() || draw.rbox()
// 需要考虑画布容器距浏览器窗口左上角的距离
newRect.x -= this.mindMap.elRect.left
newRect.y -= this.mindMap.elRect.top
@@ -394,6 +409,16 @@ class View {
bottom
}
}
// 派发事件
emitEvent(type) {
switch (type) {
case 'scale':
this.mindMap.emit('scale', this.scale)
case 'translate':
this.mindMap.emit('translate', this.x, this.y)
}
}
}
export default View

View File

@@ -144,9 +144,10 @@ class Base {
this.cacheNode(newUid, newNode)
// 数据关联实际节点
data._node = newNode
if (data.data.isActive) {
this.renderer.addNodeToActiveList(newNode)
}
}
// 如果该节点数据是已激活状态,那么添加到激活节点列表里
if (data.data.isActive) {
this.renderer.addNodeToActiveList(newNode)
}
// 如果当前节点在激活节点列表里,那么添加上激活的状态
if (this.mindMap.renderer.findActiveNodeIndex(newNode) !== -1) {

View File

@@ -0,0 +1,309 @@
import {
walk,
getNodeTreeBoundingRect,
fullscrrenEvent,
fullScreen,
exitFullScreen
} from '../utils/index'
import { keyMap } from '../core/command/keyMap'
const defaultConfig = {
boxShadowColor: 'rgba(0, 0, 0, 0.8)', // 高亮框四周的区域颜色
borderRadius: '5px', // 高亮框的圆角大小
transition: 'all 0.3s ease-out', // 高亮框动画的过渡
zIndex: 9999, // 高亮框元素的层级
padding: 20, // 高亮框的内边距
margin: 50 // 高亮框的外边距
}
// 演示插件
class Demonstrate {
constructor(opt) {
this.mindMap = opt.mindMap
this.stepList = []
this.currentStepIndex = 0
this.maskEl = null
this.highlightEl = null
this.transformState = null
this.renderTree = null
this.config = Object.assign(
{ ...defaultConfig },
this.mindMap.opt.demonstrateConfig || {}
)
}
// 进入演示模式
enter() {
// 全屏
this.bindFullscreenEvent()
// 如果已经全屏了
if (document.fullscreenElement === this.mindMap.el) {
this._enter()
} else {
// 否则申请全屏
fullScreen(this.mindMap.el)
}
}
_enter() {
// 记录演示前的画布状态
this.transformState = this.mindMap.view.getTransformData()
// 记录演示前的画布数据
this.renderTree = this.mindMap.getData()
// 暂停收集历史记录
this.mindMap.command.pause()
// 暂停思维导图快捷键响应
this.mindMap.keyCommand.pause()
// 创建高亮元素
this.createHighlightEl()
// 计算步骤数据
this.getStepList()
// 收起所有节点
this.mindMap.execCommand('UNEXPAND_ALL', false)
const onRenderEnd = () => {
this.mindMap.off('node_tree_render_end', onRenderEnd)
// 聚焦到第一步
this.jump(this.currentStepIndex)
this.bindEvent()
}
this.mindMap.on('node_tree_render_end', onRenderEnd)
}
// 退出演示模式
exit() {
exitFullScreen(this.mindMap.el)
this.mindMap.updateData(this.renderTree)
this.mindMap.view.setTransformData(this.transformState)
this.renderTree = null
this.transformState = null
this.stepList = []
this.currentStepIndex = 0
this.unBindEvent()
this.removeHighlightEl()
this.mindMap.command.recovery()
this.mindMap.keyCommand.recovery()
this.mindMap.emit('exit_demonstrate')
}
// 创建高亮元素
createHighlightEl() {
if (!this.highlightEl) {
// 遮罩元素
this.maskEl = document.createElement('div')
this.maskEl.style.cssText = `
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: ${this.config.zIndex};
`
this.mindMap.el.appendChild(this.maskEl)
// 高亮元素
this.highlightEl = document.createElement('div')
this.highlightEl.style.cssText = `
position: absolute;
box-shadow: 0 0 0 5000px ${this.config.boxShadowColor};
border-radius: ${this.config.borderRadius};
transition: ${this.config.transition};
z-index: ${this.config.zIndex + 1};
`
this.mindMap.el.appendChild(this.highlightEl)
}
}
// 移除高亮元素
removeHighlightEl() {
if (this.highlightEl) {
this.mindMap.el.removeChild(this.highlightEl)
this.highlightEl = null
}
if (this.maskEl) {
this.mindMap.el.removeChild(this.maskEl)
this.maskEl = null
}
}
// 更新高亮元素的位置和大小
updateHighlightEl({ left, top, width, height }) {
const padding = this.config.padding
if (left) {
this.highlightEl.style.left = left - padding + 'px'
}
if (top) {
this.highlightEl.style.top = top - padding + 'px'
}
if (width) {
this.highlightEl.style.width = width + padding * 2 + 'px'
}
if (height) {
this.highlightEl.style.height = height + padding * 2 + 'px'
}
}
// 绑定事件
bindEvent() {
this.onKeydown = this.onKeydown.bind(this)
window.addEventListener('keydown', this.onKeydown)
}
// 绑定全屏事件
bindFullscreenEvent() {
this.onFullscreenChange = this.onFullscreenChange.bind(this)
document.addEventListener(fullscrrenEvent, this.onFullscreenChange)
}
// 解绑事件
unBindEvent() {
window.removeEventListener('keydown', this.onKeydown)
document.removeEventListener(fullscrrenEvent, this.onFullscreenChange)
}
// 全屏状态改变
onFullscreenChange() {
if (!document.fullscreenElement) {
this.exit()
} else if (document.fullscreenElement === this.mindMap.el) {
this._enter()
}
}
// 按键事件
onKeydown(e) {
// 上一个
if (e.keyCode === keyMap.Left) {
this.prev()
} else if (e.keyCode === keyMap.Right) {
// 下一个
this.next()
} else if (e.keyCode === keyMap.Esc) {
// 退出演示
this.exit()
}
}
// 上一张
prev() {
if (this.currentStepIndex > 0) {
this.jump(this.currentStepIndex - 1)
}
}
// 下一张
next() {
const stepLength = this.stepList.length
if (this.currentStepIndex < stepLength - 1) {
this.jump(this.currentStepIndex + 1)
}
}
// 跳转到某一张
jump(index) {
this.currentStepIndex = index
this.mindMap.emit(
'demonstrate_jump',
this.currentStepIndex,
this.stepList.length
)
const step = this.stepList[index]
// 这一步的节点数据
const nodeData = step.node
// 该节点的uid
const uid = nodeData.data.uid
// 根据uid在画布上找到该节点实例
const node = this.mindMap.renderer.findNodeByUid(uid)
// 如果该节点实例不存在,那么先展开到该节点
if (!node) {
this.mindMap.renderer.expandToNodeUid(uid, () => {
this.jump(index)
})
return
}
// 1.聚焦到某个节点
if (step.type === 'node') {
// 适应画布大小
this.mindMap.view.fit(
() => {
return node.group.rbox()
},
true,
this.config.padding + this.config.margin
)
const rect = node.group.rbox()
this.updateHighlightEl({
left: rect.x,
top: rect.y,
width: rect.width,
height: rect.height
})
} else {
// 2.聚焦到某个节点的所有子节点
// 聚焦该节点的所有子节点
const task = () => {
// 先收起该节点所有子节点的子节点
nodeData.children.forEach(item => {
item.data.expand = false
})
this.mindMap.render(() => {
// 适应画布大小
this.mindMap.view.fit(
() => {
const res = getNodeTreeBoundingRect(node, 0, 0, 0, 0, true)
return {
...res,
x: res.left,
y: res.top
}
},
true,
this.config.padding + this.config.margin
)
const res = getNodeTreeBoundingRect(node, 0, 0, 0, 0, true)
this.updateHighlightEl(res)
})
}
// 如果该节点是收起状态,那么需要先展开
if (!nodeData.data.expand) {
this.mindMap.execCommand('SET_NODE_EXPAND', node, true)
const onRenderEnd = () => {
this.mindMap.off('node_tree_render_end', onRenderEnd)
task()
}
this.mindMap.on('node_tree_render_end', onRenderEnd)
} else {
// 否则直接聚焦
task()
}
}
}
// 深度度优先遍历所有节点,返回步骤列表
getStepList() {
walk(this.mindMap.renderer.renderTree, null, node => {
this.stepList.push({
type: 'node',
node
})
if (node.children.length > 1) {
this.stepList.push({
type: 'children',
node
})
}
})
}
// 插件被移除前做的事情
beforePluginRemove() {
this.unBindEvent()
}
// 插件被卸载前做的事情
beforePluginDestroy() {
this.unBindEvent()
}
}
Demonstrate.instanceName = 'demonstrate'
export default Demonstrate

View File

@@ -122,6 +122,10 @@ class Drag extends Base {
if (!this.isMousedown) {
return
}
// 停止自动移动
if (this.mindMap.opt.autoMoveWhenMouseInEdgeOnDrag && this.mindMap.select) {
this.mindMap.select.clearAutoMoveTimer()
}
this.isMousedown = false
// 恢复被拖拽节点的临时设置
this.beingDragNodeList.forEach(node => {

View File

@@ -47,15 +47,26 @@ class Export {
}
// 获取svg数据
async getSvgData() {
let { exportPaddingX, exportPaddingY, errorHandler, resetCss, addContentToHeader, addContentToFooter } =
this.mindMap.opt
let { svg, svgHTML } = this.mindMap.getSvgData({
async getSvgData(node) {
let {
exportPaddingX,
exportPaddingY,
errorHandler,
resetCss,
addContentToHeader,
addContentToFooter
} = this.mindMap.opt
let { svg, svgHTML, clipData } = this.mindMap.getSvgData({
paddingX: exportPaddingX,
paddingY: exportPaddingY,
addContentToHeader,
addContentToFooter
addContentToFooter,
node
})
if (clipData) {
clipData.paddingX = exportPaddingX
clipData.paddingY = exportPaddingY
}
// svg的image标签把图片的url转换成data:url类型否则导出会丢失图片
const task1 = this.createTransformImgTaskList(
svg,
@@ -90,12 +101,13 @@ class Export {
}
return {
node: svg,
str: svgHTML
str: svgHTML,
clipData
}
}
// svg转png
svgToPng(svgSrc, transparent) {
svgToPng(svgSrc, transparent, clipData = null) {
return new Promise((resolve, reject) => {
const img = new Image()
// 跨域图片需要添加这个属性,否则画布被污染了无法导出图片
@@ -109,6 +121,15 @@ class Export {
)
let imgWidth = img.width
let imgHeight = img.height
// 如果是裁减操作的话,那么需要手动添加内边距,及调整图片大小为实际的裁减区域的大小,不要忘了内边距哦
let paddingX = 0
let paddingY = 0
if (clipData) {
paddingX = clipData.paddingX
paddingY = clipData.paddingY
imgWidth = clipData.width + paddingX * 2
imgHeight = clipData.height + paddingY * 2
}
// 检查是否超出canvas支持的像素上限
const maxSize = 16384 / dpr
const maxArea = maxSize * maxSize
@@ -135,7 +156,22 @@ class Export {
await this.drawBackgroundToCanvas(ctx, imgWidth, imgHeight)
}
// 图片绘制到canvas里
ctx.drawImage(img, 0, 0, imgWidth, imgHeight)
// 如果有裁减数据,那么需要进行裁减
if (clipData) {
ctx.drawImage(
img,
clipData.left,
clipData.top,
clipData.width,
clipData.height,
paddingX,
paddingY,
clipData.width,
clipData.height
)
} else {
ctx.drawImage(img, 0, 0, imgWidth, imgHeight)
}
resolve(canvas.toDataURL())
} catch (error) {
reject(error)
@@ -219,13 +255,24 @@ class Export {
* 方法1.把svg的图片都转化成data:url格式再转换
* 方法2.把svg的图片提取出来再挨个绘制到canvas里最后一起转换
*/
async png(name, transparent = false) {
const { str } = await this.getSvgData()
async png(name, transparent = false, node = null) {
this.handleNodeExport(node)
const { str, clipData } = await this.getSvgData(node)
const svgUrl = await this.fixSvgStrAndToBlob(str)
const res = await this.svgToPng(svgUrl, transparent)
const res = await this.svgToPng(svgUrl, transparent, clipData)
return res
}
// 导出指定节点,如果该节点是激活状态,那么取消激活和隐藏展开收起按钮
handleNodeExport(node) {
if (node && node.getData('isActive')) {
node.deactivate()
if (!this.mindMap.opt.alwaysShowExpandBtn && node.getData('expand')) {
node.removeExpandBtn()
}
}
}
// 导出为pdf
async pdf(name, transparent = false) {
if (!this.mindMap.doExportPDF) {

View File

@@ -93,10 +93,7 @@ class MiniMap {
return {
getImgUrl: async callback => {
const blob = new Blob([svgStr], {
type: 'image/svg+xml'
})
const res = await readBlob(blob)
const res = await this.mindMap.doExport.fixSvgStrAndToBlob(svgStr)
callback(res)
},
svgHTML: svgStr, // 小地图html

View File

@@ -48,7 +48,9 @@ class RainbowLines {
// 获取一个节点的第二层级的祖先节点
getSecondLayerAncestor(node) {
if (node.layerIndex === 1) {
if (node.layerIndex === 0) {
return null
} else if (node.layerIndex === 1) {
return node
} else {
let res = null
@@ -78,6 +80,7 @@ class RainbowLines {
const { rainbowLinesConfig } = this.mindMap.opt
if (!rainbowLinesConfig || !rainbowLinesConfig.open) return ''
const ancestor = this.getSecondLayerAncestor(node)
if (!ancestor) return
const index = getNodeDataIndex(ancestor)
const colorsList = this.getColorsList()
return colorsList[index % colorsList.length]

View File

@@ -327,8 +327,8 @@ class RichText {
list.forEach(node => {
this.mindMap.execCommand('SET_NODE_TEXT', node, html, true)
// if (node.isGeneralization) {
// 概要节点
// node.generalizationBelongNode.updateGeneralization()
// 概要节点
// node.generalizationBelongNode.updateGeneralization()
// }
this.mindMap.render()
})
@@ -649,7 +649,18 @@ class RichText {
if (node.data.richText) {
node.data.richText = false
node.data.text = getTextFromHtml(node.data.text)
// delete node.data.uid
}
// 概要
let generalization =
node.data && node.data.generalization ? node.data.generalization : []
generalization = Array.isArray(generalization)
? generalization
: [generalization]
if (generalization.length > 0) {
generalization.forEach(item => {
item.richText = false
item.text = getTextFromHtml(item.text)
})
}
},
null,
@@ -670,6 +681,18 @@ class RichText {
root.data.richText = true
root.data.resetRichText = true
}
// 概要
let generalization =
root.data && root.data.generalization ? root.data.generalization : []
generalization = Array.isArray(generalization)
? generalization
: [generalization]
if (generalization.length > 0) {
generalization.forEach(item => {
item.richText = true
item.resetRichText = true
})
}
if (root.children && root.children.length > 0) {
Array.from(root.children).forEach(item => {
walk(item)

View File

@@ -86,6 +86,7 @@ class Search {
this.matchNodeList = []
this.currentIndex = -1
const { isOnlySearchCurrentRenderNodes } = this.mindMap.opt
// 如果要搜索收起来的节点,那么要遍历渲染树而不是节点树
const tree = isOnlySearchCurrentRenderNodes
? this.mindMap.renderer.root
: this.mindMap.renderer.renderTree
@@ -103,6 +104,11 @@ class Search {
})
}
// 判断对象是否是节点实例
isNodeInstance(node) {
return node instanceof Node
}
// 搜索下一个,定位到下一个匹配节点
searchNext(callback) {
if (!this.isSearching || this.matchNodeList.length <= 0) return
@@ -113,13 +119,12 @@ class Search {
}
const currentNode = this.matchNodeList[this.currentIndex]
this.notResetSearchText = true
const uid =
currentNode instanceof Node
? currentNode.getData('uid')
: currentNode.data.uid
const uid = this.isNodeInstance(currentNode)
? currentNode.getData('uid')
: currentNode.data.uid
const targetNode = this.mindMap.renderer.findNodeByUid(uid)
this.mindMap.execCommand('GO_TARGET_NODE', uid, node => {
if (!(currentNode instanceof Node)) {
if (!this.isNodeInstance(currentNode)) {
this.matchNodeList[this.currentIndex] = node
}
callback()
@@ -173,15 +178,20 @@ class Search {
return
replaceText = String(replaceText)
this.matchNodeList.forEach(node => {
let text = this.getReplacedText(node, this.searchText, replaceText)
this.mindMap.renderer.setNodeDataRender(
node,
{
text,
resetRichText: !!node.getData('richText')
},
true
)
const text = this.getReplacedText(node, this.searchText, replaceText)
if (this.isNodeInstance(node)) {
this.mindMap.renderer.setNodeDataRender(
node,
{
text,
resetRichText: !!node.getData('richText')
},
true
)
} else {
node.data.text = text
node.data.resetRichText = !!node.data.richText
}
})
this.mindMap.render()
this.mindMap.command.addHistory()
@@ -190,7 +200,9 @@ class Search {
// 获取某个节点替换后的文本
getReplacedText(node, searchText, replaceText) {
let { richText, text } = node.getData()
let { richText, text } = this.isNodeInstance(node)
? node.getData()
: node.data
if (richText) {
return replaceHtmlText(text, searchText, replaceText)
} else {

View File

@@ -44,7 +44,7 @@ class Select {
}
let { useLeftKeySelectionRightKeyDrag } = this.mindMap.opt
if (
!e.ctrlKey &&
!(e.ctrlKey || e.metaKey) &&
(useLeftKeySelectionRightKeyDrag ? e.which !== 1 : e.which !== 3)
) {
return

View File

@@ -8,6 +8,10 @@ const hyperlink =
const note =
'<svg t="1624195132675" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8792" ><path d="M152.768 985.984 152.768 49.856l434.56 0 66.816 0 234.048 267.392 0 66.816 0 601.92L152.768 985.984 152.768 985.984zM654.144 193.088l0 124.16 108.736 0L654.144 193.088 654.144 193.088zM821.312 384.064l-167.168 0L587.328 384.064 587.328 317.312 587.328 116.736 219.584 116.736 219.584 919.04l601.728 0L821.312 384.064 821.312 384.064zM386.688 517.888 319.808 517.888 319.808 450.944l66.816 0L386.624 517.888 386.688 517.888zM386.688 651.584 319.808 651.584 319.808 584.704l66.816 0L386.624 651.584 386.688 651.584zM386.688 785.344 319.808 785.344l0-66.88 66.816 0L386.624 785.344 386.688 785.344zM721.024 517.888 453.632 517.888 453.632 450.944l267.392 0L721.024 517.888 721.024 517.888zM654.144 651.584 453.632 651.584 453.632 584.704l200.512 0L654.144 651.584 654.144 651.584zM620.672 785.344l-167.04 0 0-66.88 167.04 0L620.672 785.344 620.672 785.344z" p-id="8793"></path></svg>'
// 附件图标
const attachment =
'<svg t="1711935375590" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3864" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M516.373333 375.978667l136.576-136.576a147.797333 147.797333 0 0 1 208.853334-0.021334 147.690667 147.690667 0 0 1-0.042667 208.832l-204.8 204.778667v0.021333l-153.621333 153.6c-85.973333 85.973333-225.28 85.973333-311.253334 0.021334-85.994667-85.973333-85.973333-225.216 0.149334-311.36L431.146667 256.362667a21.333333 21.333333 0 0 0-30.165334-30.165334L162.069333 465.066667c-102.805333 102.826667-102.826667 269.056-0.149333 371.733333 102.613333 102.613333 268.970667 102.613333 371.584 0l153.6-153.642667h0.021333l0.021334-0.021333 204.778666-204.778667c74.325333-74.325333 74.346667-194.858667 0.021334-269.184-74.24-74.24-194.88-74.24-269.162667 0.042667l-136.576 136.554667-187.626667 187.626666a117.845333 117.845333 0 0 0-0.106666 166.826667 118.037333 118.037333 0 0 0 166.826666-0.106667l255.850667-255.829333a21.333333 21.333333 0 0 0-30.165333-30.165333L435.136 669.973333a75.370667 75.370667 0 0 1-106.496 0.106667 75.178667 75.178667 0 0 1 0.128-106.496l187.605333-187.605333z" p-id="3865"></path></svg>'
// 节点icon
export const nodeIconList = [
{
@@ -303,6 +307,7 @@ const getNodeIconListIcon = (name, extendIconList = []) => {
export default {
hyperlink,
note,
attachment,
nodeIconList,
getNodeIconListIcon
}

View File

@@ -157,8 +157,15 @@ export const copyRenderTree = (tree, root, removeActiveState = false) => {
tree.data = simpleDeepClone(root.data)
if (removeActiveState) {
tree.data.isActive = false
if (tree.data.generalization) {
tree.data.generalization.isActive = false
const generalization = tree.data.generalization
if (generalization) {
if (Array.isArray(generalization)) {
generalization.forEach(item => {
item.isActive = false
})
} else {
generalization.isActive = false
}
}
}
tree.children = []
@@ -1361,3 +1368,96 @@ export const handleGetSvgDataExtraContent = ({
footerHeight
}
}
// 获取指定节点的包围框信息
export const getNodeTreeBoundingRect = (
node,
x = 0,
y = 0,
paddingX = 0,
paddingY = 0,
excludeSelf = false
) => {
let minX = Infinity
let maxX = -Infinity
let minY = Infinity
let maxY = -Infinity
const walk = (root, isRoot) => {
if (!(isRoot && excludeSelf)) {
const { x, y, width, height } = root.group
.findOne('.smm-node-shape')
.rbox()
if (x < minX) {
minX = x
}
if (x + width > maxX) {
maxX = x + width
}
if (y < minY) {
minY = y
}
if (y + height > maxY) {
maxY = y + height
}
}
if (root._generalizationList.length > 0) {
root._generalizationList.forEach(item => {
walk(item.generalizationNode)
})
}
if (root.children) {
root.children.forEach(item => {
walk(item)
})
}
}
walk(node, true)
minX = minX - x + paddingX
minY = minY - y + paddingY
maxX = maxX - x + paddingX
maxY = maxY - y + paddingY
return {
left: minX,
top: minY,
width: maxX - minX,
height: maxY - minY
}
}
// 全屏事件检测
const getOnfullscreEnevt = () => {
if (document.documentElement.requestFullScreen) {
return 'fullscreenchange'
} else if (document.documentElement.webkitRequestFullScreen) {
return 'webkitfullscreenchange'
} else if (document.documentElement.mozRequestFullScreen) {
return 'mozfullscreenchange'
} else if (document.documentElement.msRequestFullscreen) {
return 'msfullscreenchange'
}
}
export const fullscrrenEvent = getOnfullscreEnevt()
// 全屏
export const fullScreen = element => {
if (element.requestFullScreen) {
element.requestFullScreen()
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen()
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen()
}
}
// 退出全屏
export const exitFullScreen = () => {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
src: url('iconfont.woff2?t=1711536835850') format('woff2'),
url('iconfont.woff?t=1711536835850') format('woff'),
url('iconfont.ttf?t=1711536835850') format('truetype');
src: url('iconfont.woff2?t=1713438156457') format('woff2'),
url('iconfont.woff?t=1713438156457') format('woff'),
url('iconfont.ttf?t=1713438156457') format('truetype');
}
.iconfont {
@@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.iconyanshibofang:before {
content: "\e648";
}
.iconfujian:before {
content: "\e88a";
}
.icongeshihua:before {
content: "\e7a3";
}

View File

@@ -98,7 +98,8 @@ export default {
removeHyperlink: 'Remove hyperlink',
removeNote: 'Remove note',
removeCustomStyles: 'Remove custom styles',
removeAllNodeCustomStyles: 'Remove all node custom styles'
removeAllNodeCustomStyles: 'Remove all node custom styles',
exportNodeToPng: 'Export node to png'
},
count: {
words: 'Words',
@@ -138,6 +139,9 @@ export default {
fullscreenShow: 'Full screen show',
fullscreenEdit: 'Full screen edit'
},
demonstrate: {
demonstrate: 'Enter demonstration mode'
},
import: {
title: 'Import',
selectFile: 'Select file',
@@ -259,6 +263,7 @@ export default {
associativeLine: 'Associative line',
painter: 'Painter',
formula: 'Formula',
attachment: 'Attachment',
more: 'More',
selectFileTip: 'Please select a file',
notSupportTip:
@@ -281,7 +286,8 @@ export default {
tip: 'Tip',
yes: 'Yes',
no: 'No',
exportError: 'Export failed'
exportError: 'Export failed',
dragTip: 'Release here to import the file'
},
mouseAction: {
tip1:
@@ -331,5 +337,9 @@ export default {
formatErrorTip: 'The JSON format is incorrect. Please check and try again',
copyTip: 'Copied to clipboard',
formatTip: 'Format complete'
},
attachment: {
deleteAttachment: 'Delete attachment',
tip: 'The attachment function is only available on the client side'
}
}

View File

@@ -98,7 +98,8 @@ export default {
removeHyperlink: '移除超链接',
removeNote: '移除备注',
removeCustomStyles: '一键去除自定义样式',
removeAllNodeCustomStyles: '一键去除所有节点自定义样式'
removeAllNodeCustomStyles: '一键去除所有节点自定义样式',
exportNodeToPng: '导出该节点为图片'
},
count: {
words: '字数',
@@ -136,6 +137,9 @@ export default {
fullscreenShow: '全屏查看',
fullscreenEdit: '全屏编辑'
},
demonstrate: {
demonstrate: '进入演示模式'
},
import: {
title: '导入',
selectFile: '选取文件',
@@ -256,6 +260,7 @@ export default {
associativeLine: '关联线',
painter: '格式刷',
formula: '公式',
attachment: '附件',
more: '更多',
selectFileTip: '请选择文件',
notSupportTip: '你的浏览器不支持该功能或者当前页面非https协议',
@@ -277,7 +282,8 @@ export default {
tip: '提示',
yes: '是',
no: '否',
exportError: '导出失败'
exportError: '导出失败',
dragTip: '在此释放以导入该文件'
},
mouseAction: {
tip1: '当前:左键拖动画布,右键框选节点',
@@ -325,5 +331,9 @@ export default {
formatErrorTip: 'JSON格式有误请检查后再试',
copyTip: '已复制到剪贴板',
formatTip: '格式化完成'
},
attachment: {
deleteAttachment: '删除附件',
tip: '附件功能仅在客户端可用'
}
}

View File

@@ -11,7 +11,7 @@ let langList = [
}
]
let StartList = ['introduction', 'start', 'deploy', 'client', 'translate', 'changelog']
let CourseList = new Array(26).fill(0).map((_, index) => {
let CourseList = new Array(27).fill(0).map((_, index) => {
return 'course' + (index + 1)
})
let APIList = [
@@ -40,6 +40,7 @@ let APIList = [
'cooperate',
'rainbowLines',
'handDrawnLikeStyle',
'demonstrate',
'xmind',
'markdown',
'utils'

View File

@@ -1,5 +1,79 @@
# Changelog
## 0.9.11
Fix
> 1.Fix the issue where clicking on the summary will trigger the data_change_detail event;
>
> 2.Fix the issue where the custom style command for removing all nodes with one click does not support summaries that are not arrays;
>
> 3.Fix the issue where summary nodes created in rich text mode are not rich text;
>
> 4.Fix the issue where the rich text plugin did not process node summaries when converting node data;
>
> 5.Fix the issue where the highlighted box of the corresponding node will be displayed incorrectly when pressing enter to end in summary node text editing;
>
> 6.Fix the issue of node width and height loss after text editing when creating multiple instances simultaneously;
>
> 7.Fix the issue where the expand/collapse button does not disappear after deleting all child nodes of the currently activated node;
>
> 8.Fix the issue where the canvas automatically moves and cannot stop when dragging nodes to the edge;
New:
> 1.Support default focus and entering editing mode when inserting summaries;
>
> 2.Support holding down the Command and Win keys to select multiple nodes;
>
> 3.Support exporting a node as an image;
>
> 4.Add demonstration plugin;
Demo:
> 1.Add the Export as Image button in the right-click menu of the node;
>
> 2.Optimize the issue of incomplete menu display when clicking the right mouse button at the window edge;
>
> 3.Add demonstration mode;
>
> 4.When copying Zhixi data, create summary data in array form;
## 0.9.10
Fix:
> 1.Fix the issue of all replace operation error during search;
>
> 2.Fix the issue of rendering the mini map with entity characters that are not supported by SVG in node text;
New:
> 1.Add an event translate when moving the canvas;
>
> 2.Node content supports setting attachments;
Demo
> 1.Support dragging and dropping files onto the page for import;
Client:
> 1.Nodes support adding attachments;
## 0.9.9-fix.2
Fix:
> 1.Fix the issue of the original node style not being updated during the insertion of the parent node operation;
>
> 2.Fix the issue of errors when switching structures when opening rainbow lines;
Demo:
> 1.Fix the issue where the side bar outline opens in source code editing mode when clicking full screen editing;
## 0.9.9-fix.1
Fix the issue where the search plugin was unable to search due to changes in the previous version.

View File

@@ -1,6 +1,61 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.9.11</h2>
<p>Fix</p>
<blockquote>
<p>1.Fix the issue where clicking on the summary will trigger the data_change_detail event;</p>
<p>2.Fix the issue where the custom style command for removing all nodes with one click does not support summaries that are not arrays;</p>
<p>3.Fix the issue where summary nodes created in rich text mode are not rich text;</p>
<p>4.Fix the issue where the rich text plugin did not process node summaries when converting node data;</p>
<p>5.Fix the issue where the highlighted box of the corresponding node will be displayed incorrectly when pressing enter to end in summary node text editing;</p>
<p>6.Fix the issue of node width and height loss after text editing when creating multiple instances simultaneously;</p>
<p>7.Fix the issue where the expand/collapse button does not disappear after deleting all child nodes of the currently activated node;</p>
<p>8.Fix the issue where the canvas automatically moves and cannot stop when dragging nodes to the edge;</p>
</blockquote>
<p>New:</p>
<blockquote>
<p>1.Support default focus and entering editing mode when inserting summaries;</p>
<p>2.Support holding down the Command and Win keys to select multiple nodes;</p>
<p>3.Support exporting a node as an image;</p>
<p>4.Add demonstration plugin;</p>
</blockquote>
<p>Demo:</p>
<blockquote>
<p>1.Add the Export as Image button in the right-click menu of the node;</p>
<p>2.Optimize the issue of incomplete menu display when clicking the right mouse button at the window edge;</p>
<p>3.Add demonstration mode;</p>
<p>4.When copying Zhixi data, create summary data in array form;</p>
</blockquote>
<h2>0.9.10</h2>
<p>Fix:</p>
<blockquote>
<p>1.Fix the issue of all replace operation error during search;</p>
<p>2.Fix the issue of rendering the mini map with entity characters that are not supported by SVG in node text;</p>
</blockquote>
<p>New:</p>
<blockquote>
<p>1.Add an event translate when moving the canvas;</p>
<p>2.Node content supports setting attachments;</p>
</blockquote>
<p>Demo</p>
<blockquote>
<p>1.Support dragging and dropping files onto the page for import;</p>
</blockquote>
<p>Client:</p>
<blockquote>
<p>1.Nodes support adding attachments;</p>
</blockquote>
<h2>0.9.9-fix.2</h2>
<p>Fix:</p>
<blockquote>
<p>1.Fix the issue of the original node style not being updated during the insertion of the parent node operation;</p>
<p>2.Fix the issue of errors when switching structures when opening rainbow lines;</p>
</blockquote>
<p>Demo:</p>
<blockquote>
<p>1.Fix the issue where the side bar outline opens in source code editing mode when clicking full screen editing;</p>
</blockquote>
<h2>0.9.9-fix.1</h2>
<p>Fix the issue where the search plugin was unable to search due to changes in the previous version.</p>
<h2>0.9.9</h2>

View File

@@ -7,6 +7,18 @@ to an operation that needs to add a copy to the history stack data. The
## Methods
### pause()
> v0.9.11+
Pause collecting historical data.
### recovery()
> v0.9.11+
Restore the collection of historical data.
### add(name, fn)
Add a command.

View File

@@ -6,6 +6,16 @@ includes many built-in commands and can also be added manually. A command refers
to an operation that needs to add a copy to the history stack data. The
<code>mindMap.command</code> instance can be obtained through this.&quot;</p>
<h2>Methods</h2>
<h3>pause()</h3>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>Pause collecting historical data.</p>
<h3>recovery()</h3>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>Restore the collection of historical data.</p>
<h3>add(name, fn)</h3>
<p>Add a command.</p>
<p><code>name</code>: Command name</p>

View File

@@ -24,7 +24,7 @@ const mindMap = new MindMap({
| Field Name | Type | Default Value | Description | Required |
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ | -------- |
| el | Element | | Container element, must be a DOM element | Yes |
| el | Element | | Container element, must be a DOM elementWhen the position of container elements on the page has changed but the size has not changed, the 'getElRectInfo()' method must be called to update the relevant information inside the library; When the size also changes, the 'resize()' method must be called, otherwise it will cause some functional exceptions | Yes |
| data | Object 、null | | Mind map data, Please refer to the introduction of 【Data structure】 below. V0.9.9+supports passing empty objects or null, and the canvas will display blank space | |
| layout | String | logicalStructure | Layout type, options: logicalStructure (logical structure diagram), mindMap (mind map), catalogOrganization (catalog organization diagram), organizationStructure (organization structure diagram)、timelinev0.5.4+, timeline、timeline2v0.5.4+, up down alternating timeline、fishbonev0.5.4+, fishbone diagram | |
| fishboneDegv0.5.4+ | Number | 45 | Set the diagonal angle of the fishbone structure diagram | |
@@ -118,6 +118,7 @@ const mindMap = new MindMap({
| rainbowLinesConfigv0.9.9+ | Object | { open: false, colorsList: [] } | Rainbow line configuration requires registering the RainbowLines plugin first. Object type, Structure: { open: false【Is turn on rainbow lines】, colorsList: []【Customize the color list for rainbow lines. If not set, the default color list will be used】 } | |
| addContentToHeaderv0.9.9+ | Function、null | null | Add custom content to the header when exporting PNG, SVG, and PDF. Can pass a function that can return null to indicate no content is added, or it can return an object, For a detailed introduction, please refer to section 【How to add custom content when exporting】 below | |
| addContentToFooterv0.9.9+ | Function、null | null | The basic definition is the same as addContentToHeader, adding custom content at the end | |
| demonstrateConfigv0.9.11+ | Object、null | null | Demonstration plugin configuration. If not transmitted, the default configuration will be used. An object can be transmitted. If only a certain property is configured, only that property can be set. Other properties that have not been set will also use the default configuration. For complete configuration, please refer to the 【Demonstration Plugin Configuration】 section below | |
### Data structure
@@ -142,9 +143,11 @@ The basic data structure is as follows:
hyperlinkTitle: '', // Title of hyperlink
note: '', // Content of remarks
tag: [], // Tag list
generalization: {// The summary of the node, if there is no summary, the generalization can be set to null
text: ''// Summary Text
},
generalization: [{// (Arrays are not supported in versions below 0.9.0, and only a single summary data can be set)The summary of the node, if there is no summary, the generalization can be set to null
text: '', // Summary Text
richText: false, // Is the text of the node in rich text mode
// ...The fields of other ordinary nodes are supported, But it does not support children
}],
associativeLineTargets: [''],// If there are associated lines, then it is the uid list of the target node
associativeLineText: '',// Association Line Text
// ...For other style fields, please refer to the topic
@@ -214,6 +217,17 @@ new MindMap({
})
```
### Demonstration Plugin Configuration
| Field Name | Type | Default Value | Description |
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
| boxShadowColor | String | rgba(0, 0, 0, 0.8) | The color of the area around the highlighted box |
| borderRadius | String | 5px | The size of the rounded corners of the highlighted box |
| transition | String | all 0.3s ease-out | Transition properties of highlight box animation and CSS transition properties |
| zIndex | Number | 9999 | The hierarchy of highlighted box elements |
| padding | Number | 20 | The inner margin of the highlighted box |
| margin | Number | 50 | The outer margin of the highlighted box |
## Static methods
### defineTheme(name, config)
@@ -353,6 +367,10 @@ Current Theme Configuration.
## Instance methods
### getElRectInfo()
Update the position and size information of container elements. Be sure to call this method to update information when the position of container elements on the page changes. If the size of container elements has also changed, please call the 'resize' method.
### updateData(data)
> v0.9.9+
@@ -371,7 +389,7 @@ Clear `lineDraw`、`associativeLineDraw`、`nodeDraw`、`otherDraw` containers.
Destroy mind maps. It will remove registered plugins, remove listening events, and delete all nodes on the canvas.
### getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter })
### getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter, node })
> v0.3.0+
@@ -385,6 +403,8 @@ Destroy mind maps. It will remove registered plugins, remove listening events, a
`addContentToFooter`v0.9.9+, Function, You can return the custom content to be added to the tail, as detailed in the configuration in 【Instantiation options】
`node`: v0.9.11+, Node instance, if passed, only export the content of that node
Get the `svg` data and return an object. The detailed structure is as follows:
```js
@@ -396,6 +416,7 @@ Get the `svg` data and return an object. The detailed structure is as follows:
origHeight, // Number, canvas height
scaleX, // Number, horizontal zoom value of mind map graphics
scaleY, // Number, vertical zoom value of mind map graphics
clipData// v0.9.11+If node is passed, that is, the content of the specified node is exported, then this field will be returned, Represents the position coordinate data of the node region cropped from the complete image
}
```
@@ -455,7 +476,8 @@ Listen to an event. Event list:
| expand_btn_click | Node expand or collapse event | this (node instance) |
| before_show_text_edit | Event before node text edit box opens | |
| hide_text_edit | Node text edit box close event | textEditNode (text edit box DOM node), activeNodeList (current list of active nodes) |
| scale | Zoom event | scale (zoom ratio) |
| scale | Canvas zoom event | scale (zoom ratio) |
| translatev0.9.10+ | Canvas movement event | xtranslate x、ytranslate y |
| node_img_dblclickv0.2.15+ | Node image double-click event | this (node instance), e (event object) |
| node_img_mouseenterv0.6.5+ | Node image mouseenter event | thisnode instance、imgNodeimg node、eevent object |
| node_img_mouseleavev0.6.5+ | Node image mouseleave event | thisnode instance、imgNodeimg node、eevent object |
@@ -482,6 +504,8 @@ Listen to an event. Event list:
| node_cooperate_avatar_clickv0.9.9+ | Triggered when the mouse clicks on a person's avatar during collaborative editing | userInfo(User info)、 this(Current node instance)、 node(Avatar node)、 e(Event Object) |
| node_cooperate_avatar_mouseenterv0.9.9+ | Triggered when the mouse moves over a person's avatar during collaborative editing | userInfo(User info)、 this(Current node instance)、 node(Avatar node)、 e(Event Object) |
| node_cooperate_avatar_mouseleavev0.9.9+ | Triggered when removing personnel avatars with the mouse during collaborative editing | userInfo(User info)、 this(Current node instance)、 node(Avatar node)、 e(Event Object) |
| exit_demonstratev0.9.11+ | Triggered when exiting demonstration mode | |
| demonstrate_jumpv0.9.11+ | Trigger when switching steps in demonstration mode | currentStepIndexThe index of the steps currently played, counting from 0、stepLengthTotal number of playback steps |
### emit(event, ...args)
@@ -573,7 +597,7 @@ redo. All commands are as follows:
| CLEAR_ACTIVE_NODE | Clear the active state of the currently active node(s), the active node will be the operation node | |
| SET_NODE_EXPAND | Set whether the node is expanded | node (the node to set), expand (boolean, whether to expand) |
| EXPAND_ALL | Expand all nodes | |
| UNEXPAND_ALL | Collapse all nodes | |
| UNEXPAND_ALL | Collapse all nodes | isSetRootNodeCenterv0.9.11+default is trueWill the root node be moved to the center after retracting all nodes |
| UNEXPAND_TO_LEVEL (v0.2.8+) | Expand to a specified level | level (the level to expand to, 1, 2, 3...) |
| SET_NODE_DATA | Update node data, that is, update the data in the data object of the node data object. Note that this command will not trigger view updates | node (the node to set), data (object, the data to update, e.g. `{expand: true}`) |
| SET_NODE_TEXT | Set node text | node (the node to set), text (the new text for the node), richTextv0.4.0+, If you want to set a rich text character, you need to set it to `true`、resetRichTextv0.6.10+Do you want to reset rich text? The default is false. If true is passed, the style of the rich text node will be reset |
@@ -581,11 +605,12 @@ redo. All commands are as follows:
| SET_NODE_ICON | Set Node Icon | node (node to set), icons (array, predefined image names array, available icons can be obtained in the nodeIconList list in the [icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js) file, icon name is type_name, such as ['priority_1']) |
| SET_NODE_HYPERLINK | Set Node Hyperlink | node (node to set), link (hyperlink address), title (hyperlink name, optional) |
| SET_NODE_NOTE | Set Node Note | node (node to set), note (note text) |
| SET_NODE_ATTACHMENTv0.9.10+ | Set node attachment | nodenode to set、urlattachment url、nameattachment name, optional |
| SET_NODE_TAG | Set Node Tag | node (node to set), tag (string array, built-in color information can be obtained in [constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js)) |
| INSERT_AFTER (v0.1.5+) | Move Node to After Another Node | node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node) |
| INSERT_BEFORE (v0.1.5+) | Move Node to Before Another Node | node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node) |
| MOVE_NODE_TO (v0.1.5+) | Move a node as a child of another node | node (the node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), toNode (the target node) |
| ADD_GENERALIZATION (v0.2.0+) | Add a node summary | data (the data for the summary, in object format, all numerical fields of the node are supported, default is `{text: 'summary'}`) |
| ADD_GENERALIZATION (v0.2.0+) | Add a node summary | data (the data for the summary, in object format, all numerical fields of the node are supported, default is `{text: 'summary'}`)、openEditv0.9.11+Default is trueWhether to enter text editing status by default |
| REMOVE_GENERALIZATION (v0.2.0+) | Remove a node summary | |
| SET_NODE_CUSTOM_POSITION (v0.2.0+) | Set a custom position for a node | node (the node to set), left (custom x coordinate, default is undefined), top (custom y coordinate, default is undefined) |
| RESET_LAYOUT (v0.2.0+) | Arrange layout with one click | |

View File

@@ -32,7 +32,7 @@
<td>el</td>
<td>Element</td>
<td></td>
<td>Container element, must be a DOM element</td>
<td>Container element, must be a DOM elementWhen the position of container elements on the page has changed but the size has not changed, the 'getElRectInfo()' method must be called to update the relevant information inside the library; When the size also changes, the 'resize()' method must be called, otherwise it will cause some functional exceptions</td>
<td>Yes</td>
</tr>
<tr>
@@ -686,6 +686,13 @@
<td>The basic definition is the same as addContentToHeader, adding custom content at the end</td>
<td></td>
</tr>
<tr>
<td>demonstrateConfigv0.9.11+</td>
<td>Object、null</td>
<td>null</td>
<td>Demonstration plugin configuration. If not transmitted, the default configuration will be used. An object can be transmitted. If only a certain property is configured, only that property can be set. Other properties that have not been set will also use the default configuration. For complete configuration, please refer to the 【Demonstration Plugin Configuration】 section below</td>
<td></td>
</tr>
</tbody>
</table>
<h3>Data structure</h3>
@@ -708,9 +715,11 @@
<span class="hljs-attr">hyperlinkTitle</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// Title of hyperlink</span>
<span class="hljs-attr">note</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// Content of remarks</span>
<span class="hljs-attr">tag</span>: [], <span class="hljs-comment">// Tag list</span>
<span class="hljs-attr">generalization</span>: {<span class="hljs-comment">// The summary of the node, if there is no summary, the generalization can be set to null</span>
<span class="hljs-attr">text</span>: <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-comment">// Summary Text</span>
},
<span class="hljs-attr">generalization</span>: [{<span class="hljs-comment">// (Arrays are not supported in versions below 0.9.0, and only a single summary data can be set)The summary of the node, if there is no summary, the generalization can be set to null</span>
<span class="hljs-attr">text</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// Summary Text</span>
<span class="hljs-attr">richText</span>: <span class="hljs-literal">false</span>, <span class="hljs-comment">// Is the text of the node in rich text mode</span>
<span class="hljs-comment">// ...The fields of other ordinary nodes are supported, But it does not support children</span>
}],
<span class="hljs-attr">associativeLineTargets</span>: [<span class="hljs-string">&#x27;&#x27;</span>],<span class="hljs-comment">// If there are associated lines, then it is the uid list of the target node</span>
<span class="hljs-attr">associativeLineText</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// Association Line Text</span>
<span class="hljs-comment">// ...For other style fields, please refer to the topic</span>
@@ -832,6 +841,55 @@
}
})
</code></pre>
<h3>Demonstration Plugin Configuration</h3>
<table>
<thead>
<tr>
<th>Field Name</th>
<th>Type</th>
<th>Default Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>boxShadowColor</td>
<td>String</td>
<td>rgba(0, 0, 0, 0.8)</td>
<td>The color of the area around the highlighted box</td>
</tr>
<tr>
<td>borderRadius</td>
<td>String</td>
<td>5px</td>
<td>The size of the rounded corners of the highlighted box</td>
</tr>
<tr>
<td>transition</td>
<td>String</td>
<td>all 0.3s ease-out</td>
<td>Transition properties of highlight box animation and CSS transition properties</td>
</tr>
<tr>
<td>zIndex</td>
<td>Number</td>
<td>9999</td>
<td>The hierarchy of highlighted box elements</td>
</tr>
<tr>
<td>padding</td>
<td>Number</td>
<td>20</td>
<td>The inner margin of the highlighted box</td>
</tr>
<tr>
<td>margin</td>
<td>Number</td>
<td>50</td>
<td>The outer margin of the highlighted box</td>
</tr>
</tbody>
</table>
<h2>Static methods</h2>
<h3>defineTheme(name, config)</h3>
<blockquote>
@@ -928,6 +986,8 @@ mindMap.setTheme(<span class="hljs-string">&#x27;Theme name&#x27;</span>)
<h3>themeConfig</h3>
<p>Current Theme Configuration.</p>
<h2>Instance methods</h2>
<h3>getElRectInfo()</h3>
<p>Update the position and size information of container elements. Be sure to call this method to update information when the position of container elements on the page changes. If the size of container elements has also changed, please call the 'resize' method.</p>
<h3>updateData(data)</h3>
<blockquote>
<p>v0.9.9+</p>
@@ -943,7 +1003,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;Theme name&#x27;</span>)
<p>v0.6.0+</p>
</blockquote>
<p>Destroy mind maps. It will remove registered plugins, remove listening events, and delete all nodes on the canvas.</p>
<h3>getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter })</h3>
<h3>getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter, node })</h3>
<blockquote>
<p>v0.3.0+</p>
</blockquote>
@@ -952,6 +1012,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;Theme name&#x27;</span>)
<p><code>ignoreWatermark</code>v0.8.0+, Do not draw watermarks. If you do not need to draw watermarks, you can pass 'true' because drawing watermarks is very slow</p>
<p><code>addContentToHeader</code>v0.9.9+, Function, You can return the custom content to be added to the header, as detailed in the configuration in 【Instantiation options】</p>
<p><code>addContentToFooter</code>v0.9.9+, Function, You can return the custom content to be added to the tail, as detailed in the configuration in 【Instantiation options】</p>
<p><code>node</code>: v0.9.11+, Node instance, if passed, only export the content of that node</p>
<p>Get the <code>svg</code> data and return an object. The detailed structure is as follows:</p>
<pre class="hljs"><code>{
svg, <span class="hljs-comment">// Element, the overall svg element of the mind map graphics, including: svg (canvas container), g (actual mind map group)</span>
@@ -961,6 +1022,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;Theme name&#x27;</span>)
origHeight, <span class="hljs-comment">// Number, canvas height</span>
scaleX, <span class="hljs-comment">// Number, horizontal zoom value of mind map graphics</span>
scaleY, <span class="hljs-comment">// Number, vertical zoom value of mind map graphics</span>
clipData<span class="hljs-comment">// v0.9.11+If node is passed, that is, the content of the specified node is exported, then this field will be returned, Represents the position coordinate data of the node region cropped from the complete image</span>
}
</code></pre>
<h3>render(callback)</h3>
@@ -1116,10 +1178,15 @@ poor performance and should be used sparingly.</p>
</tr>
<tr>
<td>scale</td>
<td>Zoom event</td>
<td>Canvas zoom event</td>
<td>scale (zoom ratio)</td>
</tr>
<tr>
<td>translatev0.9.10+</td>
<td>Canvas movement event</td>
<td>xtranslate x、ytranslate y</td>
</tr>
<tr>
<td>node_img_dblclickv0.2.15+</td>
<td>Node image double-click event</td>
<td>this (node instance), e (event object)</td>
@@ -1249,6 +1316,16 @@ poor performance and should be used sparingly.</p>
<td>Triggered when removing personnel avatars with the mouse during collaborative editing</td>
<td>userInfo(User info)、 this(Current node instance)、 node(Avatar node)、 e(Event Object)</td>
</tr>
<tr>
<td>exit_demonstratev0.9.11+</td>
<td>Triggered when exiting demonstration mode</td>
<td></td>
</tr>
<tr>
<td>demonstrate_jumpv0.9.11+</td>
<td>Trigger when switching steps in demonstration mode</td>
<td>currentStepIndexThe index of the steps currently played, counting from 0、stepLengthTotal number of playback steps</td>
</tr>
</tbody>
</table>
<h3>emit(event, ...args)</h3>
@@ -1387,7 +1464,7 @@ redo. All commands are as follows:</p>
<tr>
<td>UNEXPAND_ALL</td>
<td>Collapse all nodes</td>
<td></td>
<td>isSetRootNodeCenterv0.9.11+default is trueWill the root node be moved to the center after retracting all nodes</td>
</tr>
<tr>
<td>UNEXPAND_TO_LEVEL (v0.2.8+)</td>
@@ -1425,6 +1502,11 @@ redo. All commands are as follows:</p>
<td>node (node to set), note (note text)</td>
</tr>
<tr>
<td>SET_NODE_ATTACHMENTv0.9.10+</td>
<td>Set node attachment</td>
<td>nodenode to set、urlattachment url、nameattachment name, optional</td>
</tr>
<tr>
<td>SET_NODE_TAG</td>
<td>Set Node Tag</td>
<td>node (node to set), tag (string array, built-in color information can be obtained in <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js">constant.js</a>)</td>
@@ -1447,7 +1529,7 @@ redo. All commands are as follows:</p>
<tr>
<td>ADD_GENERALIZATION (v0.2.0+)</td>
<td>Add a node summary</td>
<td>data (the data for the summary, in object format, all numerical fields of the node are supported, default is <code>{text: 'summary'}</code>)</td>
<td>data (the data for the summary, in object format, all numerical fields of the node are supported, default is <code>{text: 'summary'}</code>)、openEditv0.9.11+Default is trueWhether to enter text editing status by default</td>
</tr>
<tr>
<td>REMOVE_GENERALIZATION (v0.2.0+)</td>

View File

@@ -80,6 +80,14 @@ MindMap.usePlugin(Cooperate)
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.cooperate`.
### Config
This plugin supports some configurations that can be passed in when instantiating a mind map. The supported configurations are as follows:
`beforeCooperateUpdate`
Please refer to the 【Instantiation options】 section in the 【Constructor】 section for details.
## Methods
### getDoc()

View File

@@ -60,6 +60,10 @@ npm run wsServe
MindMap.usePlugin(Cooperate)
</code></pre>
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.cooperate</code>.</p>
<h3>Config</h3>
<p>This plugin supports some configurations that can be passed in when instantiating a mind map. The supported configurations are as follows:</p>
<p><code>beforeCooperateUpdate</code></p>
<p>Please refer to the Instantiation options section in the Constructor section for details.</p>
<h2>Methods</h2>
<h3>getDoc()</h3>
<p>Obtain Yjs doc instance.</p>

View File

@@ -0,0 +1,71 @@
# Demonstrate plugin
> v0.9.11+
The `Demonstrate` plugin provides demonstration functionality.
When entering demonstration mode, the container elements will be automatically displayed in full screen, and then default to the root node. You can switch between the previous and next steps by pressing the left and right arrow keys on the keyboard, and exit demonstration mode by pressing the 'Esc' key.
After entering demonstration mode, all shortcut keys on the mind map will be unavailable, and the mouse will not be able to operate the mind map.
## Register
```js
import MindMap from 'simple-mind-map'
import Demonstrate from 'simple-mind-map/src/plugins/Demonstrate.js'
MindMap.usePlugin(Demonstrate)
```
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.demonstrate`.
### Config
This plugin provides some configuration items for configuration, which can be configured through the instantiation option 'demonstrateConfig'. Please refer to the 【Instantiation options】 section in the 【Constructor】 section for details.
### Event
The plugin will dispatch the following events:
`exit_demonstrate`Triggered when exiting the demonstration.
`demonstrate_jump`Triggered when jumping.
Please refer to the 'on' function in the 【Instance methods】 section of the 【Constructor】 chapter for details.
## Props
### stepList
List of all steps demonstrated. Available when the 'enter' method is called.
### currentStepIndex
The index of the steps currently played, counting from 0.
### config
The current configuration of the plugin.
## Methods
### enter()
Entering demonstration mode will automatically display the container elements in full screen.
### exit()
Exit demonstration mode, which can also be exited by pressing the 'Esc' key.
### prev()
Previous step.
### next()
Next step.
### jump(index)
- `index`NumberTo jump to a certain step, count from 0.
Jump to a certain step.

View File

@@ -0,0 +1,57 @@
<template>
<div>
<h1>Demonstrate plugin</h1>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>The <code>Demonstrate</code> plugin provides demonstration functionality.</p>
<p>When entering demonstration mode, the container elements will be automatically displayed in full screen, and then default to the root node. You can switch between the previous and next steps by pressing the left and right arrow keys on the keyboard, and exit demonstration mode by pressing the 'Esc' key.</p>
<p>After entering demonstration mode, all shortcut keys on the mind map will be unavailable, and the mouse will not be able to operate the mind map.</p>
<h2>Register</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> Demonstrate <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/plugins/Demonstrate.js&#x27;</span>
MindMap.usePlugin(Demonstrate)
</code></pre>
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.demonstrate</code>.</p>
<h3>Config</h3>
<p>This plugin provides some configuration items for configuration, which can be configured through the instantiation option 'demonstrateConfig'. Please refer to the Instantiation options section in the Constructor section for details.</p>
<h3>Event</h3>
<p>The plugin will dispatch the following events:</p>
<p><code>exit_demonstrate</code>Triggered when exiting the demonstration.</p>
<p><code>demonstrate_jump</code>Triggered when jumping.</p>
<p>Please refer to the 'on' function in the Instance methods section of the Constructor chapter for details.</p>
<h2>Props</h2>
<h3>stepList</h3>
<p>List of all steps demonstrated. Available when the 'enter' method is called.</p>
<h3>currentStepIndex</h3>
<p>The index of the steps currently played, counting from 0.</p>
<h3>config</h3>
<p>The current configuration of the plugin.</p>
<h2>Methods</h2>
<h3>enter()</h3>
<p>Entering demonstration mode will automatically display the container elements in full screen.</p>
<h3>exit()</h3>
<p>Exit demonstration mode, which can also be exited by pressing the 'Esc' key.</p>
<h3>prev()</h3>
<p>Previous step.</p>
<h3>next()</h3>
<p>Next step.</p>
<h3>jump(index)</h3>
<ul>
<li><code>index</code>NumberTo jump to a certain step, count from 0.</li>
</ul>
<p>Jump to a certain step.</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@@ -63,7 +63,7 @@ However, this requires backend support, as our application is a single page clie
## Docker
> Thank you very much [水车](https://github.com/shuiche-it), This section is written by him, and the corresponding Docker package is also maintained by him.
> Thank you very much [水车](https://github.com/shuiche-it), the corresponding Docker package is maintained by him.
Install directly from Docker Hub:

View File

@@ -40,7 +40,7 @@ npm link simple-mind-map
<p>However, this requires backend support, as our application is a single page client application. If the backend is not properly configured, users will return 404 when accessing sub routes directly in the browser. Therefore, you need to add a candidate resource on the server that covers all situations: if the 'URL' cannot match any static resources, the same 'index. html' page should be returned.</p>
<h2>Docker</h2>
<blockquote>
<p>Thank you very much <a href="https://github.com/shuiche-it">水车</a>, This section is written by him, and the corresponding Docker package is also maintained by him.</p>
<p>Thank you very much <a href="https://github.com/shuiche-it">水车</a>, the corresponding Docker package is maintained by him.</p>
</blockquote>
<p>Install directly from Docker Hub:</p>
<pre class="hljs"><code>docker run -d -p 8081:8080 shuiche/mind-map:latest

View File

@@ -38,7 +38,9 @@ a.download = 'xxx'
a.click()
```
### png(name, transparent = false, checkRotate, compress)
### png(name, transparent = false, node = null)
> Versions below v0.9.2 arepng(name, transparent = false, checkRotate, compress)
> Versions below v0.7.0 are: png(name, transparent = false, rotateWhenWidthLongerThenHeight)
@@ -52,6 +54,8 @@ a.click()
- `compress`v0.8.1+, (v0.9.2+obsolete)null | { width, height }, The parameter for compressing images. In some cases, the length and width of the exported image may be very large. If you want to reduce it, you can use this parameter to control it. Only one width or height can be provided, and it will be scaled proportionally
- `node`v0.9.11+Node instances, if passed, will only export the content of that node;
Exports as `png`.
### svg(name, plusCssText)
@@ -115,14 +119,17 @@ Return `json` data.
Export as `markdown` file.
### getSvgData()
### getSvgData(node)
`node`: v0.9.11+, Node instance, if passed, will return a 'clipData' object, representing the position coordinate data of the node region cropped from the complete image;
Gets `svg` data, an async method that returns an object:
```js
{
node // svg node
str // svg string
node, // svg node
str, // svg string
clipData
}
```

View File

@@ -27,7 +27,10 @@ a.href = <span class="hljs-string">&#x27;xxx.png&#x27;</span><span class="hljs-c
a.download = <span class="hljs-string">&#x27;xxx&#x27;</span>
a.click()
</code></pre>
<h3>png(name, transparent = false, checkRotate, compress)</h3>
<h3>png(name, transparent = false, node = null)</h3>
<blockquote>
<p>Versions below v0.9.2 arepng(name, transparent = false, checkRotate, compress)</p>
</blockquote>
<blockquote>
<p>Versions below v0.7.0 are: png(name, transparent = false, rotateWhenWidthLongerThenHeight)</p>
</blockquote>
@@ -47,6 +50,9 @@ a.click()
<li>
<p><code>compress</code>v0.8.1+, (v0.9.2+obsolete)null | { width, height }, The parameter for compressing images. In some cases, the length and width of the exported image may be very large. If you want to reduce it, you can use this parameter to control it. Only one width or height can be provided, and it will be scaled proportionally</p>
</li>
<li>
<p><code>node</code>v0.9.11+Node instances, if passed, will only export the content of that node;</p>
</li>
</ul>
<p>Exports as <code>png</code>.</p>
<h3>svg(name, plusCssText)</h3>
@@ -112,11 +118,13 @@ MindMap.usePlugin(ExportPDF)
<p>v0.4.7+</p>
</blockquote>
<p>Export as <code>markdown</code> file.</p>
<h3>getSvgData()</h3>
<h3>getSvgData(node)</h3>
<p><code>node</code>: v0.9.11+, Node instance, if passed, will return a 'clipData' object, representing the position coordinate data of the node region cropped from the complete image;</p>
<p>Gets <code>svg</code> data, an async method that returns an object:</p>
<pre class="hljs"><code>{
node <span class="hljs-comment">// svg node</span>
str <span class="hljs-comment">// svg string</span>
node, <span class="hljs-comment">// svg node</span>
str, <span class="hljs-comment">// svg string</span>
clipData
}
</code></pre>
<h3>xmind(name)</h3>

View File

@@ -351,4 +351,18 @@ Open source is not easy. If this project is helpful to you, you can invite the a
<img src="../../../../assets/avatar/L.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>L</p>
</div>
</div>
<div style="display: flex;">
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>sunniberg</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/在下青铜五.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>在下青铜五</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/木星二号.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>木星二号</p>
</div>
</div>

View File

@@ -8,17 +8,17 @@
</blockquote>
<h2>Features</h2>
<ul>
<li><input type="checkbox" id="checkbox48" checked="true" /><label for="checkbox48">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
<li><input type="checkbox" id="checkbox49" checked="true" /><label for="checkbox49">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
<li><input type="checkbox" id="checkbox50" checked="true" /><label for="checkbox50">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
<li><input type="checkbox" id="checkbox51" checked="true" /><label for="checkbox51">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
<li><input type="checkbox" id="checkbox52" checked="true" /><label for="checkbox52">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
<li><input type="checkbox" id="checkbox53" checked="true" /><label for="checkbox53">Support canvas dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox54" checked="true" /><label for="checkbox54">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
<li><input type="checkbox" id="checkbox55" checked="true" /><label for="checkbox55">Supoorts to export as </label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code>, support import from <code>json</code><code>xmind</code><code>markdown</code></li>
<li><input type="checkbox" id="checkbox56" checked="true" /><label for="checkbox56">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
<li><input type="checkbox" id="checkbox57" checked="true" /><label for="checkbox57">Provide rich configurations to meet various scenarios and usage habits</label></li>
<li><input type="checkbox" id="checkbox58" checked="true" /><label for="checkbox58">Support collaborative editing</label></li>
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Support canvas dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Supoorts to export as </label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code>, support import from <code>json</code><code>xmind</code><code>markdown</code></li>
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Provide rich configurations to meet various scenarios and usage habits</label></li>
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Support collaborative editing</label></li>
</ul>
<blockquote>
<p>Features that will not be implemented:</p>
@@ -34,16 +34,16 @@ frameworks such as Vue and React, or without a framework.</p>
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
<ul>
<li><input type="checkbox" id="checkbox59" checked="true" /><label for="checkbox59">Toolbar, which supports inserting and deleting nodes, and editing node</label>
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Toolbar, which supports inserting and deleting nodes, and editing node</label>
images, icons, hyperlinks, notes, tags, and summaries</li>
<li><input type="checkbox" id="checkbox60" checked="true" /><label for="checkbox60">Sidebar, with panels for basic style settings, node style settings,</label>
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Sidebar, with panels for basic style settings, node style settings,</label>
outline, theme selection, and structure selection</li>
<li><input type="checkbox" id="checkbox61" checked="true" /><label for="checkbox61">Import and export functionality; data is saved in the browser's local</label>
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Import and export functionality; data is saved in the browser's local</label>
storage by default, but it also supports creating, opening, and editing
local files on the computer directly</li>
<li><input type="checkbox" id="checkbox62" checked="true" /><label for="checkbox62">Right-click menu, which supports operations such as expanding, collapsing,</label>
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Right-click menu, which supports operations such as expanding, collapsing,</label>
and organizing layout</li>
<li><input type="checkbox" id="checkbox63" checked="true" /><label for="checkbox63">Bottom bar, which supports node and word count statistics, switching</label>
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">Bottom bar, which supports node and word count statistics, switching</label>
between edit and read-only modes, zooming in and out, and switching to
full screen, support mini map</li>
</ul>
@@ -305,6 +305,20 @@ full screen, support mini map</li>
<img src="../../../../assets/avatar/L.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>L</p>
</div>
</div>
<div style="display: flex;">
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>sunniberg</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/在下青铜五.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>在下青铜五</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/木星二号.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>木星二号</p>
</div>
</div>
</div>
</template>

View File

@@ -56,6 +56,12 @@ Whether the node is currently being dragged
## Methods
### deactivate()
> 0.9.11+
Deactivate the node.
### getAncestorNodes()
> v0.9.9+
@@ -261,9 +267,19 @@ Setting the node hyperlink, a shortcut for the `SET_NODE_HYPERLINK` command
Setting the node note, a shortcut for the `SET_NODE_NOTE` command
### setAttachment(url, name)
> v0.9.10+
- `url`Attachment url
- `name`Attachment name, optional
Set node attachments, a shortcut for the `SET_NODE_ATTACHMENT` command
### setTag(tag)
Setting the node tag, a shortcut for the `SET_NODE_TAG` command"
Setting the node tag, a shortcut for the `SET_NODE_TAG` command
### hide()

View File

@@ -31,6 +31,11 @@
</blockquote>
<p>Whether the node is currently being dragged</p>
<h2>Methods</h2>
<h3>deactivate()</h3>
<blockquote>
<p>0.9.11+</p>
</blockquote>
<p>Deactivate the node.</p>
<h3>getAncestorNodes()</h3>
<blockquote>
<p>v0.9.9+</p>
@@ -195,8 +200,21 @@ nodeData, <code>SET_NODE_DATA</code> command's shortcut method. This method and
<p>Setting the node hyperlink, a shortcut for the <code>SET_NODE_HYPERLINK</code> command</p>
<h3>setNote(note)</h3>
<p>Setting the node note, a shortcut for the <code>SET_NODE_NOTE</code> command</p>
<h3>setAttachment(url, name)</h3>
<blockquote>
<p>v0.9.10+</p>
</blockquote>
<ul>
<li>
<p><code>url</code>Attachment url</p>
</li>
<li>
<p><code>name</code>Attachment name, optional</p>
</li>
</ul>
<p>Set node attachments, a shortcut for the <code>SET_NODE_ATTACHMENT</code> command</p>
<h3>setTag(tag)</h3>
<p>Setting the node tag, a shortcut for the <code>SET_NODE_TAG</code> command&quot;</p>
<p>Setting the node tag, a shortcut for the <code>SET_NODE_TAG</code> command</p>
<h3>hide()</h3>
<blockquote>
<p>v0.1.5+</p>

View File

@@ -479,6 +479,33 @@ Convert flat objects into a tree structure. Reverse operation of the transformTr
Remove the node of the specified selector from the specified HTML string, and then return the processed HTML string.
#### getOnfullscreEnevt()
> v0.9.11+
Detect full screen events available in the current browser. You can use it this way:
```js
const fullscrrenEvent = getOnfullscreEnevt()
// Monitor full screen events
document.addEventListener(fullscrrenEvent, () => {
// Determine whether the current state is full screen based on whether document.fullscreenElement is null
})
```
#### fullScreen(element)
> v0.9.11+
Put the specified DOM element into full screen mode.
#### exitFullScreen()
> v0.9.11+
Exit full screen mode.
## Simulate CSS background in Canvas
Import:

View File

@@ -402,6 +402,28 @@ and copying the <code>data</code> of the data object, example:</p>
</li>
</ul>
<p>Remove the node of the specified selector from the specified HTML string, and then return the processed HTML string.</p>
<h4>getOnfullscreEnevt()</h4>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>Detect full screen events available in the current browser. You can use it this way:</p>
<pre class="hljs"><code><span class="hljs-keyword">const</span> fullscrrenEvent = getOnfullscreEnevt()
<span class="hljs-comment">// Monitor full screen events</span>
<span class="hljs-built_in">document</span>.addEventListener(fullscrrenEvent, <span class="hljs-function">() =&gt;</span> {
<span class="hljs-comment">// Determine whether the current state is full screen based on whether document.fullscreenElement is null</span>
})
</code></pre>
<h4>fullScreen(element)</h4>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>Put the specified DOM element into full screen mode.</p>
<h4>exitFullScreen()</h4>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>Exit full screen mode.</p>
<h2>Simulate CSS background in Canvas</h2>
<p>Import:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/utils/simulateCSSBackgroundInCanvas&#x27;</span>

View File

@@ -33,6 +33,7 @@ export default [
{ path: 'course24', title: '如何开发一个插件' },
{ path: 'course25', title: '关于概要' },
{ path: 'course26', title: '如何实现AI生成节点内容' },
{ path: 'course27', title: '快捷键操作如何传递自定义参数' },
{ path: 'doExport', title: 'Export 插件' },
{ path: 'drag', title: 'Drag插件' },
{ path: 'introduction', title: '简介' },
@@ -62,6 +63,7 @@ export default [
{ path: 'formula', title: 'Formula插件' },
{ path: 'cooperate', title: 'Cooperate插件' },
{ path: 'rainbowLines', title: 'RainbowLines插件' },
{ path: 'demonstrate', title: 'Demonstrate插件' },
{ path: 'handDrawnLikeStyle', title: 'HandDrawnLikeStyle收费插件' },
{ path: 'help1', title: '概要/关联线' },
{ path: 'help2', title: '客户端' },
@@ -105,6 +107,7 @@ export default [
{ path: 'formula', title: 'Formula plugin' },
{ path: 'cooperate', title: 'Cooperate plugin' },
{ path: 'rainbowLines', title: 'RainbowLines plugin' },
{ path: 'demonstrate', title: 'Demonstrate plugin' },
{ path: 'handDrawnLikeStyle', title: 'HandDrawnLikeStyle chargeable plugin' },
{ path: 'client', title: 'Client' }
]

View File

@@ -1,5 +1,79 @@
# Changelog
## 0.9.11
修复:
> 1.修复点击概要会触发data_change_detail事件的问题
>
> 2.修复一键去除所有节点自定义样式命令不支持不为数组的概要的问题;
>
> 3.修复富文本模式下创建的概要节点不是富文本的问题;
>
> 4.修复富文本插件转换节点数据时没有处理节点概要的问题;
>
> 5.修复概要节点文本编辑中按回车结束时,相应的节点高亮框会错位显示的问题;
>
> 6.修复同时创建多个实例时,文本编辑后节点宽高丢失的问题;
>
> 7.修复删除当前激活的节点的所有子节点后,展开收起按钮没有消失的问题;
>
> 8.修复拖拽节点到边缘时画布自动移动无法停止的问题;
新增:
> 1.插入概要时支持默认聚焦和进入编辑状态;
>
> 2.支持按住Command键和Win键多选节点
>
> 3.支持导出某个节点为图片;
>
> 4.新增演示插件;
Demo
> 1.节点右键菜单新增导出为图片按钮;
>
> 2.优化鼠标在窗口边缘点击右键时菜单显示不全的问题;
>
> 3.新增演示模式;
>
> 4.复制知犀数据时,概要数据创建为数组形式;
## 0.9.10
修复:
> 1.修复搜索时全部替换操作报错的问题;
>
> 2.修复节点文本存在svg不支持的实体字符时小地图无法渲染的问题
新增:
> 1.新增画布移动时的事件translate
>
> 2.节点内容支持设置附件;
Demo
> 1.支持拖拽文件到页面进行导入;
客户端:
> 1.节点支持添加附件;
## 0.9.9-fix.2
修复:
> 1.修复插入父节点操作时原节点样式未更新的问题;
>
> 2.修复开启彩虹线条时切换结构会报错的问题;
Demo
> 1.修复侧边栏大纲点击全屏编辑时打开的是源码编辑模式的问题;
## 0.9.9-fix.1
修复上个版本的改动造成搜索插件无法搜索的问题。

View File

@@ -1,6 +1,61 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.9.11</h2>
<p>修复</p>
<blockquote>
<p>1.修复点击概要会触发data_change_detail事件的问题</p>
<p>2.修复一键去除所有节点自定义样式命令不支持不为数组的概要的问题</p>
<p>3.修复富文本模式下创建的概要节点不是富文本的问题</p>
<p>4.修复富文本插件转换节点数据时没有处理节点概要的问题</p>
<p>5.修复概要节点文本编辑中按回车结束时相应的节点高亮框会错位显示的问题</p>
<p>6.修复同时创建多个实例时文本编辑后节点宽高丢失的问题</p>
<p>7.修复删除当前激活的节点的所有子节点后展开收起按钮没有消失的问题</p>
<p>8.修复拖拽节点到边缘时画布自动移动无法停止的问题</p>
</blockquote>
<p>新增</p>
<blockquote>
<p>1.插入概要时支持默认聚焦和进入编辑状态</p>
<p>2.支持按住Command键和Win键多选节点</p>
<p>3.支持导出某个节点为图片</p>
<p>4.新增演示插件</p>
</blockquote>
<p>Demo</p>
<blockquote>
<p>1.节点右键菜单新增导出为图片按钮</p>
<p>2.优化鼠标在窗口边缘点击右键时菜单显示不全的问题</p>
<p>3.新增演示模式</p>
<p>4.复制知犀数据时概要数据创建为数组形式</p>
</blockquote>
<h2>0.9.10</h2>
<p>修复</p>
<blockquote>
<p>1.修复搜索时全部替换操作报错的问题</p>
<p>2.修复节点文本存在svg不支持的实体字符时小地图无法渲染的问题</p>
</blockquote>
<p>新增</p>
<blockquote>
<p>1.新增画布移动时的事件translate</p>
<p>2.节点内容支持设置附件</p>
</blockquote>
<p>Demo</p>
<blockquote>
<p>1.支持拖拽文件到页面进行导入</p>
</blockquote>
<p>客户端</p>
<blockquote>
<p>1.节点支持添加附件</p>
</blockquote>
<h2>0.9.9-fix.2</h2>
<p>修复</p>
<blockquote>
<p>1.修复插入父节点操作时原节点样式未更新的问题</p>
<p>2.修复开启彩虹线条时切换结构会报错的问题</p>
</blockquote>
<p>Demo</p>
<blockquote>
<p>1.修复侧边栏大纲点击全屏编辑时打开的是源码编辑模式的问题</p>
</blockquote>
<h2>0.9.9-fix.1</h2>
<p>修复上个版本的改动造成搜索插件无法搜索的问题</p>
<h2>0.9.9</h2>

View File

@@ -1,9 +1,21 @@
# Command实例
# Command 实例
`command`实例负责命令的添加及执行,内置了很多命令,也可以自行添加,命令指需要在历史堆栈数据里添加副本的操作。可通过`mindMap.command`获取到该实例
## 方法
### pause()
> v0.9.11+
暂停收集历史数据。
### recovery()
> v0.9.11+
恢复收集历史数据。
### add(name, fn)
添加命令。
@@ -26,4 +38,4 @@
### clearHistory()
清空历史堆栈数据
清空历史堆栈数据

View File

@@ -1,8 +1,18 @@
<template>
<div>
<h1>Command实例</h1>
<h1>Command 实例</h1>
<p><code>command</code>实例负责命令的添加及执行内置了很多命令也可以自行添加命令指需要在历史堆栈数据里添加副本的操作可通过<code>mindMap.command</code>获取到该实例</p>
<h2>方法</h2>
<h3>pause()</h3>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>暂停收集历史数据</p>
<h3>recovery()</h3>
<blockquote>
<p>v0.9.11+</p>
</blockquote>
<p>恢复收集历史数据</p>
<h3>add(name, fn)</h3>
<p>添加命令</p>
<p><code>name</code>命令名称</p>

View File

@@ -24,7 +24,7 @@ const mindMap = new MindMap({
| 字段名称 | 类型 | 默认值 | 描述 |
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
| el | Element | | 容器元素必传必须为DOM元素 |
| el | Element | | 容器元素必传必须为DOM元素(当容器元素在页面上的位置发生了改变,但大小没有改变的情况下必须调用`getElRectInfo()`方法更新库内部的相关信息;当大小也发生了改变后必须调用`resize()`方法,否则会造成一些功能异常) |
| data | Object 、 null | | 思维导图数据可参考下方【数据结构】介绍。v0.9.9+支持传空对象或者null画布会显示空白 |
| layout | String | logicalStructure | 布局类型可选列表logicalStructure逻辑结构图、mindMap思维导图、catalogOrganization目录组织图、organizationStructure组织结构图、timelinev0.5.4+时间轴、timeline2v0.5.4+上下交替型时间轴、fishbonev0.5.4+,鱼骨图) |
| fishboneDegv0.5.4+ | Number | 45 | 设置鱼骨结构图的斜线角度 |
@@ -117,7 +117,7 @@ const mindMap = new MindMap({
| rainbowLinesConfigv0.9.9+ | Object | { open: false, colorsList: [] } | 彩虹线条配置需要先注册RainbowLines插件。对象类型结构{ open: false【是否开启彩虹线条】, colorsList: []【自定义彩虹线条的颜色列表,如果不设置,会使用默认颜色列表】 } |
| addContentToHeaderv0.9.9+ | Function、null | null | 导出png、svg、pdf时在头部添加自定义内容。可传递一个函数这个函数可以返回null代表不添加内容也可以返回一个对象详细介绍请参考下方【导出时如何添加自定义内容】 |
| addContentToFooterv0.9.9+ | Function、null | null | 基本释义同addContentToHeader在尾部添加自定义内容 |
| demonstrateConfigv0.9.11+ | Object、null | null | 演示插件Demonstrate的配置。不传则使用默认配置可传递一个对象如果只配置某个属性可以只设置该属性其他没有设置的同样会使用默认配置完整配置请参考下方【演示插件配置】小节 |
### 数据结构
@@ -141,10 +141,14 @@ const mindMap = new MindMap({
hyperlink: '', // 超链接地址
hyperlinkTitle: '', // 超链接的标题
note: '', // 备注的内容
attachmentUrl: '',// v0.9.10+附件url
attachmentName: '',// v0.9.10+,附件名称
tag: [], // 标签列表
generalization: {// 节点的概要如果没有概要generalization设为null即可
text: ''// 概要的文本
},
generalization: [{// 0.9.0以下版本不支持数组,只能设置单个概要数据)节点的概要如果没有概要generalization设为null即可
text: '', // 概要的文本
richText: false, // 节点的文本是否是富文本模式
// ...其他普通节点的字段都支持但是不支持children
}],
associativeLineTargets: [''],// 如果存在关联线那么为目标节点的uid列表
associativeLineText: '',// 关联线文本
// ...其他样式字段,可以参考主题
@@ -214,6 +218,17 @@ new MindMap({
})
```
### 演示插件配置
| 字段名称 | 类型 | 默认值 | 描述 |
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
| boxShadowColor | String | rgba(0, 0, 0, 0.8) | 高亮框四周区域的颜色 |
| borderRadius | String | 5px | 高亮框的圆角大小 |
| transition | String | all 0.3s ease-out | 高亮框动画的过渡属性CSS的transition属性 |
| zIndex | Number | 9999 | 高亮框元素的层级 |
| padding | Number | 20 | 高亮框的内边距 |
| margin | Number | 50 | 高亮框的外边距 |
## 静态方法
### defineTheme(name, config)
@@ -353,6 +368,10 @@ mindMap.setTheme('主题名称')
## 实例方法
### getElRectInfo()
更新容器元素的位置和大小信息。当容器元素在页面中的位置发生了改变之后务必调用该方法更新信息。如果容器元素大小也发生了改变,那么请调用`resize`方法。
### updateData(data)
> v0.9.9+
@@ -371,7 +390,7 @@ mindMap.setTheme('主题名称')
销毁思维导图。会移除注册的插件、移除监听的事件、删除画布的所有节点。
### getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter })
### getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter, node })
> v0.3.0+
@@ -385,6 +404,8 @@ mindMap.setTheme('主题名称')
`addContentToFooter`v0.9.9+Function可以返回要追加到尾部的自定义内容详细介绍见【实例化选项】中的该配置
`node`: v0.9.11+, 节点实例,如果传了,那么仅导出该节点的内容
获取`svg`数据,返回一个对象,详细结构如下:
```js
@@ -396,6 +417,7 @@ mindMap.setTheme('主题名称')
origHeight, // Number画布高度
scaleX, // Number思维导图图形的水平缩放值
scaleY, // Number思维导图图形的垂直缩放值
clipData// v0.9.11+如果传了node即导出指定节点的内容那么会返回该字段代表从完整的图片中裁剪出该节点区域的位置坐标数据
}
```
@@ -452,7 +474,8 @@ mindMap.setTheme('主题名称')
| expand_btn_click | 节点展开或收缩事件 | this节点实例 |
| before_show_text_edit | 节点文本编辑框即将打开事件 | |
| hide_text_edit | 节点文本编辑框关闭事件 | textEditNode文本编辑框DOM节点、activeNodeList当前激活的所有节点列表 |
| scale | 放大缩小事件 | scale缩放比例 |
| scale | 画布放大缩小事件 | scale缩放比例 |
| translatev0.9.10+ | 画布移动事件 | x水平位移、y垂直位移 |
| node_img_dblclickv0.2.15+ | 节点内图片的双击事件 | this节点实例、e事件对象 |
| node_img_mouseenterv0.6.5+ | 节点内图片的鼠标移入事件 | this节点实例、imgNode图片节点、e事件对象 |
| node_img_mouseleavev0.6.5+ | 节点内图片的鼠标移出事件 | this节点实例、imgNode图片节点、e事件对象 |
@@ -479,6 +502,8 @@ mindMap.setTheme('主题名称')
| node_cooperate_avatar_clickv0.9.9+ | 协同编辑时,鼠标点击人员头像时触发 | userInfo(人员信息)、 this(当前节点实例)、 node(头像节点)、 e(事件对象) |
| node_cooperate_avatar_mouseenterv0.9.9+ | 协同编辑时,鼠标移入人员头像时触发 | userInfo(人员信息)、 this(当前节点实例)、 node(头像节点)、 e(事件对象) |
| node_cooperate_avatar_mouseleavev0.9.9+ | 协同编辑时,鼠标移除人员头像时触发 | userInfo(人员信息)、 this(当前节点实例)、 node(头像节点)、 e(事件对象) |
| exit_demonstratev0.9.11+ | 退出演示模式时触发 | |
| demonstrate_jumpv0.9.11+ | 演示模式中,切换步骤时触发 | currentStepIndex当前播放到的步骤索引从0开始计数、stepLength总的播放步骤数量 |
### emit(event, ...args)
@@ -568,7 +593,7 @@ mindMap.updateConfig({
| CLEAR_ACTIVE_NODE | 清除当前已激活节点的激活状态,操作节点为当前激活的节点 | |
| SET_NODE_EXPAND | 设置节点是否展开 | node要设置的节点、expand布尔值是否展开 |
| EXPAND_ALL | 展开所有节点 | |
| UNEXPAND_ALL | 收起所有节点 | |
| UNEXPAND_ALL | 收起所有节点 | isSetRootNodeCenterv0.9.11+默认为true收起所有节点后是否将根节点移至中心 |
| UNEXPAND_TO_LEVELv0.2.8+ | 展开到指定层级 | level要展开到的层级1、2、3... |
| SET_NODE_DATA | 更新节点数据,即更新节点数据对象里`data`对象的数据,注意这个命令不会触发视图的更新 | node要设置的节点、data对象要更新的数据`{expand: true}` |
| SET_NODE_TEXT | 设置节点文本 | node要设置的节点、text要设置的文本字符串换行可以使用`\n`、richTextv0.4.0+,如果要设置的是富文本字符,需要设为`true`、resetRichTextv0.6.10+是否要复位富文本默认为false如果传true那么会重置富文本节点的样式 |
@@ -576,11 +601,12 @@ mindMap.updateConfig({
| SET_NODE_ICON | 设置节点图标 | node要设置的节点、icons数组预定义的图片名称组成的数组可用图标可在[icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件里的`nodeIconList`列表里获取到,图标名称为`type_name`,如`['priority_1']` |
| SET_NODE_HYPERLINK | 设置节点超链接 | node要设置的节点、link超链接地址、title超链接名称可选 |
| SET_NODE_NOTE | 设置节点备注 | node要设置的节点、note备注文字 |
| SET_NODE_ATTACHMENTv0.9.10+ | 设置节点附件 | node要设置的节点、url附件url、name附件名称可选 |
| SET_NODE_TAG | 设置节点标签 | node要设置的节点、tag字符串数组内置颜色信息可在[constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js)里获取到) |
| INSERT_AFTERv0.1.5+ | 将节点移动到另一个节点的后面 | node要移动的节点v0.7.2+支持传递节点数组实现同时移动多个节点))、 exist目标节点 |
| INSERT_BEFOREv0.1.5+ | 将节点移动到另一个节点的前面v0.7.2+支持传递节点数组实现同时移动多个节点) | node要移动的节点、 exist目标节点 |
| MOVE_NODE_TOv0.1.5+ | 移动节点作为另一个节点的子节点v0.7.2+支持传递节点数组实现同时移动多个节点) | node要移动的节点、 toNode目标节点 |
| ADD_GENERALIZATIONv0.2.0+ | 添加节点概要 | data概要的数据对象格式节点的数字段都支持默认为{text: '概要'} |
| ADD_GENERALIZATIONv0.2.0+ | 添加节点概要 | data概要的数据对象格式节点的数字段都支持默认为{text: '概要'}、openEditv0.9.11+默认为true是否默认进入文本编辑状态 |
| REMOVE_GENERALIZATIONv0.2.0+ | 删除节点概要 | |
| SET_NODE_CUSTOM_POSITIONv0.2.0+ | 设置节点自定义位置 | node要设置的节点、 left自定义的x坐标默认为undefined、 top自定义的y坐标默认为undefined |
| RESET_LAYOUTv0.2.0+ | 一键整理布局 | |

View File

@@ -31,7 +31,7 @@
<td>el</td>
<td>Element</td>
<td></td>
<td>容器元素必传必须为DOM元素</td>
<td>容器元素必传必须为DOM元素当容器元素在页面上的位置发生了改变但大小没有改变的情况下必须调用<code>getElRectInfo()</code>方法更新库内部的相关信息当大小也发生了改变后必须调用<code>resize()</code>方法否则会造成一些功能异常</td>
</tr>
<tr>
<td>data</td>
@@ -585,6 +585,12 @@
<td>null</td>
<td>基本释义同addContentToHeader在尾部添加自定义内容</td>
</tr>
<tr>
<td>demonstrateConfigv0.9.11+</td>
<td>Objectnull</td>
<td>null</td>
<td>演示插件Demonstrate的配置不传则使用默认配置可传递一个对象如果只配置某个属性可以只设置该属性其他没有设置的同样会使用默认配置完整配置请参考下方演示插件配置小节</td>
</tr>
</tbody>
</table>
<h3>数据结构</h3>
@@ -606,10 +612,14 @@
<span class="hljs-attr">hyperlink</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// 超链接地址</span>
<span class="hljs-attr">hyperlinkTitle</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// 超链接的标题</span>
<span class="hljs-attr">note</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// 备注的内容</span>
<span class="hljs-attr">attachmentUrl</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// v0.9.10+附件url</span>
<span class="hljs-attr">attachmentName</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// v0.9.10+,附件名称</span>
<span class="hljs-attr">tag</span>: [], <span class="hljs-comment">// 标签列表</span>
<span class="hljs-attr">generalization</span>: {<span class="hljs-comment">// 节点的概要如果没有概要generalization设为null即可</span>
<span class="hljs-attr">text</span>: <span class="hljs-string">&#x27;&#x27;</span><span class="hljs-comment">// 概要的文本</span>
},
<span class="hljs-attr">generalization</span>: [{<span class="hljs-comment">// 0.9.0以下版本不支持数组,只能设置单个概要数据)节点的概要如果没有概要generalization设为null即可</span>
<span class="hljs-attr">text</span>: <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-comment">// 概要的文本</span>
<span class="hljs-attr">richText</span>: <span class="hljs-literal">false</span>, <span class="hljs-comment">// 节点的文本是否是富文本模式</span>
<span class="hljs-comment">// ...其他普通节点的字段都支持但是不支持children</span>
}],
<span class="hljs-attr">associativeLineTargets</span>: [<span class="hljs-string">&#x27;&#x27;</span>],<span class="hljs-comment">// 如果存在关联线那么为目标节点的uid列表</span>
<span class="hljs-attr">associativeLineText</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// 关联线文本</span>
<span class="hljs-comment">// ...其他样式字段,可以参考主题</span>
@@ -731,6 +741,55 @@
}
})
</code></pre>
<h3>演示插件配置</h3>
<table>
<thead>
<tr>
<th>字段名称</th>
<th>类型</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>boxShadowColor</td>
<td>String</td>
<td>rgba(0, 0, 0, 0.8)</td>
<td>高亮框四周区域的颜色</td>
</tr>
<tr>
<td>borderRadius</td>
<td>String</td>
<td>5px</td>
<td>高亮框的圆角大小</td>
</tr>
<tr>
<td>transition</td>
<td>String</td>
<td>all 0.3s ease-out</td>
<td>高亮框动画的过渡属性CSS的transition属性</td>
</tr>
<tr>
<td>zIndex</td>
<td>Number</td>
<td>9999</td>
<td>高亮框元素的层级</td>
</tr>
<tr>
<td>padding</td>
<td>Number</td>
<td>20</td>
<td>高亮框的内边距</td>
</tr>
<tr>
<td>margin</td>
<td>Number</td>
<td>50</td>
<td>高亮框的外边距</td>
</tr>
</tbody>
</table>
<h2>静态方法</h2>
<h3>defineTheme(name, config)</h3>
<blockquote>
@@ -827,6 +886,8 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<h3>themeConfig</h3>
<p>当前主题配置</p>
<h2>实例方法</h2>
<h3>getElRectInfo()</h3>
<p>更新容器元素的位置和大小信息当容器元素在页面中的位置发生了改变之后务必调用该方法更新信息如果容器元素大小也发生了改变那么请调用<code>resize</code>方法</p>
<h3>updateData(data)</h3>
<blockquote>
<p>v0.9.9+</p>
@@ -842,7 +903,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<p>v0.6.0+</p>
</blockquote>
<p>销毁思维导图会移除注册的插件移除监听的事件删除画布的所有节点</p>
<h3>getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter })</h3>
<h3>getSvgData({ paddingX = 0, paddingY = 0, ignoreWatermark = false, addContentToHeader, addContentToFooter, node })</h3>
<blockquote>
<p>v0.3.0+</p>
</blockquote>
@@ -851,6 +912,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<p><code>ignoreWatermark</code>v0.8.0+不要绘制水印如果不需要绘制水印的场景可以传<code>true</code>因为绘制水印非常慢</p>
<p><code>addContentToHeader</code>v0.9.9+Function可以返回要追加到头部的自定义内容详细介绍见实例化选项中的该配置</p>
<p><code>addContentToFooter</code>v0.9.9+Function可以返回要追加到尾部的自定义内容详细介绍见实例化选项中的该配置</p>
<p><code>node</code>: v0.9.11+, 节点实例如果传了那么仅导出该节点的内容</p>
<p>获取<code>svg</code>数据返回一个对象详细结构如下</p>
<pre class="hljs"><code>{
svg, <span class="hljs-comment">// Element思维导图图形的整体svg元素包括svg画布容器、g实际的思维导图组</span>
@@ -860,6 +922,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
origHeight, <span class="hljs-comment">// Number画布高度</span>
scaleX, <span class="hljs-comment">// Number思维导图图形的水平缩放值</span>
scaleY, <span class="hljs-comment">// Number思维导图图形的垂直缩放值</span>
clipData<span class="hljs-comment">// v0.9.11+如果传了node即导出指定节点的内容那么会返回该字段代表从完整的图片中裁剪出该节点区域的位置坐标数据</span>
}
</code></pre>
<h3>render(callback)</h3>
@@ -1008,10 +1071,15 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
</tr>
<tr>
<td>scale</td>
<td>放大缩小事件</td>
<td>画布放大缩小事件</td>
<td>scale缩放比例</td>
</tr>
<tr>
<td>translatev0.9.10+</td>
<td>画布移动事件</td>
<td>x水平位移y垂直位移</td>
</tr>
<tr>
<td>node_img_dblclickv0.2.15+</td>
<td>节点内图片的双击事件</td>
<td>this节点实例e事件对象</td>
@@ -1141,6 +1209,16 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<td>协同编辑时鼠标移除人员头像时触发</td>
<td>userInfo(人员信息) this(当前节点实例) node(头像节点) e(事件对象)</td>
</tr>
<tr>
<td>exit_demonstratev0.9.11+</td>
<td>退出演示模式时触发</td>
<td></td>
</tr>
<tr>
<td>demonstrate_jumpv0.9.11+</td>
<td>演示模式中切换步骤时触发</td>
<td>currentStepIndex当前播放到的步骤索引从0开始计数stepLength总的播放步骤数量</td>
</tr>
</tbody>
</table>
<h3>emit(event, ...args)</h3>
@@ -1281,7 +1359,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<tr>
<td>UNEXPAND_ALL</td>
<td>收起所有节点</td>
<td></td>
<td>isSetRootNodeCenterv0.9.11+默认为true收起所有节点后是否将根节点移至中心</td>
</tr>
<tr>
<td>UNEXPAND_TO_LEVELv0.2.8+</td>
@@ -1319,6 +1397,11 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<td>node要设置的节点note备注文字</td>
</tr>
<tr>
<td>SET_NODE_ATTACHMENTv0.9.10+</td>
<td>设置节点附件</td>
<td>node要设置的节点url附件urlname附件名称可选</td>
</tr>
<tr>
<td>SET_NODE_TAG</td>
<td>设置节点标签</td>
<td>node要设置的节点tag字符串数组内置颜色信息可在<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js">constant.js</a>里获取到</td>
@@ -1341,7 +1424,7 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<tr>
<td>ADD_GENERALIZATIONv0.2.0+</td>
<td>添加节点概要</td>
<td>data概要的数据对象格式节点的数字段都支持默认为{text: '概要'}</td>
<td>data概要的数据对象格式节点的数字段都支持默认为{text: '概要'}openEditv0.9.11+默认为true是否默认进入文本编辑状态</td>
</tr>
<tr>
<td>REMOVE_GENERALIZATIONv0.2.0+</td>

View File

@@ -80,6 +80,14 @@ MindMap.usePlugin(Cooperate)
注册完且实例化`MindMap`后可通过`mindMap.cooperate`获取到该实例。
### 配置
该插件支持一些配置,可在实例化思维导图时传入,支持的配置如下:
`beforeCooperateUpdate`
详细信息见【构造函数】篇章的【实例化选项】小节。
## 方法
### getDoc()

View File

@@ -60,6 +60,10 @@ npm run wsServe
MindMap.usePlugin(Cooperate)
</code></pre>
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.cooperate</code>获取到该实例</p>
<h3>配置</h3>
<p>该插件支持一些配置可在实例化思维导图时传入支持的配置如下</p>
<p><code>beforeCooperateUpdate</code></p>
<p>详细信息见构造函数篇章的实例化选项小节</p>
<h2>方法</h2>
<h3>getDoc()</h3>
<p>获取Yjs doc实例</p>

Some files were not shown because too many files have changed in this diff Show More