Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ef789110b | ||
|
|
9294fc4e7b | ||
|
|
abacff6ede | ||
|
|
79755e80b9 | ||
|
|
b8a23beba4 | ||
|
|
f996ec9bae | ||
|
|
8152fab185 | ||
|
|
21b404a322 | ||
|
|
c5ed48ad99 | ||
|
|
25f0668a44 | ||
|
|
67fec82c72 | ||
|
|
0760500ceb | ||
|
|
3355900bd3 | ||
|
|
417376dcb6 | ||
|
|
6a45ff2221 | ||
|
|
c967be2bc2 | ||
|
|
12dae210ef | ||
|
|
a75eb5f195 | ||
|
|
9ad71c6627 | ||
|
|
2218e7bf12 | ||
|
|
c4777fb17a | ||
|
|
edc2097d14 | ||
|
|
53bcabe3d0 | ||
|
|
27477e39de | ||
|
|
f4800746a3 | ||
|
|
7c82d16d66 | ||
|
|
dccd1c9459 | ||
|
|
1f8fad8fc5 | ||
|
|
a3d5588cd6 | ||
|
|
7c96daf6d0 | ||
|
|
db03e74f0d | ||
|
|
459044beb9 | ||
|
|
2537fb858f | ||
|
|
5c6d460455 | ||
|
|
6c3790e20e | ||
|
|
40de891695 | ||
|
|
bc9d118efd | ||
|
|
950b7ad57b |
24
README.md
@@ -109,9 +109,13 @@ const mindMap = new MindMap({
|
||||
|
||||
[](https://star-history.com/#wanglin2/mind-map&Date)
|
||||
|
||||
# 关于定制
|
||||
|
||||
如果你有个性化的商用定制需求,可以联系我们,我们提供付费开发服务。
|
||||
|
||||
# 请作者喝杯咖啡
|
||||
|
||||
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡~
|
||||
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡,你的支持是开发者持续维护的最大动力~
|
||||
|
||||
> 推荐使用支付宝,微信获取不到头像。转账请备注【思维导图】。
|
||||
|
||||
@@ -355,7 +359,7 @@ const mindMap = new MindMap({
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/孟照星.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>孟照星</span>
|
||||
<span>Alex</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/子豪.jpg" style="width: 50px;height: 50px;" />
|
||||
@@ -365,4 +369,20 @@ const mindMap = new MindMap({
|
||||
<img src="./web/src/assets/avatar/宏涛.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>宏涛</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/最多5个字.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>最多5个字</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/ZX.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>ZX</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/峰.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>峰</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
BIN
dist/img/ZX.jpg
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
dist/img/峰.jpg
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
dist/img/最多5个字.jpg
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
dist/img/雨馨.jpg
vendored
Normal file
|
After Width: | Height: | Size: 32 KiB |
2
dist/js/app.js
vendored
1
dist/js/chunk-16bd07ee.js
vendored
1
dist/js/chunk-1ba6eabc.js
vendored
2
dist/js/chunk-2d0ab10b.js
vendored
2
dist/js/chunk-2d0c191e.js
vendored
2
dist/js/chunk-2d0d9fbc.js
vendored
2
dist/js/chunk-2d0dad5f.js
vendored
2
dist/js/chunk-2d0ddf37.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0ddf37"],{8427:function(v,_,s){"use strict";s.r(_);var n=function(){var v=this;v._self._c;return v._m(0)},e=[function(){var v=this,_=v._self._c;return _("div",[_("h1",[v._v("XMind解析")]),_("blockquote",[_("p",[v._v("v0.2.7+")])]),_("p",[v._v("提供导入和导出"),_("code",[v._v("XMind")]),v._v("文件的方法。")]),_("h2",[v._v("引入")]),_("pre",{staticClass:"hljs"},[_("code",[_("span",{staticClass:"hljs-keyword"},[v._v("import")]),v._v(" xmind "),_("span",{staticClass:"hljs-keyword"},[v._v("from")]),v._v(" "),_("span",{staticClass:"hljs-string"},[v._v("'simple-mind-map/src/parse/xmind.js'")]),v._v("\n")])]),_("p",[v._v("如果使用的是"),_("code",[v._v("umd")]),v._v("格式的文件,那么可以通过如下方式获取:")]),_("pre",{staticClass:"hljs"},[_("code",[_("span",{staticClass:"hljs-tag"},[v._v("<"),_("span",{staticClass:"hljs-name"},[v._v("script")]),v._v(" "),_("span",{staticClass:"hljs-attr"},[v._v("src")]),v._v("="),_("span",{staticClass:"hljs-string"},[v._v('"simple-mind-map/dist/simpleMindMap.umd.min.js"')]),v._v(">")]),_("span",{staticClass:"hljs-tag"},[v._v("</"),_("span",{staticClass:"hljs-name"},[v._v("script")]),v._v(">")]),v._v("\n")])]),_("pre",{staticClass:"hljs"},[_("code",[v._v("simpleMindMap.xmind\n")])]),_("h2",[v._v("方法")]),_("h3",[v._v("xmind.parseXmindFile(file)")]),_("p",[v._v("解析"),_("code",[v._v(".xmind")]),v._v("文件,返回解析后的数据,可以使用"),_("code",[v._v("mindMap.setData(data)")]),v._v("来将返回的数据渲染到画布上")]),_("p",[_("code",[v._v("file")]),v._v(":"),_("code",[v._v("File")]),v._v("对象")]),_("h3",[v._v("xmind.transformXmind(content)")]),_("blockquote",[_("p",[v._v("v0.6.6+版本该方法改为异步方法,返回一个Promise实例")])]),_("p",[v._v("转换"),_("code",[v._v("xmind")]),v._v("数据,"),_("code",[v._v(".xmind")]),v._v("文件本质上是一个压缩包,改成"),_("code",[v._v("zip")]),v._v("后缀可以解压缩,里面存在一个"),_("code",[v._v("content.json")]),v._v("文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,可以使用"),_("code",[v._v("mindMap.setData(data)")]),v._v("来将返回的数据渲染到画布上")]),_("p",[_("code",[v._v("content")]),v._v(":"),_("code",[v._v(".xmind")]),v._v("压缩包内的"),_("code",[v._v("content.json")]),v._v("文件内容")]),_("h3",[v._v("xmind.transformOldXmind(content)")]),_("blockquote",[_("p",[v._v("v0.2.8+")])]),_("p",[v._v("针对"),_("code",[v._v("xmind8")]),v._v("版本的数据解析,因为该版本的"),_("code",[v._v(".xmind")]),v._v("文件内没有"),_("code",[v._v("content.json")]),v._v(",对应的是"),_("code",[v._v("content.xml")]),v._v("。")]),_("p",[_("code",[v._v("content")]),v._v(":"),_("code",[v._v(".xmind")]),v._v("压缩包内的"),_("code",[v._v("content.xml")]),v._v("文件内容")]),_("h3",[v._v("transformToXmind(data, name)")]),_("blockquote",[_("p",[v._v("v0.6.6+")])]),_("ul",[_("li",[_("p",[_("code",[v._v("data")]),v._v(":"),_("code",[v._v("simple-mind-map")]),v._v("思维导图数据,可以通过"),_("code",[v._v("mindMap.getData()")]),v._v("方法获取。")])]),_("li",[_("p",[_("code",[v._v("name")]),v._v(":要导出的文件名。")])])]),_("p",[v._v("将"),_("code",[v._v("simple-mind-map")]),v._v("数据转为"),_("code",[v._v("xmind")]),v._v("文件。该方法为异步方法,返回一个"),_("code",[v._v("Promise")]),v._v("实例,返回的数据是一个"),_("code",[v._v("blob")]),v._v("类型的"),_("code",[v._v("zip")]),v._v("压缩包数据,你可以自行下载为文件。")])])}],t={},d=t,a=s("2877"),i=Object(a["a"])(d,n,e,!1,null,null,null);_["default"]=i.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0ddf37"],{8427:function(v,_,n){"use strict";n.r(_);var s=function(){var v=this;v._self._c;return v._m(0)},e=[function(){var v=this,_=v._self._c;return _("div",[_("h1",[v._v("XMind解析")]),_("blockquote",[_("p",[v._v("v0.2.7+")])]),_("p",[v._v("提供导入和导出"),_("code",[v._v("XMind")]),v._v("文件的方法。")]),_("h2",[v._v("引入")]),_("pre",{staticClass:"hljs"},[_("code",[_("span",{staticClass:"hljs-keyword"},[v._v("import")]),v._v(" xmind "),_("span",{staticClass:"hljs-keyword"},[v._v("from")]),v._v(" "),_("span",{staticClass:"hljs-string"},[v._v("'simple-mind-map/src/parse/xmind.js'")]),v._v("\n")])]),_("p",[v._v("如果使用的是"),_("code",[v._v("umd")]),v._v("格式的文件,那么可以通过如下方式获取:")]),_("pre",{staticClass:"hljs"},[_("code",[_("span",{staticClass:"hljs-tag"},[v._v("<"),_("span",{staticClass:"hljs-name"},[v._v("script")]),v._v(" "),_("span",{staticClass:"hljs-attr"},[v._v("src")]),v._v("="),_("span",{staticClass:"hljs-string"},[v._v('"simple-mind-map/dist/simpleMindMap.umd.min.js"')]),v._v(">")]),_("span",{staticClass:"hljs-tag"},[v._v("</"),_("span",{staticClass:"hljs-name"},[v._v("script")]),v._v(">")]),v._v("\n")])]),_("pre",{staticClass:"hljs"},[_("code",[v._v("simpleMindMap.xmind\n")])]),_("h2",[v._v("方法")]),_("h3",[v._v("xmind.parseXmindFile(file, handleMultiCanvas)")]),_("p",[v._v("解析"),_("code",[v._v(".xmind")]),v._v("文件,返回解析后的数据,可以使用"),_("code",[v._v("mindMap.setData(data)")]),v._v("来将返回的数据渲染到画布上")]),_("p",[_("code",[v._v("file")]),v._v(":"),_("code",[v._v("File")]),v._v("对象")]),_("p",[_("code",[v._v("handleMultiCanvas")]),v._v(":v0.10.0+,可选,可传递一个函数,如果导入的xmind文件存在多个画布,那么会调用该函数,函数接收xmind画布列表数据为参数,需要返回其中一个画布的数据,比如接收的参数为"),_("code",[v._v("content")]),v._v(",要导入第二个画布的数据则返回"),_("code",[v._v("content[1]")]),v._v("。函数可以是异步函数,返回一个Promise实例。")]),_("h3",[v._v("xmind.transformXmind(content)")]),_("blockquote",[_("p",[v._v("v0.6.6+版本该方法改为异步方法,返回一个Promise实例")])]),_("p",[v._v("转换"),_("code",[v._v("xmind")]),v._v("数据,"),_("code",[v._v(".xmind")]),v._v("文件本质上是一个压缩包,改成"),_("code",[v._v("zip")]),v._v("后缀可以解压缩,里面存在一个"),_("code",[v._v("content.json")]),v._v("文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,可以使用"),_("code",[v._v("mindMap.setData(data)")]),v._v("来将返回的数据渲染到画布上")]),_("p",[_("code",[v._v("content")]),v._v(":"),_("code",[v._v(".xmind")]),v._v("压缩包内的"),_("code",[v._v("content.json")]),v._v("文件内容")]),_("h3",[v._v("xmind.transformOldXmind(content)")]),_("blockquote",[_("p",[v._v("v0.2.8+")])]),_("p",[v._v("针对"),_("code",[v._v("xmind8")]),v._v("版本的数据解析,因为该版本的"),_("code",[v._v(".xmind")]),v._v("文件内没有"),_("code",[v._v("content.json")]),v._v(",对应的是"),_("code",[v._v("content.xml")]),v._v("。")]),_("p",[_("code",[v._v("content")]),v._v(":"),_("code",[v._v(".xmind")]),v._v("压缩包内的"),_("code",[v._v("content.xml")]),v._v("文件内容")]),_("h3",[v._v("transformToXmind(data, name)")]),_("blockquote",[_("p",[v._v("v0.6.6+")])]),_("ul",[_("li",[_("p",[_("code",[v._v("data")]),v._v(":"),_("code",[v._v("simple-mind-map")]),v._v("思维导图数据,可以通过"),_("code",[v._v("mindMap.getData()")]),v._v("方法获取。")])]),_("li",[_("p",[_("code",[v._v("name")]),v._v(":要导出的文件名。")])])]),_("p",[v._v("将"),_("code",[v._v("simple-mind-map")]),v._v("数据转为"),_("code",[v._v("xmind")]),v._v("文件。该方法为异步方法,返回一个"),_("code",[v._v("Promise")]),v._v("实例,返回的数据是一个"),_("code",[v._v("blob")]),v._v("类型的"),_("code",[v._v("zip")]),v._v("压缩包数据,你可以自行下载为文件。")])])}],t={},d=t,a=n("2877"),i=Object(a["a"])(d,s,e,!1,null,null,null);_["default"]=i.exports}}]);
|
||||
2
dist/js/chunk-2d0f026c.js
vendored
2
dist/js/chunk-2d208ffa.js
vendored
1
dist/js/chunk-2d22a194.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22a194"],{dfea:function(p,v,_){"use strict";_.r(v);var e=function(){var p=this;p._self._c;return p._m(0)},t=[function(){var p=this,v=p._self._c;return v("div",[v("h1",[p._v("局域网docker部署解决HTTPS问题的一种方法")]),v("blockquote",[v("p",[p._v("本文来自:"),v("a",{attrs:{href:"https://github.com/Brzjomo"}},[p._v("Brzjomo")]),p._v("的"),v("a",{attrs:{href:"https://github.com/wanglin2/mind-map/issues/658"}},[p._v("issue")]),p._v("。")])]),v("p",[p._v("受Api的限制,MindMap以HTTP访问时,目录、新建和打开功能不能正常工作。因此在局域网架设时,需要给它进行配置证书等操作,使其正常工作。")]),v("p",[p._v("假设先前已经基于Github源码,架设了MindMap的docker服务。没有的先看这个"),v("a",{attrs:{href:"https://github.com/wanglin2/mind-map/issues/309"}},[p._v("Issue")])]),v("p",[p._v("事前准备: 需要准备一个域名。")]),v("p",[p._v("需要安装Linux 服务器运维管理面板"),v("a",{attrs:{href:"https://github.com/1Panel-dev/1Panel"}},[p._v("1panel")])]),v("p",[p._v("设置域名解析: 以阿里云为例,登录后进入"),v("a",{attrs:{href:"https://dns.console.aliyun.com/#/dns/domainList"}},[p._v("域名解析页面")])]),v("p",[p._v("点击对应域名的解析设置。")]),v("p",[p._v("添加或编辑对应的@和www记录,将IP记录值修改为局域网IP,比如192.168.2.36。")]),v("p",[p._v("保存后退出。")]),v("p",[p._v("获取AccessKey: 进入账号下面的AccessKey管理。")]),v("p",[p._v("创建或者使用已经记录的AccessKey。")]),v("p",[p._v("1panel设置: 进入应用商店,安装OpenResty(稍后用于申请证书和设置反代)。")]),v("p",[p._v("进入网站-网站,点击创建网站。")]),v("p",[p._v("点击反向代理。")]),v("p",[p._v("设置主域名为自己的域名。")]),v("p",[p._v("代理地址为http和127.0.0.1:MindMap容器端口。")]),v("p",[p._v("点击确认。")]),v("p",[p._v("创建证书申请账户: 进入1panel的网站-证书,点击Acme 账户。")]),v("p",[p._v("点击创建账户。")]),v("p",[p._v("输入邮箱后确认。")]),v("p",[p._v("回到刚才的证书页面,点击DNS 账户。")]),v("p",[p._v("点击创建账户。")]),v("p",[p._v("填写名称后,选择类型为阿里云DNS。")]),v("p",[p._v("再填入刚才准备好的Access Key和Secret Key。")]),v("p",[p._v("点击确认。")]),v("p",[p._v("申请证书: 回到刚才的证书页面,点击申请证书。")]),v("p",[p._v("填写主域名,其他按实际情况填写。一般会自动设置。")]),v("p",[p._v("点击确认,等待其成功。")]),v("p",[p._v("启用HTTPS访问: 回到1panel的网站管理页面。")]),v("p",[p._v("找到刚才建立的反向代理,点击配置。")]),v("p",[p._v("点击HTTPS。")]),v("p",[p._v("点击启用HTTPS。")]),v("p",[p._v("SSL 选项设置为选择已有证书。")]),v("p",[p._v("选择好刚才创建的Acme账户和证书。")]),v("p",[p._v("点击保存。")]),v("p",[p._v("此时,在局域网内访问该域名,应当能正确以Https访问MindMap了。")]),v("p",[p._v("如果不能,输入host 域名,查看返回的DNS解析是否为局域网IP。")])])}],s={},n=s,a=_("2877"),c=Object(a["a"])(n,e,t,!1,null,null,null);v["default"]=c.exports}}]);
|
||||
2
dist/js/chunk-2d22bd06.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22bd06"],{f127:function(e,t,n){"use strict";n.r(t);var s=function(){var e=this;e._self._c;return e._m(0)},a=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("XMind parse")]),t("blockquote",[t("p",[e._v("v0.2.7+")])]),t("p",[e._v("Provides methods for importing and export "),t("code",[e._v("XMind")]),e._v(" files.")]),t("h2",[e._v("Import")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[e._v("import")]),e._v(" xmind "),t("span",{staticClass:"hljs-keyword"},[e._v("from")]),e._v(" "),t("span",{staticClass:"hljs-string"},[e._v("'simple-mind-map/src/parse/xmind.js'")]),e._v("\n")])]),t("p",[e._v("If you are using the file in the format of "),t("code",[e._v("umd")]),e._v(", you can obtain it in the following way:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-tag"},[e._v("<"),t("span",{staticClass:"hljs-name"},[e._v("script")]),e._v(" "),t("span",{staticClass:"hljs-attr"},[e._v("src")]),e._v("="),t("span",{staticClass:"hljs-string"},[e._v('"simple-mind-map/dist/simpleMindMap.umd.min.js"')]),e._v(">")]),t("span",{staticClass:"hljs-tag"},[e._v("</"),t("span",{staticClass:"hljs-name"},[e._v("script")]),e._v(">")]),e._v("\n")])]),t("pre",{staticClass:"hljs"},[t("code",[e._v("simpleMindMap.xmind\n")])]),t("h2",[e._v("Methods")]),t("h3",[e._v("xmind.parseXmindFile(file)")]),t("p",[e._v("Parsing the "),t("code",[e._v(".xmind")]),e._v(" file and returning the parsed data. You can use "),t("code",[e._v("mindMap.setData(data)")]),e._v(" to render the returned data to the canvas.")]),t("p",[t("code",[e._v("file")]),e._v(": "),t("code",[e._v("File")]),e._v(" object")]),t("h3",[e._v("xmind.transformXmind(content)")]),t("blockquote",[t("p",[e._v("V0.6.6+version changes the method to asynchronous and returns a Promise instance")])]),t("p",[e._v("Convert "),t("code",[e._v("xmind")]),e._v(" data. The "),t("code",[e._v(".xmind")]),e._v(" file is essentially a "),t("code",[e._v("zip")]),e._v(" file that can be decompressed by changing the suffix to zip. Inside, there is a "),t("code",[e._v("content.json")]),e._v(" file. If you have parsed this file yourself, you can pass the contents of this file to this method for conversion. You can use "),t("code",[e._v("mindMap.setData(data)")]),e._v(" to render the returned data to the canvas.")]),t("p",[t("code",[e._v("content")]),e._v(": the contents of the "),t("code",[e._v("content.json")]),e._v(" file within the "),t("code",[e._v(".xmind")]),e._v(" zip package")]),t("h3",[e._v("xmind.transformOldXmind(content)")]),t("blockquote",[t("p",[e._v("v0.2.8+")])]),t("p",[e._v("For data parsing of the "),t("code",[e._v("xmind8")]),e._v(" version, because the "),t("code",[e._v(".xmind")]),e._v(" file in this version does not have a "),t("code",[e._v("content.json")]),e._v(", it corresponds to "),t("code",[e._v("content.xml")]),e._v(".")]),t("p",[t("code",[e._v("content")]),e._v(": the contents of the "),t("code",[e._v("content.xml")]),e._v(" file within the "),t("code",[e._v(".xmind")]),e._v(" zip package")]),t("h3",[e._v("transformToXmind(data, name)")]),t("blockquote",[t("p",[e._v("v0.6.6+")])]),t("ul",[t("li",[t("p",[t("code",[e._v("data")]),e._v(": "),t("code",[e._v("simple-mind-map")]),e._v(" data, you can get it by "),t("code",[e._v("mindMap.getData()")]),e._v(" method.")])]),t("li",[t("p",[t("code",[e._v("name")]),e._v(": The file name to export.")])])]),t("p",[e._v("Convert the "),t("code",[e._v("simple mind map")]),e._v(" data to an "),t("code",[e._v("xmind")]),e._v(" file. This method is asynchronous and returns an instance of "),t("code",[e._v("Promise")]),e._v(". The returned data is a "),t("code",[e._v("blob")]),e._v(" type "),t("code",[e._v("zip")]),e._v(" compressed package data, which you can download as a file yourself.")])])}],o={},i=o,d=n("2877"),v=Object(d["a"])(i,s,a,!1,null,null,null);t["default"]=v.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22bd06"],{f127:function(e,t,n){"use strict";n.r(t);var a=function(){var e=this;e._self._c;return e._m(0)},s=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("XMind parse")]),t("blockquote",[t("p",[e._v("v0.2.7+")])]),t("p",[e._v("Provides methods for importing and export "),t("code",[e._v("XMind")]),e._v(" files.")]),t("h2",[e._v("Import")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[e._v("import")]),e._v(" xmind "),t("span",{staticClass:"hljs-keyword"},[e._v("from")]),e._v(" "),t("span",{staticClass:"hljs-string"},[e._v("'simple-mind-map/src/parse/xmind.js'")]),e._v("\n")])]),t("p",[e._v("If you are using the file in the format of "),t("code",[e._v("umd")]),e._v(", you can obtain it in the following way:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-tag"},[e._v("<"),t("span",{staticClass:"hljs-name"},[e._v("script")]),e._v(" "),t("span",{staticClass:"hljs-attr"},[e._v("src")]),e._v("="),t("span",{staticClass:"hljs-string"},[e._v('"simple-mind-map/dist/simpleMindMap.umd.min.js"')]),e._v(">")]),t("span",{staticClass:"hljs-tag"},[e._v("</"),t("span",{staticClass:"hljs-name"},[e._v("script")]),e._v(">")]),e._v("\n")])]),t("pre",{staticClass:"hljs"},[t("code",[e._v("simpleMindMap.xmind\n")])]),t("h2",[e._v("Methods")]),t("h3",[e._v("xmind.parseXmindFile(file, handleMultiCanvas)")]),t("p",[e._v("Parsing the "),t("code",[e._v(".xmind")]),e._v(" file and returning the parsed data. You can use "),t("code",[e._v("mindMap.setData(data)")]),e._v(" to render the returned data to the canvas.")]),t("p",[t("code",[e._v("file")]),e._v(": "),t("code",[e._v("File")]),e._v(" object")]),t("p",[t("code",[e._v("handleMultiCanvas")]),e._v(":v0.10.0+,Optional, a function can be passed. If there are multiple canvases in the imported xmind file, this function will be called. The function takes the xmind canvas list data as a parameter and needs to return the data of one of the canvases, For example, if the received parameter is 'content', if you want to import data from the second canvas, you will return 'content[1]'. A function can be an asynchronous function that returns a Promise instance.")]),t("h3",[e._v("xmind.transformXmind(content)")]),t("blockquote",[t("p",[e._v("V0.6.6+version changes the method to asynchronous and returns a Promise instance")])]),t("p",[e._v("Convert "),t("code",[e._v("xmind")]),e._v(" data. The "),t("code",[e._v(".xmind")]),e._v(" file is essentially a "),t("code",[e._v("zip")]),e._v(" file that can be decompressed by changing the suffix to zip. Inside, there is a "),t("code",[e._v("content.json")]),e._v(" file. If you have parsed this file yourself, you can pass the contents of this file to this method for conversion. You can use "),t("code",[e._v("mindMap.setData(data)")]),e._v(" to render the returned data to the canvas.")]),t("p",[t("code",[e._v("content")]),e._v(": the contents of the "),t("code",[e._v("content.json")]),e._v(" file within the "),t("code",[e._v(".xmind")]),e._v(" zip package")]),t("h3",[e._v("xmind.transformOldXmind(content)")]),t("blockquote",[t("p",[e._v("v0.2.8+")])]),t("p",[e._v("For data parsing of the "),t("code",[e._v("xmind8")]),e._v(" version, because the "),t("code",[e._v(".xmind")]),e._v(" file in this version does not have a "),t("code",[e._v("content.json")]),e._v(", it corresponds to "),t("code",[e._v("content.xml")]),e._v(".")]),t("p",[t("code",[e._v("content")]),e._v(": the contents of the "),t("code",[e._v("content.xml")]),e._v(" file within the "),t("code",[e._v(".xmind")]),e._v(" zip package")]),t("h3",[e._v("transformToXmind(data, name)")]),t("blockquote",[t("p",[e._v("v0.6.6+")])]),t("ul",[t("li",[t("p",[t("code",[e._v("data")]),e._v(": "),t("code",[e._v("simple-mind-map")]),e._v(" data, you can get it by "),t("code",[e._v("mindMap.getData()")]),e._v(" method.")])]),t("li",[t("p",[t("code",[e._v("name")]),e._v(": The file name to export.")])])]),t("p",[e._v("Convert the "),t("code",[e._v("simple mind map")]),e._v(" data to an "),t("code",[e._v("xmind")]),e._v(" file. This method is asynchronous and returns an instance of "),t("code",[e._v("Promise")]),e._v(". The returned data is a "),t("code",[e._v("blob")]),e._v(" type "),t("code",[e._v("zip")]),e._v(" compressed package data, which you can download as a file yourself.")])])}],o={},i=o,d=n("2877"),v=Object(d["a"])(i,a,s,!1,null,null,null);t["default"]=v.exports}}]);
|
||||
1
dist/js/chunk-2d22dd95.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22dd95"],{f8f3:function(n,t,u){"use strict";u.r(t);var _=function(){var n=this;n._self._c;return n._m(0)},c=[function(){var n=this,t=n._self._c;return t("div",[t("h1",[n._v("如何编辑数学公式")]),t("p",[n._v("数学公式只在开启了【富文本】编辑模式下才可使用。")]),t("p",[n._v("首先可以激活节点,然后点击上方工具栏中的【公式】打开右侧的格式侧边栏,然后再输入框中输入公式后点击【完成】即可将公式输入节点。")]),t("p",[n._v("当你再次双击节点时,公式会转换成源码,你可以直接修改,回车完成后即可渲染。")]),t("p",[n._v("所以你也可以不通过侧边栏,直接在文本编辑框中输入公式,不过公式的源码前后必须通过"),t("code",[n._v("$")]),n._v("符号包裹,否则不会解析为格式。")])])}],e={},v=e,p=u("2877"),r=Object(p["a"])(v,_,c,!1,null,null,null);t["default"]=r.exports}}]);
|
||||
1
dist/js/chunk-337a3983.js
vendored
Normal file
1
dist/js/chunk-bb91a162.js
vendored
Normal file
38
index.html
@@ -1,24 +1,28 @@
|
||||
<!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?78d97b280dca5d10b8bc" rel="stylesheet"><link href="dist/css/app.css?78d97b280dca5d10b8bc" 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><script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script><script>LA.init({
|
||||
id: 'KRO0WxK8GT66tYCQ',
|
||||
ck: 'KRO0WxK8GT66tYCQ',
|
||||
autoTrack: false
|
||||
})</script><link href="dist/css/chunk-vendors.css?b34a2f0278e7d1ccab6a" rel="stylesheet"><link href="dist/css/app.css?b34a2f0278e7d1ccab6a" 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({
|
||||
mindMapData: {
|
||||
root:{
|
||||
"data": {
|
||||
"text": "根节点"
|
||||
root: {
|
||||
data: {
|
||||
text: '根节点'
|
||||
},
|
||||
"children": []
|
||||
children: []
|
||||
},
|
||||
theme:{
|
||||
"template":"avocado",
|
||||
"config":{}
|
||||
theme: {
|
||||
template: 'avocado',
|
||||
config: {}
|
||||
},
|
||||
layout:"logicalStructure",
|
||||
layout: 'logicalStructure',
|
||||
config: {},
|
||||
view: null,
|
||||
view: null
|
||||
},
|
||||
lang: 'zh',
|
||||
localConfig: null
|
||||
@@ -26,14 +30,14 @@
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
const setTakeOverAppMethods = (data) => {
|
||||
const setTakeOverAppMethods = data => {
|
||||
window.takeOverAppMethods = {}
|
||||
// 获取思维导图数据的函数
|
||||
window.takeOverAppMethods.getMindMapData = () => {
|
||||
return data.mindMapData
|
||||
}
|
||||
}
|
||||
// 保存思维导图数据的函数
|
||||
window.takeOverAppMethods.saveMindMapData = (data) => {
|
||||
window.takeOverAppMethods.saveMindMapData = data => {
|
||||
console.log(data)
|
||||
}
|
||||
// 获取语言的函数
|
||||
@@ -41,7 +45,7 @@
|
||||
return data.lang
|
||||
}
|
||||
// 保存语言的函数
|
||||
window.takeOverAppMethods.saveLanguage = (lang) => {
|
||||
window.takeOverAppMethods.saveLanguage = lang => {
|
||||
console.log(lang)
|
||||
}
|
||||
// 获取本地配置的函数
|
||||
@@ -49,7 +53,7 @@
|
||||
return data.localConfig
|
||||
}
|
||||
// 保存本地配置的函数
|
||||
window.takeOverAppMethods.saveLocalConfig = (config) => {
|
||||
window.takeOverAppMethods.saveLocalConfig = config => {
|
||||
console.log(config)
|
||||
}
|
||||
}
|
||||
@@ -60,10 +64,10 @@
|
||||
// 设置全局的方法
|
||||
setTakeOverAppMethods(data)
|
||||
// 思维导图实例创建完成事件
|
||||
window.$bus.$on('app_inited', (mindMap) => {
|
||||
window.$bus.$on('app_inited', mindMap => {
|
||||
console.log(mindMap)
|
||||
})
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
// 实例化页面
|
||||
window.initApp()
|
||||
}</script><script src="dist/js/chunk-vendors.js?78d97b280dca5d10b8bc"></script><script src="dist/js/app.js?78d97b280dca5d10b8bc"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?b34a2f0278e7d1ccab6a"></script><script src="dist/js/app.js?b34a2f0278e7d1ccab6a"></script></body></html>
|
||||
@@ -16,6 +16,7 @@ import Painter from './src/plugins/Painter.js'
|
||||
import Scrollbar from './src/plugins/Scrollbar.js'
|
||||
import Formula from './src/plugins/Formula.js'
|
||||
import RainbowLines from './src/plugins/RainbowLines.js'
|
||||
import Demonstrate from './src/plugins/Demonstrate.js'
|
||||
import xmind from './src/parse/xmind.js'
|
||||
import markdown from './src/parse/markdown.js'
|
||||
import icons from './src/svg/icons.js'
|
||||
@@ -29,7 +30,7 @@ MindMap.iconList = icons.nodeIconList
|
||||
MindMap.constants = constants
|
||||
MindMap.themes = themes
|
||||
MindMap.defaultTheme = defaultTheme
|
||||
MindMap.version = '0.9.12'
|
||||
MindMap.version = '0.10.0'
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
.usePlugin(Watermark)
|
||||
@@ -48,5 +49,6 @@ MindMap.usePlugin(MiniMap)
|
||||
.usePlugin(Scrollbar)
|
||||
.usePlugin(Formula)
|
||||
.usePlugin(RainbowLines)
|
||||
.usePlugin(Demonstrate)
|
||||
|
||||
export default MindMap
|
||||
|
||||
@@ -136,10 +136,8 @@ class MindMap {
|
||||
this.associativeLineDraw.addClass('smm-associative-line-container')
|
||||
}
|
||||
// 画布
|
||||
this.svg = SVG()
|
||||
.addTo(this.el)
|
||||
.size(this.width, this.height)
|
||||
|
||||
this.svg = SVG().addTo(this.el).size(this.width, this.height)
|
||||
|
||||
// 容器
|
||||
this.draw = this.svg.group()
|
||||
this.draw.addClass('smm-container')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.9.12",
|
||||
"version": "0.10.0",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -2,6 +2,11 @@ import { CONSTANTS } from './constant'
|
||||
|
||||
// 默认选项配置
|
||||
export const defaultOpt = {
|
||||
// 【基本】
|
||||
// 容器元素,必传,必须为DOM元素
|
||||
el: null,
|
||||
// 思维导图回显数据
|
||||
data: null,
|
||||
// 是否只读
|
||||
readonly: false,
|
||||
// 布局
|
||||
@@ -24,10 +29,6 @@ export const defaultOpt = {
|
||||
imgTextMargin: 5,
|
||||
// 节点里各种文字信息的间距,如图标和文字的间距
|
||||
textContentMargin: 2,
|
||||
// 多选节点时鼠标移动到边缘时的画布移动偏移量
|
||||
selectTranslateStep: 3,
|
||||
// 多选节点时鼠标移动距边缘多少距离时开始偏移
|
||||
selectTranslateLimit: 20,
|
||||
// 自定义节点备注内容显示
|
||||
customNoteContentShow: null,
|
||||
/*
|
||||
@@ -36,21 +37,6 @@ export const defaultOpt = {
|
||||
hide(){}
|
||||
}
|
||||
*/
|
||||
// 是否开启节点自由拖拽
|
||||
enableFreeDrag: false,
|
||||
// 水印配置
|
||||
watermarkConfig: {
|
||||
onlyExport: false, // 是否仅在导出时添加水印
|
||||
text: '',
|
||||
lineSpacing: 100,
|
||||
textSpacing: 100,
|
||||
angle: 30,
|
||||
textStyle: {
|
||||
color: '#999',
|
||||
opacity: 0.5,
|
||||
fontSize: 14
|
||||
}
|
||||
},
|
||||
// 达到该宽度文本自动换行
|
||||
textAutoWrapWidth: 500,
|
||||
// 自定义鼠标滚轮事件处理
|
||||
@@ -88,9 +74,6 @@ export const defaultOpt = {
|
||||
enableShortcutOnlyWhenMouseInSvg: true,
|
||||
// 初始根节点的位置
|
||||
initRootNodePosition: null,
|
||||
// 导出png、svg、pdf时的图形内边距,注意是单侧内边距
|
||||
exportPaddingX: 10,
|
||||
exportPaddingY: 10,
|
||||
// 节点文本编辑框的z-index
|
||||
nodeTextEditZIndex: 3000,
|
||||
// 节点备注浮层的z-index
|
||||
@@ -116,8 +99,6 @@ export const defaultOpt = {
|
||||
],
|
||||
// 节点最大缓存数量
|
||||
maxNodeCacheCount: 1000,
|
||||
// 关联线默认文字
|
||||
defaultAssociativeLineText: '关联',
|
||||
// 思维导图适应画布大小时的内边距
|
||||
fitPadding: 50,
|
||||
// 是否开启按住ctrl键多选节点功能
|
||||
@@ -132,14 +113,9 @@ export const defaultOpt = {
|
||||
customCreateNodeContent: null,
|
||||
// 指定内部一些元素(节点文本编辑元素、节点备注显示元素、关联线文本编辑元素、节点图片调整按钮元素)添加到的位置,默认添加到document.body下
|
||||
customInnerElsAppendTo: null,
|
||||
// 拖拽元素时,指示元素新位置的块的最大高度
|
||||
nodeDragPlaceholderMaxSize: 20,
|
||||
// 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式
|
||||
// 开启该特性后,需要给你的输入框绑定keydown事件,并禁止冒泡
|
||||
enableAutoEnterTextEditWhenKeydown: false,
|
||||
// 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果
|
||||
// 需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果
|
||||
richTextEditFakeInPlace: false,
|
||||
// 自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片,默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据,如果你想处理其他思维导图的数据,比如processon、zhixi等,那么可以传递一个函数,接受当前剪贴板中的文本为参数,返回处理后的数据,可以返回两种类型:
|
||||
/*
|
||||
1.返回一个纯文本,那么会直接以该文本创建一个子节点
|
||||
@@ -161,26 +137,12 @@ export const defaultOpt = {
|
||||
customHandleClipboardText: null,
|
||||
// 禁止鼠标滚轮缩放,你仍旧可以使用api进行缩放
|
||||
disableMouseWheelZoom: false,
|
||||
// 禁止双指缩放,你仍旧可以使用api进行缩放
|
||||
// 需要注册TouchEvent插件后生效
|
||||
disableTouchZoom: false,
|
||||
// 错误处理函数
|
||||
errorHandler: (code, error) => {
|
||||
console.error(code, error)
|
||||
},
|
||||
// 设置导出图片和svg时,针对富文本节点内容,也就是嵌入到svg中的html节点的默认样式覆盖
|
||||
// 如果不覆盖,会发生偏移问题
|
||||
resetCss: `
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`,
|
||||
// 是否在鼠标双击时回到根节点,也就是让根节点居中显示
|
||||
enableDblclickBackToRootNode: false,
|
||||
// 导出图片时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值
|
||||
minExportImgCanvasScale: 2,
|
||||
// 节点鼠标hover和激活时显示的矩形边框的颜色
|
||||
hoverRectColor: 'rgb(94, 200, 248)',
|
||||
// 节点鼠标hover和激活时显示的矩形边框距节点内容的距离
|
||||
@@ -189,23 +151,8 @@ export const defaultOpt = {
|
||||
selectTextOnEnterEditText: false,
|
||||
// 删除节点后激活相邻节点
|
||||
deleteNodeActive: true,
|
||||
// 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动
|
||||
autoMoveWhenMouseInEdgeOnDrag: true,
|
||||
// 是否首次加载fit view
|
||||
fit: false,
|
||||
// 拖拽多个节点时随鼠标移动的示意矩形的样式配置
|
||||
dragMultiNodeRectConfig: {
|
||||
width: 40,
|
||||
height: 20,
|
||||
fill: '' // 填充颜色,如果不传默认使用连线的颜色
|
||||
},
|
||||
// 节点拖拽时新位置的示意矩形的填充颜色,如果不传默认使用连线的颜色
|
||||
dragPlaceholderRectFill: '',
|
||||
// 节点拖拽时的透明度配置
|
||||
dragOpacityConfig: {
|
||||
cloneNodeOpacity: 0.5, // 跟随鼠标移动的克隆节点或矩形的透明度
|
||||
beingDragNodeOpacity: 0.3 // 被拖拽节点的透明度
|
||||
},
|
||||
// 自定义标签的颜色
|
||||
// {pass: 'green, unpass: 'red'}
|
||||
tagsColorMap: {},
|
||||
@@ -214,9 +161,8 @@ export const defaultOpt = {
|
||||
avatarSize: 22, // 头像大小
|
||||
fontSize: 12 // 如果是文字头像,那么文字的大小
|
||||
},
|
||||
// 关联线是否始终显示在节点上层
|
||||
// false:即创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方
|
||||
associativeLineIsAlwaysAboveNode: true,
|
||||
// 协同编辑时,同一个节点不能同时被多人选中
|
||||
onlyOneEnableActiveNodeOnCooperate: false,
|
||||
// 插入概要的默认文本
|
||||
defaultGeneralizationText: '概要',
|
||||
// 粘贴文本的方式创建新节点时,控制是否按换行自动分割节点,即如果存在换行,那么会根据换行创建多个节点,否则只会创建一个节点
|
||||
@@ -243,8 +189,6 @@ export const defaultOpt = {
|
||||
// 是否将思维导图限制在画布内
|
||||
// 比如向右拖动时,思维导图图形的最左侧到达画布中心时将无法继续向右拖动,其他同理
|
||||
isLimitMindMapInCanvas: false,
|
||||
// 当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas不再起作用
|
||||
isLimitMindMapInCanvasWhenHasScrollbar: true,
|
||||
// 在节点上粘贴剪贴板中的图片的处理方法,默认是转换为data:url数据插入到节点中,你可以通过该方法来将图片数据上传到服务器,实现保存图片的url
|
||||
// 可以传递一个异步方法,接收Blob类型的图片数据,需要返回如下结构:
|
||||
/*
|
||||
@@ -257,15 +201,6 @@ export const defaultOpt = {
|
||||
}
|
||||
*/
|
||||
handleNodePasteImg: null,
|
||||
// 默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个属性来配置
|
||||
// from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算
|
||||
associativeLineInitPointsPosition: {
|
||||
// from和to可选值:left、top、bottom、right
|
||||
from: '', // 关联线起始节点上端点的位置
|
||||
to: '' // 关联线目标节点上端点的位置
|
||||
},
|
||||
// 是否允许调整关联线两个端点的位置
|
||||
enableAdjustAssociativeLinePoints: true,
|
||||
// 自定义创建节点形状的方法,可以传一个函数,均接收一个参数
|
||||
// 矩形、圆角矩形、椭圆、圆等形状会调用该方法
|
||||
// 接收svg path字符串,返回svg节点
|
||||
@@ -276,10 +211,119 @@ export const defaultOpt = {
|
||||
// 自定义转换节点连线路径的方法
|
||||
// 接收svg path字符串,返回转换后的svg path字符串
|
||||
customTransformNodeLinePath: null,
|
||||
// 快捷键操作即将执行前的生命周期函数,返回true可以阻止操作执行
|
||||
// 函数接收两个参数:key(快捷键)、activeNodeList(当前激活的节点列表)
|
||||
beforeShortcutRun: null,
|
||||
// 移动节点到画布中心、回到根节点等操作时是否将缩放层级复位为100%
|
||||
resetScaleOnMoveNodeToCenter: false,
|
||||
// 添加附加的节点前置内容,前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分
|
||||
createNodePrefixContent: null,
|
||||
// 添加附加的节点后置内容,后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分
|
||||
createNodePostfixContent: null,
|
||||
|
||||
// 【Select插件】
|
||||
// 多选节点时鼠标移动到边缘时的画布移动偏移量
|
||||
selectTranslateStep: 3,
|
||||
// 多选节点时鼠标移动距边缘多少距离时开始偏移
|
||||
selectTranslateLimit: 20,
|
||||
|
||||
// 【Drag插件】
|
||||
// 是否开启节点自由拖拽
|
||||
enableFreeDrag: false,
|
||||
// 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动
|
||||
autoMoveWhenMouseInEdgeOnDrag: true,
|
||||
// 拖拽多个节点时随鼠标移动的示意矩形的样式配置
|
||||
dragMultiNodeRectConfig: {
|
||||
width: 40,
|
||||
height: 20,
|
||||
fill: 'rgb(94, 200, 248)' // 填充颜色
|
||||
},
|
||||
// 节点拖拽时新位置的示意矩形的填充颜色
|
||||
dragPlaceholderRectFill: 'rgb(94, 200, 248)',
|
||||
// 节点拖拽时新位置的示意连线的样式配置
|
||||
dragPlaceholderLineConfig: {
|
||||
color: 'rgb(94, 200, 248)',
|
||||
width: 2
|
||||
},
|
||||
// 节点拖拽时的透明度配置
|
||||
dragOpacityConfig: {
|
||||
cloneNodeOpacity: 0.5, // 跟随鼠标移动的克隆节点或矩形的透明度
|
||||
beingDragNodeOpacity: 0.3 // 被拖拽节点的透明度
|
||||
},
|
||||
|
||||
// 【Watermark插件】
|
||||
// 水印配置
|
||||
watermarkConfig: {
|
||||
onlyExport: false, // 是否仅在导出时添加水印
|
||||
text: '',
|
||||
lineSpacing: 100,
|
||||
textSpacing: 100,
|
||||
angle: 30,
|
||||
textStyle: {
|
||||
color: '#999',
|
||||
opacity: 0.5,
|
||||
fontSize: 14
|
||||
},
|
||||
belowNode: false
|
||||
},
|
||||
|
||||
// 【Export插件】
|
||||
// 导出png、svg、pdf时的图形内边距,注意是单侧内边距
|
||||
exportPaddingX: 10,
|
||||
exportPaddingY: 10,
|
||||
// 设置导出图片和svg时,针对富文本节点内容,也就是嵌入到svg中的html节点的默认样式覆盖
|
||||
// 如果不覆盖,会发生偏移问题
|
||||
resetCss: `
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`,
|
||||
// 导出图片时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值
|
||||
minExportImgCanvasScale: 2,
|
||||
// 导出png、svg、pdf时在头部和尾部添加自定义内容
|
||||
// 可传递一个函数,这个函数可以返回null代表不添加内容,也可以返回如下数据:
|
||||
/*
|
||||
{
|
||||
el,// 要追加的自定义DOM节点,样式可内联
|
||||
cssText,// 可选,如果样式不想内联,可以传递该值,一个css字符串
|
||||
height: 50// 返回的DOM节点的高度,必须传递
|
||||
}
|
||||
*/
|
||||
addContentToHeader: null,
|
||||
addContentToFooter: null,
|
||||
|
||||
// 【AssociativeLine插件】
|
||||
// 关联线默认文字
|
||||
defaultAssociativeLineText: '关联',
|
||||
// 关联线是否始终显示在节点上层
|
||||
// false:即创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方
|
||||
associativeLineIsAlwaysAboveNode: true,
|
||||
// 默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个属性来配置
|
||||
// from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算
|
||||
associativeLineInitPointsPosition: {
|
||||
// from和to可选值:left、top、bottom、right
|
||||
from: '', // 关联线起始节点上端点的位置
|
||||
to: '' // 关联线目标节点上端点的位置
|
||||
},
|
||||
// 是否允许调整关联线两个端点的位置
|
||||
enableAdjustAssociativeLinePoints: true,
|
||||
|
||||
// 【TouchEvent插件】
|
||||
// 禁止双指缩放,你仍旧可以使用api进行缩放
|
||||
// 需要注册TouchEvent插件后生效
|
||||
disableTouchZoom: false,
|
||||
|
||||
// 【Scrollbar插件】
|
||||
// 当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas不再起作用
|
||||
isLimitMindMapInCanvasWhenHasScrollbar: true,
|
||||
|
||||
// 【Search插件】
|
||||
// 是否仅搜索当前渲染的节点,被收起的节点不会被搜索到
|
||||
isOnlySearchCurrentRenderNodes: false,
|
||||
// 协同编辑时,同一个节点不能同时被多人选中
|
||||
onlyOneEnableActiveNodeOnCooperate: false,
|
||||
|
||||
// 【Cooperate插件】
|
||||
// 协同编辑时,节点操作即将更新到其他客户端前的生命周期函数
|
||||
// 函数接收一个对象作为参数:
|
||||
/*
|
||||
@@ -289,9 +333,8 @@ export const defaultOpt = {
|
||||
}
|
||||
*/
|
||||
beforeCooperateUpdate: null,
|
||||
// 快捷键操作即将执行前的生命周期函数,返回true可以阻止操作执行
|
||||
// 函数接收两个参数:key(快捷键)、activeNodeList(当前激活的节点列表)
|
||||
beforeShortcutRun: null,
|
||||
|
||||
// 【RainbowLines插件】
|
||||
// 彩虹线条配置,需要先注册RainbowLines插件
|
||||
rainbowLinesConfig: {
|
||||
open: false, // 是否开启彩虹线条
|
||||
@@ -308,23 +351,21 @@ export const defaultOpt = {
|
||||
]
|
||||
*/
|
||||
},
|
||||
// 导出png、svg、pdf时在头部和尾部添加自定义内容
|
||||
// 可传递一个函数,这个函数可以返回null代表不添加内容,也可以返回如下数据:
|
||||
/*
|
||||
{
|
||||
el,// 要追加的自定义DOM节点,样式可内联
|
||||
cssText,// 可选,如果样式不想内联,可以传递该值,一个css字符串
|
||||
height: 50// 返回的DOM节点的高度,必须传递
|
||||
}
|
||||
*/
|
||||
addContentToHeader: null,
|
||||
addContentToFooter: null,
|
||||
|
||||
// 【Demonstrate插件】
|
||||
// 演示插件配置
|
||||
demonstrateConfig: null,
|
||||
// 移动节点到画布中心、回到根节点等操作时是否将缩放层级复位为100%
|
||||
resetScaleOnMoveNodeToCenter: false,
|
||||
// 添加附加的节点前置内容,前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分
|
||||
createNodePrefixContent: null,
|
||||
// 添加附加的节点后置内容,后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分
|
||||
createNodePostfixContent: null
|
||||
|
||||
// 【Formula插件】
|
||||
// 是否开启在富文本编辑框中直接编辑数学公式
|
||||
enableEditFormulaInRichTextEdit: true,
|
||||
|
||||
// 【RichText插件】
|
||||
// 转换富文本内容,当进入富文本编辑时,可以通过该参数传递一个函数,函数接收文本内容,需要返回你处理后的文本内容
|
||||
transformRichTextOnEnterEdit: null,
|
||||
// 可以传递一个函数,即将结束富文本编辑前会执行该函数,函数接收richText实例,所以你可以在此时机更新quill文档数据
|
||||
beforeHideRichTextEdit: null,
|
||||
// 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果
|
||||
// 需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果
|
||||
richTextEditFakeInPlace: false,
|
||||
}
|
||||
|
||||
@@ -448,6 +448,7 @@ class Render {
|
||||
this.mindMap.emit('node_tree_render_end')
|
||||
return
|
||||
}
|
||||
this.mindMap.emit('node_tree_render_start')
|
||||
// 计算布局
|
||||
this.layout.doLayout(root => {
|
||||
// 删除本次渲染时不再需要的节点
|
||||
|
||||
@@ -8,12 +8,18 @@ import nodeCreateContentsMethods from './nodeCreateContents'
|
||||
import nodeExpandBtnPlaceholderRectMethods from './nodeExpandBtnPlaceholderRect'
|
||||
import nodeCooperateMethods from './nodeCooperate'
|
||||
import { CONSTANTS } from '../../../constants/constant'
|
||||
import { copyNodeTree, createForeignObjectNode } from '../../../utils/index'
|
||||
import {
|
||||
copyNodeTree,
|
||||
createForeignObjectNode,
|
||||
createUid,
|
||||
addXmlns
|
||||
} from '../../../utils/index'
|
||||
|
||||
// 节点类
|
||||
class Node {
|
||||
// 构造函数
|
||||
constructor(opt = {}) {
|
||||
this.opt = opt
|
||||
// 节点数据
|
||||
this.nodeData = this.handleData(opt.data || {})
|
||||
// uid
|
||||
@@ -111,31 +117,35 @@ class Node {
|
||||
this.needLayout = false
|
||||
// 当前是否是隐藏状态
|
||||
this.isHide = false
|
||||
// 概要相关方法
|
||||
Object.keys(nodeGeneralizationMethods).forEach(item => {
|
||||
this[item] = nodeGeneralizationMethods[item].bind(this)
|
||||
})
|
||||
// 展开收起按钮相关方法
|
||||
Object.keys(nodeExpandBtnMethods).forEach(item => {
|
||||
this[item] = nodeExpandBtnMethods[item].bind(this)
|
||||
})
|
||||
// 展开收起按钮占位元素相关方法
|
||||
Object.keys(nodeExpandBtnPlaceholderRectMethods).forEach(item => {
|
||||
this[item] = nodeExpandBtnPlaceholderRectMethods[item].bind(this)
|
||||
})
|
||||
// 命令的相关方法
|
||||
Object.keys(nodeCommandWrapsMethods).forEach(item => {
|
||||
this[item] = nodeCommandWrapsMethods[item].bind(this)
|
||||
})
|
||||
// 创建节点内容的相关方法
|
||||
Object.keys(nodeCreateContentsMethods).forEach(item => {
|
||||
this[item] = nodeCreateContentsMethods[item].bind(this)
|
||||
})
|
||||
// 协同相关
|
||||
if (this.mindMap.cooperate) {
|
||||
Object.keys(nodeCooperateMethods).forEach(item => {
|
||||
this[item] = nodeCooperateMethods[item].bind(this)
|
||||
const proto = Object.getPrototypeOf(this)
|
||||
if (!proto.bindEvent) {
|
||||
// 概要相关方法
|
||||
Object.keys(nodeGeneralizationMethods).forEach(item => {
|
||||
proto[item] = nodeGeneralizationMethods[item]
|
||||
})
|
||||
// 展开收起按钮相关方法
|
||||
Object.keys(nodeExpandBtnMethods).forEach(item => {
|
||||
proto[item] = nodeExpandBtnMethods[item]
|
||||
})
|
||||
// 展开收起按钮占位元素相关方法
|
||||
Object.keys(nodeExpandBtnPlaceholderRectMethods).forEach(item => {
|
||||
proto[item] = nodeExpandBtnPlaceholderRectMethods[item]
|
||||
})
|
||||
// 命令的相关方法
|
||||
Object.keys(nodeCommandWrapsMethods).forEach(item => {
|
||||
proto[item] = nodeCommandWrapsMethods[item]
|
||||
})
|
||||
// 创建节点内容的相关方法
|
||||
Object.keys(nodeCreateContentsMethods).forEach(item => {
|
||||
proto[item] = nodeCreateContentsMethods[item]
|
||||
})
|
||||
// 协同相关
|
||||
if (this.mindMap.cooperate) {
|
||||
Object.keys(nodeCooperateMethods).forEach(item => {
|
||||
proto[item] = nodeCooperateMethods[item]
|
||||
})
|
||||
}
|
||||
proto.bindEvent = true
|
||||
}
|
||||
// 初始化
|
||||
this.getSize()
|
||||
@@ -195,10 +205,7 @@ class Node {
|
||||
}
|
||||
// 如果没有返回内容,那么还是使用内置的节点内容
|
||||
if (this._customNodeContent) {
|
||||
this._customNodeContent.setAttribute(
|
||||
'xmlns',
|
||||
'http://www.w3.org/1999/xhtml'
|
||||
)
|
||||
addXmlns(this._customNodeContent)
|
||||
return
|
||||
}
|
||||
this._imgData = this.createImgNode()
|
||||
@@ -211,9 +218,15 @@ class Node {
|
||||
this._prefixData = createNodePrefixContent
|
||||
? createNodePrefixContent(this)
|
||||
: null
|
||||
if (this._prefixData && this._prefixData.el) {
|
||||
addXmlns(this._prefixData.el)
|
||||
}
|
||||
this._postfixData = createNodePostfixContent
|
||||
? createNodePostfixContent(this)
|
||||
: null
|
||||
if (this._postfixData && this._postfixData.el) {
|
||||
addXmlns(this._postfixData.el)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算节点的宽高
|
||||
@@ -521,7 +534,7 @@ class Node {
|
||||
}
|
||||
}
|
||||
// 多选和取消多选
|
||||
if ((e.ctrlKey || e.metaKey) && enableCtrlKeyNodeSelection) {
|
||||
if (!readonly && (e.ctrlKey || e.metaKey) && enableCtrlKeyNodeSelection) {
|
||||
this.isMultipleChoice = true
|
||||
let isActive = this.getData('isActive')
|
||||
if (!isActive)
|
||||
@@ -773,9 +786,9 @@ class Node {
|
||||
if (this.nodeData.inserting) {
|
||||
delete this.nodeData.inserting
|
||||
this.active()
|
||||
setTimeout(() => {
|
||||
this.mindMap.emit('node_dblclick', this, null, true)
|
||||
}, 0)
|
||||
// setTimeout(() => {
|
||||
this.mindMap.emit('node_dblclick', this, null, true)
|
||||
// }, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1175,6 +1188,19 @@ class Node {
|
||||
closeHighlight() {
|
||||
if (this.group) this.group.removeClass('smm-node-highlight')
|
||||
}
|
||||
|
||||
// 伪克隆节点
|
||||
// 克隆出的节点并不能真正当做一个节点使用
|
||||
fakeClone() {
|
||||
const newNode = new Node({
|
||||
...this.opt,
|
||||
uid: createUid()
|
||||
})
|
||||
Object.keys(this).forEach(item => {
|
||||
newNode[item] = this[item]
|
||||
})
|
||||
return newNode
|
||||
}
|
||||
}
|
||||
|
||||
export default Node
|
||||
|
||||
@@ -5,12 +5,12 @@ import {
|
||||
addHtmlStyle,
|
||||
checkIsRichText,
|
||||
isUndef,
|
||||
createForeignObjectNode
|
||||
createForeignObjectNode,
|
||||
addXmlns
|
||||
} from '../../../utils'
|
||||
import { Image as SVGImage, SVG, A, G, Rect, Text } from '@svgdotjs/svg.js'
|
||||
import iconsSvg from '../../../svg/icons'
|
||||
import { CONSTANTS } from '../../../constants/constant'
|
||||
import { defenseXSS } from '../../../utils/xss'
|
||||
|
||||
// 创建图片节点
|
||||
function createImgNode() {
|
||||
@@ -142,7 +142,7 @@ function createRichTextNode() {
|
||||
text: text
|
||||
})
|
||||
}
|
||||
let html = `<div>${defenseXSS(this.getData('text'))}</div>`
|
||||
let html = `<div>${this.getData('text')}</div>`
|
||||
if (!this.mindMap.commonCaches.measureRichtextNodeTextSizeEl) {
|
||||
this.mindMap.commonCaches.measureRichtextNodeTextSizeEl =
|
||||
document.createElement('div')
|
||||
@@ -158,7 +158,7 @@ function createRichTextNode() {
|
||||
div.innerHTML = html
|
||||
let el = div.children[0]
|
||||
el.classList.add('smm-richtext-node-wrap')
|
||||
el.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
addXmlns(el)
|
||||
el.style.maxWidth = textAutoWrapWidth + 'px'
|
||||
let { width, height } = el.getBoundingClientRect()
|
||||
// 如果文本为空,那么需要计算一个默认高度
|
||||
|
||||
@@ -29,8 +29,9 @@ class View {
|
||||
this.fit()
|
||||
})
|
||||
// 拖动视图
|
||||
this.mindMap.event.on('mousedown', () => {
|
||||
this.mindMap.event.on('mousedown', e => {
|
||||
if (this.mindMap.opt.isDisableDrag) return
|
||||
e.preventDefault()
|
||||
this.sx = this.x
|
||||
this.sy = this.y
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
} from '../utils/xmind'
|
||||
|
||||
// 解析.xmind文件
|
||||
const parseXmindFile = file => {
|
||||
const parseXmindFile = (file, handleMultiCanvas) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
JSZip.loadAsync(file).then(
|
||||
async zip => {
|
||||
@@ -25,7 +25,7 @@ const parseXmindFile = file => {
|
||||
let xmlFile = zip.files['content.xml'] || zip.files['/content.xml']
|
||||
if (jsonFile) {
|
||||
let json = await jsonFile.async('string')
|
||||
content = await transformXmind(json, zip.files)
|
||||
content = await transformXmind(json, zip.files, handleMultiCanvas)
|
||||
} else if (xmlFile) {
|
||||
let xml = await xmlFile.async('string')
|
||||
let json = xmlConvert.xml2json(xml)
|
||||
@@ -48,8 +48,15 @@ const parseXmindFile = file => {
|
||||
}
|
||||
|
||||
// 转换xmind数据
|
||||
const transformXmind = async (content, files) => {
|
||||
const data = JSON.parse(content)[0]
|
||||
const transformXmind = async (content, files, handleMultiCanvas) => {
|
||||
content = JSON.parse(content)
|
||||
let data = null
|
||||
if (content.length > 1 && typeof handleMultiCanvas === 'function') {
|
||||
data = await handleMultiCanvas(content)
|
||||
}
|
||||
if (!data) {
|
||||
data = content[0]
|
||||
}
|
||||
const nodeTree = data.rootTopic
|
||||
const newTree = {}
|
||||
const waitLoadImageList = []
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
getNodeIndexInNodeList
|
||||
} from '../utils'
|
||||
import Base from '../layouts/Base'
|
||||
import { CONSTANTS } from '../constants/constant'
|
||||
|
||||
// 节点拖动插件
|
||||
class Drag extends Base {
|
||||
@@ -38,6 +39,10 @@ class Drag extends Base {
|
||||
this.clone = null
|
||||
// 同级位置占位符
|
||||
this.placeholder = null
|
||||
this.placeholderWidth = 50
|
||||
this.placeholderHeight = 10
|
||||
this.placeHolderLine = null
|
||||
this.placeHolderExtraLines = []
|
||||
// 鼠标按下位置和节点左上角的偏移量
|
||||
this.offsetX = 0
|
||||
this.offsetY = 0
|
||||
@@ -276,6 +281,7 @@ class Drag extends Base {
|
||||
const {
|
||||
dragMultiNodeRectConfig,
|
||||
dragPlaceholderRectFill,
|
||||
dragPlaceholderLineConfig,
|
||||
dragOpacityConfig
|
||||
} = this.mindMap.opt
|
||||
const {
|
||||
@@ -309,9 +315,19 @@ class Drag extends Base {
|
||||
this.clone.opacity(dragOpacityConfig.cloneNodeOpacity)
|
||||
this.clone.css('z-index', 99999)
|
||||
// 同级位置提示元素
|
||||
this.placeholder = this.mindMap.otherDraw.rect().fill({
|
||||
color: dragPlaceholderRectFill || lineColor
|
||||
})
|
||||
this.placeholder = this.mindMap.otherDraw
|
||||
.rect()
|
||||
.fill({
|
||||
color: dragPlaceholderRectFill || lineColor
|
||||
})
|
||||
.radius(5)
|
||||
this.placeHolderLine = this.mindMap.otherDraw
|
||||
.path()
|
||||
.stroke({
|
||||
color: dragPlaceholderLineConfig.color || lineColor,
|
||||
width: dragPlaceholderLineConfig.width
|
||||
})
|
||||
.fill({ color: 'none' })
|
||||
// 当前被拖拽的节点的临时设置
|
||||
this.beingDragNodeList.forEach(node => {
|
||||
// 降低透明度
|
||||
@@ -331,6 +347,16 @@ class Drag extends Base {
|
||||
}
|
||||
this.clone.remove()
|
||||
this.placeholder.remove()
|
||||
this.placeHolderLine.remove()
|
||||
this.removeExtraLines()
|
||||
}
|
||||
|
||||
// 移除额外创建的连线
|
||||
removeExtraLines() {
|
||||
this.placeHolderExtraLines.forEach(item => {
|
||||
item.remove()
|
||||
})
|
||||
this.placeHolderExtraLines = []
|
||||
}
|
||||
|
||||
// 检测重叠节点
|
||||
@@ -338,10 +364,22 @@ class Drag extends Base {
|
||||
if (!this.drawTransform || !this.placeholder) {
|
||||
return
|
||||
}
|
||||
const {
|
||||
LOGICAL_STRUCTURE,
|
||||
MIND_MAP,
|
||||
ORGANIZATION_STRUCTURE,
|
||||
CATALOG_ORGANIZATION,
|
||||
TIMELINE,
|
||||
TIMELINE2,
|
||||
VERTICAL_TIMELINE,
|
||||
FISHBONE
|
||||
} = CONSTANTS.LAYOUT
|
||||
this.overlapNode = null
|
||||
this.prevNode = null
|
||||
this.nextNode = null
|
||||
this.placeholder.size(0, 0)
|
||||
this.placeHolderLine.hide()
|
||||
this.removeExtraLines()
|
||||
this.nodeList.forEach(node => {
|
||||
if (node.getData('isActive')) {
|
||||
this.mindMap.execCommand('SET_NODE_ACTIVE', node, false)
|
||||
@@ -350,52 +388,310 @@ class Drag extends Base {
|
||||
return
|
||||
}
|
||||
switch (this.mindMap.opt.layout) {
|
||||
case 'logicalStructure':
|
||||
case LOGICAL_STRUCTURE:
|
||||
this.handleLogicalStructure(node)
|
||||
break
|
||||
case 'mindMap':
|
||||
case MIND_MAP:
|
||||
this.handleMindMap(node)
|
||||
break
|
||||
case 'organizationStructure':
|
||||
case ORGANIZATION_STRUCTURE:
|
||||
this.handleOrganizationStructure(node)
|
||||
break
|
||||
case 'catalogOrganization':
|
||||
case CATALOG_ORGANIZATION:
|
||||
this.handleCatalogOrganization(node)
|
||||
break
|
||||
case 'timeline':
|
||||
case TIMELINE:
|
||||
this.handleTimeLine(node)
|
||||
break
|
||||
case 'timeline2':
|
||||
case TIMELINE2:
|
||||
this.handleTimeLine2(node)
|
||||
break
|
||||
case 'verticalTimeline':
|
||||
case VERTICAL_TIMELINE:
|
||||
this.handleLogicalStructure(node)
|
||||
break
|
||||
case 'fishbone':
|
||||
case FISHBONE:
|
||||
this.handleFishbone(node)
|
||||
break
|
||||
default:
|
||||
this.handleLogicalStructure(node)
|
||||
}
|
||||
})
|
||||
// 重叠节点,也就是添加为子节点
|
||||
if (this.overlapNode) {
|
||||
this.mindMap.execCommand('SET_NODE_ACTIVE', this.overlapNode, true)
|
||||
this.handleOverlapNode()
|
||||
}
|
||||
}
|
||||
|
||||
// 处理作为子节点的情况
|
||||
handleOverlapNode() {
|
||||
const {
|
||||
LOGICAL_STRUCTURE,
|
||||
MIND_MAP,
|
||||
ORGANIZATION_STRUCTURE,
|
||||
CATALOG_ORGANIZATION,
|
||||
TIMELINE,
|
||||
TIMELINE2,
|
||||
VERTICAL_TIMELINE,
|
||||
FISHBONE
|
||||
} = CONSTANTS.LAYOUT
|
||||
const { LEFT, TOP, RIGHT, BOTTOM } = CONSTANTS.LAYOUT_GROW_DIR
|
||||
const layerIndex = this.overlapNode.layerIndex
|
||||
const children = this.overlapNode.children
|
||||
const marginX = this.mindMap.renderer.layout.getMarginX(layerIndex + 1)
|
||||
const marginY = this.mindMap.renderer.layout.getMarginY(layerIndex + 1)
|
||||
const halfPlaceholderWidth = this.placeholderWidth / 2
|
||||
const halfPlaceholderHeight = this.placeholderHeight / 2
|
||||
let dir = ''
|
||||
let x = ''
|
||||
let y = ''
|
||||
let rotate = false
|
||||
let notRenderPlaceholder = false
|
||||
// 目标节点存在子节点,那么基于最后一个子节点定位
|
||||
if (children.length > 0) {
|
||||
const lastChild = children[children.length - 1]
|
||||
const lastNodeRect = this.getNodeRect(lastChild)
|
||||
dir = this.getNewChildNodeDir(lastChild)
|
||||
switch (this.mindMap.opt.layout) {
|
||||
case LOGICAL_STRUCTURE:
|
||||
case MIND_MAP:
|
||||
x =
|
||||
dir === LEFT
|
||||
? lastNodeRect.originRight - this.placeholderWidth
|
||||
: lastNodeRect.originLeft
|
||||
y = lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight
|
||||
break
|
||||
case ORGANIZATION_STRUCTURE:
|
||||
rotate = true
|
||||
x = lastNodeRect.originRight + this.minOffset - halfPlaceholderHeight
|
||||
y = lastNodeRect.originTop
|
||||
break
|
||||
case CATALOG_ORGANIZATION:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
x =
|
||||
lastNodeRect.originRight + this.minOffset - halfPlaceholderHeight
|
||||
y = lastNodeRect.originTop
|
||||
} else {
|
||||
x = lastNodeRect.originLeft
|
||||
y =
|
||||
lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight
|
||||
}
|
||||
break
|
||||
case TIMELINE:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
x =
|
||||
lastNodeRect.originRight + this.minOffset - halfPlaceholderHeight
|
||||
y =
|
||||
lastNodeRect.originTop +
|
||||
lastNodeRect.originHeight / 2 -
|
||||
halfPlaceholderWidth
|
||||
} else {
|
||||
x = lastNodeRect.originLeft
|
||||
y =
|
||||
lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight
|
||||
}
|
||||
break
|
||||
case TIMELINE2:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
x =
|
||||
lastNodeRect.originRight + this.minOffset - halfPlaceholderHeight
|
||||
y =
|
||||
lastNodeRect.originTop +
|
||||
lastNodeRect.originHeight / 2 -
|
||||
halfPlaceholderWidth
|
||||
} else {
|
||||
x = lastNodeRect.originLeft
|
||||
if (layerIndex === 1) {
|
||||
y =
|
||||
dir === TOP
|
||||
? lastNodeRect.originTop -
|
||||
this.placeholderHeight -
|
||||
this.minOffset +
|
||||
halfPlaceholderHeight
|
||||
: lastNodeRect.originBottom +
|
||||
this.minOffset -
|
||||
halfPlaceholderHeight
|
||||
} else {
|
||||
y =
|
||||
lastNodeRect.originBottom +
|
||||
this.minOffset -
|
||||
halfPlaceholderHeight
|
||||
}
|
||||
}
|
||||
break
|
||||
case VERTICAL_TIMELINE:
|
||||
if (layerIndex === 0) {
|
||||
x =
|
||||
lastNodeRect.originLeft +
|
||||
lastNodeRect.originWidth / 2 -
|
||||
halfPlaceholderWidth
|
||||
y =
|
||||
lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight
|
||||
} else {
|
||||
x =
|
||||
dir === RIGHT
|
||||
? lastNodeRect.originLeft
|
||||
: lastNodeRect.originRight - this.placeholderWidth
|
||||
y =
|
||||
lastNodeRect.originBottom + this.minOffset - halfPlaceholderHeight
|
||||
}
|
||||
break
|
||||
case FISHBONE:
|
||||
if (layerIndex <= 1) {
|
||||
notRenderPlaceholder = true
|
||||
this.mindMap.execCommand('SET_NODE_ACTIVE', this.overlapNode, true)
|
||||
} else {
|
||||
x = lastNodeRect.originLeft
|
||||
y =
|
||||
dir === TOP
|
||||
? lastNodeRect.originBottom +
|
||||
this.minOffset -
|
||||
halfPlaceholderHeight
|
||||
: lastNodeRect.originTop -
|
||||
this.placeholderHeight -
|
||||
this.minOffset +
|
||||
halfPlaceholderHeight
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
// 目标节点不存在子节点,那么基于目标节点定位
|
||||
const nodeRect = this.getNodeRect(this.overlapNode)
|
||||
dir = this.getNewChildNodeDir(this.overlapNode)
|
||||
switch (this.mindMap.opt.layout) {
|
||||
case LOGICAL_STRUCTURE:
|
||||
case MIND_MAP:
|
||||
x =
|
||||
dir === RIGHT
|
||||
? nodeRect.originRight + marginX
|
||||
: nodeRect.originLeft - this.placeholderWidth - marginX
|
||||
y =
|
||||
nodeRect.originTop +
|
||||
(nodeRect.originHeight - this.placeholderHeight) / 2
|
||||
break
|
||||
case ORGANIZATION_STRUCTURE:
|
||||
rotate = true
|
||||
x =
|
||||
nodeRect.originLeft +
|
||||
(nodeRect.originWidth - this.placeholderHeight) / 2
|
||||
y = nodeRect.originBottom + marginX
|
||||
break
|
||||
case CATALOG_ORGANIZATION:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
}
|
||||
x = nodeRect.originLeft + nodeRect.originWidth * 0.5
|
||||
y = nodeRect.originBottom + marginX
|
||||
break
|
||||
case TIMELINE:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
}
|
||||
x = nodeRect.originLeft + nodeRect.originWidth * 0.5
|
||||
y = nodeRect.originBottom + marginY
|
||||
break
|
||||
case TIMELINE2:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
}
|
||||
x = nodeRect.originLeft + nodeRect.originWidth * 0.5
|
||||
if (layerIndex === 1) {
|
||||
y =
|
||||
dir === TOP
|
||||
? nodeRect.originTop - this.placeholderHeight - marginX
|
||||
: nodeRect.originBottom + marginX
|
||||
} else {
|
||||
y = nodeRect.originBottom + marginX
|
||||
}
|
||||
break
|
||||
case VERTICAL_TIMELINE:
|
||||
if (layerIndex === 0) {
|
||||
rotate = true
|
||||
}
|
||||
x =
|
||||
dir === RIGHT
|
||||
? nodeRect.originRight + marginX
|
||||
: nodeRect.originLeft - this.placeholderWidth - marginX
|
||||
y =
|
||||
nodeRect.originTop +
|
||||
nodeRect.originHeight / 2 -
|
||||
halfPlaceholderHeight
|
||||
break
|
||||
case FISHBONE:
|
||||
if (layerIndex <= 1) {
|
||||
notRenderPlaceholder = true
|
||||
this.mindMap.execCommand('SET_NODE_ACTIVE', this.overlapNode, true)
|
||||
} else {
|
||||
x = nodeRect.originLeft + nodeRect.originWidth * 0.5
|
||||
y =
|
||||
dir === BOTTOM
|
||||
? nodeRect.originTop -
|
||||
this.placeholderHeight -
|
||||
this.minOffset +
|
||||
halfPlaceholderHeight
|
||||
: nodeRect.originBottom + this.minOffset - halfPlaceholderHeight
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
if (!notRenderPlaceholder) {
|
||||
this.setPlaceholderRect({
|
||||
x,
|
||||
y,
|
||||
dir,
|
||||
rotate
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 获取节点的生长方向
|
||||
getNewChildNodeDir(node) {
|
||||
const {
|
||||
LOGICAL_STRUCTURE,
|
||||
MIND_MAP,
|
||||
TIMELINE2,
|
||||
VERTICAL_TIMELINE,
|
||||
FISHBONE
|
||||
} = CONSTANTS.LAYOUT
|
||||
switch (this.mindMap.opt.layout) {
|
||||
case LOGICAL_STRUCTURE:
|
||||
return CONSTANTS.LAYOUT_GROW_DIR.RIGHT
|
||||
case MIND_MAP:
|
||||
case TIMELINE2:
|
||||
case VERTICAL_TIMELINE:
|
||||
case FISHBONE:
|
||||
return node.dir
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
// 垂直方向比较
|
||||
// isReverse:是否反向
|
||||
handleVerticalCheck(node, checkList, isReverse = false) {
|
||||
let x = this.mouseMoveX
|
||||
let y = this.mouseMoveY
|
||||
let nodeRect = this.getNodeRect(node)
|
||||
if (isReverse) {
|
||||
const { layout } = this.mindMap.opt
|
||||
const { LAYOUT, LAYOUT_GROW_DIR } = CONSTANTS
|
||||
const { VERTICAL_TIMELINE, FISHBONE } = LAYOUT
|
||||
const { BOTTOM, LEFT } = LAYOUT_GROW_DIR
|
||||
const mouseMoveX = this.mouseMoveX
|
||||
const mouseMoveY = this.mouseMoveY
|
||||
const nodeRect = this.getNodeRect(node)
|
||||
const dir = this.getNewChildNodeDir(node)
|
||||
const layerIndex = node.layerIndex
|
||||
if (
|
||||
isReverse ||
|
||||
(layout === FISHBONE && dir === BOTTOM && layerIndex >= 3)
|
||||
) {
|
||||
checkList = checkList.reverse()
|
||||
}
|
||||
let oneFourthHeight = nodeRect.height / 4
|
||||
let oneFourthHeight = nodeRect.originHeight / 4
|
||||
let { prevBrotherOffset, nextBrotherOffset } =
|
||||
this.getNodeDistanceToSiblingNode(checkList, node, nodeRect, 'v')
|
||||
if (nodeRect.left <= x && nodeRect.right >= x) {
|
||||
if (nodeRect.left <= mouseMoveX && nodeRect.right >= mouseMoveX) {
|
||||
// 检测兄弟节点位置
|
||||
if (
|
||||
!this.overlapNode &&
|
||||
@@ -405,38 +701,92 @@ class Drag extends Base {
|
||||
) {
|
||||
let checkIsPrevNode =
|
||||
nextBrotherOffset > 0 // 距离下一个兄弟节点的距离大于0
|
||||
? y > nodeRect.bottom && y <= nodeRect.bottom + nextBrotherOffset // 那么在当前节点外底部判断
|
||||
: y >= nodeRect.bottom - oneFourthHeight && y <= nodeRect.bottom // 否则在当前节点内底部1/4区间判断
|
||||
? mouseMoveY > nodeRect.bottom &&
|
||||
mouseMoveY <= nodeRect.bottom + nextBrotherOffset // 那么在当前节点外底部判断
|
||||
: mouseMoveY >= nodeRect.bottom - oneFourthHeight &&
|
||||
mouseMoveY <= nodeRect.bottom // 否则在当前节点内底部1/4区间判断
|
||||
let checkIsNextNode =
|
||||
prevBrotherOffset > 0 // 距离上一个兄弟节点的距离大于0
|
||||
? y < nodeRect.top && y >= nodeRect.top - prevBrotherOffset // 那么在当前节点外底部判断
|
||||
: y >= nodeRect.top && y <= nodeRect.top + oneFourthHeight
|
||||
? mouseMoveY < nodeRect.top &&
|
||||
mouseMoveY >= nodeRect.top - prevBrotherOffset // 那么在当前节点外底部判断
|
||||
: mouseMoveY >= nodeRect.top &&
|
||||
mouseMoveY <= nodeRect.top + oneFourthHeight
|
||||
|
||||
const { scaleY } = this.drawTransform
|
||||
let x =
|
||||
dir === LEFT
|
||||
? nodeRect.originRight - this.placeholderWidth
|
||||
: nodeRect.originLeft
|
||||
let notRenderLine = false
|
||||
switch (layout) {
|
||||
case VERTICAL_TIMELINE:
|
||||
if (layerIndex === 1) {
|
||||
x =
|
||||
nodeRect.originLeft +
|
||||
nodeRect.originWidth / 2 -
|
||||
this.placeholderWidth / 2
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
if (checkIsPrevNode) {
|
||||
if (isReverse) {
|
||||
this.nextNode = node
|
||||
} else {
|
||||
this.prevNode = node
|
||||
}
|
||||
let size = this.formatPlaceholderSize(nextBrotherOffset)
|
||||
this.setPlaceholderRect(
|
||||
node.width,
|
||||
size,
|
||||
nodeRect.originLeft,
|
||||
nodeRect.originBottom
|
||||
)
|
||||
let y =
|
||||
nodeRect.originBottom +
|
||||
nextBrotherOffset / scaleY - //nextBrotherOffset已经是实际间距的一半了
|
||||
this.placeholderHeight / 2
|
||||
switch (layout) {
|
||||
case FISHBONE:
|
||||
if (layerIndex === 2) {
|
||||
notRenderLine = true
|
||||
y =
|
||||
nodeRect.originBottom +
|
||||
this.minOffset -
|
||||
this.placeholderHeight / 2
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
this.setPlaceholderRect({
|
||||
x,
|
||||
y,
|
||||
dir,
|
||||
notRenderLine
|
||||
})
|
||||
} else if (checkIsNextNode) {
|
||||
if (isReverse) {
|
||||
this.prevNode = node
|
||||
} else {
|
||||
this.nextNode = node
|
||||
}
|
||||
let size = this.formatPlaceholderSize(prevBrotherOffset)
|
||||
this.setPlaceholderRect(
|
||||
node.width,
|
||||
size,
|
||||
nodeRect.originLeft,
|
||||
nodeRect.originTop - size
|
||||
)
|
||||
let y =
|
||||
nodeRect.originTop -
|
||||
this.placeholderHeight -
|
||||
prevBrotherOffset / scaleY +
|
||||
this.placeholderHeight / 2
|
||||
switch (layout) {
|
||||
case FISHBONE:
|
||||
if (layerIndex === 2) {
|
||||
notRenderLine = true
|
||||
y =
|
||||
nodeRect.originTop -
|
||||
this.placeholderHeight -
|
||||
this.minOffset +
|
||||
this.placeholderHeight / 2
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
this.setPlaceholderRect({
|
||||
x,
|
||||
y,
|
||||
dir,
|
||||
notRenderLine
|
||||
})
|
||||
}
|
||||
}
|
||||
// 检测是否重叠
|
||||
@@ -446,7 +796,7 @@ class Drag extends Base {
|
||||
prevBrotherOffset,
|
||||
nextBrotherOffset,
|
||||
size: oneFourthHeight,
|
||||
pos: y,
|
||||
pos: mouseMoveY,
|
||||
nodeRect
|
||||
})
|
||||
}
|
||||
@@ -454,13 +804,16 @@ class Drag extends Base {
|
||||
|
||||
// 水平方向比较
|
||||
handleHorizontalCheck(node, checkList) {
|
||||
let x = this.mouseMoveX
|
||||
let y = this.mouseMoveY
|
||||
const { layout } = this.mindMap.opt
|
||||
const { LAYOUT } = CONSTANTS
|
||||
const { FISHBONE, TIMELINE, TIMELINE2 } = LAYOUT
|
||||
let mouseMoveX = this.mouseMoveX
|
||||
let mouseMoveY = this.mouseMoveY
|
||||
let nodeRect = this.getNodeRect(node)
|
||||
let oneFourthWidth = nodeRect.width / 4
|
||||
let oneFourthWidth = nodeRect.originWidth / 4
|
||||
let { prevBrotherOffset, nextBrotherOffset } =
|
||||
this.getNodeDistanceToSiblingNode(checkList, node, nodeRect, 'h')
|
||||
if (nodeRect.top <= y && nodeRect.bottom >= y) {
|
||||
if (nodeRect.top <= mouseMoveY && nodeRect.bottom >= mouseMoveY) {
|
||||
// 检测兄弟节点位置
|
||||
if (
|
||||
!this.overlapNode &&
|
||||
@@ -470,30 +823,62 @@ class Drag extends Base {
|
||||
) {
|
||||
let checkIsPrevNode =
|
||||
nextBrotherOffset > 0 // 距离下一个兄弟节点的距离大于0
|
||||
? x < nodeRect.right + nextBrotherOffset && x >= nodeRect.right // 那么在当前节点外底部判断
|
||||
: x <= nodeRect.right && x >= nodeRect.right - oneFourthWidth // 否则在当前节点内底部1/4区间判断
|
||||
? mouseMoveX < nodeRect.right + nextBrotherOffset &&
|
||||
mouseMoveX >= nodeRect.right // 那么在当前节点外底部判断
|
||||
: mouseMoveX <= nodeRect.right &&
|
||||
mouseMoveX >= nodeRect.right - oneFourthWidth // 否则在当前节点内底部1/4区间判断
|
||||
let checkIsNextNode =
|
||||
prevBrotherOffset > 0 // 距离上一个兄弟节点的距离大于0
|
||||
? x > nodeRect.left - prevBrotherOffset && x <= nodeRect.left // 那么在当前节点外底部判断
|
||||
: x <= nodeRect.left + oneFourthWidth && x >= nodeRect.left
|
||||
? mouseMoveX > nodeRect.left - prevBrotherOffset &&
|
||||
mouseMoveX <= nodeRect.left // 那么在当前节点外底部判断
|
||||
: mouseMoveX <= nodeRect.left + oneFourthWidth &&
|
||||
mouseMoveX >= nodeRect.left
|
||||
const { scaleX } = this.drawTransform
|
||||
const layerIndex = node.layerIndex
|
||||
let y = nodeRect.originTop
|
||||
let notRenderLine = false
|
||||
switch (layout) {
|
||||
case TIMELINE:
|
||||
case TIMELINE2:
|
||||
y =
|
||||
nodeRect.originTop +
|
||||
nodeRect.originHeight / 2 -
|
||||
this.placeholderWidth / 2
|
||||
break
|
||||
case FISHBONE:
|
||||
if (layerIndex === 1) {
|
||||
notRenderLine = true
|
||||
y =
|
||||
nodeRect.originTop +
|
||||
nodeRect.originHeight / 2 -
|
||||
this.placeholderWidth / 2
|
||||
}
|
||||
break
|
||||
default:
|
||||
}
|
||||
if (checkIsPrevNode) {
|
||||
this.prevNode = node
|
||||
let size = this.formatPlaceholderSize(nextBrotherOffset)
|
||||
this.setPlaceholderRect(
|
||||
size,
|
||||
node.height,
|
||||
nodeRect.originRight,
|
||||
nodeRect.originTop
|
||||
)
|
||||
this.setPlaceholderRect({
|
||||
x:
|
||||
nodeRect.originRight +
|
||||
nextBrotherOffset / scaleX - //nextBrotherOffset已经是实际间距的一半了
|
||||
this.placeholderHeight / 2,
|
||||
y,
|
||||
rotate: true,
|
||||
notRenderLine
|
||||
})
|
||||
} else if (checkIsNextNode) {
|
||||
this.nextNode = node
|
||||
let size = this.formatPlaceholderSize(prevBrotherOffset)
|
||||
this.setPlaceholderRect(
|
||||
size,
|
||||
node.height,
|
||||
nodeRect.originLeft - size,
|
||||
nodeRect.originTop
|
||||
)
|
||||
this.setPlaceholderRect({
|
||||
x:
|
||||
nodeRect.originLeft -
|
||||
this.placeholderHeight -
|
||||
prevBrotherOffset / scaleX +
|
||||
this.placeholderHeight / 2,
|
||||
y,
|
||||
rotate: true,
|
||||
notRenderLine
|
||||
})
|
||||
}
|
||||
}
|
||||
// 检测是否重叠
|
||||
@@ -503,7 +888,7 @@ class Drag extends Base {
|
||||
prevBrotherOffset,
|
||||
nextBrotherOffset,
|
||||
size: oneFourthWidth,
|
||||
pos: x,
|
||||
pos: mouseMoveX,
|
||||
nodeRect
|
||||
})
|
||||
}
|
||||
@@ -511,8 +896,12 @@ class Drag extends Base {
|
||||
|
||||
// 获取节点距前一个和后一个节点的距离
|
||||
getNodeDistanceToSiblingNode(checkList, node, nodeRect, dir) {
|
||||
let dir1 = dir === 'v' ? 'top' : 'left'
|
||||
let dir2 = dir === 'v' ? 'bottom' : 'right'
|
||||
const { TOP, LEFT, BOTTOM, RIGHT } = CONSTANTS.LAYOUT_GROW_DIR
|
||||
let { scaleX, scaleY } = this.drawTransform
|
||||
let dir1 = dir === 'v' ? TOP : LEFT
|
||||
let dir2 = dir === 'v' ? BOTTOM : RIGHT
|
||||
let scale = dir === 'v' ? scaleY : scaleX
|
||||
let minOffset = this.minOffset * scale
|
||||
let index = getNodeIndexInNodeList(node, checkList)
|
||||
let prevBrother = null
|
||||
let nextBrother = null
|
||||
@@ -531,10 +920,10 @@ class Drag extends Base {
|
||||
prevBrotherOffset = nodeRect[dir1] - prevNodeRect[dir2]
|
||||
// 间距小于10就当它不存在
|
||||
prevBrotherOffset =
|
||||
prevBrotherOffset >= this.minOffset ? prevBrotherOffset / 2 : 0
|
||||
prevBrotherOffset >= minOffset ? prevBrotherOffset / 2 : 0
|
||||
} else {
|
||||
// 没有前一个兄弟节点,那么假设和前一个节点的距离为20
|
||||
prevBrotherOffset = this.minOffset
|
||||
prevBrotherOffset = minOffset
|
||||
}
|
||||
// 和后一个兄弟节点的距离
|
||||
let nextBrotherOffset = 0
|
||||
@@ -542,25 +931,70 @@ class Drag extends Base {
|
||||
let nextNodeRect = this.getNodeRect(nextBrother)
|
||||
nextBrotherOffset = nextNodeRect[dir1] - nodeRect[dir2]
|
||||
nextBrotherOffset =
|
||||
nextBrotherOffset >= this.minOffset ? nextBrotherOffset / 2 : 0
|
||||
nextBrotherOffset >= minOffset ? nextBrotherOffset / 2 : 0
|
||||
} else {
|
||||
nextBrotherOffset = this.minOffset
|
||||
nextBrotherOffset = minOffset
|
||||
}
|
||||
return {
|
||||
prevBrother,
|
||||
prevBrotherOffset,
|
||||
nextBrother,
|
||||
nextBrotherOffset
|
||||
}
|
||||
}
|
||||
|
||||
// 处理提示元素的大小
|
||||
formatPlaceholderSize(size) {
|
||||
const { nodeDragPlaceholderMaxSize } = this.mindMap.opt
|
||||
return size > 0 ? Math.min(size, nodeDragPlaceholderMaxSize) : 5
|
||||
}
|
||||
|
||||
// 设置提示元素的大小和位置
|
||||
setPlaceholderRect(w, h, x, y) {
|
||||
setPlaceholderRect({ x, y, dir, rotate, notRenderLine }) {
|
||||
let w = this.placeholderWidth
|
||||
let h = this.placeholderHeight
|
||||
if (rotate) {
|
||||
const tmp = w
|
||||
w = h
|
||||
h = tmp
|
||||
}
|
||||
this.placeholder.size(w, h).move(x, y)
|
||||
if (notRenderLine) {
|
||||
return
|
||||
}
|
||||
const { dragPlaceholderLineConfig } = this.mindMap.opt
|
||||
let node = null
|
||||
let parent = null
|
||||
if (this.overlapNode) {
|
||||
node = this.overlapNode
|
||||
parent = this.overlapNode
|
||||
} else {
|
||||
node = this.prevNode || this.nextNode
|
||||
parent = node.parent
|
||||
}
|
||||
parent = parent.fakeClone()
|
||||
node = node.fakeClone()
|
||||
const tmpNode = this.beingDragNodeList[0].fakeClone()
|
||||
tmpNode.dir = dir
|
||||
tmpNode.left = x
|
||||
tmpNode.top = y
|
||||
tmpNode.width = w
|
||||
tmpNode.height = h
|
||||
parent.children = [tmpNode]
|
||||
parent._lines = []
|
||||
this.placeHolderLine.show()
|
||||
this.mindMap.renderer.layout.renderLine(
|
||||
parent,
|
||||
[this.placeHolderLine],
|
||||
(...args) => {
|
||||
// node.styleLine(...args)
|
||||
},
|
||||
node.style.getStyle('lineStyle', true)
|
||||
)
|
||||
this.placeHolderExtraLines = [...parent._lines]
|
||||
this.placeHolderExtraLines.forEach(line => {
|
||||
this.mindMap.otherDraw.add(line)
|
||||
line
|
||||
.stroke({
|
||||
color: dragPlaceholderLineConfig.color,
|
||||
width: dragPlaceholderLineConfig.width
|
||||
})
|
||||
.fill({ color: 'none' })
|
||||
})
|
||||
}
|
||||
|
||||
// 检测是否重叠
|
||||
@@ -573,8 +1007,9 @@ class Drag extends Base {
|
||||
pos,
|
||||
nodeRect
|
||||
}) {
|
||||
let dir1 = dir === 'v' ? 'top' : 'left'
|
||||
let dir2 = dir === 'v' ? 'bottom' : 'right'
|
||||
const { TOP, LEFT, BOTTOM, RIGHT } = CONSTANTS.LAYOUT_GROW_DIR
|
||||
let dir1 = dir === 'v' ? TOP : LEFT
|
||||
let dir2 = dir === 'v' ? BOTTOM : RIGHT
|
||||
if (!this.overlapNode && !this.prevNode && !this.nextNode) {
|
||||
if (
|
||||
nodeRect[dir1] + (prevBrotherOffset > 0 ? 0 : size) <= pos &&
|
||||
@@ -638,7 +1073,7 @@ class Drag extends Base {
|
||||
this.handleHorizontalCheck(node, checkList)
|
||||
} else {
|
||||
// 处于上方的三级节点需要特殊处理,因为节点排列方向反向了
|
||||
if (node.dir === 'top' && node.layerIndex === 2) {
|
||||
if (node.dir === CONSTANTS.LAYOUT_GROW_DIR.TOP && node.layerIndex === 2) {
|
||||
this.handleVerticalCheck(node, checkList, true)
|
||||
} else {
|
||||
this.handleVerticalCheck(node, checkList)
|
||||
@@ -657,7 +1092,7 @@ class Drag extends Base {
|
||||
this.handleHorizontalCheck(node, checkList)
|
||||
} else {
|
||||
// 处于上方的三级节点需要特殊处理,因为节点排列方向反向了
|
||||
if (node.dir === 'top' && node.layerIndex === 2) {
|
||||
if (node.dir === CONSTANTS.LAYOUT_GROW_DIR.TOP && node.layerIndex === 2) {
|
||||
this.handleVerticalCheck(node, checkList, true)
|
||||
} else {
|
||||
this.handleVerticalCheck(node, checkList)
|
||||
@@ -678,6 +1113,8 @@ class Drag extends Base {
|
||||
getNodeRect(node) {
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
let { left, top, width, height } = node
|
||||
let originWidth = width
|
||||
let originHeight = height
|
||||
let originLeft = left
|
||||
let originTop = top
|
||||
let originBottom = top + height
|
||||
@@ -687,12 +1124,12 @@ class Drag extends Base {
|
||||
left = left * scaleX + translateX
|
||||
top = top * scaleY + translateY
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
left,
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
originWidth,
|
||||
originHeight,
|
||||
originLeft,
|
||||
originTop,
|
||||
originBottom,
|
||||
|
||||
@@ -10,9 +10,18 @@ class Formula {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
window.katex = katex
|
||||
this.init()
|
||||
this.extendQuill()
|
||||
}
|
||||
|
||||
init() {
|
||||
if (this.mindMap.opt.enableEditFormulaInRichTextEdit) {
|
||||
this.mindMap.opt.transformRichTextOnEnterEdit =
|
||||
this.latexRichToText.bind(this)
|
||||
this.mindMap.opt.beforeHideRichTextEdit = this.formatLatex.bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取katex配置
|
||||
getKatexConfig() {
|
||||
const config = {
|
||||
@@ -59,6 +68,74 @@ class Formula {
|
||||
richTextPlugin.setTextStyleIfNotRichText(richTextPlugin.node)
|
||||
richTextPlugin.hideEditText([node])
|
||||
}
|
||||
|
||||
// 将公式富文本转换为公式源码
|
||||
latexRichToText(nodeText) {
|
||||
if (nodeText.indexOf('class="ql-formula"') !== -1) {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(nodeText, 'text/html')
|
||||
const els = doc.getElementsByClassName('ql-formula')
|
||||
for (const el of els)
|
||||
nodeText = nodeText.replace(
|
||||
el.outerHTML,
|
||||
`\$${el
|
||||
.getAttribute('data-value')
|
||||
.replaceAll('&', '&')
|
||||
.replaceAll('<', '<')
|
||||
.replaceAll('>', '>')}\$`
|
||||
)
|
||||
}
|
||||
return nodeText
|
||||
}
|
||||
|
||||
// 使用格式化的 latex 字符串内容更新 quill 内容:输入 $*****$
|
||||
formatLatex(richText) {
|
||||
const contents = richText.quill.getContents()
|
||||
const ops = contents.ops
|
||||
let mod = false
|
||||
for (let i = ops.length - 1; i >= 0; i--) {
|
||||
const op = ops[i]
|
||||
const insert = op.insert
|
||||
if (insert && typeof insert !== 'object' && insert !== '\n') {
|
||||
if (/\$.+?\$/g.test(insert)) {
|
||||
const m = [...insert.matchAll(/\$.+?\$/g)]
|
||||
const arr = insert.split(/\$.+?\$/g)
|
||||
for (let j = m.length - 1; j >= 0; j--) {
|
||||
const exp = m[j]?.[0].slice(1, -1) ?? null // $...$ 之间的表达式
|
||||
if (exp !== null && exp.trim().length > 0) {
|
||||
const isLegal = this.checkFormulaIsLegal(exp)
|
||||
if (isLegal) {
|
||||
arr.splice(j + 1, 0, { insert: { formula: exp } }) // 添加到对应位置之后
|
||||
mod = true
|
||||
} else {
|
||||
arr.splice(j + 1, 0, '')
|
||||
}
|
||||
} else arr.splice(j + 1, 0, '') // 表达式为空时,占位
|
||||
}
|
||||
while (arr.length > 0) {
|
||||
let v = arr.pop()
|
||||
if (typeof v === 'string') {
|
||||
if (v.length < 1) continue
|
||||
v = { insert: v }
|
||||
}
|
||||
v['attributes'] = ops[i]['attributes']
|
||||
ops.splice(i + 1, 0, v)
|
||||
}
|
||||
ops.splice(i, 1) // 删除原来的字符串
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mod) richText.quill.setContents(contents)
|
||||
}
|
||||
|
||||
checkFormulaIsLegal(str) {
|
||||
try {
|
||||
katex.renderToString(str)
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Formula.instanceName = 'formula'
|
||||
|
||||
@@ -154,6 +154,7 @@ class NodeImgAdjust {
|
||||
})
|
||||
btnEl.addEventListener('mousedown', e => {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.onMousedown(e)
|
||||
})
|
||||
btnEl.addEventListener('mouseup', e => {
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
isUndef,
|
||||
checkSmmFormatData,
|
||||
removeHtmlNodeByClass,
|
||||
formatGetNodeGeneralization
|
||||
formatGetNodeGeneralization,
|
||||
nodeRichTextToTextWithWrap
|
||||
} from '../utils'
|
||||
import { CONSTANTS } from '../constants/constant'
|
||||
|
||||
@@ -170,7 +171,8 @@ class RichText {
|
||||
customInnerElsAppendTo,
|
||||
nodeTextEditZIndex,
|
||||
textAutoWrapWidth,
|
||||
selectTextOnEnterEditText
|
||||
selectTextOnEnterEditText,
|
||||
transformRichTextOnEnterEdit
|
||||
} = this.mindMap.opt
|
||||
this.node = node
|
||||
this.isInserting = isInserting
|
||||
@@ -240,7 +242,10 @@ class RichText {
|
||||
}
|
||||
}
|
||||
// 节点文本内容
|
||||
const nodeText = node.getData('text')
|
||||
let nodeText = node.getData('text')
|
||||
if (typeof transformRichTextOnEnterEdit === 'function') {
|
||||
nodeText = transformRichTextOnEnterEdit(nodeText)
|
||||
}
|
||||
// 是否是空文本
|
||||
const isEmptyText = isUndef(nodeText)
|
||||
// 是否是非空的非富文本
|
||||
@@ -312,7 +317,9 @@ class RichText {
|
||||
getEditText() {
|
||||
let html = this.quill.container.firstChild.innerHTML
|
||||
// 去除ql-cursor节点
|
||||
html = removeHtmlNodeByClass(html, '.ql-cursor')
|
||||
// https://github.com/wanglin2/mind-map/commit/138cc4b3e824671143f0bf70e5c46796f48520d0
|
||||
// https://github.com/wanglin2/mind-map/commit/0760500cebe8ec4e8ad84ab63f877b8b2a193aa1
|
||||
// html = removeHtmlNodeByClass(html, '.ql-cursor')
|
||||
// 去除最后的空行
|
||||
return html.replace(/<p><br><\/p>$/, '')
|
||||
}
|
||||
@@ -322,6 +329,10 @@ class RichText {
|
||||
if (!this.showTextEdit) {
|
||||
return
|
||||
}
|
||||
const { beforeHideRichTextEdit } = this.mindMap.opt
|
||||
if (typeof beforeHideRichTextEdit === 'function') {
|
||||
beforeHideRichTextEdit(this)
|
||||
}
|
||||
let html = this.getEditText()
|
||||
let list =
|
||||
nodes && nodes.length > 0 ? nodes : this.mindMap.renderer.activeNodeList
|
||||
@@ -365,6 +376,21 @@ class RichText {
|
||||
},
|
||||
theme: 'snow'
|
||||
})
|
||||
// 拦截粘贴事件
|
||||
this.quill.root.addEventListener('copy', event => {
|
||||
event.preventDefault()
|
||||
const sel = window.getSelection()
|
||||
const originStr = sel.toString()
|
||||
try {
|
||||
const range = sel.getRangeAt(0)
|
||||
const div = document.createElement('div')
|
||||
div.appendChild(range.cloneContents())
|
||||
const text = nodeRichTextToTextWithWrap(div.innerHTML)
|
||||
event.clipboardData.setData('text/plain', text)
|
||||
} catch (e) {
|
||||
event.clipboardData.setData('text/plain', originStr)
|
||||
}
|
||||
})
|
||||
this.quill.on('selection-change', range => {
|
||||
// 刚创建的节点全选不需要显示操作条
|
||||
if (this.isInserting) return
|
||||
|
||||
@@ -16,10 +16,12 @@ class TouchEvent {
|
||||
this.onTouchmove = this.onTouchmove.bind(this)
|
||||
this.onTouchcancel = this.onTouchcancel.bind(this)
|
||||
this.onTouchend = this.onTouchend.bind(this)
|
||||
window.addEventListener('touchstart', this.onTouchstart)
|
||||
window.addEventListener('touchmove', this.onTouchmove)
|
||||
window.addEventListener('touchcancel', this.onTouchcancel)
|
||||
window.addEventListener('touchend', this.onTouchend)
|
||||
window.addEventListener('touchstart', this.onTouchstart, { passive: false })
|
||||
window.addEventListener('touchmove', this.onTouchmove, { passive: false })
|
||||
window.addEventListener('touchcancel', this.onTouchcancel, {
|
||||
passive: false
|
||||
})
|
||||
window.addEventListener('touchend', this.onTouchend, { passive: false })
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
@@ -32,6 +34,7 @@ class TouchEvent {
|
||||
|
||||
// 手指按下事件
|
||||
onTouchstart(e) {
|
||||
e.preventDefault()
|
||||
this.touchesNum = e.touches.length
|
||||
this.touchStartScaleView = null
|
||||
if (this.touchesNum === 1) {
|
||||
@@ -43,6 +46,7 @@ class TouchEvent {
|
||||
|
||||
// 手指移动事件
|
||||
onTouchmove(e) {
|
||||
e.preventDefault()
|
||||
let len = e.touches.length
|
||||
if (len === 1) {
|
||||
let touch = e.touches[0]
|
||||
@@ -103,6 +107,7 @@ class TouchEvent {
|
||||
|
||||
// 手指松开事件
|
||||
onTouchend(e) {
|
||||
e.preventDefault()
|
||||
this.dispatchMouseEvent('mouseup', e.target)
|
||||
if (this.touchesNum === 1) {
|
||||
// 模拟双击事件
|
||||
|
||||
@@ -41,10 +41,21 @@ class Watermark {
|
||||
// 创建水印容器
|
||||
createContainer() {
|
||||
if (this.watermarkDraw) return
|
||||
this.watermarkDraw = this.mindMap.svg
|
||||
.group()
|
||||
this.watermarkDraw = new G()
|
||||
.css({ 'pointer-events': 'none', 'user-select': 'none' })
|
||||
.addClass('smm-water-mark-container')
|
||||
this.updateLayer()
|
||||
}
|
||||
|
||||
// 更新水印容器层级
|
||||
updateLayer() {
|
||||
if (!this.watermarkDraw) return
|
||||
const { belowNode } = this.mindMap.opt.watermarkConfig
|
||||
if (belowNode) {
|
||||
this.watermarkDraw.insertBefore(this.mindMap.draw)
|
||||
} else {
|
||||
this.mindMap.svg.add(this.watermarkDraw)
|
||||
}
|
||||
}
|
||||
|
||||
// 删除水印容器
|
||||
@@ -160,6 +171,7 @@ class Watermark {
|
||||
this.mindMap.opt.watermarkConfig,
|
||||
config
|
||||
)
|
||||
this.updateLayer()
|
||||
this.handleConfig(config)
|
||||
this.draw()
|
||||
}
|
||||
@@ -167,11 +179,13 @@ class Watermark {
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
this.removeContainer()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
this.removeContainer()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1335,7 +1335,7 @@ export const handleGetSvgDataExtraContent = ({
|
||||
if (!res) return
|
||||
const { el, cssText, height } = res
|
||||
if (el instanceof HTMLElement) {
|
||||
el.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
addXmlns(el)
|
||||
const foreignObject = createForeignObjectNode({ el, height })
|
||||
callback(foreignObject, height)
|
||||
}
|
||||
@@ -1476,3 +1476,57 @@ export const formatGetNodeGeneralization = data => {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 防御 XSS 攻击,过滤恶意 HTML 标签和属性
|
||||
* @param {string} text 需要过滤的文本
|
||||
* @returns {string} 过滤后的文本
|
||||
*/
|
||||
export const defenseXSS = text => {
|
||||
text = String(text)
|
||||
|
||||
// 初始化结果变量
|
||||
let result = text
|
||||
|
||||
// 使用正则表达式匹配 HTML 标签
|
||||
const match = text.match(/<(\S*?)[^>]*>.*?|<.*? \/>/g)
|
||||
if (match == null) {
|
||||
// 如果没有匹配到任何标签,则直接返回原始文本
|
||||
return text
|
||||
}
|
||||
|
||||
// 遍历匹配到的标签
|
||||
for (let value of match) {
|
||||
// 定义白名单属性正则表达式(style、target、href)
|
||||
const whiteAttrRegex = new RegExp(/(style|target|href)=["'][^"']*["']/g)
|
||||
|
||||
// 定义黑名单href正则表达式(javascript:)
|
||||
const aHrefBlackRegex = new RegExp(/href=["']javascript:/g)
|
||||
|
||||
// 过滤 HTML 标签
|
||||
const filterHtml = value.replace(
|
||||
// 匹配属性键值对(如:key="value")
|
||||
/([a-zA-Z-]+)\s*=\s*["']([^"']*)["']/g,
|
||||
text => {
|
||||
// 如果属性值包含黑名单href或不在白名单中,则删除该属性
|
||||
if (aHrefBlackRegex.test(text) || !whiteAttrRegex.test(text)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// 否则,保留该属性
|
||||
return text
|
||||
}
|
||||
)
|
||||
|
||||
// 将过滤后的标签替换回原始文本
|
||||
result = result.replace(value, filterHtml)
|
||||
}
|
||||
|
||||
// 返回最终结果
|
||||
return result
|
||||
}
|
||||
|
||||
// 给节点添加命名空间
|
||||
export const addXmlns = el => {
|
||||
el.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* 防御 XSS 攻击,过滤恶意 HTML 标签和属性
|
||||
* @param {string} text 需要过滤的文本
|
||||
* @returns {string} 过滤后的文本
|
||||
*/
|
||||
export function defenseXSS(text) {
|
||||
text = String(text)
|
||||
|
||||
// 初始化结果变量
|
||||
let result = text;
|
||||
|
||||
// 使用正则表达式匹配 HTML 标签
|
||||
const match = text.match(/<(\S*?)[^>]*>.*?|<.*? \/>/g);
|
||||
if (match == null) {
|
||||
// 如果没有匹配到任何标签,则直接返回原始文本
|
||||
return text;
|
||||
}
|
||||
|
||||
// 遍历匹配到的标签
|
||||
for (let value of match) {
|
||||
// 定义白名单属性正则表达式(style、target、href)
|
||||
const whiteAttrRegex = new RegExp(/(style|target|href)=["'][^"']*["']/g);
|
||||
|
||||
// 定义黑名单href正则表达式(javascript:)
|
||||
const aHrefBlackRegex = new RegExp(/href=["']javascript:/g);
|
||||
|
||||
// 过滤 HTML 标签
|
||||
const filterHtml = value.replace(
|
||||
// 匹配属性键值对(如:key="value")
|
||||
/([a-zA-Z-]+)\s*=\s*["']([^"']*)["']/g,
|
||||
(text) => {
|
||||
// 如果属性值包含黑名单href或不在白名单中,则删除该属性
|
||||
if (aHrefBlackRegex.test(text) || !whiteAttrRegex.test(text)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// 否则,保留该属性
|
||||
return text;
|
||||
}
|
||||
);
|
||||
|
||||
// 将过滤后的标签替换回原始文本
|
||||
result = result.replace(value, filterHtml);
|
||||
}
|
||||
|
||||
// 返回最终结果
|
||||
return result;
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
<!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.0,maximum-scale=1.0,minimum-scale=1.0">
|
||||
<link rel="icon" href="dist/logo.ico">
|
||||
<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.0,maximum-scale=1.0,minimum-scale=1.0"
|
||||
/>
|
||||
<link rel="icon" href="dist/logo.ico" />
|
||||
<title>思绪思维导图</title>
|
||||
<script>
|
||||
// 自定义静态资源的路径
|
||||
@@ -12,10 +15,26 @@
|
||||
// 接管应用
|
||||
window.takeOverApp = false
|
||||
</script>
|
||||
<script
|
||||
charset="UTF-8"
|
||||
id="LA_COLLECT"
|
||||
src="//sdk.51.la/js-sdk-pro.min.js"
|
||||
></script>
|
||||
<script>
|
||||
LA.init({
|
||||
id: 'KRO0WxK8GT66tYCQ',
|
||||
ck: 'KRO0WxK8GT66tYCQ',
|
||||
autoTrack: false
|
||||
})
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
<strong
|
||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||
properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong
|
||||
>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
@@ -25,19 +44,19 @@
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
mindMapData: {
|
||||
root:{
|
||||
"data": {
|
||||
"text": "根节点"
|
||||
root: {
|
||||
data: {
|
||||
text: '根节点'
|
||||
},
|
||||
"children": []
|
||||
children: []
|
||||
},
|
||||
theme:{
|
||||
"template":"avocado",
|
||||
"config":{}
|
||||
theme: {
|
||||
template: 'avocado',
|
||||
config: {}
|
||||
},
|
||||
layout:"logicalStructure",
|
||||
layout: 'logicalStructure',
|
||||
config: {},
|
||||
view: null,
|
||||
view: null
|
||||
},
|
||||
lang: 'zh',
|
||||
localConfig: null
|
||||
@@ -45,14 +64,14 @@
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
const setTakeOverAppMethods = (data) => {
|
||||
const setTakeOverAppMethods = data => {
|
||||
window.takeOverAppMethods = {}
|
||||
// 获取思维导图数据的函数
|
||||
window.takeOverAppMethods.getMindMapData = () => {
|
||||
return data.mindMapData
|
||||
}
|
||||
}
|
||||
// 保存思维导图数据的函数
|
||||
window.takeOverAppMethods.saveMindMapData = (data) => {
|
||||
window.takeOverAppMethods.saveMindMapData = data => {
|
||||
console.log(data)
|
||||
}
|
||||
// 获取语言的函数
|
||||
@@ -60,7 +79,7 @@
|
||||
return data.lang
|
||||
}
|
||||
// 保存语言的函数
|
||||
window.takeOverAppMethods.saveLanguage = (lang) => {
|
||||
window.takeOverAppMethods.saveLanguage = lang => {
|
||||
console.log(lang)
|
||||
}
|
||||
// 获取本地配置的函数
|
||||
@@ -68,7 +87,7 @@
|
||||
return data.localConfig
|
||||
}
|
||||
// 保存本地配置的函数
|
||||
window.takeOverAppMethods.saveLocalConfig = (config) => {
|
||||
window.takeOverAppMethods.saveLocalConfig = config => {
|
||||
console.log(config)
|
||||
}
|
||||
}
|
||||
@@ -79,7 +98,7 @@
|
||||
// 设置全局的方法
|
||||
setTakeOverAppMethods(data)
|
||||
// 思维导图实例创建完成事件
|
||||
window.$bus.$on('app_inited', (mindMap) => {
|
||||
window.$bus.$on('app_inited', mindMap => {
|
||||
console.log(mindMap)
|
||||
})
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
|
||||
BIN
web/src/assets/avatar/ZX.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
web/src/assets/avatar/峰.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
web/src/assets/avatar/最多5个字.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
web/src/assets/avatar/雨馨.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
@@ -178,6 +178,11 @@ export const backgroundPositionList = [
|
||||
}
|
||||
]
|
||||
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
const ctrl = isMac ? '⌘' : 'Ctrl'
|
||||
const enter = isMac ? 'Return' : 'Enter'
|
||||
const macFn = isMac ? 'fn + ' : ''
|
||||
|
||||
// 背景图片大小
|
||||
export const backgroundSizeList = [
|
||||
{
|
||||
@@ -207,7 +212,7 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconjiedian',
|
||||
name: 'Insert sibling node',
|
||||
value: 'Enter'
|
||||
value: enter
|
||||
},
|
||||
{
|
||||
icon: 'icondodeparent',
|
||||
@@ -217,17 +222,17 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconshangyi',
|
||||
name: 'Move up node',
|
||||
value: 'Ctrl + ↑'
|
||||
value: `${ctrl} + ↑`
|
||||
},
|
||||
{
|
||||
icon: 'iconxiayi',
|
||||
name: 'Move down node',
|
||||
value: 'Ctrl + ↓'
|
||||
value: `${ctrl} + ↓`
|
||||
},
|
||||
{
|
||||
icon: 'icongaikuozonglan',
|
||||
name: 'Insert summary',
|
||||
value: 'Ctrl + G'
|
||||
value: `${ctrl} + G`
|
||||
},
|
||||
{
|
||||
icon: 'iconzhankai',
|
||||
@@ -247,57 +252,57 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconfuzhi',
|
||||
name: 'Copy node',
|
||||
value: 'Ctrl + C'
|
||||
value: `${ctrl} + C`
|
||||
},
|
||||
{
|
||||
icon: 'iconjianqie',
|
||||
name: 'Cut node',
|
||||
value: 'Ctrl + X'
|
||||
value: `${ctrl} + X`
|
||||
},
|
||||
{
|
||||
icon: 'iconniantie',
|
||||
name: 'Paste node',
|
||||
value: 'Ctrl + V'
|
||||
value: `${ctrl} + V`
|
||||
},
|
||||
{
|
||||
icon: 'iconbianji',
|
||||
name: 'Edit node',
|
||||
value: 'F2'
|
||||
value: macFn + 'F2'
|
||||
},
|
||||
{
|
||||
icon: 'iconhuanhang',
|
||||
name: 'Text Wrap',
|
||||
value: 'Shift + Enter'
|
||||
value: `Shift + ${enter}`
|
||||
},
|
||||
{
|
||||
icon: 'iconhoutui-shi',
|
||||
name: 'Undo',
|
||||
value: 'Ctrl + Z'
|
||||
value: `${ctrl} + Z`
|
||||
},
|
||||
{
|
||||
icon: 'iconqianjin1',
|
||||
name: 'Redo',
|
||||
value: 'Ctrl + Y'
|
||||
value: `${ctrl} + Y`
|
||||
},
|
||||
{
|
||||
icon: 'iconquanxuan',
|
||||
name: 'Select All',
|
||||
value: 'Ctrl + A'
|
||||
value: `${ctrl} + A`
|
||||
},
|
||||
{
|
||||
icon: 'iconquanxuan',
|
||||
name: 'Multiple choice',
|
||||
value: 'Right click / Ctrl + Left click'
|
||||
value: `Right click / ${ctrl} + Left click`
|
||||
},
|
||||
{
|
||||
icon: 'iconzhengli',
|
||||
name: 'Arrange layout',
|
||||
value: 'Ctrl + L'
|
||||
value: `${ctrl} + L`
|
||||
},
|
||||
{
|
||||
icon: 'iconsousuo',
|
||||
name: 'Search and Replace',
|
||||
value: 'Ctrl + F'
|
||||
value: `${ctrl} + F`
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -307,27 +312,27 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconfangda',
|
||||
name: 'Zoom in',
|
||||
value: 'Ctrl + +'
|
||||
value: `${ctrl} + +`
|
||||
},
|
||||
{
|
||||
icon: 'iconsuoxiao',
|
||||
name: 'Zoom out',
|
||||
value: 'Ctrl + -'
|
||||
value: `${ctrl} + -`
|
||||
},
|
||||
{
|
||||
icon: 'iconfangda',
|
||||
name: 'Zoom in/Zoom out',
|
||||
value: 'Ctrl + Mouse wheel'
|
||||
value: `${ctrl} + Mouse wheel`
|
||||
},
|
||||
{
|
||||
icon: 'icondingwei',
|
||||
name: 'Back root node',
|
||||
value: 'Ctrl + Enter'
|
||||
value: `${ctrl} + ${enter}`
|
||||
},
|
||||
{
|
||||
icon: 'iconquanping1',
|
||||
name: 'fit canvas',
|
||||
value: 'Ctrl + i'
|
||||
value: `${ctrl} + i`
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -337,7 +342,7 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconhuanhang',
|
||||
name: 'Text Wrap',
|
||||
value: 'Shift + Enter'
|
||||
value: `Shift + ${enter}`
|
||||
},
|
||||
{
|
||||
icon: 'iconshanchu',
|
||||
@@ -352,13 +357,13 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconjiedian',
|
||||
name: 'Insert sibling node',
|
||||
value: 'Enter'
|
||||
value: enter
|
||||
},
|
||||
{
|
||||
icon: 'icondodeparent',
|
||||
name: 'Move up one level',
|
||||
value: 'Shift + Tab'
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -487,4 +492,4 @@ export const downTypeList = [
|
||||
icon: 'iconTXT',
|
||||
desc: 'Plain text file'
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -260,6 +260,10 @@ export const backgroundSizeList = [
|
||||
export const store = {
|
||||
sidebarZIndex: 1 //侧边栏zIndex
|
||||
}
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
const ctrl = isMac ? '⌘' : 'Ctrl'
|
||||
const enter = isMac ? 'Return' : 'Enter'
|
||||
const macFn = isMac ? 'fn + ' : ''
|
||||
|
||||
// 快捷键列表
|
||||
export const shortcutKeyList = [
|
||||
@@ -274,7 +278,7 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconjiedian',
|
||||
name: '插入同级节点',
|
||||
value: 'Enter'
|
||||
value: enter
|
||||
},
|
||||
{
|
||||
icon: 'icondodeparent',
|
||||
@@ -284,17 +288,17 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconshangyi',
|
||||
name: '上移节点',
|
||||
value: 'Ctrl + ↑'
|
||||
value: `${ctrl} + ↑`
|
||||
},
|
||||
{
|
||||
icon: 'iconxiayi',
|
||||
name: '下移节点',
|
||||
value: 'Ctrl + ↓'
|
||||
value: `${ctrl} + ↓`
|
||||
},
|
||||
{
|
||||
icon: 'icongaikuozonglan',
|
||||
name: '插入概要',
|
||||
value: 'Ctrl + G'
|
||||
value: `${ctrl} + G`
|
||||
},
|
||||
{
|
||||
icon: 'iconzhankai',
|
||||
@@ -314,57 +318,57 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconfuzhi',
|
||||
name: '复制节点',
|
||||
value: 'Ctrl + C'
|
||||
value: `${ctrl} + C`
|
||||
},
|
||||
{
|
||||
icon: 'iconjianqie',
|
||||
name: '剪切节点',
|
||||
value: 'Ctrl + X'
|
||||
value: `${ctrl} + X`
|
||||
},
|
||||
{
|
||||
icon: 'iconniantie',
|
||||
name: '粘贴节点',
|
||||
value: 'Ctrl + V'
|
||||
value: `${ctrl} + V`
|
||||
},
|
||||
{
|
||||
icon: 'iconbianji',
|
||||
name: '编辑节点',
|
||||
value: 'F2'
|
||||
value: macFn + 'F2'
|
||||
},
|
||||
{
|
||||
icon: 'iconhuanhang',
|
||||
name: '文本换行',
|
||||
value: 'Shift + Enter'
|
||||
value: `Shift + ${enter}`
|
||||
},
|
||||
{
|
||||
icon: 'iconhoutui-shi',
|
||||
name: '回退',
|
||||
value: 'Ctrl + Z'
|
||||
value: `${ctrl} + Z`
|
||||
},
|
||||
{
|
||||
icon: 'iconqianjin1',
|
||||
name: '前进',
|
||||
value: 'Ctrl + Y'
|
||||
value: `${ctrl} + Y`
|
||||
},
|
||||
{
|
||||
icon: 'iconquanxuan',
|
||||
name: '全选',
|
||||
value: 'Ctrl + A'
|
||||
value: `${ctrl} + A`
|
||||
},
|
||||
{
|
||||
icon: 'iconquanxuan',
|
||||
name: '多选',
|
||||
value: '右键 / Ctrl + 左键'
|
||||
value: `右键 / ${ctrl} + 左键`
|
||||
},
|
||||
{
|
||||
icon: 'iconzhengli',
|
||||
name: '一键整理布局',
|
||||
value: 'Ctrl + L'
|
||||
value: `${ctrl} + L`
|
||||
},
|
||||
{
|
||||
icon: 'iconsousuo',
|
||||
name: '搜索和替换',
|
||||
value: 'Ctrl + F'
|
||||
value: `${ctrl} + F`
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -374,27 +378,27 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconfangda',
|
||||
name: '放大',
|
||||
value: 'Ctrl + +'
|
||||
value: `${ctrl} + +`
|
||||
},
|
||||
{
|
||||
icon: 'iconsuoxiao',
|
||||
name: '缩小',
|
||||
value: 'Ctrl + -'
|
||||
value: `${ctrl} + -`
|
||||
},
|
||||
{
|
||||
icon: 'iconfangda',
|
||||
name: '放大/缩小',
|
||||
value: 'Ctrl + 鼠标滚动'
|
||||
value: `${ctrl} + 鼠标滚动`
|
||||
},
|
||||
{
|
||||
icon: 'icondingwei',
|
||||
name: '回到根节点',
|
||||
value: 'Ctrl + Enter'
|
||||
value: `${ctrl} + ${enter}`
|
||||
},
|
||||
{
|
||||
icon: 'iconquanping1',
|
||||
name: '适应画布',
|
||||
value: 'Ctrl + i'
|
||||
value: `${ctrl} + i`
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -404,7 +408,7 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconhuanhang',
|
||||
name: '文本换行',
|
||||
value: 'Shift + Enter'
|
||||
value: `Shift + ${enter}`
|
||||
},
|
||||
{
|
||||
icon: 'iconshanchu',
|
||||
@@ -419,7 +423,7 @@ export const shortcutKeyList = [
|
||||
{
|
||||
icon: 'iconjiedian',
|
||||
name: '插入同级节点',
|
||||
value: 'Enter'
|
||||
value: enter
|
||||
},
|
||||
{
|
||||
icon: 'icondodeparent',
|
||||
@@ -582,4 +586,4 @@ export const downTypeList = [
|
||||
icon: 'iconTXT',
|
||||
desc: '纯文本文件'
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -38,6 +38,7 @@ export default {
|
||||
watermarkAngle: 'Angle',
|
||||
watermarkTextOpacity: 'Text opacity',
|
||||
watermarkTextFontSize: 'Font size',
|
||||
belowNode: 'Display below nodes',
|
||||
isEnableNodeRichText: 'Enable node rich text editing',
|
||||
mousewheelAction: 'Mouse wheel behavior',
|
||||
zoomView: 'Zoom view',
|
||||
@@ -151,7 +152,8 @@ export default {
|
||||
notSelectTip: 'Please select the file to import',
|
||||
fileContentError: 'The file content is incorrect',
|
||||
importSuccess: 'Import success',
|
||||
fileParsingFailed: 'File parsing failed'
|
||||
fileParsingFailed: 'File parsing failed',
|
||||
xmindCanvasSelectDialogTitle: 'Select the canvas to import'
|
||||
},
|
||||
navigatorToolbar: {
|
||||
openMiniMap: 'Open mini map',
|
||||
@@ -275,7 +277,9 @@ export default {
|
||||
fileOpenFailed: 'File open failed',
|
||||
defaultFileName: 'Mind map',
|
||||
creatingTip: 'Creating file',
|
||||
directory: 'Directory'
|
||||
directory: 'Directory',
|
||||
newFileTip: 'Please export the currently edited file before creating a new one, otherwise the content will be lost',
|
||||
openFileTip: 'Please export the currently edited file before opening it, otherwise the content will be lost'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: 'New feature reminder',
|
||||
|
||||
@@ -38,6 +38,7 @@ export default {
|
||||
watermarkAngle: '旋转角度',
|
||||
watermarkTextOpacity: '文字透明度',
|
||||
watermarkTextFontSize: '文字字号',
|
||||
belowNode: '显示在节点下方',
|
||||
isEnableNodeRichText: '是否开启节点富文本编辑',
|
||||
mousewheelAction: '鼠标滚轮行为',
|
||||
zoomView: '缩放视图',
|
||||
@@ -149,7 +150,8 @@ export default {
|
||||
notSelectTip: '请选择要导入的文件',
|
||||
fileContentError: '文件内容有误',
|
||||
importSuccess: '导入成功',
|
||||
fileParsingFailed: '文件解析失败'
|
||||
fileParsingFailed: '文件解析失败',
|
||||
xmindCanvasSelectDialogTitle: '选择要导入的画布'
|
||||
},
|
||||
navigatorToolbar: {
|
||||
openMiniMap: '开启小地图',
|
||||
@@ -271,7 +273,9 @@ export default {
|
||||
fileOpenFailed: '文件打开失败',
|
||||
defaultFileName: '思维导图',
|
||||
creatingTip: '正在创建文件',
|
||||
directory: '目录'
|
||||
directory: '目录',
|
||||
newFileTip: '新建文件前请先导出当前编辑的文件,否则内容会丢失',
|
||||
openFileTip: '打开文件前请先导出当前编辑的文件,否则内容会丢'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: '新特性提醒',
|
||||
|
||||
@@ -11,7 +11,7 @@ let langList = [
|
||||
}
|
||||
]
|
||||
let StartList = ['introduction', 'start', 'deploy', 'client', 'translate', 'changelog']
|
||||
let CourseList = new Array(28).fill(0).map((_, index) => {
|
||||
let CourseList = new Array(29).fill(0).map((_, index) => {
|
||||
return 'course' + (index + 1)
|
||||
})
|
||||
let APIList = [
|
||||
@@ -45,7 +45,7 @@ let APIList = [
|
||||
'markdown',
|
||||
'utils'
|
||||
]
|
||||
let helpList = new Array(5).fill(0).map((_, index) => {
|
||||
let helpList = new Array(6).fill(0).map((_, index) => {
|
||||
return 'help' + (index + 1)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,51 @@
|
||||
# Changelog
|
||||
|
||||
## 0.10.0
|
||||
|
||||
Major updates: Upgrade the interaction effect when dragging nodes;
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fix the issue where read-only mode can still activate nodes by Ctrl+clicking on them;
|
||||
>
|
||||
> 2.Fix the issue of page scaling when setting up scaling in some mobile browsers;
|
||||
>
|
||||
> 3.Fix the issue of selecting text when dragging the canvas and adjusting images;
|
||||
>
|
||||
> 4.Fix the issue of multiple line breaks when copying node text with line breaks and pasting it;
|
||||
>
|
||||
> 5.Fix the issue of displaying blank space when exporting images with custom content before and after nodes;
|
||||
|
||||
New:
|
||||
|
||||
> 1.Add a new rendering start event node.treeRender_start;
|
||||
>
|
||||
> 2.Support displaying watermarks below nodes;
|
||||
>
|
||||
> 3.Importing xmind files with multiple canvases supports selecting the specified canvas for import;
|
||||
>
|
||||
> 4.Canceling the call to the defenseXSS function has a significant impact on performance; The defenseXSS method is provided as a tool method;
|
||||
>
|
||||
> 5.Remove the logic of removing nodes with ql cursor class names from rich text content, and fix the issue of ineffective addition of empty lines when text breaks;
|
||||
>
|
||||
> 6.Remove the logic of delayed node editing when inserting new nodes;
|
||||
>
|
||||
> 7.Support direct editing of mathematical formulas in rich text editing boxes;
|
||||
>
|
||||
> 8.Add demonstration plugins to the packaged file;
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.支持配置水印显示在节点下方;
|
||||
>
|
||||
> 2.导入存在多个画布的xmind文件支持选择指定的画布进行导入;
|
||||
>
|
||||
> 3.优化富文本工具条下拉选项列表高度问题;
|
||||
>
|
||||
> 4.新建和打开按钮增加导出的提示,防止内容丢失;
|
||||
>
|
||||
> 5.快捷键提示支持区分windows和mac;
|
||||
|
||||
## 0.9.12
|
||||
|
||||
Fix:
|
||||
|
||||
@@ -1,6 +1,35 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.10.0</h2>
|
||||
<p>Major updates: Upgrade the interaction effect when dragging nodes;</p>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue where read-only mode can still activate nodes by Ctrl+clicking on them;</p>
|
||||
<p>2.Fix the issue of page scaling when setting up scaling in some mobile browsers;</p>
|
||||
<p>3.Fix the issue of selecting text when dragging the canvas and adjusting images;</p>
|
||||
<p>4.Fix the issue of multiple line breaks when copying node text with line breaks and pasting it;</p>
|
||||
<p>5.Fix the issue of displaying blank space when exporting images with custom content before and after nodes;</p>
|
||||
</blockquote>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.Add a new rendering start event node.treeRender_start;</p>
|
||||
<p>2.Support displaying watermarks below nodes;</p>
|
||||
<p>3.Importing xmind files with multiple canvases supports selecting the specified canvas for import;</p>
|
||||
<p>4.Canceling the call to the defenseXSS function has a significant impact on performance; The defenseXSS method is provided as a tool method;</p>
|
||||
<p>5.Remove the logic of removing nodes with ql cursor class names from rich text content, and fix the issue of ineffective addition of empty lines when text breaks;</p>
|
||||
<p>6.Remove the logic of delayed node editing when inserting new nodes;</p>
|
||||
<p>7.Support direct editing of mathematical formulas in rich text editing boxes;</p>
|
||||
<p>8.Add demonstration plugins to the packaged file;</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.支持配置水印显示在节点下方;</p>
|
||||
<p>2.导入存在多个画布的xmind文件支持选择指定的画布进行导入;</p>
|
||||
<p>3.优化富文本工具条下拉选项列表高度问题;</p>
|
||||
<p>4.新建和打开按钮增加导出的提示,防止内容丢失;</p>
|
||||
<p>5.快捷键提示支持区分windows和mac;</p>
|
||||
</blockquote>
|
||||
<h2>0.9.12</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
|
||||
@@ -22,8 +22,10 @@ const mindMap = new MindMap({
|
||||
|
||||
## Instantiation options
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ | -------- |
|
||||
### 1.Base
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| el | Element | | Container element, must be a DOM element(When 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)、timeline(v0.5.4+, timeline)、timeline2(v0.5.4+, up down alternating timeline)、fishbone(v0.5.4+, fishbone diagram) | |
|
||||
@@ -32,15 +34,10 @@ const mindMap = new MindMap({
|
||||
| themeConfig | Object | {} | Theme configuration, will be merged with the selected theme, available fields refer to: [default.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js) | |
|
||||
| scaleRatio | Number | 0.1 | The incremental scaling ratio | |
|
||||
| maxTag | Number | 5 | The maximum number of tags displayed in the node, any additional tags will be discarded | |
|
||||
| exportPadding | Number | 20 | The padding for exporting images | |
|
||||
| imgTextMargin | Number | 5 | The spacing between the image and text in the node | |
|
||||
| textContentMargin | Number | 2 | The spacing between various text information in the node, such as the spacing between the icon and text | |
|
||||
| selectTranslateStep | Number | 3 | The canvas offset when mouse moves to the edge during multi-select node | |
|
||||
| selectTranslateLimit | Number | 20 | The distance from the edge when the canvas begins to offset during multi-select node | |
|
||||
| customNoteContentShow(v0.1.6+) | Object | null | Custom node note content display, object type, structure: {show: (noteContent, left, top, node) => {// your display node note logic. node is a new parameter added in v0.8.1+ version, representing node instances }, hide: () => {// your hide node note logic }} | |
|
||||
| readonly(v0.1.7+) | Boolean | false | Whether it is read-only mode | |
|
||||
| enableFreeDrag(v0.2.4+) | Boolean | false | Enable node free(Free drag means that nodes can be dragged to any position on the canvas. Please note that it is not a function of dragging nodes to become siblings of other nodes. The connection of free drag may have certain problems, so it is best not to use this feature) drag | |
|
||||
| watermarkConfig(v0.2.4+) | Object | | Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration | |
|
||||
| textAutoWrapWidth(v0.3.4+) | Number | 500 | Each line of text in the node will wrap automatically when it reaches the width | |
|
||||
| customHandleMousewheel(v0.4.3+) | Function | null | User-defined mouse wheel event processing can pass a function, and the callback parameter is the event object | |
|
||||
| mousewheelAction(v0.4.3+) | String | zoom(v0.9.1+ default is move) | The behavior of the mouse wheel, `zoom`(Zoom in and out)、`move`(Move up and down). If `customHandleMousewheel` passes a custom function, this property will not take effect | |
|
||||
@@ -56,8 +53,6 @@ const mindMap = new MindMap({
|
||||
| enableNodeTransitionMove(v0.5.1+)(v0.6.7+ is remove this feature) | Boolean | true | Whether to enable node animation transition | |
|
||||
| nodeTransitionMoveDuration(v0.5.1+)(v0.6.7+ is remove this feature) | Number | 300 | If node animation transition is enabled, the transition time can be set using this attribute, in milliseconds | |
|
||||
| initRootNodePosition(v0.5.3+) | Array | null | The position of the initial root node can be passed as an array, default is `['center', 'center']`, Represents the root node at the center of the canvas, In addition to `center`, keywords can also be set to `left`, `top`, `right`, and `bottom`, In addition to passing keywords, each item in the array can also pass a number representing a specific pixel, Can pass a percentage string, such as `['40%', '60%']`, Represents a horizontal position at `40%` of the canvas width, and a vertical position at `60%` of the canvas height | |
|
||||
| exportPaddingX(v0.5.5+) | Number | 10 | Horizontal padding of graphics when exporting PNG, SVG, and PDF | |
|
||||
| exportPaddingY(v0.5.5+) | Number | 10 | Vertical padding of graphics when exporting PNG, SVG, and PDF | |
|
||||
| nodeTextEditZIndex(v0.5.5+) | Number | 3000 | | z-index of node text edit box elements |
|
||||
| nodeNoteTooltipZIndex(v0.5.5+) | Number | 3000 | z-index of floating layer elements in node comments | |
|
||||
| isEndNodeTextEditOnClickOuter(v0.5.5+) | Boolean | true | Whether to end the editing status of node text when clicking on an area outside the canvas | |
|
||||
@@ -65,7 +60,6 @@ const mindMap = new MindMap({
|
||||
| alwaysShowExpandBtn(v0.5.8+) | Boolean | false | Whether to always display the expand and collapse buttons of nodes, which are only displayed when the mouse is moved up and activated by default | |
|
||||
| iconList(v0.5.8+) | Array | [] | The icons that can be inserted into the extension node, and each item in the array is an object. Please refer to the "Icon Configuration" table below for the detailed structure of the object | |
|
||||
| maxNodeCacheCount(v0.5.10+) | Number | 1000 | The maximum number of cached nodes. To optimize performance, an internal node cache pool is maintained to reuse nodes. This attribute allows you to specify the maximum number of caches in the pool | |
|
||||
| defaultAssociativeLineText(v0.5.11+) | String | 关联 | Association Line Default Text | |
|
||||
| fitPadding(v0.6.0+) | Number | 50 | The padding of mind mapping when adapting to canvas size, Unit: px | |
|
||||
| enableCtrlKeyNodeSelection(v0.6.0+) | Boolean | true | Whether to enable the function of holding down the Ctrl key to select multiple nodes | |
|
||||
| useLeftKeySelectionRightKeyDrag(v0.6.0+) | Boolean | false | Setting to left click to select multiple nodes and right click to drag the canvas. | |
|
||||
@@ -74,56 +68,36 @@ const mindMap = new MindMap({
|
||||
| customCreateNodeContent(v0.6.3+) | Function/null | null | If `isUseCustomNodeContent` is set to `true`, then this option needs to be used to pass in a method that receives the node instance `node` as a parameter (if you want to obtain data for that node, you can use `node.nodeData.data`). You need to return the custom node content element, which is the DOM node. If a node does not require customization, you can return `null` | |
|
||||
| mouseScaleCenterUseMousePosition(v0.6.4-fix.1+) | Boolean | true | Is the mouse zoom centered around the current position of the mouse, otherwise centered around the canvas | |
|
||||
| customInnerElsAppendTo(v0.6.12+) | null/HTMLElement | null | Specify the location where some internal elements (node text editing element, node note display element, associated line text editing element, node image adjustment button element) are added, and default to document.body | |
|
||||
| nodeDragPlaceholderMaxSize(v0.6.12+) | Number | 20 | When dragging an element, the maximum height of the block indicating the new position of the element | |
|
||||
| enableCreateHiddenInput(v0.6.13+)(v0.6.14+ remove this feature) | Boolean | true | Is it allowed to create a hidden input box that will be focused when the node is activated for pasting data and automatically entering the text editing state | |
|
||||
| enableAutoEnterTextEditWhenKeydown(v0.6.13+) | Boolean | true | Does it automatically enter text editing mode when pressing the Chinese, English, or numeric buttons when there is an activation node?| |
|
||||
| richTextEditFakeInPlace(v0.6.13+) | Boolean | false | Set the rich text node edit box to match the size of the node, creating a pseudo in place editing effect. It should be noted that only when there is only text within the node and the shape is rectangular, can the effect be better | |
|
||||
| customHandleClipboardText(v0.6.14+) | Function | null | Customize the processing of clipboard text. When pressing ctrl+v to paste, it will read the text and images from the user's clipboard. By default, it will only determine whether the text is regular text and node data in simple mind map format. If you want to process data from other mind maps, such as process, zhixi, etc., you can pass a function that takes the text from the current clipboard as a parameter and returns the processed data, which can be of two types: 1.If a pure text is returned, a child node will be directly created with that text; 2.Returns a node object in the following format: { simpleMindMap: true, data: { data: { text: '' }, children: [] } }, The representative is data in simple bind map format, and the node data is in the same format as the simple bind map node data. If your processing logic has asynchronous logic, you can also return a promise | |
|
||||
| errorHandler(v0.6.15+) | Function | | Custom error handling functions currently only throw some asynchronous logic errors. Can pass a function that takes two parameters, the first being the wrong type and the second being the wrong object | |
|
||||
| disableMouseWheelZoom(v0.6.15+) | Boolean | false | Prohibit mouse wheel scaling, you can still use the API for scaling | |
|
||||
| resetCss(v0.6.16+) | String | * { margin: 0; padding: 0; box-sizing: border-box; } | When exporting images and SVGs, the default style overlay for rich text node content, which is embedded in HTML nodes in SVGs, will occur. If not overlaid, the node content will be offset | |
|
||||
| enableDblclickReset(v0.6.17+)(v0.8.0+this attribute has been deleted) | Boolean | true(v0.7.0+changed to false) | Turn on the mouse and double-click to reset the position and zoom of the mind map | |
|
||||
| enableDblclickBackToRootNode(v0.8.0+) | Boolean | false | Whether to return to the root node when double clicking with the mouse, that is, to center the display of the root node | |
|
||||
| minExportImgCanvasScale(v0.7.0+) | Number | 2 | The scaling factor of canvas when exporting images and PDFs, which is set to the maximum value of window.devicePixelRatio to improve image clarity | |
|
||||
| hoverRectColor(v0.7.0+) | String | rgb(94, 200, 248) | The node mouse hover and the rectangular border color displayed when activated will add a transparency of 0.6 when hovering | |
|
||||
| hoverRectPadding(v0.7.0+) | Number | 2 | The distance between the node mouse hover and the displayed rectangular border when activated and the node content | |
|
||||
| selectTextOnEnterEditText(v0.7.0+) | Boolean | true | Is the text selected by default when double-clicking a node to enter node text editing? By default, it will only be selected when creating a new node | |
|
||||
| deleteNodeActive(v0.7.1+) | Boolean | true | Enable the function of automatically activating adjacent nodes or parent nodes after deleting nodes | |
|
||||
| autoMoveWhenMouseInEdgeOnDrag(v0.7.1+) | Boolean | true | Whether to enable automatic canvas movement when the mouse moves to the edge of the canvas while dragging nodes | |
|
||||
| fit(v0.7.1-fix.2+) | Boolean | false | Is the first rendering scaled to fit the canvas size | |
|
||||
| dragMultiNodeRectConfig(v0.7.2+) | Object | { width: 40, height: 20, fill: '' } | The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle | |
|
||||
| dragPlaceholderRectFill(v0.7.2+) | String | | The filling color of the schematic rectangle for the new position when dragging nodes. If not transmitted, the default color for the connected line is used | |
|
||||
| dragOpacityConfig(v0.7.2+) | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node | |
|
||||
| tagsColorMap(v0.7.2+) | Object | {} | The color of a custom node label can be transferred to an object, where key is the label content to be assigned a color, and value is the color of the label content. If not transferred internally, a corresponding color will be generated based on the label content | |
|
||||
| cooperateStyle(v0.7.3+) | Object | { avatarSize: 22, fontSize: 12 } | The configuration of personnel avatar style during node collaboration editing, with field meanings as follows: avatar size, and if it is a text avatar, the size of the text | |
|
||||
| associativeLineIsAlwaysAboveNode(v0.8.0+) | Boolean | true | Is the associated line always displayed above the node? If set to false, it will be at the top level when creating and activating the associated line, and in other cases, it will be below the node | |
|
||||
| onlyOneEnableActiveNodeOnCooperate(v0.9.8+) | Boolean | false | During collaborative editing, the same node cannot be selected by multiple people at the same time | |
|
||||
| defaultGeneralizationText(v0.8.0+) | String | 概要 | Insert default text for summary | |
|
||||
| handleIsSplitByWrapOnPasteCreateNewNode(v0.8.0+) | Function / null | null | When creating a new node by pasting text, control whether to automatically split the nodes based on line breaks. If there is a line break, multiple nodes will be created based on the line break. Otherwise, only one node will be created, and a function can be passed to return promise. resolve represents splitting based on line breaks, and reject represents ignoring line breaks | |
|
||||
| addHistoryTime(v0.8.0+) | Number | 100 | Only one historical record can be added within the specified time to avoid adding unnecessary intermediate states. Unit: ms | |
|
||||
| isDisableDrag(v0.8.1+) | Boolean | false | Is disable dragging the canvas | |
|
||||
| disableTouchZoom(v0.8.1+) | Boolean | false | Prohibit double finger scaling, you can still use the API for scaling, which takes effect on the TouchEvent plugin | |
|
||||
| highlightNodeBoxStyle(v0.9.0+) | Object | { stroke: 'rgb(94, 200, 248)', fill: 'transparent' } | Highlight box style when the mouse moves into the summary to highlight the node it belongs to | |
|
||||
| createNewNodeBehavior(v0.9.1+) | String | default | Behavior when creating a new node. default(By default, newly created nodes will be activated and enter editing mode. If multiple new nodes are created simultaneously, they will only be activated and will not enter editing mode)、notActive(Do not activate newly created nodes)、activeOnly(Only activate newly created nodes and do not enter editing mode) | |
|
||||
| defaultNodeImage(v0.9.1-fix.2+) | String | | Image address, the default image displayed when node image loading fails | |
|
||||
| handleNodePasteImg(v0.9.2+) | null or Function | null | The processing method for pasting images from the clipboard on a node is to convert them into data:URL data and insert them into the node by default. You can use this method to upload image data to the server and save the URL of the image. An asynchronous method can be passed to receive image data of Blob type, and the specified structure needs to be returned: { url, size: {width, height} } | |
|
||||
| isLimitMindMapInCanvas(v0.9.2+) | Boolean | false | Whether to limit the mind map within the canvas. For example, when dragging to the right, the leftmost part of the mind map graphic will not be able to continue dragging to the right when it reaches the center of the canvas, and the same applies to other things | |
|
||||
| isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+) | Boolean | true | When registering the Scrollbar plugin, will the mind map be limited to the canvas and the isLimitMindMapInCanvas configuration no longer work | |
|
||||
| associativeLineInitPointsPosition(v0.9.5+) | null / { from, to } | { from: '', to: '' } | By default, the position of the two endpoints of a newly created association line is calculated based on the relative position of the center points of the two nodes. If you want to fix the position, you can configure it through this option. If neither from nor to is transmitted, they will be automatically calculated. If only one is transmitted, the other will be automatically calculated. from and to optional values
|
||||
:left、top、bottom、right | |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | Is it allowed to adjust the position of the two endpoints of the associated line | |
|
||||
| isOnlySearchCurrentRenderNodes(v0.9.8+) | Boolean | false | Is it necessary to only search for the current rendered node, and nodes that have been collapsed will not be searched for | |
|
||||
| onlyOneEnableActiveNodeOnCooperate(v0.9.8+) | Boolean | false | During collaborative editing, the same node cannot be selected by multiple people at the same time | |
|
||||
| beforeCooperateUpdate(v0.9.8+) | Function、null | null | During collaborative editing, node operations are about to be updated to the lifecycle functions of other clients. The function takes an object as a parameter:{ type: 【createOrUpdate(Create or update nodes)、delete(Delete node)】, list: 【Array type, 1.When type=createOrUpdate, it represents the node data that has been created or updated, which will be synchronized to other clients, so you can modify the data; 2.When type=delete, represents the deleted node data】 } | |
|
||||
| beforeShortcutRun(v0.9.9+) | Function、null | null | The lifecycle function before the shortcut operation is about to be executed, returning true can prevent the operation from executing. The function takes two parameters: key(Shortcut key)、activeNodeList(List of currently activated nodes) | |
|
||||
| rainbowLinesConfig(v0.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】 } | |
|
||||
| addContentToHeader(v0.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 | |
|
||||
| addContentToFooter(v0.9.9+) | Function、null | null | The basic definition is the same as addContentToHeader, adding custom content at the end | |
|
||||
| demonstrateConfig(v0.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 | |
|
||||
| resetScaleOnMoveNodeToCenter(v0.9.12+) | Boolean | false | Whether to reset the scaling level to 100% when moving nodes to the canvas center, returning to the root node, and other operations(The underlying impact is on the moveNodeToCenter method of the render class) | |
|
||||
| createNodePrefixContent(v0.9.12+) | Function、null | null | Add additional node pre content.Pre content refers to the pre content in the area of the same line as the text, excluding the node image section.You can pass a function that takes the parameters of a node instance, returns a DOM node, or returns null | |
|
||||
| createNodePostfixContent(v0.9.12+) | Function、null | null | Add additional node post content.Post content refers to the post content in the area of the same line as the text, excluding the node image section.You can pass a function that takes the parameters of a node instance, returns a DOM node, or returns null | |
|
||||
| createNodePrefixContent(v0.9.12+) | Function、null | null | Add additional node pre content.Pre content refers to the pre content in the area of the same line as the text, excluding the node image section.You can pass a function that takes the parameters of a node instance, Can return objects in {el, width, height} format, el is a DOM node object, width and height represent the width, height, and numerical type of the content. If custom content is not required, null can also be returned | |
|
||||
| createNodePostfixContent(v0.9.12+) | Function、null | null | Add additional node post content.Post content refers to the post content in the area of the same line as the text, excluding the node image section. The usage is the same as createNodePrefixContent | |
|
||||
|
||||
### Data structure
|
||||
### 1.1Data structure
|
||||
|
||||
The basic data structure is as follows:
|
||||
|
||||
@@ -166,18 +140,7 @@ The basic data structure is as follows:
|
||||
|
||||
If you want to add custom fields, you can add them to the same level as 'data' and 'children'. If you want to add them to the 'data' object, please use the `_` Name your custom field at the beginning, and it will be used internally to determine whether it is a custom field.
|
||||
|
||||
### Watermark config
|
||||
|
||||
| Field Name | Type | Default Value | Description |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------------------------------ |
|
||||
| text | String | '' | Watermark text. If it is an empty string, the watermark will not be displayed |
|
||||
| lineSpacing | Number | 100 | Spacing between watermark lines |
|
||||
| textSpacing | Number | 100 | Spacing between watermarks in the same row |
|
||||
| angle | Number | 30 | Tilt angle of watermark, range: [0, 90] |
|
||||
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | Watermark text style |
|
||||
| onlyExport(v0.9.2+) | Boolean | false | Is only add watermarks during export |
|
||||
|
||||
### Icon Configuration
|
||||
### 1.2Icon Configuration
|
||||
|
||||
| Field Name | Type | Default Value | Description |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------------------------------ |
|
||||
@@ -185,7 +148,19 @@ If you want to add custom fields, you can add them to the same level as 'data' a
|
||||
| type | String | | Values for icon grouping |
|
||||
| list | Array | | A list of icons under grouping, with each item in the array being an object, `{ name: '', icon: '' }`,`name`represents the name of the icon, `icon`represents the icon, Can be an `svg` icon, such as `<svg ...><path></path></svg>`, also can be a image `url`, or `base64` icon, such as `data:image/png;base64,...` |
|
||||
|
||||
### How to add custom content when exporting
|
||||
### 2.Export plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| exportPadding | Number | 20 | The padding for exporting images | |
|
||||
| exportPaddingX(v0.5.5+) | Number | 10 | Horizontal padding of graphics when exporting PNG, SVG, and PDF | |
|
||||
| exportPaddingY(v0.5.5+) | Number | 10 | Vertical padding of graphics when exporting PNG, SVG, and PDF | |
|
||||
| resetCss(v0.6.16+) | String | * { margin: 0; padding: 0; box-sizing: border-box; } | When exporting images and SVGs, the default style overlay for rich text node content, which is embedded in HTML nodes in SVGs, will occur. If not overlaid, the node content will be offset | |
|
||||
| minExportImgCanvasScale(v0.7.0+) | Number | 2 | The scaling factor of canvas when exporting images and PDFs, which is set to the maximum value of window.devicePixelRatio to improve image clarity | |
|
||||
| addContentToHeader(v0.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 | |
|
||||
| addContentToFooter(v0.9.9+) | Function、null | null | The basic definition is the same as addContentToHeader, adding custom content at the end | |
|
||||
|
||||
#### 2.1How to add custom content when exporting
|
||||
|
||||
The two instantiation options `addContentToHeader` and `addContentToFooter` can be used to add custom content at the beginning and end when exporting `png`、`svg`、`pdf`, The default value is `null`, which means no configuration. A function can be passed and can return `null`, which means no content will be added. If you want to add content, you need to return the following structure:
|
||||
|
||||
@@ -220,7 +195,99 @@ new MindMap({
|
||||
})
|
||||
```
|
||||
|
||||
### Demonstration Plugin Configuration
|
||||
### 3.Select plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| selectTranslateStep | Number | 3 | The canvas offset when mouse moves to the edge during multi-select node | |
|
||||
| selectTranslateLimit | Number | 20 | The distance from the edge when the canvas begins to offset during multi-select node | |
|
||||
|
||||
### 4.Drag plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| enableFreeDrag(v0.2.4+) | Boolean | false | Enable node free(Free drag means that nodes can be dragged to any position on the canvas. Please note that it is not a function of dragging nodes to become siblings of other nodes. The connection of free drag may have certain problems, so it is best not to use this feature) drag | |
|
||||
| nodeDragPlaceholderMaxSize(v0.6.12+)(v0.10.0+ has been abolished) | Number | 20 | When dragging an element, the maximum height of the block indicating the new position of the element | |
|
||||
| autoMoveWhenMouseInEdgeOnDrag(v0.7.1+) | Boolean | true | Whether to enable automatic canvas movement when the mouse moves to the edge of the canvas while dragging nodes | |
|
||||
| dragMultiNodeRectConfig(v0.7.2+) | Object | { width: 40, height: 20, fill: 'rgb(94, 200, 248)' } | The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle | |
|
||||
| dragPlaceholderRectFill(v0.7.2+) | String | rgb(94, 200, 248) | The filling color of the schematic rectangle for the new position when dragging nodes. | |
|
||||
| dragPlaceholderLineConfig(v0.10.0+) | Object | { color: 'rgb(94, 200, 248)', width: 2 } | Style configuration of schematic lines for new positions when dragging nodes | |
|
||||
| dragOpacityConfig(v0.7.2+) | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node | |
|
||||
|
||||
### 5.Watermark plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| watermarkConfig(v0.2.4+) | Object | | Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration | |
|
||||
|
||||
#### 5.1Watermark config
|
||||
|
||||
| Field Name | Type | Default Value | Description |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------------------------------ |
|
||||
| text | String | '' | Watermark text. If it is an empty string, the watermark will not be displayed |
|
||||
| lineSpacing | Number | 100 | Spacing between watermark lines |
|
||||
| textSpacing | Number | 100 | Spacing between watermarks in the same row |
|
||||
| angle | Number | 30 | Tilt angle of watermark, range: [0, 90] |
|
||||
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | Watermark text style |
|
||||
| onlyExport(v0.9.2+) | Boolean | false | Is only add watermarks during export |
|
||||
| belowNode(v0.10.0+) | Boolean | false | Is the watermark displayed below the node |
|
||||
|
||||
### 6.AssociativeLine plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| defaultAssociativeLineText(v0.5.11+) | String | 关联 | Association Line Default Text | |
|
||||
| associativeLineIsAlwaysAboveNode(v0.8.0+) | Boolean | true | Is the associated line always displayed above the node? If set to false, it will be at the top level when creating and activating the associated line, and in other cases, it will be below the node | |
|
||||
| associativeLineInitPointsPosition(v0.9.5+) | null / { from, to } | { from: '', to: '' } | By default, the position of the two endpoints of a newly created association line is calculated based on the relative position of the center points of the two nodes. If you want to fix the position, you can configure it through this option. If neither from nor to is transmitted, they will be automatically calculated. If only one is transmitted, the other will be automatically calculated. from and to optional values
|
||||
:left、top、bottom、right | |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | Is it allowed to adjust the position of the two endpoints of the associated line | |
|
||||
|
||||
### 7.RichText plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| richTextEditFakeInPlace(v0.6.13+) | Boolean | false | Set the rich text node edit box to match the size of the node, creating a pseudo in place editing effect. It should be noted that only when there is only text within the node and the shape is rectangular, can the effect be better | |
|
||||
| enableEditFormulaInRichTextEdit(v0.10.0+) | Boolean | true | | Whether to enable direct editing of mathematical formulas in rich text editing boxes |
|
||||
| transformRichTextOnEnterEdit(v0.10.0+) | null、Function | null | To convert rich text content, you can pass a function that will be called when entering rich text editing. The function receives the rich text content that is about to be edited and needs to return the processed rich text content | |
|
||||
| beforeHideRichTextEdit(v0.10.0+) | null、Function | null | You can pass a function that will be executed before the end of rich text editing. The function receives a richText instance, so you can update the kill document data at this time | |
|
||||
|
||||
### 8.TouchEvent plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| disableTouchZoom(v0.8.1+) | Boolean | false | Prohibit double finger scaling, you can still use the API for scaling, which takes effect on the TouchEvent plugin | |
|
||||
|
||||
### 9.Scrollbar plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+) | Boolean | true | When registering the Scrollbar plugin, will the mind map be limited to the canvas and the isLimitMindMapInCanvas configuration no longer work | |
|
||||
|
||||
### 10.Search plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| isOnlySearchCurrentRenderNodes(v0.9.8+) | Boolean | false | Is it necessary to only search for the current rendered node, and nodes that have been collapsed will not be searched for | |
|
||||
|
||||
### 11.Cooperate plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| beforeCooperateUpdate(v0.9.8+) | Function、null | null | During collaborative editing, node operations are about to be updated to the lifecycle functions of other clients. The function takes an object as a parameter:{ type: 【createOrUpdate(Create or update nodes)、delete(Delete node)】, list: 【Array type, 1.When type=createOrUpdate, it represents the node data that has been created or updated, which will be synchronized to other clients, so you can modify the data; 2.When type=delete, represents the deleted node data】 } | |
|
||||
|
||||
### 12.RainbowLines plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| rainbowLinesConfig(v0.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】 } | |
|
||||
|
||||
### 13.Demonstrate plugin
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------- | -------- |
|
||||
| demonstrateConfig(v0.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 | |
|
||||
|
||||
#### 13.1Demonstration Plugin Configuration
|
||||
|
||||
| Field Name | Type | Default Value | Description |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
|
||||
@@ -486,7 +553,8 @@ Listen to an event. Event list:
|
||||
| node_img_mouseenter(v0.6.5+) | Node image mouseenter event | this(node instance)、imgNode(img node)、e(event object) |
|
||||
| node_img_mouseleave(v0.6.5+) | Node image mouseleave event | this(node instance)、imgNode(img node)、e(event object) |
|
||||
| node_img_mousemove(v0.6.5+) | Node image mousemove event | this(node instance)、imgNode(img node)、e(event object) |
|
||||
| node_tree_render_end(v0.2.16+) | Node tree render end event | |
|
||||
| node_tree_render_end(v0.2.16+) | Node tree render end event | |
|
||||
| node_tree_render_start(v0.10.0+) | Node tree start rendering event | |
|
||||
| rich_text_selection_change(v0.4.0+) | Available when the `RichText` plugin is registered. Triggered when the text selection area changes when the node is edited | hasRange(Whether there is a selection)、rectInfo(Size and location information of the selected area)、formatInfo(Text formatting information of the selected area) |
|
||||
| transforming-dom-to-images(v0.4.0+) | Available when the `RichText` plugin is registered. When there is a `DOM` node in `svg`, the `DOM` node will be converted to an image when exporting to an image. This event will be triggered during the conversion process. You can use this event to prompt the user about the node to which you are currently converting | index(Index of the node currently converted to)、len(Total number of nodes to be converted) |
|
||||
| node_dragging(v0.4.5+) | Triggered when a node is dragged | node(The currently dragged node) |
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
});
|
||||
</code></pre>
|
||||
<h2>Instantiation options</h2>
|
||||
<h3>1.Base</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -85,13 +86,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPadding</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>The padding for exporting images</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>imgTextMargin</td>
|
||||
<td>Number</td>
|
||||
<td>5</td>
|
||||
@@ -106,20 +100,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectTranslateStep</td>
|
||||
<td>Number</td>
|
||||
<td>3</td>
|
||||
<td>The canvas offset when mouse moves to the edge during multi-select node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectTranslateLimit</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>The distance from the edge when the canvas begins to offset during multi-select node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>customNoteContentShow(v0.1.6+)</td>
|
||||
<td>Object</td>
|
||||
<td>null</td>
|
||||
@@ -134,20 +114,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableFreeDrag(v0.2.4+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Enable node free(Free drag means that nodes can be dragged to any position on the canvas. Please note that it is not a function of dragging nodes to become siblings of other nodes. The connection of free drag may have certain problems, so it is best not to use this feature) drag</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>watermarkConfig(v0.2.4+)</td>
|
||||
<td>Object</td>
|
||||
<td></td>
|
||||
<td>Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>textAutoWrapWidth(v0.3.4+)</td>
|
||||
<td>Number</td>
|
||||
<td>500</td>
|
||||
@@ -253,20 +219,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingX(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>Horizontal padding of graphics when exporting PNG, SVG, and PDF</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingY(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>Vertical padding of graphics when exporting PNG, SVG, and PDF</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeTextEditZIndex(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>3000</td>
|
||||
@@ -316,13 +268,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultAssociativeLineText(v0.5.11+)</td>
|
||||
<td>String</td>
|
||||
<td>关联</td>
|
||||
<td>Association Line Default Text</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>fitPadding(v0.6.0+)</td>
|
||||
<td>Number</td>
|
||||
<td>50</td>
|
||||
@@ -379,13 +324,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeDragPlaceholderMaxSize(v0.6.12+)</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>When dragging an element, the maximum height of the block indicating the new position of the element</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableCreateHiddenInput(v0.6.13+)(v0.6.14+ remove this feature)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
@@ -400,13 +338,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>richTextEditFakeInPlace(v0.6.13+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Set the rich text node edit box to match the size of the node, creating a pseudo in place editing effect. It should be noted that only when there is only text within the node and the shape is rectangular, can the effect be better</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>customHandleClipboardText(v0.6.14+)</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
@@ -428,13 +359,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resetCss(v0.6.16+)</td>
|
||||
<td>String</td>
|
||||
<td>* { margin: 0; padding: 0; box-sizing: border-box; }</td>
|
||||
<td>When exporting images and SVGs, the default style overlay for rich text node content, which is embedded in HTML nodes in SVGs, will occur. If not overlaid, the node content will be offset</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableDblclickReset(v0.6.17+)(v0.8.0+this attribute has been deleted)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true(v0.7.0+changed to false)</td>
|
||||
@@ -449,13 +373,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>minExportImgCanvasScale(v0.7.0+)</td>
|
||||
<td>Number</td>
|
||||
<td>2</td>
|
||||
<td>The scaling factor of canvas when exporting images and PDFs, which is set to the maximum value of window.devicePixelRatio to improve image clarity</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hoverRectColor(v0.7.0+)</td>
|
||||
<td>String</td>
|
||||
<td>rgb(94, 200, 248)</td>
|
||||
@@ -484,13 +401,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>autoMoveWhenMouseInEdgeOnDrag(v0.7.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Whether to enable automatic canvas movement when the mouse moves to the edge of the canvas while dragging nodes</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>fit(v0.7.1-fix.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
@@ -498,27 +408,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragMultiNodeRectConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ width: 40, height: 20, fill: '' }</td>
|
||||
<td>The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderRectFill(v0.7.2+)</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>The filling color of the schematic rectangle for the new position when dragging nodes. If not transmitted, the default color for the connected line is used</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragOpacityConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
|
||||
<td>The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>tagsColorMap(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{}</td>
|
||||
@@ -533,10 +422,10 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>associativeLineIsAlwaysAboveNode(v0.8.0+)</td>
|
||||
<td>onlyOneEnableActiveNodeOnCooperate(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Is the associated line always displayed above the node? If set to false, it will be at the top level when creating and activating the associated line, and in other cases, it will be below the node</td>
|
||||
<td>false</td>
|
||||
<td>During collaborative editing, the same node cannot be selected by multiple people at the same time</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -568,13 +457,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>disableTouchZoom(v0.8.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Prohibit double finger scaling, you can still use the API for scaling, which takes effect on the TouchEvent plugin</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>highlightNodeBoxStyle(v0.9.0+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ stroke: 'rgb(94, 200, 248)', fill: 'transparent' }</td>
|
||||
@@ -610,55 +492,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>When registering the Scrollbar plugin, will the mind map be limited to the canvas and the isLimitMindMapInCanvas configuration no longer work</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>associativeLineInitPointsPosition(v0.9.5+)</td>
|
||||
<td>null / { from, to }</td>
|
||||
<td>{ from: '', to: '' }</td>
|
||||
<td>By default, the position of the two endpoints of a newly created association line is calculated based on the relative position of the center points of the two nodes. If you want to fix the position, you can configure it through this option. If neither from nor to is transmitted, they will be automatically calculated. If only one is transmitted, the other will be automatically calculated. from and to optional values</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:left、top、bottom、right</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableAdjustAssociativeLinePoints(v0.9.5+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Is it allowed to adjust the position of the two endpoints of the associated line</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isOnlySearchCurrentRenderNodes(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Is it necessary to only search for the current rendered node, and nodes that have been collapsed will not be searched for</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onlyOneEnableActiveNodeOnCooperate(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>During collaborative editing, the same node cannot be selected by multiple people at the same time</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeCooperateUpdate(v0.9.8+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>During collaborative editing, node operations are about to be updated to the lifecycle functions of other clients. The function takes an object as a parameter:{ type: 【createOrUpdate(Create or update nodes)、delete(Delete node)】, list: 【Array type, 1.When type=createOrUpdate, it represents the node data that has been created or updated, which will be synchronized to other clients, so you can modify the data; 2.When type=delete, represents the deleted node data】 }</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeShortcutRun(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
@@ -666,34 +499,6 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rainbowLinesConfig(v0.9.9+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ open: false, colorsList: [] }</td>
|
||||
<td>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】 }</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToHeader(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>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</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToFooter(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>The basic definition is the same as addContentToHeader, adding custom content at the end</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>demonstrateConfig(v0.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>
|
||||
<tr>
|
||||
<td>resetScaleOnMoveNodeToCenter(v0.9.12+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
@@ -704,19 +509,19 @@
|
||||
<td>createNodePrefixContent(v0.9.12+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>Add additional node pre content.Pre content refers to the pre content in the area of the same line as the text, excluding the node image section.You can pass a function that takes the parameters of a node instance, returns a DOM node, or returns null</td>
|
||||
<td>Add additional node pre content.Pre content refers to the pre content in the area of the same line as the text, excluding the node image section.You can pass a function that takes the parameters of a node instance, Can return objects in {el, width, height} format, el is a DOM node object, width and height represent the width, height, and numerical type of the content. If custom content is not required, null can also be returned</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>createNodePostfixContent(v0.9.12+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>Add additional node post content.Post content refers to the post content in the area of the same line as the text, excluding the node image section.You can pass a function that takes the parameters of a node instance, returns a DOM node, or returns null</td>
|
||||
<td>Add additional node post content.Post content refers to the post content in the area of the same line as the text, excluding the node image section. The usage is the same as createNodePrefixContent</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Data structure</h3>
|
||||
<h3>1.1Data structure</h3>
|
||||
<p>The basic data structure is as follows:</p>
|
||||
<pre class="hljs"><code>{
|
||||
<span class="hljs-attr">data</span>: {
|
||||
@@ -754,7 +559,241 @@
|
||||
}
|
||||
</code></pre>
|
||||
<p>If you want to add custom fields, you can add them to the same level as 'data' and 'children'. If you want to add them to the 'data' object, please use the <code>_</code> Name your custom field at the beginning, and it will be used internally to determine whether it is a custom field.</p>
|
||||
<h3>Watermark config</h3>
|
||||
<h3>1.2Icon Configuration</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>name</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>The name of the icon group</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>type</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>Values for icon grouping</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>list</td>
|
||||
<td>Array</td>
|
||||
<td></td>
|
||||
<td>A list of icons under grouping, with each item in the array being an object, <code>{ name: '', icon: '' }</code>,<code>name</code>represents the name of the icon, <code>icon</code>represents the icon, Can be an <code>svg</code> icon, such as <code><svg ...><path></path></svg></code>, also can be a image <code>url</code>, or <code>base64</code> icon, such as <code>data:image/png;base64,...</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>2.Export plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>exportPadding</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>The padding for exporting images</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingX(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>Horizontal padding of graphics when exporting PNG, SVG, and PDF</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingY(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>Vertical padding of graphics when exporting PNG, SVG, and PDF</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resetCss(v0.6.16+)</td>
|
||||
<td>String</td>
|
||||
<td>* { margin: 0; padding: 0; box-sizing: border-box; }</td>
|
||||
<td>When exporting images and SVGs, the default style overlay for rich text node content, which is embedded in HTML nodes in SVGs, will occur. If not overlaid, the node content will be offset</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>minExportImgCanvasScale(v0.7.0+)</td>
|
||||
<td>Number</td>
|
||||
<td>2</td>
|
||||
<td>The scaling factor of canvas when exporting images and PDFs, which is set to the maximum value of window.devicePixelRatio to improve image clarity</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToHeader(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>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</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToFooter(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>The basic definition is the same as addContentToHeader, adding custom content at the end</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>2.1How to add custom content when exporting</h4>
|
||||
<p>The two instantiation options <code>addContentToHeader</code> and <code>addContentToFooter</code> can be used to add custom content at the beginning and end when exporting <code>png</code>、<code>svg</code>、<code>pdf</code>, The default value is <code>null</code>, which means no configuration. A function can be passed and can return <code>null</code>, which means no content will be added. If you want to add content, you need to return the following structure:</p>
|
||||
<pre class="hljs"><code>{
|
||||
el,// Custom DOM node to be added, styles can be inline
|
||||
cssText,// Optional, if the style does not want to be inlined, you can pass this value as a CSS string
|
||||
height: 50// The height of the returned DOM node must be passed
|
||||
}
|
||||
</code></pre>
|
||||
<p>A simple example:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">new</span> MindMap({
|
||||
<span class="hljs-attr">addContentToFooter</span>: <span class="hljs-function">() =></span> {
|
||||
<span class="hljs-keyword">const</span> el = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>)
|
||||
el.className = <span class="hljs-string">'footer'</span>
|
||||
el.innerHTML = <span class="hljs-string">'From: simple-mind-map'</span>
|
||||
<span class="hljs-keyword">const</span> cssText = <span class="hljs-string">`
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
`</span>
|
||||
<span class="hljs-keyword">return</span> {
|
||||
el,
|
||||
cssText,
|
||||
<span class="hljs-attr">height</span>: <span class="hljs-number">30</span>
|
||||
}
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
<h3>3.Select plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>selectTranslateStep</td>
|
||||
<td>Number</td>
|
||||
<td>3</td>
|
||||
<td>The canvas offset when mouse moves to the edge during multi-select node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectTranslateLimit</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>The distance from the edge when the canvas begins to offset during multi-select node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>4.Drag plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>enableFreeDrag(v0.2.4+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Enable node free(Free drag means that nodes can be dragged to any position on the canvas. Please note that it is not a function of dragging nodes to become siblings of other nodes. The connection of free drag may have certain problems, so it is best not to use this feature) drag</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeDragPlaceholderMaxSize(v0.6.12+)(v0.10.0+ has been abolished)</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>When dragging an element, the maximum height of the block indicating the new position of the element</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>autoMoveWhenMouseInEdgeOnDrag(v0.7.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Whether to enable automatic canvas movement when the mouse moves to the edge of the canvas while dragging nodes</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragMultiNodeRectConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ width: 40, height: 20, fill: 'rgb(94, 200, 248)' }</td>
|
||||
<td>The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderRectFill(v0.7.2+)</td>
|
||||
<td>String</td>
|
||||
<td>rgb(94, 200, 248)</td>
|
||||
<td>The filling color of the schematic rectangle for the new position when dragging nodes.</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderLineConfig(v0.10.0+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ color: 'rgb(94, 200, 248)', width: 2 }</td>
|
||||
<td>Style configuration of schematic lines for new positions when dragging nodes</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragOpacityConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
|
||||
<td>The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>5.Watermark plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>watermarkConfig(v0.2.4+)</td>
|
||||
<td>Object</td>
|
||||
<td></td>
|
||||
<td>Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>5.1Watermark config</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -801,9 +840,15 @@
|
||||
<td>false</td>
|
||||
<td>Is only add watermarks during export</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>belowNode(v0.10.0+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Is the watermark displayed below the node</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Icon Configuration</h3>
|
||||
<h3>6.AssociativeLine plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -811,58 +856,216 @@
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>name</td>
|
||||
<td>defaultAssociativeLineText(v0.5.11+)</td>
|
||||
<td>String</td>
|
||||
<td>关联</td>
|
||||
<td>Association Line Default Text</td>
|
||||
<td></td>
|
||||
<td>The name of the icon group</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>type</td>
|
||||
<td>String</td>
|
||||
<td>associativeLineIsAlwaysAboveNode(v0.8.0+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Is the associated line always displayed above the node? If set to false, it will be at the top level when creating and activating the associated line, and in other cases, it will be below the node</td>
|
||||
<td></td>
|
||||
<td>Values for icon grouping</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>list</td>
|
||||
<td>Array</td>
|
||||
<td>associativeLineInitPointsPosition(v0.9.5+)</td>
|
||||
<td>null / { from, to }</td>
|
||||
<td>{ from: '', to: '' }</td>
|
||||
<td>By default, the position of the two endpoints of a newly created association line is calculated based on the relative position of the center points of the two nodes. If you want to fix the position, you can configure it through this option. If neither from nor to is transmitted, they will be automatically calculated. If only one is transmitted, the other will be automatically calculated. from and to optional values</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>:left、top、bottom、right</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableAdjustAssociativeLinePoints(v0.9.5+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Is it allowed to adjust the position of the two endpoints of the associated line</td>
|
||||
<td></td>
|
||||
<td>A list of icons under grouping, with each item in the array being an object, <code>{ name: '', icon: '' }</code>,<code>name</code>represents the name of the icon, <code>icon</code>represents the icon, Can be an <code>svg</code> icon, such as <code><svg ...><path></path></svg></code>, also can be a image <code>url</code>, or <code>base64</code> icon, such as <code>data:image/png;base64,...</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>How to add custom content when exporting</h3>
|
||||
<p>The two instantiation options <code>addContentToHeader</code> and <code>addContentToFooter</code> can be used to add custom content at the beginning and end when exporting <code>png</code>、<code>svg</code>、<code>pdf</code>, The default value is <code>null</code>, which means no configuration. A function can be passed and can return <code>null</code>, which means no content will be added. If you want to add content, you need to return the following structure:</p>
|
||||
<pre class="hljs"><code>{
|
||||
el,// Custom DOM node to be added, styles can be inline
|
||||
cssText,// Optional, if the style does not want to be inlined, you can pass this value as a CSS string
|
||||
height: 50// The height of the returned DOM node must be passed
|
||||
}
|
||||
</code></pre>
|
||||
<p>A simple example:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">new</span> MindMap({
|
||||
<span class="hljs-attr">addContentToFooter</span>: <span class="hljs-function">() =></span> {
|
||||
<span class="hljs-keyword">const</span> el = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>)
|
||||
el.className = <span class="hljs-string">'footer'</span>
|
||||
el.innerHTML = <span class="hljs-string">'From: simple-mind-map'</span>
|
||||
<span class="hljs-keyword">const</span> cssText = <span class="hljs-string">`
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
`</span>
|
||||
<span class="hljs-keyword">return</span> {
|
||||
el,
|
||||
cssText,
|
||||
<span class="hljs-attr">height</span>: <span class="hljs-number">30</span>
|
||||
}
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
<h3>Demonstration Plugin Configuration</h3>
|
||||
<h3>7.RichText plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>richTextEditFakeInPlace(v0.6.13+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Set the rich text node edit box to match the size of the node, creating a pseudo in place editing effect. It should be noted that only when there is only text within the node and the shape is rectangular, can the effect be better</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableEditFormulaInRichTextEdit(v0.10.0+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td></td>
|
||||
<td>Whether to enable direct editing of mathematical formulas in rich text editing boxes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>transformRichTextOnEnterEdit(v0.10.0+)</td>
|
||||
<td>null、Function</td>
|
||||
<td>null</td>
|
||||
<td>To convert rich text content, you can pass a function that will be called when entering rich text editing. The function receives the rich text content that is about to be edited and needs to return the processed rich text content</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeHideRichTextEdit(v0.10.0+)</td>
|
||||
<td>null、Function</td>
|
||||
<td>null</td>
|
||||
<td>You can pass a function that will be executed before the end of rich text editing. The function receives a richText instance, so you can update the kill document data at this time</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>8.TouchEvent plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>disableTouchZoom(v0.8.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Prohibit double finger scaling, you can still use the API for scaling, which takes effect on the TouchEvent plugin</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>9.Scrollbar plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>When registering the Scrollbar plugin, will the mind map be limited to the canvas and the isLimitMindMapInCanvas configuration no longer work</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>10.Search plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>isOnlySearchCurrentRenderNodes(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Is it necessary to only search for the current rendered node, and nodes that have been collapsed will not be searched for</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>11.Cooperate plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>beforeCooperateUpdate(v0.9.8+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>During collaborative editing, node operations are about to be updated to the lifecycle functions of other clients. The function takes an object as a parameter:{ type: 【createOrUpdate(Create or update nodes)、delete(Delete node)】, list: 【Array type, 1.When type=createOrUpdate, it represents the node data that has been created or updated, which will be synchronized to other clients, so you can modify the data; 2.When type=delete, represents the deleted node data】 }</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>12.RainbowLines plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>rainbowLinesConfig(v0.9.9+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ open: false, colorsList: [] }</td>
|
||||
<td>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】 }</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>13.Demonstrate plugin</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default Value</th>
|
||||
<th>Description</th>
|
||||
<th>Required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>demonstrateConfig(v0.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>
|
||||
<h4>13.1Demonstration Plugin Configuration</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -1239,6 +1442,11 @@ poor performance and should be used sparingly.</p>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>node_tree_render_start(v0.10.0+)</td>
|
||||
<td>Node tree start rendering event</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rich_text_selection_change(v0.4.0+)</td>
|
||||
<td>Available when the <code>RichText</code> plugin is registered. Triggered when the text selection area changes when the node is edited</td>
|
||||
<td>hasRange(Whether there is a selection)、rectInfo(Size and location information of the selected area)、formatInfo(Text formatting information of the selected area)</td>
|
||||
|
||||
@@ -384,7 +384,7 @@ Open source is not easy. If this project is helpful to you, you can invite the a
|
||||
</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>
|
||||
<p>Alex</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%;" />
|
||||
@@ -394,4 +394,20 @@ Open source is not easy. If this project is helpful to you, you can invite the a
|
||||
<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/最多5个字.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>最多5个字</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/ZX.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>ZX</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>
|
||||
@@ -8,18 +8,18 @@
|
||||
</blockquote>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox252" checked="true" /><label for="checkbox252">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="checkbox253" checked="true" /><label for="checkbox253">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="checkbox254" checked="true" /><label for="checkbox254">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox255" checked="true" /><label for="checkbox255">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox256" checked="true" /><label for="checkbox256">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, Support for expanding node content, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox257" checked="true" /><label for="checkbox257">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox258" checked="true" /><label for="checkbox258">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox259" checked="true" /><label for="checkbox259">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>、<code>txt</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox260" checked="true" /><label for="checkbox260">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, scrollbar, Hand drawn style, and rainbow lines</label></li>
|
||||
<li><input type="checkbox" id="checkbox261" checked="true" /><label for="checkbox261">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox262" checked="true" /><label for="checkbox262">Support collaborative editing</label></li>
|
||||
<li><input type="checkbox" id="checkbox263" checked="true" /><label for="checkbox263">Support demonstration mode</label></li>
|
||||
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">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="checkbox18" checked="true" /><label for="checkbox18">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="checkbox19" checked="true" /><label for="checkbox19">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, Support for expanding node content, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>、<code>txt</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, scrollbar, Hand drawn style, and rainbow lines</label></li>
|
||||
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Support collaborative editing</label></li>
|
||||
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Support demonstration mode</label></li>
|
||||
</ul>
|
||||
<p>The official provides the following plugins, which can be introduced as needed (a certain function may not be effective because you did not introduce the corresponding plugin). Please refer to the documentation for specific usage methods:</p>
|
||||
<blockquote>
|
||||
@@ -39,16 +39,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="checkbox264" checked="true" /><label for="checkbox264">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</li>
|
||||
<li><input type="checkbox" id="checkbox265" checked="true" /><label for="checkbox265">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</li>
|
||||
<li><input type="checkbox" id="checkbox266" checked="true" /><label for="checkbox266">Import and export functionality; data is saved in the browser's local</label>
|
||||
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">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="checkbox267" checked="true" /><label for="checkbox267">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</li>
|
||||
<li><input type="checkbox" id="checkbox268" checked="true" /><label for="checkbox268">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">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>
|
||||
@@ -338,7 +338,7 @@ full screen, support mini map</li>
|
||||
</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>
|
||||
<p>Alex</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%;" />
|
||||
@@ -348,6 +348,22 @@ full screen, support mini map</li>
|
||||
<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/最多5个字.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>最多5个字</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/ZX.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>ZX</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>
|
||||
|
||||
@@ -506,6 +506,16 @@ Put the specified DOM element into full screen mode.
|
||||
|
||||
Exit full screen mode.
|
||||
|
||||
#### defenseXSS(htmlStr)
|
||||
|
||||
> v0.10.0+
|
||||
|
||||
- `htmlStr`:HTML strings that need to be filtered
|
||||
|
||||
Return:Filtered HTML string
|
||||
|
||||
Defend against XSS attacks, filter malicious HTML tags and attributes. You can recursively traverse the tree data before passing the node data to SimpleMindMap, using this method to process the rich text content of nodes and avoid XSS attacks.
|
||||
|
||||
## Simulate CSS background in Canvas
|
||||
|
||||
Import:
|
||||
|
||||
@@ -424,6 +424,15 @@ and copying the <code>data</code> of the data object, example:</p>
|
||||
<p>v0.9.11+</p>
|
||||
</blockquote>
|
||||
<p>Exit full screen mode.</p>
|
||||
<h4>defenseXSS(htmlStr)</h4>
|
||||
<blockquote>
|
||||
<p>v0.10.0+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>htmlStr</code>:HTML strings that need to be filtered</li>
|
||||
</ul>
|
||||
<p>Return:Filtered HTML string</p>
|
||||
<p>Defend against XSS attacks, filter malicious HTML tags and attributes. You can recursively traverse the tree data before passing the node data to SimpleMindMap, using this method to process the rich text content of nodes and avoid XSS attacks.</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">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
|
||||
@@ -22,13 +22,15 @@ simpleMindMap.xmind
|
||||
|
||||
## Methods
|
||||
|
||||
### xmind.parseXmindFile(file)
|
||||
### xmind.parseXmindFile(file, handleMultiCanvas)
|
||||
|
||||
Parsing the `.xmind` file and returning the parsed data. You can use
|
||||
`mindMap.setData(data)` to render the returned data to the canvas.
|
||||
|
||||
`file`: `File` object
|
||||
|
||||
`handleMultiCanvas`:v0.10.0+,Optional, a function can be passed. If there are multiple canvases in the imported xmind file, this function will be called. The function takes the xmind canvas list data as a parameter and needs to return the data of one of the canvases, For example, if the received parameter is 'content', if you want to import data from the second canvas, you will return 'content[1]'. A function can be an asynchronous function that returns a Promise instance.
|
||||
|
||||
### xmind.transformXmind(content)
|
||||
|
||||
> V0.6.6+version changes the method to asynchronous and returns a Promise instance
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
<pre class="hljs"><code>simpleMindMap.xmind
|
||||
</code></pre>
|
||||
<h2>Methods</h2>
|
||||
<h3>xmind.parseXmindFile(file)</h3>
|
||||
<h3>xmind.parseXmindFile(file, handleMultiCanvas)</h3>
|
||||
<p>Parsing the <code>.xmind</code> file and returning the parsed data. You can use
|
||||
<code>mindMap.setData(data)</code> to render the returned data to the canvas.</p>
|
||||
<p><code>file</code>: <code>File</code> object</p>
|
||||
<p><code>handleMultiCanvas</code>:v0.10.0+,Optional, a function can be passed. If there are multiple canvases in the imported xmind file, this function will be called. The function takes the xmind canvas list data as a parameter and needs to return the data of one of the canvases, For example, if the received parameter is 'content', if you want to import data from the second canvas, you will return 'content[1]'. A function can be an asynchronous function that returns a Promise instance.</p>
|
||||
<h3>xmind.transformXmind(content)</h3>
|
||||
<blockquote>
|
||||
<p>V0.6.6+version changes the method to asynchronous and returns a Promise instance</p>
|
||||
|
||||
@@ -35,6 +35,7 @@ export default [
|
||||
{ path: 'course26', title: '如何实现AI生成节点内容' },
|
||||
{ path: 'course27', title: '快捷键操作如何传递自定义参数' },
|
||||
{ path: 'course28', title: '如何动态修改自定义元素的大小' },
|
||||
{ path: 'course29', title: '局域网docker部署解决HTTPS问题的一种方法' },
|
||||
{ path: 'doExport', title: 'Export 插件' },
|
||||
{ path: 'drag', title: 'Drag插件' },
|
||||
{ path: 'introduction', title: '简介' },
|
||||
@@ -69,7 +70,8 @@ export default [
|
||||
{ path: 'help2', title: '客户端' },
|
||||
{ path: 'help3', title: '打开预览在线文件' },
|
||||
{ path: 'help4', title: '复制粘贴' },
|
||||
{ path: 'help5', title: '导出' }
|
||||
{ path: 'help5', title: '导出' },
|
||||
{ path: 'help6', title: '如何编辑数学公式' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,5 +1,51 @@
|
||||
# Changelog
|
||||
|
||||
## 0.10.0
|
||||
|
||||
较大更新:升级节点拖拽时的交互效果;
|
||||
|
||||
修复:
|
||||
|
||||
> 1.修复只读模式仍可通过Ctrl+点击节点方式激活节点的问题;
|
||||
>
|
||||
> 2.修复移动端部分浏览器设置缩放时会进行页面缩放的问题;
|
||||
>
|
||||
> 3.修复拖拽画布和拖拽调整图片时会选中文字的问题;
|
||||
>
|
||||
> 4.修复复制带换行符的节点文本粘贴后会出现多行换行的问题;
|
||||
>
|
||||
> 5.修复节点前后自定义内容导出图片时显示空白的问题;
|
||||
|
||||
新增:
|
||||
|
||||
> 1.新增渲染开始事件node_tree_render_start;
|
||||
>
|
||||
> 2.支持设置水印显示在节点下方;
|
||||
>
|
||||
> 3.导入存在多个画布的xmind文件支持选择指定的画布进行导入;
|
||||
>
|
||||
> 4.取消调用defenseXSS函数,对性能影响太大;defenseXSS方法作为工具方法提供;
|
||||
>
|
||||
> 5.去除移除富文本内容中ql-cursor类名的节点的逻辑,修复文本换行时新增空行不生效的问题;
|
||||
>
|
||||
> 6.插入新节点时去除延时开启节点编辑的逻辑;
|
||||
>
|
||||
> 7.支持直接在富文本编辑框中编辑数学公式;
|
||||
>
|
||||
> 8.打包后的文件中增加演示插件;
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.支持配置水印显示在节点下方;
|
||||
>
|
||||
> 2.导入存在多个画布的xmind文件支持选择指定的画布进行导入;
|
||||
>
|
||||
> 3.优化富文本工具条下拉选项列表高度问题;
|
||||
>
|
||||
> 4.新建和打开按钮增加导出的提示,防止内容丢失;
|
||||
>
|
||||
> 5.快捷键提示支持区分windows和mac;
|
||||
|
||||
## 0.9.12
|
||||
|
||||
修复:
|
||||
|
||||
@@ -1,6 +1,35 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.10.0</h2>
|
||||
<p>较大更新:升级节点拖拽时的交互效果;</p>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
<p>1.修复只读模式仍可通过Ctrl+点击节点方式激活节点的问题;</p>
|
||||
<p>2.修复移动端部分浏览器设置缩放时会进行页面缩放的问题;</p>
|
||||
<p>3.修复拖拽画布和拖拽调整图片时会选中文字的问题;</p>
|
||||
<p>4.修复复制带换行符的节点文本粘贴后会出现多行换行的问题;</p>
|
||||
<p>5.修复节点前后自定义内容导出图片时显示空白的问题;</p>
|
||||
</blockquote>
|
||||
<p>新增:</p>
|
||||
<blockquote>
|
||||
<p>1.新增渲染开始事件node_tree_render_start;</p>
|
||||
<p>2.支持设置水印显示在节点下方;</p>
|
||||
<p>3.导入存在多个画布的xmind文件支持选择指定的画布进行导入;</p>
|
||||
<p>4.取消调用defenseXSS函数,对性能影响太大;defenseXSS方法作为工具方法提供;</p>
|
||||
<p>5.去除移除富文本内容中ql-cursor类名的节点的逻辑,修复文本换行时新增空行不生效的问题;</p>
|
||||
<p>6.插入新节点时去除延时开启节点编辑的逻辑;</p>
|
||||
<p>7.支持直接在富文本编辑框中编辑数学公式;</p>
|
||||
<p>8.打包后的文件中增加演示插件;</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.支持配置水印显示在节点下方;</p>
|
||||
<p>2.导入存在多个画布的xmind文件支持选择指定的画布进行导入;</p>
|
||||
<p>3.优化富文本工具条下拉选项列表高度问题;</p>
|
||||
<p>4.新建和打开按钮增加导出的提示,防止内容丢失;</p>
|
||||
<p>5.快捷键提示支持区分windows和mac;</p>
|
||||
</blockquote>
|
||||
<h2>0.9.12</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
|
||||
@@ -22,6 +22,8 @@ const mindMap = new MindMap({
|
||||
|
||||
## 实例化选项
|
||||
|
||||
### 1.基本
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| el | Element | | 容器元素,必传,必须为DOM元素(当容器元素在页面上的位置发生了改变,但大小没有改变的情况下必须调用`getElRectInfo()`方法更新库内部的相关信息;当大小也发生了改变后必须调用`resize()`方法,否则会造成一些功能异常) |
|
||||
@@ -32,15 +34,10 @@ const mindMap = new MindMap({
|
||||
| themeConfig | Object | {} | 主题配置,会和所选择的主题进行合并,可用字段可参考:[default.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js) |
|
||||
| scaleRatio | Number | 0.1 | 放大缩小的增量比例 |
|
||||
| maxTag | Number | 5 | 节点里最多显示的标签数量,多余的会被丢弃 |
|
||||
| exportPadding | Number | 20 | 导出图片时的内边距 |
|
||||
| imgTextMargin | Number | 5 | 节点里图片和文字的间距 |
|
||||
| textContentMargin | Number | 2 | 节点里各种文字信息的间距,如图标和文字的间距 |
|
||||
| selectTranslateStep | Number | 3 | 多选节点时鼠标移动到边缘时的画布移动偏移量 |
|
||||
| selectTranslateLimit | Number | 20 | 多选节点时鼠标移动距边缘多少距离时开始偏移 |
|
||||
| customNoteContentShow(v0.1.6+) | Object | null | 自定义节点备注内容显示,Object类型,结构为:{show: (noteContent, left, top, node) => {// 你的显示节点备注逻辑。node为v0.8.1+版本新增的回参,代表节点实例 }, hide: () => {// 你的隐藏节点备注逻辑 }} |
|
||||
| readonly(v0.1.7+) | Boolean | false | 是否是只读模式 |
|
||||
| enableFreeDrag(v0.2.4+) | Boolean | false | 是否开启节点自由拖拽(自由拖拽即可以把节点拖拽到画布的任意位置,注意不是拖拽节点成为其他节点的子节点兄弟节点的功能,自由拖拽的连线会存在一定问题,所以该特性最好不要使用) |
|
||||
| watermarkConfig(v0.2.4+) | Object | | 水印配置,详细配置请参考下方表格【水印配置】 |
|
||||
| textAutoWrapWidth(v0.3.4+) | Number | 500 | 节点内每行文本达到该宽度后自动换行 |
|
||||
| customHandleMousewheel(v0.4.3+) | Function | null | 自定义鼠标滚轮事件处理,可以传一个函数,回调参数为事件对象 |
|
||||
| mousewheelAction(v0.4.3+) | String | zoom(v0.9.1+默认改为move) | 鼠标滚轮的行为,`zoom`(放大缩小)、`move`(上下移动)。如果`customHandleMousewheel`传了自定义函数,这个属性不生效 |
|
||||
@@ -56,8 +53,6 @@ const mindMap = new MindMap({
|
||||
| enableNodeTransitionMove(v0.5.1+)(v0.6.7+已去除该特性) | Boolean | true | 是否开启节点动画过渡 |
|
||||
| nodeTransitionMoveDuration(v0.5.1+)(v0.6.7+已去除该特性) | Number | 300 | 如果开启节点动画过渡,可以通过该属性设置过渡的时间,单位ms |
|
||||
| initRootNodePosition(v0.5.3+) | Array | null | 初始根节点的位置,可传一个数组,默认为`['center', 'center']`,代表根节点处于画布中心位置,除了`center`,关键词还可以设置`left`、`top`、`right`、`bottom`,除了可以传关键词,数组的每项还可以传递一个数字,代表具体的像素,可以传递一个百分比字符串,比如`['40%', '60%']`,代表水平位置在画布宽度的`40%`的位置,垂直位置在画布高度的`60%`的位置 |
|
||||
| exportPaddingX(v0.5.5+) | Number | 10 | 导出png、svg、pdf时的图形水平内边距 |
|
||||
| exportPaddingY(v0.5.5+) | Number | 10 | 导出png、svg、pdf时的图形垂直内边距 |
|
||||
| nodeTextEditZIndex(v0.5.5+) | Number | 3000 | 节点文本编辑框元素的z-index |
|
||||
| nodeNoteTooltipZIndex(v0.5.5+) | Number | 3000 | 节点备注浮层元素的z-index |
|
||||
| isEndNodeTextEditOnClickOuter(v0.5.5+) | Boolean | true | 是否在点击了画布外的区域时结束节点文本的编辑状态 |
|
||||
@@ -65,7 +60,6 @@ const mindMap = new MindMap({
|
||||
| alwaysShowExpandBtn(v0.5.8+) | Boolean | false | 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示 |
|
||||
| iconList(v0.5.8+) | Array | [] | 扩展节点可插入的图标,数组的每一项为一个对象,对象详细结构请参考下方【图标配置】表格 |
|
||||
| maxNodeCacheCount(v0.5.10+) | Number | 1000 | 节点最大缓存数量。为了优化性能,内部会维护一个节点缓存池,用来复用节点,通过该属性可以指定池的最大缓存数量 |
|
||||
| defaultAssociativeLineText(v0.5.11+) | String | 关联 | 关联线默认文字 |
|
||||
| fitPadding(v0.6.0+) | Number | 50 | 思维导图适应画布大小时的内边距,单位:px |
|
||||
| enableCtrlKeyNodeSelection(v0.6.0+) | Boolean | true | 是否开启按住ctrl键多选节点的功能 |
|
||||
| useLeftKeySelectionRightKeyDrag(v0.6.0+) | Boolean | false | 设置为左键多选节点,右键拖动画布 |
|
||||
@@ -74,55 +68,36 @@ const mindMap = new MindMap({
|
||||
| customCreateNodeContent(v0.6.3+) | Function/null | null | 如果`isUseCustomNodeContent`设为`true`,那么需要使用该选项传入一个方法,接收节点实例`node`为参数(如果要获取该节点的数据,可以通过`node.nodeData.data`),需要返回自定义节点内容元素,也就是DOM节点,如果某个节点不需要自定义,那么返回`null`即可 |
|
||||
| mouseScaleCenterUseMousePosition(v0.6.4-fix.1+) | Boolean | true | 鼠标缩放是否以鼠标当前位置为中心点,否则以画布中心点 |
|
||||
| customInnerElsAppendTo(v0.6.12+) | null/HTMLElement | null | 指定内部一些元素(节点文本编辑元素、节点备注显示元素、关联线文本编辑元素、节点图片调整按钮元素)添加到的位置,默认添加到document.body下 |
|
||||
| nodeDragPlaceholderMaxSize(v0.6.12+) | Number | 20 | 拖拽元素时,指示元素新位置的块的最大高度 |
|
||||
| enableCreateHiddenInput(v0.6.13+)(v0.6.14+版本已去除该特性) | Boolean | true | 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态 |
|
||||
| enableAutoEnterTextEditWhenKeydown(v0.6.13+) | Boolean | true | 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式 |
|
||||
| richTextEditFakeInPlace(v0.6.13+) | Boolean | false | 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果 |
|
||||
| customHandleClipboardText(v0.6.14+) | Function | null | 自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片,默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据,如果你想处理其他思维导图的数据,比如processon、zhixi等,那么可以传递一个函数,接受当前剪贴板中的文本为参数,返回处理后的数据,可以返回两种类型:1.返回一个纯文本,那么会直接以该文本创建一个子节点;2.返回一个节点对象,格式如下:{ simpleMindMap: true, data: { data: { text: '' }, children: [] } },代表是simple-mind-map格式的数据,节点数据同simple-mind-map节点数据格式,如果你的处理逻辑存在异步逻辑,也可以返回一个promise |
|
||||
| errorHandler(v0.6.15+) | Function | | 自定义错误处理函数,目前只会抛出一些异步逻辑出错的情况。可以传递一个函数,会接收两个参数,第一个为错误的类型,第二个为错误对象 |
|
||||
| disableMouseWheelZoom(v0.6.15+) | Boolean | false | 禁止鼠标滚轮缩放,你仍旧可以使用api进行缩放 |
|
||||
| resetCss(v0.6.16+) | String | * { margin: 0; padding: 0; box-sizing: border-box; } | 设置导出图片和svg时,针对富文本节点内容,也就是嵌入到svg中的html节点的默认样式覆盖,如果不覆盖,节点内容会发生偏移 |
|
||||
| enableDblclickReset(v0.6.17+)(v0.8.0+已删除该属性) | Boolean | true(v0.7.0+改为false) | 开启鼠标双击复位思维导图位置及缩放 |
|
||||
| enableDblclickBackToRootNode(v0.8.0+) | Boolean | false | 是否在鼠标双击时回到根节点,也就是让根节点居中显示 |
|
||||
| minExportImgCanvasScale(v0.7.0+) | Number | 2 | 导出图片和pdf时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值,用于提升图片清晰度 |
|
||||
| hoverRectColor(v0.7.0+) | String | rgb(94, 200, 248) | 节点鼠标hover和激活时显示的矩形边框颜色,hover时会添加0.6的透明度 |
|
||||
| hoverRectPadding(v0.7.0+) | Number | 2 | 节点鼠标hover和激活时显示的矩形边框距节点内容的距离 |
|
||||
| selectTextOnEnterEditText(v0.7.0+) | Boolean | true | 双击节点进入节点文本编辑时是否默认选中文本,默认只在创建新节点时会选中 |
|
||||
| deleteNodeActive(v0.7.1+) | Boolean | true | 是否开启删除节点后自动激活节点相邻节点或父节点的功能 |
|
||||
| autoMoveWhenMouseInEdgeOnDrag(v0.7.1+) | Boolean | true | 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动 |
|
||||
| fit(v0.7.1-fix.2+) | Boolean | false | 首次渲染时是否缩放至适应画布大小 |
|
||||
| dragMultiNodeRectConfig(v0.7.2+) | Object | { width: 40, height: 20, fill: '' } | 拖拽多个节点时随鼠标移动的示意矩形的样式配置,传递一个对象,字段含义分别为矩形的宽、高、填充色 |
|
||||
| dragPlaceholderRectFill(v0.7.2+) | String | | 节点拖拽时新位置的示意矩形的填充颜色,如果不传默认使用连线的颜色 |
|
||||
| dragOpacityConfig(v0.7.2+) | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | 节点拖拽时的透明度配置,传递一个对象,字段含义分别为:跟随鼠标移动的克隆节点或矩形的透明度、被拖拽节点的透明度 |
|
||||
| tagsColorMap(v0.7.2+) | Object | {} | 自定义节点标签的颜色,可传一个对象,key为要指定颜色的标签内容,value为该标签内容的颜色,如果不传内部会根据标签内容生成对应的颜色 |
|
||||
| cooperateStyle(v0.7.3+) | Object | { avatarSize: 22, fontSize: 12 } | 节点协作编辑时的人员头像样式配置,字段含义分别为:头像大小、如果是文字头像,那么文字的大小 |
|
||||
| associativeLineIsAlwaysAboveNode(v0.8.0+) | Boolean | true | 关联线是否始终显示在节点上层,如果设为false,那么创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方 |
|
||||
| onlyOneEnableActiveNodeOnCooperate(v0.9.8+) | Boolean | false | 协同编辑时,同一个节点不能同时被多人选中 |
|
||||
| defaultGeneralizationText(v0.8.0+) | String | 概要 | 插入概要的默认文本 |
|
||||
| handleIsSplitByWrapOnPasteCreateNewNode(v0.8.0+) | Function / null | null | 粘贴文本的方式创建新节点时,控制是否按换行自动分割节点,即如果存在换行,那么会根据换行创建多个节点,否则只会创建一个节点,可以传递一个函数,返回promise,resolve代表根据换行分割,reject代表忽略换行 |
|
||||
| addHistoryTime(v0.8.0+) | Number | 100 | 指定时间内只允许添加一次历史记录,避免添加没有必要的中间状态,单位:ms |
|
||||
| isDisableDrag(v0.8.1+) | Boolean | false | 是否禁止拖动画布 |
|
||||
| disableTouchZoom(v0.8.1+) | Boolean | false | 禁止双指缩放,你仍旧可以使用api进行缩放,对TouchEvent插件生效 |
|
||||
| highlightNodeBoxStyle(v0.9.0+) | Object | { stroke: 'rgb(94, 200, 248)', fill: 'transparent' } | 鼠标移入概要高亮所属节点时的高亮框样式 |
|
||||
| createNewNodeBehavior(v0.9.1+) | String | default | 创建新节点时的行为。default(默认会激活新创建的节点,并且进入编辑模式。如果同时创建了多个新节点,那么只会激活而不会进入编辑模式)、notActive(不激活新创建的节点)、activeOnly(只激活新创建的节点,不进入编辑模式) |
|
||||
| defaultNodeImage(v0.9.1-fix.2+) | String | | 图片地址,当节点图片加载失败时显示的默认图片 |
|
||||
| handleNodePasteImg(v0.9.2+) | null 或 Function | null | 在节点上粘贴剪贴板中的图片的处理方法,默认是转换为data:url数据插入到节点中,你可以通过该方法来将图片数据上传到服务器,实现保存图片的url。可以传递一个异步方法,接收Blob类型的图片数据,需要返回指定结构:{ url, size: {width, height} } |
|
||||
| isLimitMindMapInCanvas(v0.9.2+) | Boolean | false | 是否将思维导图限制在画布内。比如向右拖动时,思维导图图形的最左侧到达画布中心时将无法继续向右拖动,其他同理 |
|
||||
| isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+) | Boolean | true | 当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas配置不再起作用 |
|
||||
| associativeLineInitPointsPosition(v0.9.5+) | null / { from, to } | { from: '', to: '' } | 默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个选项来配置。from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算。from和to可选值:left、top、bottom、right |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | 是否允许调整关联线两个端点的位置 |
|
||||
| isOnlySearchCurrentRenderNodes(v0.9.8+) | Boolean | false | 是否仅搜索当前渲染的节点,被收起的节点不会被搜索到 |
|
||||
| onlyOneEnableActiveNodeOnCooperate(v0.9.8+) | Boolean | false | 协同编辑时,同一个节点不能同时被多人选中 |
|
||||
| beforeCooperateUpdate(v0.9.8+) | Function、null | null | 协同编辑时,节点操作即将更新到其他客户端前的生命周期函数。函数接收一个对象作为参数:{ type: 【createOrUpdate(创建节点或更新节点)、delete(删除节点)】, list: 【数组类型,1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据】 } |
|
||||
| beforeShortcutRun(v0.9.9+) | Function、null | null | 快捷键操作即将执行前的生命周期函数,返回true可以阻止操作执行。函数接收两个参数:key(快捷键)、activeNodeList(当前激活的节点列表) |
|
||||
| rainbowLinesConfig(v0.9.9+) | Object | { open: false, colorsList: [] } | 彩虹线条配置,需要先注册RainbowLines插件。对象类型,结构:{ open: false【是否开启彩虹线条】, colorsList: []【自定义彩虹线条的颜色列表,如果不设置,会使用默认颜色列表】 } |
|
||||
| addContentToHeader(v0.9.9+) | Function、null | null | 导出png、svg、pdf时在头部添加自定义内容。可传递一个函数,这个函数可以返回null代表不添加内容,也可以返回一个对象,详细介绍请参考下方【导出时如何添加自定义内容】 |
|
||||
| addContentToFooter(v0.9.9+) | Function、null | null | 基本释义同addContentToHeader,在尾部添加自定义内容 |
|
||||
| demonstrateConfig(v0.9.11+) | Object、null | null | 演示插件Demonstrate的配置。不传则使用默认配置,可传递一个对象,如果只配置某个属性,可以只设置该属性,其他没有设置的同样会使用默认配置,完整配置请参考下方【演示插件配置】小节 |
|
||||
| resetScaleOnMoveNodeToCenter(v0.9.12+) | Boolean | false | 移动节点到画布中心、回到根节点等操作时是否将缩放层级复位为100%(底层影响的是render类的moveNodeToCenter方法) |
|
||||
| createNodePrefixContent(v0.9.12+) | Function、null | null | 添加附加的节点前置内容。前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分。可以传递一个函数,这个函数接收一个节点实例的参数,可以返回一个DOM节点,也可以返回null |
|
||||
| createNodePostfixContent(v0.9.12+) | Function、null | null | 添加附加的节点后置内容。后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分。可以传递一个函数,这个函数接收一个节点实例的参数,可以返回一个DOM节点,也可以返回null |
|
||||
| createNodePrefixContent(v0.9.12+) | Function、null | null | 添加附加的节点前置内容。前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分。可以传递一个函数,这个函数接收一个节点实例的参数,可以返回{el, width, height}格式的对象,el为DOM节点对象,width和height代表内容的宽高,数字类型,如果不需要自定义内容,也可以返回null |
|
||||
| createNodePostfixContent(v0.9.12+) | Function、null | null | 添加附加的节点后置内容。后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分。用法同createNodePrefixContent |
|
||||
|
||||
### 数据结构
|
||||
#### 1.1数据结构
|
||||
|
||||
基本的数据结构如下:
|
||||
|
||||
@@ -167,18 +142,7 @@ const mindMap = new MindMap({
|
||||
|
||||
如果你要添加自定义的字段,可以添加到`data`、`children`同级,如果你要添加到`data`对象里,那么请使用`_`开头来命名你的自定义字段,内部会通过这个来判断是否是自定义字段。
|
||||
|
||||
### 水印配置
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
|
||||
| text | String | '' | 水印文字,如果为空字符串则不显示水印 |
|
||||
| lineSpacing | Number | 100 | 水印每行之间的间距 |
|
||||
| textSpacing | Number | 100 | 同一行水印之间的间距 |
|
||||
| angle | Number | 30 | 水印的倾斜角度,范围:[0, 90] |
|
||||
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | 水印文字样式 |
|
||||
| onlyExport(v0.9.2+) | Boolean | false | 是否仅在导出时添加水印 |
|
||||
|
||||
### 图标配置
|
||||
#### 1.2图标配置
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
|
||||
@@ -186,7 +150,20 @@ const mindMap = new MindMap({
|
||||
| type | String | | 图标分组的值 |
|
||||
| list | Array | | 分组下的图标列表,数组的每一项为一个对象,`{ name: '', icon: '' }`,`name`代表图标的名称,`icon`代表图标,可以是`svg`图标,比如`<svg ...><path></path></svg>`,也可以是图片`url`,或者是`base64`图标,比如`data:image/png;base64,...` |
|
||||
|
||||
### 导出时如何添加自定义内容
|
||||
|
||||
### 2.Export插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| exportPadding(已废除) | Number | 20 | 导出图片时的内边距 |
|
||||
| exportPaddingX(v0.5.5+) | Number | 10 | 导出png、svg、pdf时的图形水平内边距 |
|
||||
| exportPaddingY(v0.5.5+) | Number | 10 | 导出png、svg、pdf时的图形垂直内边距 |
|
||||
| resetCss(v0.6.16+) | String | * { margin: 0; padding: 0; box-sizing: border-box; } | 设置导出图片和svg时,针对富文本节点内容,也就是嵌入到svg中的html节点的默认样式覆盖,如果不覆盖,节点内容会发生偏移 |
|
||||
| minExportImgCanvasScale(v0.7.0+) | Number | 2 | 导出图片和pdf时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值,用于提升图片清晰度 |
|
||||
| addContentToHeader(v0.9.9+) | Function、null | null | 导出png、svg、pdf时在头部添加自定义内容。可传递一个函数,这个函数可以返回null代表不添加内容,也可以返回一个对象,详细介绍请参考下方【导出时如何添加自定义内容】 |
|
||||
| addContentToFooter(v0.9.9+) | Function、null | null | 基本释义同addContentToHeader,在尾部添加自定义内容 |
|
||||
|
||||
#### 2.1导出时如何添加自定义内容
|
||||
|
||||
`addContentToHeader`和`addContentToFooter`两个实例化选项可以用于在导出`png`、`svg`、`pdf`时在头部和尾部添加自定义的内容,默认为`null`,代表不配置,可以传递一个函数,函数可以返回`null`,代表不添加内容,如果要添加内容那么需要返回如下的结构:
|
||||
|
||||
@@ -221,7 +198,98 @@ new MindMap({
|
||||
})
|
||||
```
|
||||
|
||||
### 演示插件配置
|
||||
### 3.Select插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| selectTranslateStep | Number | 3 | 多选节点时鼠标移动到边缘时的画布移动偏移量 |
|
||||
| selectTranslateLimit | Number | 20 | 多选节点时鼠标移动距边缘多少距离时开始偏移 |
|
||||
|
||||
### 4.Drag插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| enableFreeDrag(v0.2.4+) | Boolean | false | 是否开启节点自由拖拽(自由拖拽即可以把节点拖拽到画布的任意位置,注意不是拖拽节点成为其他节点的子节点兄弟节点的功能,自由拖拽的连线会存在一定问题,所以该特性最好不要使用) |
|
||||
| nodeDragPlaceholderMaxSize(v0.6.12+)(v0.10.0+已废除) | Number | 20 | 拖拽元素时,指示元素新位置的块的最大高度 |
|
||||
| autoMoveWhenMouseInEdgeOnDrag(v0.7.1+) | Boolean | true | 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动 |
|
||||
| dragMultiNodeRectConfig(v0.7.2+) | Object | { width: 40, height: 20, fill: 'rgb(94, 200, 248)' } | 拖拽多个节点时随鼠标移动的示意矩形的样式配置,传递一个对象,字段含义分别为矩形的宽、高、填充色 |
|
||||
| dragPlaceholderRectFill(v0.7.2+) | String | rgb(94, 200, 248) | 节点拖拽时新位置的示意矩形的填充颜色 |
|
||||
| dragPlaceholderLineConfig(v0.10.0+) | Object | { color: 'rgb(94, 200, 248)', width: 2 } | 节点拖拽时新位置的示意连线的样式配置 |
|
||||
| dragOpacityConfig(v0.7.2+) | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | 节点拖拽时的透明度配置,传递一个对象,字段含义分别为:跟随鼠标移动的克隆节点或矩形的透明度、被拖拽节点的透明度 |
|
||||
|
||||
### 5.Watermark插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| watermarkConfig(v0.2.4+) | Object | | 水印配置,详细配置请参考下方表格【水印配置】 |
|
||||
|
||||
#### 5.1水印配置
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
|
||||
| text | String | '' | 水印文字,如果为空字符串则不显示水印 |
|
||||
| lineSpacing | Number | 100 | 水印每行之间的间距 |
|
||||
| textSpacing | Number | 100 | 同一行水印之间的间距 |
|
||||
| angle | Number | 30 | 水印的倾斜角度,范围:[0, 90] |
|
||||
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | 水印文字样式 |
|
||||
| onlyExport(v0.9.2+) | Boolean | false | 是否仅在导出时添加水印 |
|
||||
| belowNode(v0.10.0+) | Boolean | false | 水印是否显示在节点下方 |
|
||||
|
||||
### 6.AssociativeLine插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| defaultAssociativeLineText(v0.5.11+) | String | 关联 | 关联线默认文字 |
|
||||
| associativeLineIsAlwaysAboveNode(v0.8.0+) | Boolean | true | 关联线是否始终显示在节点上层,如果设为false,那么创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方 |
|
||||
| associativeLineInitPointsPosition(v0.9.5+) | null / { from, to } | { from: '', to: '' } | 默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个选项来配置。from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算。from和to可选值:left、top、bottom、right |
|
||||
| enableAdjustAssociativeLinePoints(v0.9.5+) | Boolean | true | 是否允许调整关联线两个端点的位置 |
|
||||
|
||||
### 7.RichText插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| richTextEditFakeInPlace(v0.6.13+) | Boolean | false | 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果 |
|
||||
| enableEditFormulaInRichTextEdit(v0.10.0+) | Boolean | true | 是否开启在富文本编辑框中直接编辑数学公式 |
|
||||
| transformRichTextOnEnterEdit(v0.10.0+) | null、Function | null | 转换富文本内容,可以传递一个函数,当进入富文本编辑时会调用该函数,函数接收即将被编辑的富文本内容,需要返回你处理后的富文本内容 |
|
||||
| beforeHideRichTextEdit(v0.10.0+) | null、Function | null | 可以传递一个函数,即将结束富文本编辑前会执行该函数,函数接收richText实例,所以你可以在此时机更新quill文档数据 |
|
||||
|
||||
### 8.TouchEvent插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| disableTouchZoom(v0.8.1+) | Boolean | false | 禁止双指缩放,你仍旧可以使用api进行缩放,对TouchEvent插件生效 |
|
||||
|
||||
### 9.Scrollbar插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+) | Boolean | true | 当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas配置不再起作用 |
|
||||
|
||||
### 10.Search插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| isOnlySearchCurrentRenderNodes(v0.9.8+) | Boolean | false | 是否仅搜索当前渲染的节点,被收起的节点不会被搜索到 |
|
||||
|
||||
### 11.Cooperate插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| beforeCooperateUpdate(v0.9.8+) | Function、null | null | 协同编辑时,节点操作即将更新到其他客户端前的生命周期函数。函数接收一个对象作为参数:{ type: 【createOrUpdate(创建节点或更新节点)、delete(删除节点)】, list: 【数组类型,1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据】 } |
|
||||
|
||||
### 12.RainbowLines插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| rainbowLinesConfig(v0.9.9+) | Object | { open: false, colorsList: [] } | 彩虹线条配置,需要先注册RainbowLines插件。对象类型,结构:{ open: false【是否开启彩虹线条】, colorsList: []【自定义彩虹线条的颜色列表,如果不设置,会使用默认颜色列表】 } |
|
||||
|
||||
### 13.Demonstrate插件
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
|
||||
| demonstrateConfig(v0.9.11+) | Object、null | null | 演示插件Demonstrate的配置。不传则使用默认配置,可传递一个对象,如果只配置某个属性,可以只设置该属性,其他没有设置的同样会使用默认配置,完整配置请参考下方【演示插件配置】小节 |
|
||||
|
||||
#### 13.1演示插件配置
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 |
|
||||
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
|
||||
@@ -484,7 +552,8 @@ mindMap.setTheme('主题名称')
|
||||
| node_img_mouseenter(v0.6.5+) | 节点内图片的鼠标移入事件 | this(节点实例)、imgNode(图片节点)、e(事件对象) |
|
||||
| node_img_mouseleave(v0.6.5+) | 节点内图片的鼠标移出事件 | this(节点实例)、imgNode(图片节点)、e(事件对象) |
|
||||
| node_img_mousemove(v0.6.5+) | 节点内图片的鼠标移动事件 | this(节点实例)、imgNode(图片节点)、e(事件对象) |
|
||||
| node_tree_render_end(v0.2.16+) | 节点树渲染完毕事件 | |
|
||||
| node_tree_render_end(v0.2.16+) | 节点树渲染完毕事件 | |
|
||||
| node_tree_render_start(v0.10.0+) | 节点树开始渲染事件 | |
|
||||
| rich_text_selection_change(v0.4.0+) | 当注册了`RichText`插件时可用。当节点编辑时,文本选区发生改变时触发 | hasRange(是否存在选区)、rectInfo(选区的尺寸和位置信息)、formatInfo(选区的文本格式化信息) |
|
||||
| transforming-dom-to-images(v0.4.0+) | 当注册了`RichText`插件时可用。当`svg`中存在`DOM`节点时,导出为图片时会将`DOM`节点转换为图片,转换过程中会触发该事件,可用通过该事件给用户提示,告知目前转换到的节点 | index(当前转换到的节点索引)、len(一共需要转换的节点数量) |
|
||||
| node_dragging(v0.4.5+) | 当某个节点被拖拽时触发 | node(当前被拖拽的节点) |
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
});
|
||||
</code></pre>
|
||||
<h2>实例化选项</h2>
|
||||
<h3>1.基本</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -76,12 +77,6 @@
|
||||
<td>节点里最多显示的标签数量,多余的会被丢弃</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPadding</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>导出图片时的内边距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>imgTextMargin</td>
|
||||
<td>Number</td>
|
||||
<td>5</td>
|
||||
@@ -94,18 +89,6 @@
|
||||
<td>节点里各种文字信息的间距,如图标和文字的间距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectTranslateStep</td>
|
||||
<td>Number</td>
|
||||
<td>3</td>
|
||||
<td>多选节点时鼠标移动到边缘时的画布移动偏移量</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectTranslateLimit</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>多选节点时鼠标移动距边缘多少距离时开始偏移</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>customNoteContentShow(v0.1.6+)</td>
|
||||
<td>Object</td>
|
||||
<td>null</td>
|
||||
@@ -118,18 +101,6 @@
|
||||
<td>是否是只读模式</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableFreeDrag(v0.2.4+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否开启节点自由拖拽(自由拖拽即可以把节点拖拽到画布的任意位置,注意不是拖拽节点成为其他节点的子节点兄弟节点的功能,自由拖拽的连线会存在一定问题,所以该特性最好不要使用)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>watermarkConfig(v0.2.4+)</td>
|
||||
<td>Object</td>
|
||||
<td></td>
|
||||
<td>水印配置,详细配置请参考下方表格【水印配置】</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>textAutoWrapWidth(v0.3.4+)</td>
|
||||
<td>Number</td>
|
||||
<td>500</td>
|
||||
@@ -220,18 +191,6 @@
|
||||
<td>初始根节点的位置,可传一个数组,默认为<code>['center', 'center']</code>,代表根节点处于画布中心位置,除了<code>center</code>,关键词还可以设置<code>left</code>、<code>top</code>、<code>right</code>、<code>bottom</code>,除了可以传关键词,数组的每项还可以传递一个数字,代表具体的像素,可以传递一个百分比字符串,比如<code>['40%', '60%']</code>,代表水平位置在画布宽度的<code>40%</code>的位置,垂直位置在画布高度的<code>60%</code>的位置</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingX(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>导出png、svg、pdf时的图形水平内边距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingY(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>导出png、svg、pdf时的图形垂直内边距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeTextEditZIndex(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>3000</td>
|
||||
@@ -274,12 +233,6 @@
|
||||
<td>节点最大缓存数量。为了优化性能,内部会维护一个节点缓存池,用来复用节点,通过该属性可以指定池的最大缓存数量</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultAssociativeLineText(v0.5.11+)</td>
|
||||
<td>String</td>
|
||||
<td>关联</td>
|
||||
<td>关联线默认文字</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>fitPadding(v0.6.0+)</td>
|
||||
<td>Number</td>
|
||||
<td>50</td>
|
||||
@@ -328,12 +281,6 @@
|
||||
<td>指定内部一些元素(节点文本编辑元素、节点备注显示元素、关联线文本编辑元素、节点图片调整按钮元素)添加到的位置,默认添加到document.body下</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeDragPlaceholderMaxSize(v0.6.12+)</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>拖拽元素时,指示元素新位置的块的最大高度</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableCreateHiddenInput(v0.6.13+)(v0.6.14+版本已去除该特性)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
@@ -346,12 +293,6 @@
|
||||
<td>是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>richTextEditFakeInPlace(v0.6.13+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>customHandleClipboardText(v0.6.14+)</td>
|
||||
<td>Function</td>
|
||||
<td>null</td>
|
||||
@@ -370,12 +311,6 @@
|
||||
<td>禁止鼠标滚轮缩放,你仍旧可以使用api进行缩放</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resetCss(v0.6.16+)</td>
|
||||
<td>String</td>
|
||||
<td>* { margin: 0; padding: 0; box-sizing: border-box; }</td>
|
||||
<td>设置导出图片和svg时,针对富文本节点内容,也就是嵌入到svg中的html节点的默认样式覆盖,如果不覆盖,节点内容会发生偏移</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableDblclickReset(v0.6.17+)(v0.8.0+已删除该属性)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true(v0.7.0+改为false)</td>
|
||||
@@ -388,12 +323,6 @@
|
||||
<td>是否在鼠标双击时回到根节点,也就是让根节点居中显示</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>minExportImgCanvasScale(v0.7.0+)</td>
|
||||
<td>Number</td>
|
||||
<td>2</td>
|
||||
<td>导出图片和pdf时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值,用于提升图片清晰度</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hoverRectColor(v0.7.0+)</td>
|
||||
<td>String</td>
|
||||
<td>rgb(94, 200, 248)</td>
|
||||
@@ -418,36 +347,12 @@
|
||||
<td>是否开启删除节点后自动激活节点相邻节点或父节点的功能</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>autoMoveWhenMouseInEdgeOnDrag(v0.7.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>拖拽节点时鼠标移动到画布边缘是否开启画布自动移动</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>fit(v0.7.1-fix.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>首次渲染时是否缩放至适应画布大小</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragMultiNodeRectConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ width: 40, height: 20, fill: '' }</td>
|
||||
<td>拖拽多个节点时随鼠标移动的示意矩形的样式配置,传递一个对象,字段含义分别为矩形的宽、高、填充色</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderRectFill(v0.7.2+)</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>节点拖拽时新位置的示意矩形的填充颜色,如果不传默认使用连线的颜色</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragOpacityConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
|
||||
<td>节点拖拽时的透明度配置,传递一个对象,字段含义分别为:跟随鼠标移动的克隆节点或矩形的透明度、被拖拽节点的透明度</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>tagsColorMap(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{}</td>
|
||||
@@ -460,10 +365,10 @@
|
||||
<td>节点协作编辑时的人员头像样式配置,字段含义分别为:头像大小、如果是文字头像,那么文字的大小</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>associativeLineIsAlwaysAboveNode(v0.8.0+)</td>
|
||||
<td>onlyOneEnableActiveNodeOnCooperate(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>关联线是否始终显示在节点上层,如果设为false,那么创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方</td>
|
||||
<td>false</td>
|
||||
<td>协同编辑时,同一个节点不能同时被多人选中</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultGeneralizationText(v0.8.0+)</td>
|
||||
@@ -490,12 +395,6 @@
|
||||
<td>是否禁止拖动画布</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>disableTouchZoom(v0.8.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>禁止双指缩放,你仍旧可以使用api进行缩放,对TouchEvent插件生效</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>highlightNodeBoxStyle(v0.9.0+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ stroke: 'rgb(94, 200, 248)', fill: 'transparent' }</td>
|
||||
@@ -526,72 +425,12 @@
|
||||
<td>是否将思维导图限制在画布内。比如向右拖动时,思维导图图形的最左侧到达画布中心时将无法继续向右拖动,其他同理</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas配置不再起作用</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>associativeLineInitPointsPosition(v0.9.5+)</td>
|
||||
<td>null / { from, to }</td>
|
||||
<td>{ from: '', to: '' }</td>
|
||||
<td>默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个选项来配置。from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算。from和to可选值:left、top、bottom、right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableAdjustAssociativeLinePoints(v0.9.5+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>是否允许调整关联线两个端点的位置</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isOnlySearchCurrentRenderNodes(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否仅搜索当前渲染的节点,被收起的节点不会被搜索到</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onlyOneEnableActiveNodeOnCooperate(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>协同编辑时,同一个节点不能同时被多人选中</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeCooperateUpdate(v0.9.8+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>协同编辑时,节点操作即将更新到其他客户端前的生命周期函数。函数接收一个对象作为参数:{ type: 【createOrUpdate(创建节点或更新节点)、delete(删除节点)】, list: 【数组类型,1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据】 }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeShortcutRun(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>快捷键操作即将执行前的生命周期函数,返回true可以阻止操作执行。函数接收两个参数:key(快捷键)、activeNodeList(当前激活的节点列表)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rainbowLinesConfig(v0.9.9+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ open: false, colorsList: [] }</td>
|
||||
<td>彩虹线条配置,需要先注册RainbowLines插件。对象类型,结构:{ open: false【是否开启彩虹线条】, colorsList: []【自定义彩虹线条的颜色列表,如果不设置,会使用默认颜色列表】 }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToHeader(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>导出png、svg、pdf时在头部添加自定义内容。可传递一个函数,这个函数可以返回null代表不添加内容,也可以返回一个对象,详细介绍请参考下方【导出时如何添加自定义内容】</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToFooter(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>基本释义同addContentToHeader,在尾部添加自定义内容</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>demonstrateConfig(v0.9.11+)</td>
|
||||
<td>Object、null</td>
|
||||
<td>null</td>
|
||||
<td>演示插件Demonstrate的配置。不传则使用默认配置,可传递一个对象,如果只配置某个属性,可以只设置该属性,其他没有设置的同样会使用默认配置,完整配置请参考下方【演示插件配置】小节</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resetScaleOnMoveNodeToCenter(v0.9.12+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
@@ -601,17 +440,17 @@
|
||||
<td>createNodePrefixContent(v0.9.12+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>添加附加的节点前置内容。前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分。可以传递一个函数,这个函数接收一个节点实例的参数,可以返回一个DOM节点,也可以返回null</td>
|
||||
<td>添加附加的节点前置内容。前置内容指和文本同一行的区域中的前置内容,不包括节点图片部分。可以传递一个函数,这个函数接收一个节点实例的参数,可以返回{el, width, height}格式的对象,el为DOM节点对象,width和height代表内容的宽高,数字类型,如果不需要自定义内容,也可以返回null</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>createNodePostfixContent(v0.9.12+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>添加附加的节点后置内容。后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分。可以传递一个函数,这个函数接收一个节点实例的参数,可以返回一个DOM节点,也可以返回null</td>
|
||||
<td>添加附加的节点后置内容。后置内容指和文本同一行的区域中的后置内容,不包括节点图片部分。用法同createNodePrefixContent</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>数据结构</h3>
|
||||
<h4>1.1数据结构</h4>
|
||||
<p>基本的数据结构如下:</p>
|
||||
<pre class="hljs"><code>{
|
||||
<span class="hljs-attr">data</span>: {
|
||||
@@ -651,7 +490,220 @@
|
||||
}
|
||||
</code></pre>
|
||||
<p>如果你要添加自定义的字段,可以添加到<code>data</code>、<code>children</code>同级,如果你要添加到<code>data</code>对象里,那么请使用<code>_</code>开头来命名你的自定义字段,内部会通过这个来判断是否是自定义字段。</p>
|
||||
<h3>水印配置</h3>
|
||||
<h4>1.2图标配置</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>name</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>图标分组的名称</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>type</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>图标分组的值</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>list</td>
|
||||
<td>Array</td>
|
||||
<td></td>
|
||||
<td>分组下的图标列表,数组的每一项为一个对象,<code>{ name: '', icon: '' }</code>,<code>name</code>代表图标的名称,<code>icon</code>代表图标,可以是<code>svg</code>图标,比如<code><svg ...><path></path></svg></code>,也可以是图片<code>url</code>,或者是<code>base64</code>图标,比如<code>data:image/png;base64,...</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>2.Export插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>exportPadding(已废除)</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>导出图片时的内边距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingX(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>导出png、svg、pdf时的图形水平内边距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>exportPaddingY(v0.5.5+)</td>
|
||||
<td>Number</td>
|
||||
<td>10</td>
|
||||
<td>导出png、svg、pdf时的图形垂直内边距</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>resetCss(v0.6.16+)</td>
|
||||
<td>String</td>
|
||||
<td>* { margin: 0; padding: 0; box-sizing: border-box; }</td>
|
||||
<td>设置导出图片和svg时,针对富文本节点内容,也就是嵌入到svg中的html节点的默认样式覆盖,如果不覆盖,节点内容会发生偏移</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>minExportImgCanvasScale(v0.7.0+)</td>
|
||||
<td>Number</td>
|
||||
<td>2</td>
|
||||
<td>导出图片和pdf时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值,用于提升图片清晰度</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToHeader(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>导出png、svg、pdf时在头部添加自定义内容。可传递一个函数,这个函数可以返回null代表不添加内容,也可以返回一个对象,详细介绍请参考下方【导出时如何添加自定义内容】</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>addContentToFooter(v0.9.9+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>基本释义同addContentToHeader,在尾部添加自定义内容</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>2.1导出时如何添加自定义内容</h4>
|
||||
<p><code>addContentToHeader</code>和<code>addContentToFooter</code>两个实例化选项可以用于在导出<code>png</code>、<code>svg</code>、<code>pdf</code>时在头部和尾部添加自定义的内容,默认为<code>null</code>,代表不配置,可以传递一个函数,函数可以返回<code>null</code>,代表不添加内容,如果要添加内容那么需要返回如下的结构:</p>
|
||||
<pre class="hljs"><code>{
|
||||
el,// 要追加的自定义DOM节点,样式可内联
|
||||
cssText,// 可选,如果样式不想内联,可以传递该值,一个css字符串
|
||||
height: 50// 返回的DOM节点的高度,必须传递
|
||||
}
|
||||
</code></pre>
|
||||
<p>一个简单的示例:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">new</span> MindMap({
|
||||
<span class="hljs-attr">addContentToFooter</span>: <span class="hljs-function">() =></span> {
|
||||
<span class="hljs-keyword">const</span> el = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>)
|
||||
el.className = <span class="hljs-string">'footer'</span>
|
||||
el.innerHTML = <span class="hljs-string">'来自:simple-mind-map'</span>
|
||||
<span class="hljs-keyword">const</span> cssText = <span class="hljs-string">`
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
`</span>
|
||||
<span class="hljs-keyword">return</span> {
|
||||
el,
|
||||
cssText,
|
||||
<span class="hljs-attr">height</span>: <span class="hljs-number">30</span>
|
||||
}
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
<h3>3.Select插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>selectTranslateStep</td>
|
||||
<td>Number</td>
|
||||
<td>3</td>
|
||||
<td>多选节点时鼠标移动到边缘时的画布移动偏移量</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>selectTranslateLimit</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>多选节点时鼠标移动距边缘多少距离时开始偏移</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>4.Drag插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>enableFreeDrag(v0.2.4+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否开启节点自由拖拽(自由拖拽即可以把节点拖拽到画布的任意位置,注意不是拖拽节点成为其他节点的子节点兄弟节点的功能,自由拖拽的连线会存在一定问题,所以该特性最好不要使用)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeDragPlaceholderMaxSize(v0.6.12+)(v0.10.0+已废除)</td>
|
||||
<td>Number</td>
|
||||
<td>20</td>
|
||||
<td>拖拽元素时,指示元素新位置的块的最大高度</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>autoMoveWhenMouseInEdgeOnDrag(v0.7.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>拖拽节点时鼠标移动到画布边缘是否开启画布自动移动</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragMultiNodeRectConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ width: 40, height: 20, fill: 'rgb(94, 200, 248)' }</td>
|
||||
<td>拖拽多个节点时随鼠标移动的示意矩形的样式配置,传递一个对象,字段含义分别为矩形的宽、高、填充色</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderRectFill(v0.7.2+)</td>
|
||||
<td>String</td>
|
||||
<td>rgb(94, 200, 248)</td>
|
||||
<td>节点拖拽时新位置的示意矩形的填充颜色</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderLineConfig(v0.10.0+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ color: 'rgb(94, 200, 248)', width: 2 }</td>
|
||||
<td>节点拖拽时新位置的示意连线的样式配置</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragOpacityConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
|
||||
<td>节点拖拽时的透明度配置,传递一个对象,字段含义分别为:跟随鼠标移动的克隆节点或矩形的透明度、被拖拽节点的透明度</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>5.Watermark插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>watermarkConfig(v0.2.4+)</td>
|
||||
<td>Object</td>
|
||||
<td></td>
|
||||
<td>水印配置,详细配置请参考下方表格【水印配置】</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>5.1水印配置</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -698,9 +750,15 @@
|
||||
<td>false</td>
|
||||
<td>是否仅在导出时添加水印</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>belowNode(v0.10.0+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>水印是否显示在节点下方</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>图标配置</h3>
|
||||
<h3>6.AssociativeLine插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -712,54 +770,183 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>name</td>
|
||||
<td>defaultAssociativeLineText(v0.5.11+)</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>图标分组的名称</td>
|
||||
<td>关联</td>
|
||||
<td>关联线默认文字</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>type</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>图标分组的值</td>
|
||||
<td>associativeLineIsAlwaysAboveNode(v0.8.0+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>关联线是否始终显示在节点上层,如果设为false,那么创建关联线和激活关联线时处于最顶层,其他情况下处于节点下方</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>list</td>
|
||||
<td>Array</td>
|
||||
<td></td>
|
||||
<td>分组下的图标列表,数组的每一项为一个对象,<code>{ name: '', icon: '' }</code>,<code>name</code>代表图标的名称,<code>icon</code>代表图标,可以是<code>svg</code>图标,比如<code><svg ...><path></path></svg></code>,也可以是图片<code>url</code>,或者是<code>base64</code>图标,比如<code>data:image/png;base64,...</code></td>
|
||||
<td>associativeLineInitPointsPosition(v0.9.5+)</td>
|
||||
<td>null / { from, to }</td>
|
||||
<td>{ from: '', to: '' }</td>
|
||||
<td>默认情况下,新创建的关联线两个端点的位置是根据两个节点中心点的相对位置来计算的,如果你想固定位置,可以通过这个选项来配置。from和to都不传,则都自动计算,如果只传一个,另一个则会自动计算。from和to可选值:left、top、bottom、right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableAdjustAssociativeLinePoints(v0.9.5+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>是否允许调整关联线两个端点的位置</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>导出时如何添加自定义内容</h3>
|
||||
<p><code>addContentToHeader</code>和<code>addContentToFooter</code>两个实例化选项可以用于在导出<code>png</code>、<code>svg</code>、<code>pdf</code>时在头部和尾部添加自定义的内容,默认为<code>null</code>,代表不配置,可以传递一个函数,函数可以返回<code>null</code>,代表不添加内容,如果要添加内容那么需要返回如下的结构:</p>
|
||||
<pre class="hljs"><code>{
|
||||
el,// 要追加的自定义DOM节点,样式可内联
|
||||
cssText,// 可选,如果样式不想内联,可以传递该值,一个css字符串
|
||||
height: 50// 返回的DOM节点的高度,必须传递
|
||||
}
|
||||
</code></pre>
|
||||
<p>一个简单的示例:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">new</span> MindMap({
|
||||
<span class="hljs-attr">addContentToFooter</span>: <span class="hljs-function">() =></span> {
|
||||
<span class="hljs-keyword">const</span> el = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'div'</span>)
|
||||
el.className = <span class="hljs-string">'footer'</span>
|
||||
el.innerHTML = <span class="hljs-string">'来自:simple-mind-map'</span>
|
||||
<span class="hljs-keyword">const</span> cssText = <span class="hljs-string">`
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
`</span>
|
||||
<span class="hljs-keyword">return</span> {
|
||||
el,
|
||||
cssText,
|
||||
<span class="hljs-attr">height</span>: <span class="hljs-number">30</span>
|
||||
}
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
<h3>演示插件配置</h3>
|
||||
<h3>7.RichText插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>richTextEditFakeInPlace(v0.6.13+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableEditFormulaInRichTextEdit(v0.10.0+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>是否开启在富文本编辑框中直接编辑数学公式</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>transformRichTextOnEnterEdit(v0.10.0+)</td>
|
||||
<td>null、Function</td>
|
||||
<td>null</td>
|
||||
<td>转换富文本内容,可以传递一个函数,当进入富文本编辑时会调用该函数,函数接收即将被编辑的富文本内容,需要返回你处理后的富文本内容</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>beforeHideRichTextEdit(v0.10.0+)</td>
|
||||
<td>null、Function</td>
|
||||
<td>null</td>
|
||||
<td>可以传递一个函数,即将结束富文本编辑前会执行该函数,函数接收richText实例,所以你可以在此时机更新quill文档数据</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>8.TouchEvent插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>disableTouchZoom(v0.8.1+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>禁止双指缩放,你仍旧可以使用api进行缩放,对TouchEvent插件生效</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>9.Scrollbar插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas配置不再起作用</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>10.Search插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>isOnlySearchCurrentRenderNodes(v0.9.8+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否仅搜索当前渲染的节点,被收起的节点不会被搜索到</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>11.Cooperate插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>beforeCooperateUpdate(v0.9.8+)</td>
|
||||
<td>Function、null</td>
|
||||
<td>null</td>
|
||||
<td>协同编辑时,节点操作即将更新到其他客户端前的生命周期函数。函数接收一个对象作为参数:{ type: 【createOrUpdate(创建节点或更新节点)、delete(删除节点)】, list: 【数组类型,1.当type=createOrUpdate时,代表被创建或被更新的节点数据,即将同步到其他客户端,所以你可以修改该数据;2.当type=delete时,代表被删除的节点数据】 }</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>12.RainbowLines插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>rainbowLinesConfig(v0.9.9+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ open: false, colorsList: [] }</td>
|
||||
<td>彩虹线条配置,需要先注册RainbowLines插件。对象类型,结构:{ open: false【是否开启彩虹线条】, colorsList: []【自定义彩虹线条的颜色列表,如果不设置,会使用默认颜色列表】 }</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>13.Demonstrate插件</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>字段名称</th>
|
||||
<th>类型</th>
|
||||
<th>默认值</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>demonstrateConfig(v0.9.11+)</td>
|
||||
<td>Object、null</td>
|
||||
<td>null</td>
|
||||
<td>演示插件Demonstrate的配置。不传则使用默认配置,可传递一个对象,如果只配置某个属性,可以只设置该属性,其他没有设置的同样会使用默认配置,完整配置请参考下方【演示插件配置】小节</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4>13.1演示插件配置</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -1129,6 +1316,11 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>node_tree_render_start(v0.10.0+)</td>
|
||||
<td>节点树开始渲染事件</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>rich_text_selection_change(v0.4.0+)</td>
|
||||
<td>当注册了<code>RichText</code>插件时可用。当节点编辑时,文本选区发生改变时触发</td>
|
||||
<td>hasRange(是否存在选区)、rectInfo(选区的尺寸和位置信息)、formatInfo(选区的文本格式化信息)</td>
|
||||
|
||||
82
web/src/pages/Doc/zh/course29/index.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# 局域网docker部署解决HTTPS问题的一种方法
|
||||
|
||||
> 本文来自:[Brzjomo](https://github.com/Brzjomo)的[issue](https://github.com/wanglin2/mind-map/issues/658)。
|
||||
|
||||
受Api的限制,MindMap以HTTP访问时,目录、新建和打开功能不能正常工作。因此在局域网架设时,需要给它进行配置证书等操作,使其正常工作。
|
||||
|
||||
假设先前已经基于Github源码,架设了MindMap的docker服务。没有的先看这个[Issue](https://github.com/wanglin2/mind-map/issues/309)
|
||||
|
||||
事前准备:
|
||||
需要准备一个域名。
|
||||
|
||||
需要安装Linux 服务器运维管理面板[1panel](https://github.com/1Panel-dev/1Panel)
|
||||
|
||||
设置域名解析:
|
||||
以阿里云为例,登录后进入[域名解析页面](https://dns.console.aliyun.com/#/dns/domainList)
|
||||
|
||||
点击对应域名的解析设置。
|
||||
|
||||
添加或编辑对应的@和www记录,将IP记录值修改为局域网IP,比如192.168.2.36。
|
||||
|
||||
保存后退出。
|
||||
|
||||
获取AccessKey:
|
||||
进入账号下面的AccessKey管理。
|
||||
|
||||
创建或者使用已经记录的AccessKey。
|
||||
|
||||
1panel设置:
|
||||
进入应用商店,安装OpenResty(稍后用于申请证书和设置反代)。
|
||||
|
||||
进入网站-网站,点击创建网站。
|
||||
|
||||
点击反向代理。
|
||||
|
||||
设置主域名为自己的域名。
|
||||
|
||||
代理地址为http和127.0.0.1:MindMap容器端口。
|
||||
|
||||
点击确认。
|
||||
|
||||
创建证书申请账户:
|
||||
进入1panel的网站-证书,点击Acme 账户。
|
||||
|
||||
点击创建账户。
|
||||
|
||||
输入邮箱后确认。
|
||||
|
||||
回到刚才的证书页面,点击DNS 账户。
|
||||
|
||||
点击创建账户。
|
||||
|
||||
填写名称后,选择类型为阿里云DNS。
|
||||
|
||||
再填入刚才准备好的Access Key和Secret Key。
|
||||
|
||||
点击确认。
|
||||
|
||||
申请证书:
|
||||
回到刚才的证书页面,点击申请证书。
|
||||
|
||||
填写主域名,其他按实际情况填写。一般会自动设置。
|
||||
|
||||
点击确认,等待其成功。
|
||||
|
||||
启用HTTPS访问:
|
||||
回到1panel的网站管理页面。
|
||||
|
||||
找到刚才建立的反向代理,点击配置。
|
||||
|
||||
点击HTTPS。
|
||||
|
||||
点击启用HTTPS。
|
||||
|
||||
SSL 选项设置为选择已有证书。
|
||||
|
||||
选择好刚才创建的Acme账户和证书。
|
||||
|
||||
点击保存。
|
||||
|
||||
此时,在局域网内访问该域名,应当能正确以Https访问MindMap了。
|
||||
|
||||
如果不能,输入host 域名,查看返回的DNS解析是否为局域网IP。
|
||||
62
web/src/pages/Doc/zh/course29/index.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>局域网docker部署解决HTTPS问题的一种方法</h1>
|
||||
<blockquote>
|
||||
<p>本文来自:<a href="https://github.com/Brzjomo">Brzjomo</a>的<a href="https://github.com/wanglin2/mind-map/issues/658">issue</a>。</p>
|
||||
</blockquote>
|
||||
<p>受Api的限制,MindMap以HTTP访问时,目录、新建和打开功能不能正常工作。因此在局域网架设时,需要给它进行配置证书等操作,使其正常工作。</p>
|
||||
<p>假设先前已经基于Github源码,架设了MindMap的docker服务。没有的先看这个<a href="https://github.com/wanglin2/mind-map/issues/309">Issue</a></p>
|
||||
<p>事前准备:
|
||||
需要准备一个域名。</p>
|
||||
<p>需要安装Linux 服务器运维管理面板<a href="https://github.com/1Panel-dev/1Panel">1panel</a></p>
|
||||
<p>设置域名解析:
|
||||
以阿里云为例,登录后进入<a href="https://dns.console.aliyun.com/#/dns/domainList">域名解析页面</a></p>
|
||||
<p>点击对应域名的解析设置。</p>
|
||||
<p>添加或编辑对应的@和www记录,将IP记录值修改为局域网IP,比如192.168.2.36。</p>
|
||||
<p>保存后退出。</p>
|
||||
<p>获取AccessKey:
|
||||
进入账号下面的AccessKey管理。</p>
|
||||
<p>创建或者使用已经记录的AccessKey。</p>
|
||||
<p>1panel设置:
|
||||
进入应用商店,安装OpenResty(稍后用于申请证书和设置反代)。</p>
|
||||
<p>进入网站-网站,点击创建网站。</p>
|
||||
<p>点击反向代理。</p>
|
||||
<p>设置主域名为自己的域名。</p>
|
||||
<p>代理地址为http和127.0.0.1:MindMap容器端口。</p>
|
||||
<p>点击确认。</p>
|
||||
<p>创建证书申请账户:
|
||||
进入1panel的网站-证书,点击Acme 账户。</p>
|
||||
<p>点击创建账户。</p>
|
||||
<p>输入邮箱后确认。</p>
|
||||
<p>回到刚才的证书页面,点击DNS 账户。</p>
|
||||
<p>点击创建账户。</p>
|
||||
<p>填写名称后,选择类型为阿里云DNS。</p>
|
||||
<p>再填入刚才准备好的Access Key和Secret Key。</p>
|
||||
<p>点击确认。</p>
|
||||
<p>申请证书:
|
||||
回到刚才的证书页面,点击申请证书。</p>
|
||||
<p>填写主域名,其他按实际情况填写。一般会自动设置。</p>
|
||||
<p>点击确认,等待其成功。</p>
|
||||
<p>启用HTTPS访问:
|
||||
回到1panel的网站管理页面。</p>
|
||||
<p>找到刚才建立的反向代理,点击配置。</p>
|
||||
<p>点击HTTPS。</p>
|
||||
<p>点击启用HTTPS。</p>
|
||||
<p>SSL 选项设置为选择已有证书。</p>
|
||||
<p>选择好刚才创建的Acme账户和证书。</p>
|
||||
<p>点击保存。</p>
|
||||
<p>此时,在局域网内访问该域名,应当能正确以Https访问MindMap了。</p>
|
||||
<p>如果不能,输入host 域名,查看返回的DNS解析是否为局域网IP。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
9
web/src/pages/Doc/zh/help6/index.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 如何编辑数学公式
|
||||
|
||||
数学公式只在开启了【富文本】编辑模式下才可使用。
|
||||
|
||||
首先可以激活节点,然后点击上方工具栏中的【公式】打开右侧的格式侧边栏,然后再输入框中输入公式后点击【完成】即可将公式输入节点。
|
||||
|
||||
当你再次双击节点时,公式会转换成源码,你可以直接修改,回车完成后即可渲染。
|
||||
|
||||
所以你也可以不通过侧边栏,直接在文本编辑框中输入公式,不过公式的源码前后必须通过`$`符号包裹,否则不会解析为格式。
|
||||
20
web/src/pages/Doc/zh/help6/index.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>如何编辑数学公式</h1>
|
||||
<p>数学公式只在开启了【富文本】编辑模式下才可使用。</p>
|
||||
<p>首先可以激活节点,然后点击上方工具栏中的【公式】打开右侧的格式侧边栏,然后再输入框中输入公式后点击【完成】即可将公式输入节点。</p>
|
||||
<p>当你再次双击节点时,公式会转换成源码,你可以直接修改,回车完成后即可渲染。</p>
|
||||
<p>所以你也可以不通过侧边栏,直接在文本编辑框中输入公式,不过公式的源码前后必须通过<code>$</code>符号包裹,否则不会解析为格式。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -380,7 +380,7 @@
|
||||
</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>
|
||||
<p>Alex</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%;" />
|
||||
@@ -390,4 +390,20 @@
|
||||
<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/最多5个字.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>最多5个字</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/ZX.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>ZX</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>
|
||||
@@ -8,18 +8,18 @@
|
||||
</blockquote>
|
||||
<h2>特性</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox235" checked="true" /><label for="checkbox235">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox236" checked="true" /><label for="checkbox236">支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox237" checked="true" /><label for="checkbox237">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox238" checked="true" /><label for="checkbox238">节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式</label></li>
|
||||
<li><input type="checkbox" id="checkbox239" checked="true" /><label for="checkbox239">节点支持拖拽(拖拽移动、自由调整)、多种节点形状;支持扩展节点内容、支持使用 DDM 完全自定义节点内容</label></li>
|
||||
<li><input type="checkbox" id="checkbox240" checked="true" /><label for="checkbox240">支持画布拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox241" checked="true" /><label for="checkbox241">支持鼠标按键拖动选择和 Ctrl+左键两种多选节点方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox242" checked="true" /><label for="checkbox242">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>、<code>txt</code>,支持从<code>json</code>、<code>xmind</code>、<code>markdown</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox243" checked="true" /><label for="checkbox243">支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条、手绘风格、彩虹线条</label></li>
|
||||
<li><input type="checkbox" id="checkbox244" checked="true" /><label for="checkbox244">提供丰富的配置,满足各种场景各种使用习惯</label></li>
|
||||
<li><input type="checkbox" id="checkbox245" checked="true" /><label for="checkbox245">支持协同编辑</label></li>
|
||||
<li><input type="checkbox" id="checkbox246" checked="true" /><label for="checkbox246">支持演示模式</label></li>
|
||||
<li><input type="checkbox" id="checkbox0" checked="true" /><label for="checkbox0">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox1" checked="true" /><label for="checkbox1">支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox2" checked="true" /><label for="checkbox2">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox3" checked="true" /><label for="checkbox3">节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式</label></li>
|
||||
<li><input type="checkbox" id="checkbox4" checked="true" /><label for="checkbox4">节点支持拖拽(拖拽移动、自由调整)、多种节点形状;支持扩展节点内容、支持使用 DDM 完全自定义节点内容</label></li>
|
||||
<li><input type="checkbox" id="checkbox5" checked="true" /><label for="checkbox5">支持画布拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox6" checked="true" /><label for="checkbox6">支持鼠标按键拖动选择和 Ctrl+左键两种多选节点方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox7" checked="true" /><label for="checkbox7">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>、<code>txt</code>,支持从<code>json</code>、<code>xmind</code>、<code>markdown</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox8" checked="true" /><label for="checkbox8">支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条、手绘风格、彩虹线条</label></li>
|
||||
<li><input type="checkbox" id="checkbox9" checked="true" /><label for="checkbox9">提供丰富的配置,满足各种场景各种使用习惯</label></li>
|
||||
<li><input type="checkbox" id="checkbox10" checked="true" /><label for="checkbox10">支持协同编辑</label></li>
|
||||
<li><input type="checkbox" id="checkbox11" checked="true" /><label for="checkbox11">支持演示模式</label></li>
|
||||
</ul>
|
||||
<p>官方提供了如下插件,可根据需求按需引入(某个功能不生效大概率是因为你没有引入对应的插件),具体使用方式请查看文档:</p>
|
||||
<blockquote>
|
||||
@@ -37,11 +37,11 @@
|
||||
<p>2.<code>web</code></p>
|
||||
<p>使用<code>simple-mind-map</code>库,基于<code>vue2.x</code>、<code>ElementUI</code>搭建的在线思维导图。特性:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox247" checked="true" /><label for="checkbox247">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox248" checked="true" /><label for="checkbox248">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox249" checked="true" /><label for="checkbox249">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox250" checked="true" /><label for="checkbox250">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox251" checked="true" /><label for="checkbox251">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
<li><input type="checkbox" id="checkbox12" checked="true" /><label for="checkbox12">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox13" checked="true" /><label for="checkbox13">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox14" checked="true" /><label for="checkbox14">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox15" checked="true" /><label for="checkbox15">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
</ul>
|
||||
<p>提供文档页面服务。</p>
|
||||
<p>3.<code>dist</code></p>
|
||||
@@ -331,7 +331,7 @@
|
||||
</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>
|
||||
<p>Alex</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%;" />
|
||||
@@ -341,6 +341,22 @@
|
||||
<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/最多5个字.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>最多5个字</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/ZX.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>ZX</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>
|
||||
|
||||
@@ -511,6 +511,16 @@ document.addEventListener(fullscrrenEvent, () => {
|
||||
|
||||
退出全屏状态。
|
||||
|
||||
#### defenseXSS(htmlStr)
|
||||
|
||||
> v0.10.0+
|
||||
|
||||
- `htmlStr`:需要过滤的html字符串
|
||||
|
||||
返回:过滤后的html字符串
|
||||
|
||||
防御 XSS 攻击,过滤恶意 HTML 标签和属性。你可以在将节点数据传递给SimpleMindMap前递归遍历树数据,通过该方法处理节点富文本内容,避免 XSS 攻击。
|
||||
|
||||
## 在 canvas 中模拟 css 的背景属性
|
||||
|
||||
引入:
|
||||
|
||||
@@ -427,6 +427,15 @@
|
||||
<p>v0.9.11+</p>
|
||||
</blockquote>
|
||||
<p>退出全屏状态。</p>
|
||||
<h4>defenseXSS(htmlStr)</h4>
|
||||
<blockquote>
|
||||
<p>v0.10.0+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>htmlStr</code>:需要过滤的html字符串</li>
|
||||
</ul>
|
||||
<p>返回:过滤后的html字符串</p>
|
||||
<p>防御 XSS 攻击,过滤恶意 HTML 标签和属性。你可以在将节点数据传递给SimpleMindMap前递归遍历树数据,通过该方法处理节点富文本内容,避免 XSS 攻击。</p>
|
||||
<h2>在 canvas 中模拟 css 的背景属性</h2>
|
||||
<p>引入:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
|
||||
@@ -22,12 +22,14 @@ simpleMindMap.xmind
|
||||
|
||||
## 方法
|
||||
|
||||
### xmind.parseXmindFile(file)
|
||||
### xmind.parseXmindFile(file, handleMultiCanvas)
|
||||
|
||||
解析`.xmind`文件,返回解析后的数据,可以使用`mindMap.setData(data)`来将返回的数据渲染到画布上
|
||||
|
||||
`file`:`File`对象
|
||||
|
||||
`handleMultiCanvas`:v0.10.0+,可选,可传递一个函数,如果导入的xmind文件存在多个画布,那么会调用该函数,函数接收xmind画布列表数据为参数,需要返回其中一个画布的数据,比如接收的参数为`content`,要导入第二个画布的数据则返回`content[1]`。函数可以是异步函数,返回一个Promise实例。
|
||||
|
||||
### xmind.transformXmind(content)
|
||||
|
||||
> v0.6.6+版本该方法改为异步方法,返回一个Promise实例
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
<pre class="hljs"><code>simpleMindMap.xmind
|
||||
</code></pre>
|
||||
<h2>方法</h2>
|
||||
<h3>xmind.parseXmindFile(file)</h3>
|
||||
<h3>xmind.parseXmindFile(file, handleMultiCanvas)</h3>
|
||||
<p>解析<code>.xmind</code>文件,返回解析后的数据,可以使用<code>mindMap.setData(data)</code>来将返回的数据渲染到画布上</p>
|
||||
<p><code>file</code>:<code>File</code>对象</p>
|
||||
<p><code>handleMultiCanvas</code>:v0.10.0+,可选,可传递一个函数,如果导入的xmind文件存在多个画布,那么会调用该函数,函数接收xmind画布列表数据为参数,需要返回其中一个画布的数据,比如接收的参数为<code>content</code>,要导入第二个画布的数据则返回<code>content[1]</code>。函数可以是异步函数,返回一个Promise实例。</p>
|
||||
<h3>xmind.transformXmind(content)</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.6+版本该方法改为异步方法,返回一个Promise实例</p>
|
||||
|
||||
@@ -696,6 +696,16 @@
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 是否在节点下方 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<el-checkbox
|
||||
v-model="watermarkConfig.belowNode"
|
||||
@change="updateWatermarkConfig"
|
||||
>{{ $t('baseStyle.belowNode') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 水印文字 -->
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
import {defenseXSS} from 'simple-mind-map/src/utils/xss'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
@@ -39,7 +38,7 @@ export default {
|
||||
computed: {
|
||||
...mapState({
|
||||
isDark: state => state.localConfig.isDark
|
||||
}),
|
||||
})
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('data_change', this.onDataChange)
|
||||
@@ -61,7 +60,7 @@ export default {
|
||||
this.words = 0
|
||||
this.num = 0
|
||||
this.walk(data)
|
||||
countEl.innerHTML = defenseXSS(this.textStr)
|
||||
countEl.innerHTML = this.textStr
|
||||
this.words = countEl.textContent.length
|
||||
},
|
||||
|
||||
@@ -102,7 +101,7 @@ export default {
|
||||
background: #262a2e;
|
||||
|
||||
.item {
|
||||
color: hsla(0, 0%, 100%, .6);
|
||||
color: hsla(0, 0%, 100%, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,56 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="nodeImportDialog"
|
||||
:title="$t('import.title')"
|
||||
:visible.sync="dialogVisible"
|
||||
width="300px"
|
||||
>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action="x"
|
||||
accept=".smm,.json,.xmind,.xlsx,.md"
|
||||
:file-list="fileList"
|
||||
:auto-upload="false"
|
||||
:multiple="false"
|
||||
:on-change="onChange"
|
||||
:on-remove="onRemove"
|
||||
:limit="1"
|
||||
:on-exceed="onExceed"
|
||||
<div>
|
||||
<el-dialog
|
||||
class="nodeImportDialog"
|
||||
:title="$t('import.title')"
|
||||
:visible.sync="dialogVisible"
|
||||
width="300px"
|
||||
>
|
||||
<el-button slot="trigger" size="small" type="primary">{{
|
||||
$t('import.selectFile')
|
||||
}}</el-button>
|
||||
<div slot="tip" class="el-upload__tip">
|
||||
{{ $t('import.supportFile') }}
|
||||
</div>
|
||||
</el-upload>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirm">{{
|
||||
$t('dialog.confirm')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action="x"
|
||||
accept=".smm,.json,.xmind,.xlsx,.md"
|
||||
:file-list="fileList"
|
||||
:auto-upload="false"
|
||||
:multiple="false"
|
||||
:on-change="onChange"
|
||||
:on-remove="onRemove"
|
||||
:limit="1"
|
||||
:on-exceed="onExceed"
|
||||
>
|
||||
<el-button slot="trigger" size="small" type="primary">{{
|
||||
$t('import.selectFile')
|
||||
}}</el-button>
|
||||
<div slot="tip" class="el-upload__tip">
|
||||
{{ $t('import.supportFile') }}
|
||||
</div>
|
||||
</el-upload>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="confirm">{{
|
||||
$t('dialog.confirm')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
class="xmindCanvasSelectDialog"
|
||||
:title="$t('import.xmindCanvasSelectDialogTitle')"
|
||||
:visible.sync="xmindCanvasSelectDialogVisible"
|
||||
width="300px"
|
||||
:show-close="false"
|
||||
>
|
||||
<el-radio-group v-model="selectCanvas" class="canvasList">
|
||||
<el-radio v-for="(item, index) in canvasList" :key="index" :label="index">{{
|
||||
item.title
|
||||
}}</el-radio>
|
||||
</el-radio-group>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="confirmSelect">{{
|
||||
$t('dialog.confirm')
|
||||
}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -50,7 +70,11 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
fileList: []
|
||||
fileList: [],
|
||||
selectPromiseResolve: null,
|
||||
xmindCanvasSelectDialogVisible: false,
|
||||
selectCanvas: '',
|
||||
canvasList: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -106,11 +130,7 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-08-03 22:48:42
|
||||
* @Desc: 文件选择
|
||||
*/
|
||||
// 文件选择
|
||||
onChange(file) {
|
||||
let reg = /\.(smm|xmind|json|xlsx|md)$/
|
||||
if (!reg.test(file.name)) {
|
||||
@@ -126,29 +146,17 @@ export default {
|
||||
this.fileList = fileList
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-08-03 22:48:47
|
||||
* @Desc: 数量超出限制
|
||||
*/
|
||||
// 数量超出限制
|
||||
onExceed() {
|
||||
this.$message.error(this.$t('import.maxFileNum'))
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-22 22:08:11
|
||||
* @Desc: 取消
|
||||
*/
|
||||
// 取消
|
||||
cancel() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-06 22:28:20
|
||||
* @Desc: 确定
|
||||
*/
|
||||
// 确定
|
||||
confirm() {
|
||||
if (this.fileList.length <= 0) {
|
||||
return this.$message.error(this.$t('import.notSelectTip'))
|
||||
@@ -168,11 +176,7 @@ export default {
|
||||
this.setActiveSidebar(null)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-10-24 14:19:33
|
||||
* @Desc: 处理.smm文件
|
||||
*/
|
||||
// 处理.smm文件
|
||||
handleSmm(file) {
|
||||
let fileReader = new FileReader()
|
||||
fileReader.readAsText(file.raw)
|
||||
@@ -191,14 +195,15 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-10-24 14:19:41
|
||||
* @Desc: 处理.xmind文件
|
||||
*/
|
||||
// 处理.xmind文件
|
||||
async handleXmind(file) {
|
||||
try {
|
||||
let data = await xmind.parseXmindFile(file.raw)
|
||||
let data = await xmind.parseXmindFile(file.raw, content => {
|
||||
this.showSelectXmindCanvasDialog(content)
|
||||
return new Promise(resolve => {
|
||||
this.selectPromiseResolve = resolve
|
||||
})
|
||||
})
|
||||
this.$bus.$emit('setData', data)
|
||||
this.$message.success(this.$t('import.importSuccess'))
|
||||
} catch (error) {
|
||||
@@ -207,11 +212,22 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-10-24 14:19:51
|
||||
* @Desc: 处理.xlsx文件
|
||||
*/
|
||||
// 显示xmind文件的多个画布选择弹窗
|
||||
showSelectXmindCanvasDialog(content) {
|
||||
this.canvasList = content
|
||||
this.selectCanvas = 0
|
||||
this.xmindCanvasSelectDialogVisible = true
|
||||
},
|
||||
|
||||
// 确认导入指定的画布
|
||||
confirmSelect() {
|
||||
this.selectPromiseResolve(this.canvasList[this.selectCanvas])
|
||||
this.xmindCanvasSelectDialogVisible = false
|
||||
this.canvasList = []
|
||||
this.selectCanvas = 0
|
||||
},
|
||||
|
||||
// 处理.xlsx文件
|
||||
async handleExcel(file) {
|
||||
try {
|
||||
const wb = read(await fileToBuffer(file.raw))
|
||||
@@ -306,4 +322,17 @@ export default {
|
||||
<style lang="less" scoped>
|
||||
.nodeImportDialog {
|
||||
}
|
||||
|
||||
.canvasList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
/deep/ .el-radio {
|
||||
margin-bottom: 12px;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -70,7 +70,10 @@
|
||||
class="fontOptionItem"
|
||||
v-for="item in fontSizeList"
|
||||
:key="item"
|
||||
:style="{ fontSize: item + 'px' }"
|
||||
:style="{
|
||||
fontSize: item + 'px',
|
||||
height: (item < 30 ? 30 : item + 10) + 'px'
|
||||
}"
|
||||
:class="{ active: formatInfo.size === item + 'px' }"
|
||||
@click="changeFontSize(item)"
|
||||
>
|
||||
|
||||
@@ -30,14 +30,26 @@
|
||||
<span class="icon iconfont icondakai"></span>
|
||||
<span class="text">{{ $t('toolbar.directory') }}</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="createNewLocalFile">
|
||||
<span class="icon iconfont iconxinjian"></span>
|
||||
<span class="text">{{ $t('toolbar.newFile') }}</span>
|
||||
</div>
|
||||
<div class="toolbarBtn" @click="openLocalFile">
|
||||
<span class="icon iconfont iconwenjian1"></span>
|
||||
<span class="text">{{ $t('toolbar.openFile') }}</span>
|
||||
</div>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('toolbar.newFileTip')"
|
||||
placement="bottom"
|
||||
>
|
||||
<div class="toolbarBtn" @click="createNewLocalFile">
|
||||
<span class="icon iconfont iconxinjian"></span>
|
||||
<span class="text">{{ $t('toolbar.newFile') }}</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('toolbar.openFileTip')"
|
||||
placement="bottom"
|
||||
>
|
||||
<div class="toolbarBtn" @click="openLocalFile">
|
||||
<span class="icon iconfont iconwenjian1"></span>
|
||||
<span class="text">{{ $t('toolbar.openFile') }}</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div class="toolbarBtn" @click="saveLocalFile">
|
||||
<span class="icon iconfont iconlingcunwei"></span>
|
||||
<span class="text">{{ $t('toolbar.saveAs') }}</span>
|
||||
|
||||
@@ -42,11 +42,11 @@ export default {
|
||||
dataList: [
|
||||
{
|
||||
icon: 'iconstar',
|
||||
value: 'Github star数量3000+'
|
||||
value: 'Github star数量4000+'
|
||||
},
|
||||
{
|
||||
icon: 'iconfork',
|
||||
value: 'Github fork数量400+'
|
||||
value: 'Github fork数量500+'
|
||||
},
|
||||
{
|
||||
icon: 'iconxiazai',
|
||||
@@ -54,7 +54,7 @@ export default {
|
||||
},
|
||||
{
|
||||
icon: 'iconteamwork',
|
||||
value: '代码贡献者16+'
|
||||
value: '代码贡献者17+'
|
||||
}
|
||||
],
|
||||
functionList: [
|
||||
|
||||