mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-24 18:38:26 +08:00
Compare commits
40 Commits
0.9.1-fix.
...
0.9.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d378ca2e5 | ||
|
|
5739fae4f7 | ||
|
|
06ad8cfbf6 | ||
|
|
aed8e24afc | ||
|
|
b7cb52b703 | ||
|
|
d4fc37fc98 | ||
|
|
7b4bd6b0bb | ||
|
|
80f8a357fe | ||
|
|
a66cced73c | ||
|
|
29c5075fa5 | ||
|
|
5bea2606f6 | ||
|
|
9db988e3ec | ||
|
|
bac174c8df | ||
|
|
c0db185ca6 | ||
|
|
642f486841 | ||
|
|
69a97d44bc | ||
|
|
d19fd7e186 | ||
|
|
2bcf763ea2 | ||
|
|
9ea36a852f | ||
|
|
4d2665c98b | ||
|
|
33a2e20ee2 | ||
|
|
7b8946bec4 | ||
|
|
88f2e60720 | ||
|
|
b4e0ad6881 | ||
|
|
d80ee1e7c8 | ||
|
|
3d0b257325 | ||
|
|
4d9aa1d3c2 | ||
|
|
abc30da43b | ||
|
|
f887b14d1f | ||
|
|
346e5b4ac8 | ||
|
|
6f7bb40c49 | ||
|
|
f3694d0c00 | ||
|
|
f2fbde3763 | ||
|
|
b950c2bfe9 | ||
|
|
69a7deedd7 | ||
|
|
63b04e5acc | ||
|
|
4a2816fc75 | ||
|
|
42ffbd728c | ||
|
|
0ec16bd136 | ||
|
|
d517ee338f |
@@ -238,4 +238,8 @@ const mindMap = new MindMap({
|
||||
<img src="./web/src/assets/avatar/HaHN.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>HaHN</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/继龙.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>继龙</span>
|
||||
</span>
|
||||
</p>
|
||||
File diff suppressed because one or more lines are too long
BIN
dist/img/继龙.jpg
vendored
Normal file
BIN
dist/img/继龙.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
2
dist/js/app.js
vendored
2
dist/js/app.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0aa978.js
vendored
2
dist/js/chunk-2d0aa978.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0ab10b.js
vendored
2
dist/js/chunk-2d0ab10b.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0abe0f.js
vendored
2
dist/js/chunk-2d0abe0f.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0abe0f"],{"16c7":function(t,e,o){"use strict";o.r(e);var a=function(){var t=this;t._self._c;return t._m(0)},n=[function(){var t=this,e=t._self._c;return e("div",[e("h1",[t._v("View instance")]),e("p",[t._v("The "),e("code",[t._v("view")]),t._v(" instance is responsible for view operations, and can be obtained through "),e("code",[t._v("mindMap.view")])]),e("h2",[t._v("Methods")]),e("h3",[t._v("fit()")]),e("blockquote",[e("p",[t._v("v0.6.0+")])]),e("p",[t._v("Zoom the mind map to fit the canvas.")]),e("h3",[t._v("translateX(step)")]),e("p",[t._v("Translate in the "),e("code",[t._v("x")]),t._v(" direction, "),e("code",[t._v("step")]),t._v(": number of pixels to translate")]),e("h3",[t._v("translateY(step)")]),e("p",[t._v("Translate in the "),e("code",[t._v("y")]),t._v(" direction, "),e("code",[t._v("step")]),t._v(": number of pixels to translate")]),e("h3",[t._v("translateXTo(x)")]),e("blockquote",[e("p",[t._v("v0.2.11+")])]),e("p",[t._v("Translate the "),e("code",[t._v("x")]),t._v(" direction to a specific position")]),e("h3",[t._v("translateYTo(y)")]),e("blockquote",[e("p",[t._v("v0.2.11+")])]),e("p",[t._v("Translate the "),e("code",[t._v("y")]),t._v(" direction to a specific position")]),e("h3",[t._v("reset()")]),e("p",[t._v("Revert to the default transformation")]),e("h3",[t._v("narrow(cx, cy)")]),e("ul",[e("li",[e("p",[e("code",[t._v("cx")]),t._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])]),e("li",[e("p",[e("code",[t._v("cy")]),t._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])])]),e("p",[t._v("Zoom out")]),e("h3",[t._v("enlarge(cx, cy)")]),e("ul",[e("li",[e("p",[e("code",[t._v("cx")]),t._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])]),e("li",[e("p",[e("code",[t._v("cy")]),t._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])])]),e("p",[t._v("Zoom in")]),e("h3",[t._v("getTransformData()")]),e("blockquote",[e("p",[t._v("v0.1.1+")])]),e("p",[t._v("Get the current transform data, can be used for display")]),e("h3",[t._v("setTransformData(data)")]),e("blockquote",[e("p",[t._v("v0.1.1+")])]),e("p",[t._v('Dynamically set transform data, transform data can be obtained through the getTransformData method"')]),e("h3",[t._v("setScale(scale, cx, cy)")]),e("blockquote",[e("p",[t._v("v0.2.17+")])]),e("ul",[e("li",[e("p",[e("code",[t._v("cx")]),t._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])]),e("li",[e("p",[e("code",[t._v("cy")]),t._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])])]),e("p",[t._v("Setting Zoom")])])}],v={},c=v,i=o("2877"),s=Object(i["a"])(c,a,n,!1,null,null,null);e["default"]=s.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0abe0f"],{"16c7":function(e,t,o){"use strict";o.r(t);var a=function(){var e=this;e._self._c;return e._m(0)},n=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("View instance")]),t("p",[e._v("The "),t("code",[e._v("view")]),e._v(" instance is responsible for view operations, and can be obtained through "),t("code",[e._v("mindMap.view")])]),t("h2",[e._v("Methods")]),t("h3",[e._v("fit()")]),t("blockquote",[t("p",[e._v("v0.6.0+")])]),t("p",[e._v("Zoom the mind map to fit the canvas.")]),t("p",[e._v("Note that this method cannot be called immediately after calling the 'setData' and 'setFullData' methods, and needs to listen to the 'node_tree_render_end' event calls 'fit'.")]),t("h3",[e._v("translateX(step)")]),t("p",[e._v("Translate in the "),t("code",[e._v("x")]),e._v(" direction, "),t("code",[e._v("step")]),e._v(": number of pixels to translate")]),t("h3",[e._v("translateY(step)")]),t("p",[e._v("Translate in the "),t("code",[e._v("y")]),e._v(" direction, "),t("code",[e._v("step")]),e._v(": number of pixels to translate")]),t("h3",[e._v("translateXTo(x)")]),t("blockquote",[t("p",[e._v("v0.2.11+")])]),t("p",[e._v("Translate the "),t("code",[e._v("x")]),e._v(" direction to a specific position")]),t("h3",[e._v("translateYTo(y)")]),t("blockquote",[t("p",[e._v("v0.2.11+")])]),t("p",[e._v("Translate the "),t("code",[e._v("y")]),e._v(" direction to a specific position")]),t("h3",[e._v("reset()")]),t("p",[e._v("Revert to the default transformation")]),t("h3",[e._v("narrow(cx, cy)")]),t("ul",[t("li",[t("p",[t("code",[e._v("cx")]),e._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])]),t("li",[t("p",[t("code",[e._v("cy")]),e._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])])]),t("p",[e._v("Zoom out")]),t("h3",[e._v("enlarge(cx, cy)")]),t("ul",[t("li",[t("p",[t("code",[e._v("cx")]),e._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])]),t("li",[t("p",[t("code",[e._v("cy")]),e._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])])]),t("p",[e._v("Zoom in")]),t("h3",[e._v("getTransformData()")]),t("blockquote",[t("p",[e._v("v0.1.1+")])]),t("p",[e._v("Get the current transform data, can be used for display")]),t("h3",[e._v("setTransformData(data)")]),t("blockquote",[t("p",[e._v("v0.1.1+")])]),t("p",[e._v('Dynamically set transform data, transform data can be obtained through the getTransformData method"')]),t("h3",[e._v("setScale(scale, cx, cy)")]),t("blockquote",[t("p",[e._v("v0.2.17+")])]),t("ul",[t("li",[t("p",[t("code",[e._v("cx")]),e._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])]),t("li",[t("p",[t("code",[e._v("cy")]),e._v(":(v0.6.4+)Zoom to the specified position on the canvas, default to the center point of the canvas")])])]),t("p",[e._v("Setting Zoom")])])}],v={},i=v,c=o("2877"),s=Object(c["a"])(i,a,n,!1,null,null,null);t["default"]=s.exports}}]);
|
||||
2
dist/js/chunk-2d0afe0d.js
vendored
2
dist/js/chunk-2d0afe0d.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0b361e.js
vendored
2
dist/js/chunk-2d0b361e.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0b361e"],{"27ad":function(s,a,t){"use strict";t.r(a);var e=function(){var s=this;s._self._c;return s._m(0)},n=[function(){var s=this,a=s._self._c;return a("div",[a("h1",[s._v("Watermark plugin")]),a("blockquote",[a("p",[s._v("0.2.24+")])]),a("p",[a("code",[s._v("Watermark")]),s._v(" instance is responsible for displaying the watermark.")]),a("p",[s._v("Please refer to the "),a("a",{attrs:{href:"/mind-map/#/doc/zh/constructor"}},[s._v("Instantiation Options")]),s._v(" of the "),a("code",[s._v("MindMap")]),s._v(" class for configuration.")]),a("h2",[s._v("Register")]),a("pre",{staticClass:"hljs"},[a("code",[a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" MindMap "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map'")]),s._v("\n"),a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" Watermark "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map/src/plugins/Watermark.js'")]),s._v("\n"),a("span",{staticClass:"hljs-comment"},[s._v("// import Watermark from 'simple-mind-map/src/Watermark.js' Use this path for versions below v0.6.0")]),s._v("\n\nMindMap.usePlugin(Watermark)\n")])]),a("p",[s._v("After registration and instantiation of "),a("code",[s._v("MindMap")]),s._v(", the instance can be obtained through "),a("code",[s._v("mindMap.watermark")]),s._v(".")]),a("h2",[s._v("Methods")]),a("h3",[s._v("draw()")]),a("p",[s._v("Redraw the watermark.")]),a("p",[s._v("Note: For imprecise rendering, some watermarks beyond the visible area will be drawn. If you have extreme performance requirements, it is recommended to develop the watermark function yourself.")]),a("h3",[s._v("updateWatermark(config)")]),a("p",[s._v("Update watermark config. Example:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.watermark.updateWatermark({\n "),a("span",{staticClass:"hljs-attr"},[s._v("text")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'Watermark text'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("lineSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("angle")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("50")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textStyle")]),s._v(": {\n "),a("span",{staticClass:"hljs-attr"},[s._v("color")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'#000'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("opacity")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("1")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("fontSize")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("20")]),s._v("\n }\n})\n")])]),a("h3",[s._v("hasWatermark()")]),a("blockquote",[a("p",[s._v("v0.3.2+")])]),a("p",[s._v("Gets whether the watermark exists.")])])}],r={},i=r,l=t("2877"),v=Object(l["a"])(i,e,n,!1,null,null,null);a["default"]=v.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0b361e"],{"27ad":function(s,a,t){"use strict";t.r(a);var e=function(){var s=this;s._self._c;return s._m(0)},r=[function(){var s=this,a=s._self._c;return a("div",[a("h1",[s._v("Watermark plugin")]),a("blockquote",[a("p",[s._v("0.2.24+")])]),a("p",[a("code",[s._v("Watermark")]),s._v(" instance is responsible for displaying the watermark.")]),a("p",[s._v("Please refer to the "),a("a",{attrs:{href:"/mind-map/#/doc/zh/constructor"}},[s._v("Instantiation Options")]),s._v(" of the "),a("code",[s._v("MindMap")]),s._v(" class for configuration.")]),a("h2",[s._v("Register")]),a("pre",{staticClass:"hljs"},[a("code",[a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" MindMap "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map'")]),s._v("\n"),a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" Watermark "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map/src/plugins/Watermark.js'")]),s._v("\n"),a("span",{staticClass:"hljs-comment"},[s._v("// import Watermark from 'simple-mind-map/src/Watermark.js' Use this path for versions below v0.6.0")]),s._v("\n\nMindMap.usePlugin(Watermark)\n")])]),a("p",[s._v("After registration and instantiation of "),a("code",[s._v("MindMap")]),s._v(", the instance can be obtained through "),a("code",[s._v("mindMap.watermark")]),s._v(".")]),a("h2",[s._v("Methods")]),a("h3",[s._v("draw()")]),a("p",[s._v("Redraw the watermark.")]),a("p",[s._v("Note: For imprecise rendering, some watermarks beyond the visible area will be drawn. If you have extreme performance requirements, it is recommended to develop the watermark function yourself.")]),a("h3",[s._v("updateWatermark(config)")]),a("p",[s._v("Update watermark config. Example:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.watermark.updateWatermark({\n "),a("span",{staticClass:"hljs-attr"},[s._v("text")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'Watermark text'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("lineSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("angle")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("50")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textStyle")]),s._v(": {\n "),a("span",{staticClass:"hljs-attr"},[s._v("color")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'#000'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("opacity")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("1")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("fontSize")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("20")]),s._v("\n }\n})\n")])]),a("h3",[s._v("hasWatermark()")]),a("blockquote",[a("p",[s._v("v0.3.2+")])]),a("p",[s._v("Gets whether the watermark exists.")]),a("h3",[s._v("clear()")]),a("blockquote",[a("p",[s._v("v0.9.2+")])]),a("p",[s._v("Clear watermark.")])])}],n={},i=n,l=t("2877"),v=Object(l["a"])(i,e,r,!1,null,null,null);a["default"]=v.exports}}]);
|
||||
2
dist/js/chunk-2d0b9b64.js
vendored
2
dist/js/chunk-2d0b9b64.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0b9b64"],{"33b0":function(t,s,a){"use strict";a.r(s);var n=function(){var t=this;t._self._c;return t._m(0)},i=[function(){var t=this,s=t._self._c;return s("div",[s("h1",[t._v("结构")]),s("p",[s("code",[t._v("simple-mind-map")]),t._v("目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)、verticalTimeline(v0.6.6+竖向时间轴)。")]),s("p",[t._v("可以在实例化"),s("code",[t._v("simple-mind-map")]),t._v("时通过选项指定使用的结构:")]),s("pre",{staticClass:"hljs"},[s("code",[s("span",{staticClass:"hljs-keyword"},[t._v("new")]),t._v(" MindMap({\n "),s("span",{staticClass:"hljs-comment"},[t._v("// ...")]),t._v("\n "),s("span",{staticClass:"hljs-attr"},[t._v("layout")]),t._v(": "),s("span",{staticClass:"hljs-string"},[t._v("'logicalStructure'")]),t._v("\n})\n")])]),s("p",[t._v("也可以动态切换结构:")]),s("pre",{staticClass:"hljs"},[s("code",[t._v("mindMap.setLayout("),s("span",{staticClass:"hljs-string"},[t._v("'organizationStructure'")]),t._v(")\n")])]),s("p",[t._v("获取当前使用的结构可以使用"),s("code",[t._v("getLayout")]),t._v("方法:")]),s("pre",{staticClass:"hljs"},[s("code",[s("span",{staticClass:"hljs-keyword"},[t._v("const")]),t._v(" layout = mindMap.getLayout()\n")])]),s("h2",[t._v("完整示例")]),s("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVVtrFDEU/iuHiMxWtrNb8Gndlnp7EFqR+tgUSWfS3WgmGSaZXiwLUgrWS0Hpg6Ag6os++ChCW8Q/0+72Z3iymZkd2z745sIsk3P5vpOc72S2yc00DddzTjqka6JMpBYMt3k6R5VIUp1Z2IaMrzVBq0WdK8vjJpg+k1JvLPE1GMBaphMIECGoMhaFihdZ6l2UGDRLPp2gdTphKSVUAVAluQVnc5GzoHIpvb3VgtNfB6cv9oe/nw1/HI/e75693BntHJ7uvTv7/I2qSCtjgUVWrPP7OuYGsycVNZZXpqjyKHvPh/tfRscHw4+7ZVrUZ6rHF7aYzi3mNaZgdg62HXFRSoi7X2Bb6G4EOusxJZ4yK7R6aLM8snnGA4QfOIbqQBoXUdyG+EZ5EI2xC4DLDsQ6yhOubNjj9q7k7vXW1r24ERSZt7WyTCieBVNNnxUzyzoe3f0ocQZKaiZvtnzTOjMlw0+H/sj8UbvfoABzgVFfyDjjygUvTzDOwV3Kcp7p5Oj16OjrebK/CS8hXZn46nH/qYLytbCVeUIJu6S1dRp7oI1wKsDMQPI1GzQhiLB12KaVIlyORdOBQOqeiJicCMb5B1M3vLoBUJmjD29P33z3RXuVnxy9Ojn+WdehVo1AIfUjr3RkbLhlE9z/gjB2IjqoT0O4zmTOnQCLOE+PosWn2/IzjtONC8txMJnluALoxmIdIsmMmaWkKOIOTzQlY3cRIOKJt5IqhnRb6K0HlkhWa7nKXIh3Uttdza3VCuYjKaInGFKfSYyrj2235YNL5IqlfOu2apvApbFb0u9nvriMKAlb/gYqpjHkJgkjYyipWhLW9lse6YaIbb8DM+321XEcQFqJIOPIiAc+doz1454r58+lhJokslWjZW59ImoGpdSBdrGyOp0sLtL3uej1Mfx6u51ulsyX814rmROW9QTylqgpi2OheqWhKj0s2vSPFc+UFRRFV2sERImNe0CaxHfA3fnhY6MVfmLG8LRwYAeq4aYEvyB+osMWvoYZXq0i4a5Z06uZ3jA8QxBKimm75Kvicy+22mUVtQ3I4A+xm1Zg"}})])}],e={},l=e,o=a("2877"),r=Object(o["a"])(l,n,i,!1,null,null,null);s["default"]=r.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0b9b64"],{"33b0":function(t,s,a){"use strict";a.r(s);var n=function(){var t=this;t._self._c;return t._m(0)},i=[function(){var t=this,s=t._self._c;return s("div",[s("h1",[t._v("结构")]),s("p",[s("code",[t._v("simple-mind-map")]),t._v("目前支持的结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)、verticalTimeline(v0.6.6+竖向时间轴)。")]),s("p",[t._v("可以在实例化"),s("code",[t._v("simple-mind-map")]),t._v("时通过选项指定使用的结构:")]),s("pre",{staticClass:"hljs"},[s("code",[s("span",{staticClass:"hljs-keyword"},[t._v("new")]),t._v(" MindMap({\n "),s("span",{staticClass:"hljs-comment"},[t._v("// ...")]),t._v("\n "),s("span",{staticClass:"hljs-attr"},[t._v("layout")]),t._v(": "),s("span",{staticClass:"hljs-string"},[t._v("'logicalStructure'")]),t._v("\n})\n")])]),s("p",[t._v("也可以动态切换结构:")]),s("pre",{staticClass:"hljs"},[s("code",[t._v("mindMap.setLayout("),s("span",{staticClass:"hljs-string"},[t._v("'organizationStructure'")]),t._v(")\n")])]),s("p",[t._v("获取当前使用的结构可以使用"),s("code",[t._v("getLayout")]),t._v("方法:")]),s("pre",{staticClass:"hljs"},[s("code",[s("span",{staticClass:"hljs-keyword"},[t._v("const")]),t._v(" layout = mindMap.getLayout()\n")])]),s("h2",[t._v("完整示例")]),s("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVVtrFDEU/iuHiMxWtrNb8Gndlnp7EFqR+tgUSWfS3WgmGSaZXiwLUgrWS0Hpg6Ag6os++ChCW8Q/0+72Z3iymZkd2z745sIsk3P5vpOc72S2yc00DddzTjqka6JMpBYMt3k6R5VIUp1Z2IaMrzVBq0WdK8vjJpg+k1JvLPE1GMBaphMIECGoMhaFihdZ6l2UGDRLPp2gdTphKSVUAVAluQVnc5GzoHIpvb3VgtNfB6cv9oe/nw1/HI/e75693BntHJ7uvTv7/I2qSCtjgUVWrPP7OuYGsycVNZZXpqjyKHvPh/tfRscHw4+7ZVrUZ6rHF7aYzi3mNaZgdg62HXFRSoi7X2Bb6G4EOusxJZ4yK7R6aLM8snnGA4QfOIbqQBoXUdyG+EZ5EI2xC4DLDsQ6yhOubNjj9q7k7vXW1r24ERSZt7WyTCieBVNNnxUzyzoe3f0ocQZKaiZvtnzTOjMlw0+H/sj8UbvfoABzgVFfyDjjygUvTzDOwV3Kcp7p5Oj16OjrebK/CS8hXZn46nH/qYLytbCVeUIJu6S1dRp7oI1wKsDMQPI1GzQhiLB12KaVIlyORdOBQOqeiJicCMb5B1M3vLoBUJmjD29P33z3RXuVnxy9Ojn+WdehVo1AIfUjr3RkbLhlE9z/gjB2IjqoT0O4zmTOnQCLOE+PosWn2/IzjtONC8txMJnluALoxmIdIsmMmaWkKOIOTzQlY3cRIOKJt5IqhnRb6K0HlkhWa7nKXIh3Uttdza3VCuYjKaInGFKfSYyrj2235YNL5IqlfOu2apvApbFb0u9nvriMKAlb/gYqpjHkJgkjYyipWhLW9lse6YaIbb8DM+321XEcQFqJIOPIiAc+doz1454r58+lhJokslWjZW59ImoGpdSBdrGyOp0sLtL3uej1Mfx6u51ulsyX814rmROW9QTylqgpi2OheqWhKj0s2vSPFc+UFRRFV2sERImNe0CaxHfA3fnhY6MVfmLG8LRwYAeq4aYEvyB+osMWvoYZXq0i4a5Z06uZ3jA8QxBKimm75Kvicy+22mUVtQ3I4A+xm1Zg"}})])}],e={},l=e,o=a("2877"),r=Object(o["a"])(l,n,i,!1,null,null,null);s["default"]=r.exports}}]);
|
||||
2
dist/js/chunk-2d0c0a44.js
vendored
2
dist/js/chunk-2d0c0a44.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0c191e.js
vendored
2
dist/js/chunk-2d0c191e.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0d9fbc.js
vendored
2
dist/js/chunk-2d0d9fbc.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0da701.js
vendored
2
dist/js/chunk-2d0da701.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0dad5f.js
vendored
2
dist/js/chunk-2d0dad5f.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0dddce.js
vendored
2
dist/js/chunk-2d0dddce.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0dddce"],{"82ca":function(v,_,e){"use strict";e.r(_);var c=function(){var v=this;v._self._c;return v._m(0)},o=[function(){var v=this,_=v._self._c;return _("div",[_("h1",[v._v("View实例")]),_("p",[_("code",[v._v("view")]),v._v("实例负责视图操作,可通过"),_("code",[v._v("mindMap.view")]),v._v("获取到该实例")]),_("h2",[v._v("方法")]),_("h3",[v._v("fit()")]),_("blockquote",[_("p",[v._v("v0.6.0+")])]),_("p",[v._v("缩放思维导图至适应画布。")]),_("h3",[v._v("translateX(step)")]),_("p",[_("code",[v._v("x")]),v._v("方向进行平移,"),_("code",[v._v("step")]),v._v(":要平移的像素")]),_("h3",[v._v("translateY(step)")]),_("p",[_("code",[v._v("y")]),v._v("方向进行平移,"),_("code",[v._v("step")]),v._v(":要平移的像素")]),_("h3",[v._v("translateXTo(x)")]),_("blockquote",[_("p",[v._v("v0.2.11+")])]),_("p",[v._v("平移"),_("code",[v._v("x")]),v._v("方向到指定位置")]),_("h3",[v._v("translateYTo(y)")]),_("blockquote",[_("p",[v._v("v0.2.11+")])]),_("p",[v._v("平移"),_("code",[v._v("y")]),v._v("方向到指定位置")]),_("h3",[v._v("reset()")]),_("p",[v._v("恢复到默认的变换")]),_("h3",[v._v("narrow(cx, cy)")]),_("ul",[_("li",[_("p",[_("code",[v._v("cx")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])]),_("li",[_("p",[_("code",[v._v("cy")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])])]),_("p",[v._v("缩小")]),_("h3",[v._v("enlarge(cx, cy)")]),_("ul",[_("li",[_("p",[_("code",[v._v("cx")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])]),_("li",[_("p",[_("code",[v._v("cy")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])])]),_("p",[v._v("放大")]),_("h3",[v._v("getTransformData()")]),_("blockquote",[_("p",[v._v("v0.1.1+")])]),_("p",[v._v("获取当前变换数据,可用于回显")]),_("h3",[v._v("setTransformData(data)")]),_("blockquote",[_("p",[v._v("v0.1.1+")])]),_("p",[v._v("动态设置变换数据,可以通过getTransformData方法获取变换数据")]),_("h3",[v._v("setScale(scale, cx, cy)")]),_("blockquote",[_("p",[v._v("v0.2.17+")])]),_("ul",[_("li",[_("p",[_("code",[v._v("cx")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])]),_("li",[_("p",[_("code",[v._v("cy")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])])]),_("p",[v._v("设置缩放")])])}],t={},p=t,a=e("2877"),l=Object(a["a"])(p,c,o,!1,null,null,null);_["default"]=l.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0dddce"],{"82ca":function(v,_,e){"use strict";e.r(_);var c=function(){var v=this;v._self._c;return v._m(0)},t=[function(){var v=this,_=v._self._c;return _("div",[_("h1",[v._v("View实例")]),_("p",[_("code",[v._v("view")]),v._v("实例负责视图操作,可通过"),_("code",[v._v("mindMap.view")]),v._v("获取到该实例")]),_("h2",[v._v("方法")]),_("h3",[v._v("fit()")]),_("blockquote",[_("p",[v._v("v0.6.0+")])]),_("p",[v._v("缩放思维导图至适应画布。")]),_("p",[v._v("注意该方法不能在"),_("code",[v._v("setData")]),v._v("、"),_("code",[v._v("setFullData")]),v._v("方法调用后立即调用,需要监听"),_("code",[v._v("node_tree_render_end")]),v._v("事件调用"),_("code",[v._v("fit")]),v._v("。")]),_("h3",[v._v("translateX(step)")]),_("p",[_("code",[v._v("x")]),v._v("方向进行平移,"),_("code",[v._v("step")]),v._v(":要平移的像素")]),_("h3",[v._v("translateY(step)")]),_("p",[_("code",[v._v("y")]),v._v("方向进行平移,"),_("code",[v._v("step")]),v._v(":要平移的像素")]),_("h3",[v._v("translateXTo(x)")]),_("blockquote",[_("p",[v._v("v0.2.11+")])]),_("p",[v._v("平移"),_("code",[v._v("x")]),v._v("方向到指定位置")]),_("h3",[v._v("translateYTo(y)")]),_("blockquote",[_("p",[v._v("v0.2.11+")])]),_("p",[v._v("平移"),_("code",[v._v("y")]),v._v("方向到指定位置")]),_("h3",[v._v("reset()")]),_("p",[v._v("恢复到默认的变换")]),_("h3",[v._v("narrow(cx, cy)")]),_("ul",[_("li",[_("p",[_("code",[v._v("cx")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])]),_("li",[_("p",[_("code",[v._v("cy")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])])]),_("p",[v._v("缩小")]),_("h3",[v._v("enlarge(cx, cy)")]),_("ul",[_("li",[_("p",[_("code",[v._v("cx")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])]),_("li",[_("p",[_("code",[v._v("cy")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])])]),_("p",[v._v("放大")]),_("h3",[v._v("getTransformData()")]),_("blockquote",[_("p",[v._v("v0.1.1+")])]),_("p",[v._v("获取当前变换数据,可用于回显")]),_("h3",[v._v("setTransformData(data)")]),_("blockquote",[_("p",[v._v("v0.1.1+")])]),_("p",[v._v("动态设置变换数据,可以通过getTransformData方法获取变换数据")]),_("h3",[v._v("setScale(scale, cx, cy)")]),_("blockquote",[_("p",[v._v("v0.2.17+")])]),_("ul",[_("li",[_("p",[_("code",[v._v("cx")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])]),_("li",[_("p",[_("code",[v._v("cy")]),v._v(":(v0.6.4+)以画布指定位置进行缩放,默认为画布中心点")])])]),_("p",[v._v("设置缩放")])])}],o={},a=o,p=e("2877"),l=Object(p["a"])(a,c,t,!1,null,null,null);_["default"]=l.exports}}]);
|
||||
2
dist/js/chunk-2d0de01b.js
vendored
2
dist/js/chunk-2d0de01b.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0de01b"],{"848a":function(s,a,t){"use strict";t.r(a);var n=function(){var s=this;s._self._c;return s._m(0)},v=[function(){var s=this,a=s._self._c;return a("div",[a("h1",[s._v("Watermark插件")]),a("blockquote",[a("p",[s._v("0.2.24+")])]),a("p",[a("code",[s._v("Watermark")]),s._v("插件负责显示水印。")]),a("p",[s._v("配置请参考"),a("code",[s._v("MindMap")]),s._v("类的"),a("a",{attrs:{href:"/mind-map/#/doc/zh/constructor"}},[s._v("实例化选项")]),s._v("。")]),a("h2",[s._v("注册")]),a("pre",{staticClass:"hljs"},[a("code",[a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" MindMap "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map'")]),s._v("\n"),a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" Watermark "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map/src/plugins/Watermark.js'")]),s._v("\n"),a("span",{staticClass:"hljs-comment"},[s._v("// import Watermark from 'simple-mind-map/src/Watermark.js' v0.6.0以下版本使用该路径")]),s._v("\n\nMindMap.usePlugin(Watermark)\n")])]),a("p",[s._v("注册完且实例化"),a("code",[s._v("MindMap")]),s._v("后可通过"),a("code",[s._v("mindMap.watermark")]),s._v("获取到该实例。")]),a("h2",[s._v("方法")]),a("h3",[s._v("draw()")]),a("p",[s._v("重新绘制水印。")]),a("p",[s._v("注意:非精确绘制,会绘制一些超出可视区域的水印,如果对性能有极致要求,推荐自行开发水印功能。")]),a("h3",[s._v("updateWatermark(config)")]),a("p",[s._v("更新水印配置。示例:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.watermark.updateWatermark({\n "),a("span",{staticClass:"hljs-attr"},[s._v("text")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'水印文字'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("lineSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("angle")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("50")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textStyle")]),s._v(": {\n "),a("span",{staticClass:"hljs-attr"},[s._v("color")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'#000'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("opacity")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("1")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("fontSize")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("20")]),s._v("\n }\n})\n")])]),a("h3",[s._v("hasWatermark()")]),a("blockquote",[a("p",[s._v("v0.3.2+")])]),a("p",[s._v("获取是否存在水印。")])])}],_={},r=_,l=t("2877"),i=Object(l["a"])(r,n,v,!1,null,null,null);a["default"]=i.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0de01b"],{"848a":function(s,a,t){"use strict";t.r(a);var n=function(){var s=this;s._self._c;return s._m(0)},v=[function(){var s=this,a=s._self._c;return a("div",[a("h1",[s._v("Watermark插件")]),a("blockquote",[a("p",[s._v("0.2.24+")])]),a("p",[a("code",[s._v("Watermark")]),s._v("插件负责显示水印。")]),a("p",[s._v("配置请参考"),a("code",[s._v("MindMap")]),s._v("类的"),a("a",{attrs:{href:"/mind-map/#/doc/zh/constructor"}},[s._v("实例化选项")]),s._v("。")]),a("h2",[s._v("注册")]),a("pre",{staticClass:"hljs"},[a("code",[a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" MindMap "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map'")]),s._v("\n"),a("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" Watermark "),a("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),a("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map/src/plugins/Watermark.js'")]),s._v("\n"),a("span",{staticClass:"hljs-comment"},[s._v("// import Watermark from 'simple-mind-map/src/Watermark.js' v0.6.0以下版本使用该路径")]),s._v("\n\nMindMap.usePlugin(Watermark)\n")])]),a("p",[s._v("注册完且实例化"),a("code",[s._v("MindMap")]),s._v("后可通过"),a("code",[s._v("mindMap.watermark")]),s._v("获取到该实例。")]),a("h2",[s._v("方法")]),a("h3",[s._v("draw()")]),a("p",[s._v("重新绘制水印。")]),a("p",[s._v("注意:非精确绘制,会绘制一些超出可视区域的水印,如果对性能有极致要求,推荐自行开发水印功能。")]),a("h3",[s._v("updateWatermark(config)")]),a("p",[s._v("更新水印配置。示例:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.watermark.updateWatermark({\n "),a("span",{staticClass:"hljs-attr"},[s._v("text")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'水印文字'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("lineSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textSpacing")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("angle")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("50")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("textStyle")]),s._v(": {\n "),a("span",{staticClass:"hljs-attr"},[s._v("color")]),s._v(": "),a("span",{staticClass:"hljs-string"},[s._v("'#000'")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("opacity")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("1")]),s._v(",\n "),a("span",{staticClass:"hljs-attr"},[s._v("fontSize")]),s._v(": "),a("span",{staticClass:"hljs-number"},[s._v("20")]),s._v("\n }\n})\n")])]),a("h3",[s._v("hasWatermark()")]),a("blockquote",[a("p",[s._v("v0.3.2+")])]),a("p",[s._v("获取是否存在水印。")]),a("h3",[s._v("clear()")]),a("blockquote",[a("p",[s._v("v0.9.2+")])]),a("p",[s._v("清除水印。")])])}],_={},r=_,l=t("2877"),p=Object(l["a"])(r,n,v,!1,null,null,null);a["default"]=p.exports}}]);
|
||||
2
dist/js/chunk-2d0e9742.js
vendored
2
dist/js/chunk-2d0e9742.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d0f026c.js
vendored
2
dist/js/chunk-2d0f026c.js
vendored
File diff suppressed because one or more lines are too long
1
dist/js/chunk-2d0f0784.js
vendored
Normal file
1
dist/js/chunk-2d0f0784.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0f0784"],{"9d03":function(e,t,n){"use strict";n.r(t);var i=function(){var e=this;e._self._c;return e._m(0)},d=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("TextEdit instance")]),t("p",[e._v("Node text editing instance. It can be obtained through "),t("code",[e._v("mindMap.renderer.textEdit")]),e._v(".")]),t("h2",[e._v("Methods")]),t("h3",[e._v("isShowTextEdit()")]),t("p",[e._v("Get whether the current text editing box is in a display state, that is, whether it is in a text editing state.")]),t("h3",[e._v("hideEditTextBox()")]),t("p",[e._v("Hiding the text editing box will set the content of the current text editing box as node text.")]),t("h3",[e._v("registerTmpShortcut()")]),t("p",[e._v("Register temporary shortcut keys, which means editing can be completed through the Enter and Tab keys.")]),t("h3",[e._v("show({ node})")]),t("ul",[t("li",[t("code",[e._v("node")]),e._v(":Node instance to enter for editing")])]),t("p",[e._v("Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.")])])}],o={},h=o,r=n("2877"),s=Object(r["a"])(h,i,d,!1,null,null,null);t["default"]=s.exports}}]);
|
||||
2
dist/js/chunk-2d208ffa.js
vendored
2
dist/js/chunk-2d208ffa.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d20ff53.js
vendored
2
dist/js/chunk-2d20ff53.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d20ff53"],{b69b:function(s,t,a){"use strict";a.r(t);var n=function(){var s=this;s._self._c;return s._m(0)},e=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("修改鼠标滚轮的行为")]),t("p",[s._v("鼠标滚轮的行为支持放大缩小画布和上下移动画布,可以在实例化时通过配置指定:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelAction")]),s._v(": "),t("span",{staticClass:"hljs-string"},[s._v("'zoom'")]),t("span",{staticClass:"hljs-comment"},[s._v("// zoom(放大缩小)、move(上下移动)")]),s._v("\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 当mousewheelAction设为move时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位px")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelMoveStep")]),s._v(": "),t("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n})\n")])]),t("p",[s._v("如果需要动态的切换行为可以使用"),t("code",[s._v("updateConfig")]),s._v("方法:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.updateConfig({\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelAction")]),s._v(": "),t("span",{staticClass:"hljs-string"},[s._v("'move'")]),s._v("\n})\n")])]),t("p",[s._v("此外也支持让你自行处理鼠标滚轮事件:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("customHandleMousewheel")]),s._v(": "),t("span",{staticClass:"hljs-function"},[s._v("("),t("span",{staticClass:"hljs-params"},[s._v("e")]),s._v(") =>")]),s._v(" {\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 你的自定义逻辑")]),s._v("\n }\n})\n")])]),t("p",[s._v("当传了"),t("code",[s._v("customHandleMousewheel")]),s._v("选项,"),t("code",[s._v("mousewheelAction")]),s._v("选项将不生效。")]),t("h2",[s._v("完整示例")]),t("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVU+P20QU/ypPRshZlNipxCkkpeXPAYlFqNedFXLsSTJlPGM842SXyBKqkFpKK4FAQiqXLZcWCXFCiO628GU2yfIteOPxON6QAzciOZp57/fe7828P7P0bmdZMC+oN/CGKs5ZpkFRXWQ3iWBpJnMNS8jppAtSHMpCaJp0Qc0izuXiDp1ACZNcpuCjB7+xOGQiOYwyqyKeQjGnvRSlvTTKiEcEABGcajAygxyBKDi38jCE1avvVl89Xv/1xfq3i82TL68e3tvce7F68MPV0+dExFIoDVGs2Zx+JBOq0HobUefo+IAIh4qLPKdC30awFIjDk3T8z6VM/QpkqB7cXz/+6e+XZ+uz++uLJ1evfr16+ujyj3PnQcvplFM8uqKLGaW8cdU5gNFNWJqYr7EE84gXFAF7paMRWH54G/xUzqkPg1piPNX3ERRZEmn6rhQTNu1UHKjbiWGwjwFPpUs8W2mO16Ss0wq2deV04VLlOCgfQCLjIkW3wZTq9zk1y3dOP0g6fm2JUemICZr7B11rhbFGA+vd/IhnBMRriaxY0xNtxMRbn72wSbXFYH5l7cwA4xnjCR7NgI+2Pnbc7WXZZbo8f7Q5f7ZLdp1wD+nxVtfG/U8RuGUtc3ZMMH1HSm264GOpmK2KI5/Tifa74MeYOkzTcQUvD96y/QWAZb/58dvVN7/YoGyfXZ5/fXnxe7sIpej4Al1/YnsNPXbMtgvm/0Om9LaooN2PTQc4nKXHosRvGNopg/MFN5riaMBKxx3AMGFziHmk1Ih4dRDv0VQSr1LXAJZstU0pImQYorYNdJ60lHwcGYhVEj0cF1pjE9+KOYs/rSD7mhwtlsvdEXKtge3wwGmxeXaxevi86uWt7OXP6+//9KEsh6EldNE1kbrVMGxdBG6VPuX2Tm7VI5V4QWjnaN2xAVVpECtFvCatQevOXFoWLNGzAdzo91+vcABZUyg5RUZMWqWoasx8r+3erXO1NYzGSvJCW0MAU24D6Nc7LbPt5t/0M8qmM4S/2e9nJ455P+8bjjmN8ilDXuc1i5KEiakTNKEHdar/Y8Q3XAR10M0eHWKZVjnwup7NgHm5grtKCnwoK/ekVmAGmgFAPHwHbdcHIS6DHMcvS6lJVm+cy4WiOTohXt3Ae95GYzvTOlODMOQnnwl1qgKpVC8WvTFld/HYQcTZaSFiFcQyDbHGqVZ7asPQ1IcpvfIftRG5qQ=="}})])}],l={},v=l,c=a("2877"),i=Object(c["a"])(v,n,e,!1,null,null,null);t["default"]=i.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d20ff53"],{b69b:function(s,t,a){"use strict";a.r(t);var e=function(){var s=this;s._self._c;return s._m(0)},n=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("修改鼠标滚轮的行为")]),t("p",[s._v("鼠标滚轮的行为支持放大缩小画布和上下移动画布,可以在实例化时通过配置指定:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelAction")]),s._v(": "),t("span",{staticClass:"hljs-string"},[s._v("'move'")]),t("span",{staticClass:"hljs-comment"},[s._v("// zoom(放大缩小)、move(上下移动)")]),s._v("\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 当mousewheelAction设为move时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位px")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelMoveStep")]),s._v(": "),t("span",{staticClass:"hljs-number"},[s._v("100")]),s._v(",\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 鼠标缩放是否以鼠标当前位置为中心点,否则以画布中心点")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("mouseScaleCenterUseMousePosition")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v(",\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 当mousewheelAction设为zoom时,或者按住Ctrl键时,默认向前滚动是缩小,向后滚动是放大,如果该属性设为true,那么会反过来")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelZoomActionReverse")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v(",\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 禁止鼠标滚轮缩放,你仍旧可以使用api进行缩放")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("disableMouseWheelZoom")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("false")]),s._v(",\n})\n")])]),t("p",[s._v("如果需要动态的切换行为可以使用"),t("code",[s._v("updateConfig")]),s._v("方法:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.updateConfig({\n "),t("span",{staticClass:"hljs-attr"},[s._v("mousewheelAction")]),s._v(": "),t("span",{staticClass:"hljs-string"},[s._v("'zoom'")]),s._v("\n})\n")])]),t("p",[s._v("此外也支持让你自行处理鼠标滚轮事件:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("customHandleMousewheel")]),s._v(": "),t("span",{staticClass:"hljs-function"},[s._v("("),t("span",{staticClass:"hljs-params"},[s._v("e")]),s._v(") =>")]),s._v(" {\n "),t("span",{staticClass:"hljs-comment"},[s._v("// 你的自定义逻辑")]),s._v("\n }\n})\n")])]),t("p",[s._v("当传了"),t("code",[s._v("customHandleMousewheel")]),s._v("选项,"),t("code",[s._v("mousewheelAction")]),s._v("选项将不生效。")]),t("h2",[s._v("完整示例")]),t("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVU+P20QU/ypPRshZlNipxCkkpeXPAYlFqNedFXLsSTJlPGM842SXyBKqkFpKK4FAQiqXLZcWCXFCiO628GU2yfIteOPxON6QAzciOZp57/fe7828P7P0bmdZMC+oN/CGKs5ZpkFRXWQ3iWBpJnMNS8jppAtSHMpCaJp0Qc0izuXiDp1ACZNcpuCjB7+xOGQiOYwyqyKeQjGnvRSlvTTKiEcEABGcajAygxyBKDi38jCE1avvVl89Xv/1xfq3i82TL68e3tvce7F68MPV0+dExFIoDVGs2Zx+JBOq0HobUefo+IAIh4qLPKdC30awFIjDk3T8z6VM/QpkqB7cXz/+6e+XZ+uz++uLJ1evfr16+ujyj3PnQcvplFM8uqKLGaW8cdU5gNFNWJqYr7EE84gXFAF7paMRWH54G/xUzqkPg1piPNX3ERRZEmn6rhQTNu1UHKjbiWGwjwFPpUs8W2mO16Ss0wq2deV04VLlOCgfQCLjIkW3wZTq9zk1y3dOP0g6fm2JUemICZr7B11rhbFGA+vd/IhnBMRriaxY0xNtxMRbn72wSbXFYH5l7cwA4xnjCR7NgI+2Pnbc7WXZZbo8f7Q5f7ZLdp1wD+nxVtfG/U8RuGUtc3ZMMH1HSm264GOpmK2KI5/Tifa74MeYOkzTcQUvD96y/QWAZb/58dvVN7/YoGyfXZ5/fXnxe7sIpej4Al1/YnsNPXbMtgvm/0Om9LaooN2PTQc4nKXHosRvGNopg/MFN5riaMBKxx3AMGFziHmk1Ih4dRDv0VQSr1LXAJZstU0pImQYorYNdJ60lHwcGYhVEj0cF1pjE9+KOYs/rSD7mhwtlsvdEXKtge3wwGmxeXaxevi86uWt7OXP6+//9KEsh6EldNE1kbrVMGxdBG6VPuX2Tm7VI5V4QWjnaN2xAVVpECtFvCatQevOXFoWLNGzAdzo91+vcABZUyg5RUZMWqWoasx8r+3erXO1NYzGSvJCW0MAU24D6Nc7LbPt5t/0M8qmM4S/2e9nJ455P+8bjjmN8ilDXuc1i5KEiakTNKEHdar/Y8Q3XAR10M0eHWKZVjnwup7NgHm5grtKCnwoK/ekVmAGmgFAPHwHbdcHIS6DHMcvS6lJVm+cy4WiOTohXt3Ae95GYzvTOlODMOQnnwl1qgKpVC8WvTFld/HYQcTZaSFiFcQyDbHGqVZ7asPQ1IcpvfIftRG5qQ=="}})])}],l={},v=l,c=a("2877"),i=Object(c["a"])(v,e,n,!1,null,null,null);t["default"]=i.exports}}]);
|
||||
2
dist/js/chunk-2d216004.js
vendored
2
dist/js/chunk-2d216004.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d216037.js
vendored
2
dist/js/chunk-2d216037.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216037"],{c13f:function(s,t,n){"use strict";n.r(t);var a=function(){var s=this;s._self._c;return s._m(0)},e=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("开启节点自由拖拽")]),t("p",[s._v("节点支持自由拖拽,也就是可以把它拖动到你指定的位置,默认是不开启的,如果需要开启可以在实例化"),t("code",[s._v("simple-mind-map")]),s._v("时传入开启的选项:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v("\n})\n")])]),t("p",[s._v("也可以动态切换是否开启:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.updateConfig({\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),t("span",{staticClass:"hljs-comment"},[s._v("// false")]),s._v("\n})\n")])]),t("p",[s._v("自由拖拽很容器将节点拖的乱七八糟,所以也可以通过命令回到默认的位置:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.execCommand("),t("span",{staticClass:"hljs-string"},[s._v("'RESET_LAYOUT'")]),s._v(")\n")])]),t("p",[s._v("也可以使用快捷键"),t("code",[s._v("Ctrl + L")]),s._v("来恢复。")]),t("h2",[s._v("完整示例")]),t("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVd1uG0UUfpVhEVoH2buuxJVxSksbJKSEolAuUDeqxrtje8rszLIzm8SyVgoF1EKIFASiFdxAVQFCQFWBEE2oeJmsnb4FZ3b2L44veldLa82c853znZnzM1PrchQ52wmxelZf+jGNFJJEJdFFj9MwErFCUxSTYRsJviESrkjQRnKMGRM7m2SIUjSMRYhs8GBXFhuUBxs4MirPkiBmpBOCtBPiyLM8jpDHGVFIyzRyFfGEMSN3XZQ9/Tr7/GD2397sr+P5d5+efnF7fvtJdvfe6Y+/eNwXXCqEfUW3yTsiIBKs64haN7ZWPF6iqLwWEf5WTMjVGI8ACEdpDTGTJAdpqrt3ZgcPZvcfZYc/Zf/uZYePTu/8Ov/m8Wz/29n+09KPEqMRIw0/rRW0ehFNdcRnOZxtzBICiJeWyTW+OLOTRAFW5IrgQzpq5Z4QIhwPap7eUt8QuEoh/LQ4wezjB9nDg2fH90//eJj980n2eK+MOiaQynU8EYk6G3IZAtkl/hURhpgHLXtz7b216zfXL39w7f3rdum/ynrrvLnOGtkps10dgfVQIPwkJFw5I6LWGNHLNydvA0dhCYdWmHIS2yttYwVXgXvGu/55lhZ4VkNkxIrsKi32rNkPT0xdmHrSv7RwpoH+mLIgJlyDb9Q+FtwtZVlkOjn6cn708yLZWcIlpFu1rol7QRGUy0JW2lFO1aYQSjfSu0JSRQUHS5uRobLbyPYhdZCmrQK+WJ95K2lVuvK66V6EoCTn33+VHf5m4jVdfHK0f3L8d7P2BG/ZHFhvmk4GspbetpH+X6dS1fWGmt1eNViJM/RQr/D1XTPDYHrBRhEYPNBjsEOoH9Bt5DMs5apnFUFcJaHwrFxdAGhQa6sqBUjfBW0TWHpSQrAB1hCj9FR/kCglOLrkM+p/mEOawwOQ0+niYHoD2dlnfz6793tz+NioB+JzM8lGadp3DUlBCjEtkjZ6HxjPz4gFD/X5ylXfbVwfbKWaMHOTl4ox71mOa2Z7MQIcIkPHl9KzqmJwGjddJnOHBmrcQxe63VdyHEJRVXkxAUZIda7Ii1Z/Ly9mpHRVG+KBFCxRxhAhXb891C12SkT15jz9mNDRGOCvdbvRbsm8nPfVkjnE8YgCb+k1wkFAObSEEVShO0WBPGfEF8oIiqCrPTiE4s5zYLUtkwH9mjq3pODweOfuvUIBGagmimfB22zGiOPC0olhntOQ6GR1BrHYkSQGJ55VtPiS91rbjpWKZM912e5HXE6kI6Ts+LwzIPQWHNvBjE4S7kvHF6ELnUGUXFIbmqY4TGql/wPpBfrv"}})])}],l={},r=l,i=n("2877"),p=Object(i["a"])(r,a,e,!1,null,null,null);t["default"]=p.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216037"],{c13f:function(s,t,n){"use strict";n.r(t);var a=function(){var s=this;s._self._c;return s._m(0)},e=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("开启节点自由拖拽")]),t("blockquote",[t("p",[s._v("节点自由拖拽的连线可能不会符合你的预期,这个问题基本上不会改,所以自由拖拽功能不建议使用。")])]),t("p",[s._v("节点支持自由拖拽,也就是可以把它拖动到你指定的位置,默认是不开启的,如果需要开启可以在实例化"),t("code",[s._v("simple-mind-map")]),s._v("时传入开启的选项:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("new")]),s._v(" MindMap({\n "),t("span",{staticClass:"hljs-comment"},[s._v("// ...")]),s._v("\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v("\n})\n")])]),t("p",[s._v("也可以动态切换是否开启:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.updateConfig({\n "),t("span",{staticClass:"hljs-attr"},[s._v("enableFreeDrag")]),s._v(": "),t("span",{staticClass:"hljs-literal"},[s._v("true")]),t("span",{staticClass:"hljs-comment"},[s._v("// false")]),s._v("\n})\n")])]),t("p",[s._v("自由拖拽很容器将节点拖的乱七八糟,所以也可以通过命令回到默认的位置:")]),t("pre",{staticClass:"hljs"},[t("code",[s._v("mindMap.execCommand("),t("span",{staticClass:"hljs-string"},[s._v("'RESET_LAYOUT'")]),s._v(")\n")])]),t("p",[s._v("也可以使用快捷键"),t("code",[s._v("Ctrl + L")]),s._v("来恢复。")]),t("h2",[s._v("完整示例")]),t("iframe",{staticStyle:{width:"100%",height:"455px",border:"none"},attrs:{src:"https://wanglin2.github.io/playground/#eNrFVd1uG0UUfpVhEVoH2buuxJVxSksbJKSEolAuUDeqxrtje8rszLIzm8SyVgoF1EKIFASiFdxAVQFCQFWBEE2oeJmsnb4FZ3b2L44veldLa82c853znZnzM1PrchQ52wmxelZf+jGNFJJEJdFFj9MwErFCUxSTYRsJviESrkjQRnKMGRM7m2SIUjSMRYhs8GBXFhuUBxs4MirPkiBmpBOCtBPiyLM8jpDHGVFIyzRyFfGEMSN3XZQ9/Tr7/GD2397sr+P5d5+efnF7fvtJdvfe6Y+/eNwXXCqEfUW3yTsiIBKs64haN7ZWPF6iqLwWEf5WTMjVGI8ACEdpDTGTJAdpqrt3ZgcPZvcfZYc/Zf/uZYePTu/8Ov/m8Wz/29n+09KPEqMRIw0/rRW0ehFNdcRnOZxtzBICiJeWyTW+OLOTRAFW5IrgQzpq5Z4QIhwPap7eUt8QuEoh/LQ4wezjB9nDg2fH90//eJj980n2eK+MOiaQynU8EYk6G3IZAtkl/hURhpgHLXtz7b216zfXL39w7f3rdum/ynrrvLnOGtkps10dgfVQIPwkJFw5I6LWGNHLNydvA0dhCYdWmHIS2yttYwVXgXvGu/55lhZ4VkNkxIrsKi32rNkPT0xdmHrSv7RwpoH+mLIgJlyDb9Q+FtwtZVlkOjn6cn708yLZWcIlpFu1rol7QRGUy0JW2lFO1aYQSjfSu0JSRQUHS5uRobLbyPYhdZCmrQK+WJ95K2lVuvK66V6EoCTn33+VHf5m4jVdfHK0f3L8d7P2BG/ZHFhvmk4GspbetpH+X6dS1fWGmt1eNViJM/RQr/D1XTPDYHrBRhEYPNBjsEOoH9Bt5DMs5apnFUFcJaHwrFxdAGhQa6sqBUjfBW0TWHpSQrAB1hCj9FR/kCglOLrkM+p/mEOawwOQ0+niYHoD2dlnfz6793tz+NioB+JzM8lGadp3DUlBCjEtkjZ6HxjPz4gFD/X5ylXfbVwfbKWaMHOTl4ox71mOa2Z7MQIcIkPHl9KzqmJwGjddJnOHBmrcQxe63VdyHEJRVXkxAUZIda7Ii1Z/Ly9mpHRVG+KBFCxRxhAhXb891C12SkT15jz9mNDRGOCvdbvRbsm8nPfVkjnE8YgCb+k1wkFAObSEEVShO0WBPGfEF8oIiqCrPTiE4s5zYLUtkwH9mjq3pODweOfuvUIBGagmimfB22zGiOPC0olhntOQ6GR1BrHYkSQGJ55VtPiS91rbjpWKZM912e5HXE6kI6Ts+LwzIPQWHNvBjE4S7kvHF6ELnUGUXFIbmqY4TGql/wPpBfrv"}})])}],l={},r=l,i=n("2877"),p=Object(i["a"])(r,a,e,!1,null,null,null);t["default"]=p.exports}}]);
|
||||
2
dist/js/chunk-2d216642.js
vendored
2
dist/js/chunk-2d216642.js
vendored
File diff suppressed because one or more lines are too long
1
dist/js/chunk-2d216f87.js
vendored
Normal file
1
dist/js/chunk-2d216f87.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d216f87"],{c576:function(e,t,n){"use strict";n.r(t);var _=function(){var e=this;e._self._c;return e._m(0)},v=[function(){var e=this,t=e._self._c;return t("div",[t("h1",[e._v("TextEdit 实例")]),t("p",[e._v("节点文本编辑实例。可以通过"),t("code",[e._v("mindMap.renderer.textEdit")]),e._v("获取到。")]),t("h2",[e._v("方法")]),t("h3",[e._v("isShowTextEdit()")]),t("p",[e._v("获取当前文本编辑框是否处于显示状态,也就是是否处在文本编辑状态。")]),t("h3",[e._v("hideEditTextBox()")]),t("p",[e._v("隐藏文本编辑框,会将当前文本编辑框中的内容设置为节点文本。")]),t("h3",[e._v("registerTmpShortcut()")]),t("p",[e._v("注册临时快捷键,也就是可以通过 Enter 键和 Tab 键完成编辑。")]),t("h3",[e._v("show({ node})")]),t("ul",[t("li",[t("code",[e._v("node")]),e._v(":要进入编辑的节点实例")])]),t("p",[e._v("手动开启节点编辑。默认会在节点双击、按 F2 时进入节点编辑。")])])}],i={},r=i,d=n("2877"),o=Object(d["a"])(r,_,v,!1,null,null,null);t["default"]=o.exports}}]);
|
||||
2
dist/js/chunk-2d217907.js
vendored
2
dist/js/chunk-2d217907.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d21d064.js
vendored
2
dist/js/chunk-2d21d064.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d21d064"],{d013:function(s,a,t){"use strict";t.r(a);var n=function(){var s=this;s._self._c;return s._m(0)},_=[function(){var s=this,a=s._self._c;return a("div",[a("h1",[s._v("如何实现搜索替换")]),a("blockquote",[a("p",[s._v("需要先注册 Search 插件")])]),a("p",[s._v("要实现搜索替换很简单,你只要先创建两个输入框,两个按钮,然后调用相关方法即可。")]),a("p",[s._v("第一个输入框用于搜索,可以绑定一个回车事件,然后调用如下方法:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.search.search("),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".searchText, "),a("span",{staticClass:"hljs-function"},[s._v("() =>")]),s._v(" {\n "),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".$refs.searchInputRef.focus()\n})\n")])]),a("p",[a("code",[s._v("search")]),s._v("方法调用一次就会跳转到下一个匹配的节点,当搜索文本改变后再调用,默认会重新搜索从头开始。")]),a("p",[a("code",[s._v("search")]),s._v("方法第二个参数是一个回调函数,当本次搜索完成,即在跳转到节点后调用,一般需要在这个回调函数里重新让你的输入框聚焦,因为激活节点会拿走焦点,所以你需要把焦点拿回来。")]),a("p",[s._v("第二个输入框用于替换,替换支持单个替换和全部替换,需要注意的是要先在调用了"),a("code",[s._v("search")]),s._v("方法后才能调用这两个方法,单个替换只需要调用如下方法:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.search.replace("),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".replaceText, "),a("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v(")\n")])]),a("p",[s._v("第二个参数传"),a("code",[s._v("true")]),s._v("会在替换完成后自动跳转到下一个匹配的节点,这样可以进行连续替换。")]),a("p",[s._v("要进行全部替换可以调用如下方法:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.search.replaceAll("),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".replaceText)\n")])]),a("p",[s._v("最后你可以通过监听"),a("code",[s._v("search_info_change")]),s._v("方法来获取匹配的节点数量和当前定位到的索引:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.on("),a("span",{staticClass:"hljs-string"},[s._v("'search_info_change'")]),s._v(", "),a("span",{staticClass:"hljs-function"},[a("span",{staticClass:"hljs-params"},[s._v("data")]),s._v(" =>")]),s._v(" {\n "),a("span",{staticClass:"hljs-built_in"},[s._v("console")]),s._v(".log("),a("span",{staticClass:"hljs-string"},[s._v("'当前所在:'")]),s._v("+ (data.currentIndex + "),a("span",{staticClass:"hljs-number"},[s._v("1")]),s._v("), "),a("span",{staticClass:"hljs-string"},[s._v("'匹配总数:'")]),s._v(" + data.total)\n})\n")])])])}],c={},l=c,e=t("2877"),i=Object(e["a"])(l,n,_,!1,null,null,null);a["default"]=i.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d21d064"],{d013:function(s,a,t){"use strict";t.r(a);var n=function(){var s=this;s._self._c;return s._m(0)},_=[function(){var s=this,a=s._self._c;return a("div",[a("h1",[s._v("如何实现搜索替换")]),a("blockquote",[a("p",[s._v("需要先注册 Search 插件")])]),a("p",[s._v("要实现搜索替换很简单,你只要先创建两个输入框,两个按钮,然后调用相关方法即可。")]),a("p",[s._v("第一个输入框用于搜索,可以绑定一个回车事件,然后调用如下方法:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.search.search("),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".searchText, "),a("span",{staticClass:"hljs-function"},[s._v("() =>")]),s._v(" {\n "),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".$refs.searchInputRef.focus()\n})\n")])]),a("p",[a("code",[s._v("search")]),s._v("方法调用一次就会跳转到下一个匹配的节点,当搜索文本改变后再调用,默认会重新搜索从头开始。")]),a("p",[a("code",[s._v("search")]),s._v("方法第二个参数是一个回调函数,当本次搜索完成,即在跳转到节点后调用,一般需要在这个回调函数里重新让你的输入框聚焦,因为激活节点会拿走焦点,所以你需要把焦点拿回来。")]),a("p",[s._v("第二个输入框用于替换,替换支持单个替换和全部替换,需要注意的是要先在调用了"),a("code",[s._v("search")]),s._v("方法后才能调用这两个方法,单个替换只需要调用如下方法:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.search.replace("),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".replaceText, "),a("span",{staticClass:"hljs-literal"},[s._v("true")]),s._v(")\n")])]),a("p",[s._v("第二个参数传"),a("code",[s._v("true")]),s._v("会在替换完成后自动跳转到下一个匹配的节点,这样可以进行连续替换。")]),a("p",[s._v("要进行全部替换可以调用如下方法:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.search.replaceAll("),a("span",{staticClass:"hljs-built_in"},[s._v("this")]),s._v(".replaceText)\n")])]),a("p",[s._v("最后你可以通过监听"),a("code",[s._v("search_info_change")]),s._v("方法来获取匹配的节点数量和当前定位到的索引:")]),a("pre",{staticClass:"hljs"},[a("code",[s._v("mindMap.on("),a("span",{staticClass:"hljs-string"},[s._v("'search_info_change'")]),s._v(", "),a("span",{staticClass:"hljs-function"},[a("span",{staticClass:"hljs-params"},[s._v("data")]),s._v(" =>")]),s._v(" {\n "),a("span",{staticClass:"hljs-built_in"},[s._v("console")]),s._v(".log("),a("span",{staticClass:"hljs-string"},[s._v("'当前所在:'")]),s._v("+ (data.currentIndex + "),a("span",{staticClass:"hljs-number"},[s._v("1")]),s._v("), "),a("span",{staticClass:"hljs-string"},[s._v("'匹配总数:'")]),s._v(" + data.total)\n})\n")])]),a("p",[s._v("如果是只读模式下搜索,搜索匹配到的节点不会被激活,而是被高亮。")])])}],c={},l=c,e=t("2877"),i=Object(e["a"])(l,n,_,!1,null,null,null);a["default"]=i.exports}}]);
|
||||
2
dist/js/chunk-2d221c76.js
vendored
2
dist/js/chunk-2d221c76.js
vendored
@@ -1 +1 @@
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d221c76"],{cc99:function(s,t,i){"use strict";i.r(t);var n=function(){var s=this;s._self._c;return s._m(0)},a=[function(){var s=this,t=s._self._c;return t("div",[t("h1",[s._v("开启节点富文本编辑")]),t("p",[s._v("默认节点编辑是不支持富文本模式的,如果要开启需要使用富文本编辑插件,但是富文本编辑模式目前存在缺陷,详情可以阅读"),t("a",{attrs:{href:"https://wanglin2.github.io/mind-map/#/doc/zh/richText"}},[s._v("richText")]),s._v("。")]),t("p",[s._v("富文本编辑的优势就是可以对一个节点内的部分文本设置样式,所以通常来说还需要搭配一个悬浮的工具栏,这个功能默认也是没有的,涉及到UI的功能一般都不提供,所以也需要你自行开发,如何渲染这个悬浮工具栏可以阅读"),t("a",{attrs:{href:"https://wanglin2.github.io/mind-map/#/doc/zh/course16"}},[s._v("如何渲染富文本的悬浮工具栏")]),s._v("。")]),t("p",[s._v("如果也你需要动态切换是否开启富文本编辑的功能可以参考如下代码:")]),t("pre",{staticClass:"hljs"},[t("code",[t("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" MindMap "),t("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),t("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map'")]),s._v("\n"),t("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" RichText "),t("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),t("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map/src/plugins/RichText.js'")]),s._v("\n"),t("span",{staticClass:"hljs-comment"},[s._v("// import RichText from 'simple-mind-map/src/RichText.js' v0.6.0以下版本使用该路径")]),s._v("\n\n"),t("span",{staticClass:"hljs-comment"},[s._v("// 动态开启富文本编辑")]),s._v("\nmindMap.addPlugin(RichText)\n\n"),t("span",{staticClass:"hljs-comment"},[s._v("// 动态关闭富文本编辑")]),s._v("\nmindMap.removePlugin(RichText)\n")])]),t("p",[s._v("如果你使用的是"),t("code",[s._v("simpleMindMap.umd.js")]),s._v("或"),t("code",[s._v("simpleMindMap.esm.js")]),s._v("这种打包后的完整版,那么是不支持切换的,默认是就是开启的,如有相关需求可以提"),t("a",{attrs:{href:"https://github.com/wanglin2/mind-map/issues"}},[s._v("issue")]),s._v("。")])])}],c={},e=c,p=i("2877"),l=Object(p["a"])(e,n,a,!1,null,null,null);t["default"]=l.exports}}]);
|
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d221c76"],{cc99:function(s,n,t){"use strict";t.r(n);var i=function(){var s=this;s._self._c;return s._m(0)},a=[function(){var s=this,n=s._self._c;return n("div",[n("h1",[s._v("开启节点富文本编辑")]),n("p",[s._v("默认节点编辑是不支持富文本模式的,如果要开启需要使用富文本编辑插件。")]),n("p",[s._v("富文本编辑的优势就是可以对一个节点内的部分文本设置样式,所以通常来说还需要搭配一个悬浮的工具栏,这个功能默认也是没有的,涉及到UI的功能库都不提供,所以也需要你自行开发,如何渲染这个悬浮工具栏可以阅读"),n("a",{attrs:{href:"https://wanglin2.github.io/mind-map/#/doc/zh/course16"}},[s._v("如何渲染富文本的悬浮工具栏")]),s._v("。")]),n("p",[s._v("如果也你需要动态切换是否开启富文本编辑的功能可以参考如下代码:")]),n("pre",{staticClass:"hljs"},[n("code",[n("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" MindMap "),n("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),n("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map'")]),s._v("\n"),n("span",{staticClass:"hljs-keyword"},[s._v("import")]),s._v(" RichText "),n("span",{staticClass:"hljs-keyword"},[s._v("from")]),s._v(" "),n("span",{staticClass:"hljs-string"},[s._v("'simple-mind-map/src/plugins/RichText.js'")]),s._v("\n"),n("span",{staticClass:"hljs-comment"},[s._v("// import RichText from 'simple-mind-map/src/RichText.js' v0.6.0以下版本使用该路径")]),s._v("\n\n"),n("span",{staticClass:"hljs-comment"},[s._v("// 动态开启富文本编辑")]),s._v("\nmindMap.addPlugin(RichText)\n\n"),n("span",{staticClass:"hljs-comment"},[s._v("// 动态关闭富文本编辑")]),s._v("\nmindMap.removePlugin(RichText)\n")])]),n("p",[s._v("如果你使用的是"),n("code",[s._v("simpleMindMap.umd.js")]),s._v("或"),n("code",[s._v("simpleMindMap.esm.js")]),s._v("这种打包后的完整版,那么是不支持切换的,默认是就是开启的。")])])}],c={},p=c,l=t("2877"),e=Object(l["a"])(p,i,a,!1,null,null,null);n["default"]=e.exports}}]);
|
||||
2
dist/js/chunk-2d2253c4.js
vendored
2
dist/js/chunk-2d2253c4.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/chunk-2d2375fa.js
vendored
2
dist/js/chunk-2d2375fa.js
vendored
File diff suppressed because one or more lines are too long
1
dist/js/chunk-3b7380d1.js
vendored
Normal file
1
dist/js/chunk-3b7380d1.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
dist/js/chunk-7f271756.js
vendored
1
dist/js/chunk-7f271756.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="icon" href="dist/logo.ico"><title>思绪思维导图</title><script>// 自定义静态资源的路径
|
||||
window.externalPublicPath = './dist/'
|
||||
// 接管应用
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?8fccd498baeca61b68aa" rel="stylesheet"><link href="dist/css/app.css?8fccd498baeca61b68aa" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?dc223b3a0a24b7dd7194" rel="stylesheet"><link href="dist/css/app.css?dc223b3a0a24b7dd7194" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
@@ -66,4 +66,4 @@
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
// 实例化页面
|
||||
window.initApp()
|
||||
}</script><script src="dist/js/chunk-vendors.js?8fccd498baeca61b68aa"></script><script src="dist/js/app.js?8fccd498baeca61b68aa"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?dc223b3a0a24b7dd7194"></script><script src="dist/js/app.js?dc223b3a0a24b7dd7194"></script></body></html>
|
||||
@@ -162,19 +162,16 @@ class MindMap {
|
||||
render(callback, source = '') {
|
||||
this.batchExecution.push('render', () => {
|
||||
this.initTheme()
|
||||
this.renderer.reRender = false
|
||||
this.renderer.render(callback, source)
|
||||
})
|
||||
}
|
||||
|
||||
// 重新渲染
|
||||
reRender(callback, source = '') {
|
||||
this.batchExecution.push('render', () => {
|
||||
this.clearDraw()
|
||||
this.initTheme()
|
||||
this.renderer.reRender = true
|
||||
this.renderer.render(callback, source)
|
||||
})
|
||||
this.renderer.reRender = true // 标记为重新渲染
|
||||
this.renderer.clearCache() // 清空节点缓存池
|
||||
this.clearDraw() // 清空画布
|
||||
this.render(callback, (source = ''))
|
||||
}
|
||||
|
||||
// 获取或更新容器尺寸位置信息
|
||||
@@ -410,20 +407,34 @@ class MindMap {
|
||||
draw.translate(-rect.x + elRect.left, -rect.y + elRect.top)
|
||||
// 克隆一份数据
|
||||
let clone = svg.clone()
|
||||
// 如果实际图形宽高超出了屏幕宽高,且存在水印的话需要重新绘制水印,否则会出现超出部分没有水印的问题
|
||||
if (
|
||||
!ignoreWatermark &&
|
||||
(rect.width > origWidth || rect.height > origHeight) &&
|
||||
this.watermark &&
|
||||
this.watermark.hasWatermark()
|
||||
) {
|
||||
this.width = rect.width
|
||||
this.height = rect.height
|
||||
this.watermark.draw()
|
||||
clone = svg.clone()
|
||||
this.width = origWidth
|
||||
this.height = origHeight
|
||||
this.watermark.draw()
|
||||
// 是否存在水印
|
||||
const hasWatermark = this.watermark && this.watermark.hasWatermark()
|
||||
if (!ignoreWatermark && hasWatermark) {
|
||||
this.watermark.isInExport = true
|
||||
// 是否是仅导出时需要水印
|
||||
const { onlyExport } = this.opt.watermarkConfig
|
||||
// 是否需要重新绘制水印
|
||||
const needReDrawWatermark =
|
||||
rect.width > origWidth || rect.height > origHeight
|
||||
// 如果实际图形宽高超出了屏幕宽高,且存在水印的话需要重新绘制水印,否则会出现超出部分没有水印的问题
|
||||
if (needReDrawWatermark) {
|
||||
this.width = rect.width
|
||||
this.height = rect.height
|
||||
this.watermark.onResize()
|
||||
clone = svg.clone()
|
||||
this.width = origWidth
|
||||
this.height = origHeight
|
||||
this.watermark.onResize()
|
||||
} else if (onlyExport) {
|
||||
// 如果是仅导出时需要水印,那么需要进行绘制
|
||||
this.watermark.onResize()
|
||||
clone = svg.clone()
|
||||
}
|
||||
// 如果是仅导出时需要水印,需要清除
|
||||
if (onlyExport) {
|
||||
this.watermark.clear()
|
||||
}
|
||||
this.watermark.isInExport = false
|
||||
}
|
||||
// 添加必要的样式
|
||||
clone.add(SVG(`<style>${cssContent}</style>`))
|
||||
@@ -495,7 +506,10 @@ class MindMap {
|
||||
}
|
||||
// 移除插件
|
||||
;[...MindMap.pluginList].forEach(plugin => {
|
||||
if (this[plugin.instanceName] && this[plugin.instanceName].beforePluginDestroy) {
|
||||
if (
|
||||
this[plugin.instanceName] &&
|
||||
this[plugin.instanceName].beforePluginDestroy
|
||||
) {
|
||||
this[plugin.instanceName].beforePluginDestroy()
|
||||
}
|
||||
this[plugin.instanceName] = null
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.9.1-fix.2",
|
||||
"version": "0.9.2",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -332,12 +332,6 @@ export const ERROR_TYPES = {
|
||||
EXPORT_LOAD_IMAGE_ERROR: 'export_load_image_error'
|
||||
}
|
||||
|
||||
// a4纸的宽高
|
||||
export const a4Size = {
|
||||
width: 592.28,
|
||||
height: 841.89
|
||||
}
|
||||
|
||||
// css
|
||||
export const cssContent = `
|
||||
/* 鼠标hover和激活时渲染的矩形 */
|
||||
|
||||
@@ -40,6 +40,7 @@ export const defaultOpt = {
|
||||
enableFreeDrag: false,
|
||||
// 水印配置
|
||||
watermarkConfig: {
|
||||
onlyExport: false,// 是否仅在导出时添加水印
|
||||
text: '',
|
||||
lineSpacing: 100,
|
||||
textSpacing: 100,
|
||||
@@ -97,7 +98,7 @@ export const defaultOpt = {
|
||||
// 是否在点击了画布外的区域时结束节点文本的编辑状态
|
||||
isEndNodeTextEditOnClickOuter: true,
|
||||
// 最大历史记录数
|
||||
maxHistoryCount: 1000,
|
||||
maxHistoryCount: 500,
|
||||
// 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示
|
||||
alwaysShowExpandBtn: false,
|
||||
// 扩展节点可插入的图标
|
||||
@@ -238,5 +239,22 @@ export const defaultOpt = {
|
||||
*/
|
||||
createNewNodeBehavior: CONSTANTS.CREATE_NEW_NODE_BEHAVIOR.DEFAULT,
|
||||
// 当节点图片加载失败时显示的默认图片
|
||||
defaultNodeImage: ''
|
||||
defaultNodeImage: '',
|
||||
// 是否将思维导图限制在画布内
|
||||
// 比如向右拖动时,思维导图图形的最左侧到达画布中心时将无法继续向右拖动,其他同理
|
||||
isLimitMindMapInCanvas: false,
|
||||
// 当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas不再起作用
|
||||
isLimitMindMapInCanvasWhenHasScrollbar: true,
|
||||
// 在节点上粘贴剪贴板中的图片的处理方法,默认是转换为data:url数据插入到节点中,你可以通过该方法来将图片数据上传到服务器,实现保存图片的url
|
||||
// 可以传递一个异步方法,接收Blob类型的图片数据,需要返回如下结构:
|
||||
/*
|
||||
{
|
||||
url, // 图片url
|
||||
size: {
|
||||
width, // 图片的宽度
|
||||
height //图片的高度
|
||||
}
|
||||
}
|
||||
*/
|
||||
handleNodePasteImg: null
|
||||
}
|
||||
|
||||
@@ -44,13 +44,10 @@ export default class KeyCommand {
|
||||
this.isInSvg = true
|
||||
})
|
||||
this.mindMap.on('svg_mouseleave', () => {
|
||||
if (this.mindMap.richText && this.mindMap.richText.showTextEdit) {
|
||||
return
|
||||
}
|
||||
if (this.mindMap.renderer.textEdit.isShowTextEdit()) return
|
||||
if (
|
||||
this.mindMap.renderer.textEdit.showTextEdit ||
|
||||
(this.mindMap.associativeLine &&
|
||||
this.mindMap.associativeLine.showTextEdit)
|
||||
this.mindMap.associativeLine &&
|
||||
this.mindMap.associativeLine.showTextEdit
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@ class Event extends EventEmitter {
|
||||
|
||||
// 绑定函数上下文
|
||||
bindFn() {
|
||||
this.onBodyMousedown = this.onBodyMousedown.bind(this)
|
||||
this.onBodyClick = this.onBodyClick.bind(this)
|
||||
this.onDrawClick = this.onDrawClick.bind(this)
|
||||
this.onMousedown = this.onMousedown.bind(this)
|
||||
this.onMousemove = this.onMousemove.bind(this)
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
this.onNodeMouseup = this.onNodeMouseup.bind(this)
|
||||
this.onMousewheel = this.onMousewheel.bind(this)
|
||||
this.onContextmenu = this.onContextmenu.bind(this)
|
||||
this.onSvgMousedown = this.onSvgMousedown.bind(this)
|
||||
@@ -44,12 +46,14 @@ class Event extends EventEmitter {
|
||||
|
||||
// 绑定事件
|
||||
bind() {
|
||||
document.body.addEventListener('mousedown', this.onBodyMousedown)
|
||||
document.body.addEventListener('click', this.onBodyClick)
|
||||
this.mindMap.svg.on('click', this.onDrawClick)
|
||||
this.mindMap.el.addEventListener('mousedown', this.onMousedown)
|
||||
this.mindMap.svg.on('mousedown', this.onSvgMousedown)
|
||||
window.addEventListener('mousemove', this.onMousemove)
|
||||
window.addEventListener('mouseup', this.onMouseup)
|
||||
this.on('node_mouseup', this.onNodeMouseup)
|
||||
this.mindMap.el.addEventListener('wheel', this.onMousewheel)
|
||||
this.mindMap.svg.on('contextmenu', this.onContextmenu)
|
||||
this.mindMap.svg.on('mouseenter', this.onMouseenter)
|
||||
@@ -59,11 +63,13 @@ class Event extends EventEmitter {
|
||||
|
||||
// 解绑事件
|
||||
unbind() {
|
||||
document.body.removeEventListener('mousedown', this.onBodyMousedown)
|
||||
document.body.removeEventListener('click', this.onBodyClick)
|
||||
this.mindMap.svg.off('click', this.onDrawClick)
|
||||
this.mindMap.el.removeEventListener('mousedown', this.onMousedown)
|
||||
window.removeEventListener('mousemove', this.onMousemove)
|
||||
window.removeEventListener('mouseup', this.onMouseup)
|
||||
this.off('node_mouseup', this.onNodeMouseup)
|
||||
this.mindMap.el.removeEventListener('wheel', this.onMousewheel)
|
||||
this.mindMap.svg.off('contextmenu', this.onContextmenu)
|
||||
this.mindMap.svg.off('mouseenter', this.onMouseenter)
|
||||
@@ -76,6 +82,11 @@ class Event extends EventEmitter {
|
||||
this.emit('draw_click', e)
|
||||
}
|
||||
|
||||
// 页面的鼠标按下事件
|
||||
onBodyMousedown(e) {
|
||||
this.emit('body_mousedown', e)
|
||||
}
|
||||
|
||||
// 页面的单击事件
|
||||
onBodyClick(e) {
|
||||
this.emit('body_click', e)
|
||||
@@ -122,28 +133,33 @@ class Event extends EventEmitter {
|
||||
|
||||
// 鼠标松开事件
|
||||
onMouseup(e) {
|
||||
this.isLeftMousedown = false
|
||||
this.isRightMousedown = false
|
||||
this.isMiddleMousedown = false
|
||||
this.onNodeMouseup()
|
||||
this.emit('mouseup', e, this)
|
||||
}
|
||||
|
||||
// 鼠标滚动
|
||||
// 节点鼠标松开事件
|
||||
onNodeMouseup() {
|
||||
this.isLeftMousedown = false
|
||||
this.isRightMousedown = false
|
||||
this.isMiddleMousedown = false
|
||||
}
|
||||
|
||||
// 鼠标滚动/触控板滑动
|
||||
onMousewheel(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let dir
|
||||
if (e.deltaY < 0) dir = CONSTANTS.DIR.UP
|
||||
if (e.deltaY > 0) dir = CONSTANTS.DIR.DOWN
|
||||
if (e.deltaX < 0) dir = CONSTANTS.DIR.LEFT
|
||||
if (e.deltaX > 0) dir = CONSTANTS.DIR.RIGHT
|
||||
const dirs = []
|
||||
if (e.deltaY < 0) dirs.push(CONSTANTS.DIR.UP)
|
||||
if (e.deltaY > 0) dirs.push(CONSTANTS.DIR.DOWN)
|
||||
if (e.deltaX < 0) dirs.push(CONSTANTS.DIR.LEFT)
|
||||
if (e.deltaX > 0) dirs.push(CONSTANTS.DIR.RIGHT)
|
||||
// 判断是否是触控板
|
||||
let isTouchPad = false
|
||||
// mac、windows
|
||||
if (e.wheelDeltaY === e.deltaY * -3 || Math.abs(e.wheelDeltaY) <= 10) {
|
||||
isTouchPad = true
|
||||
}
|
||||
this.emit('mousewheel', e, dir, this, isTouchPad)
|
||||
this.emit('mousewheel', e, dirs, this, isTouchPad)
|
||||
}
|
||||
|
||||
// 鼠标右键菜单事件
|
||||
|
||||
@@ -276,9 +276,6 @@ class Render {
|
||||
})
|
||||
// 插入同级节点
|
||||
this.mindMap.keyCommand.addShortcut('Enter', () => {
|
||||
if (this.textEdit.showTextEdit) {
|
||||
return
|
||||
}
|
||||
this.mindMap.execCommand('INSERT_NODE')
|
||||
})
|
||||
// 插入父节点
|
||||
@@ -323,16 +320,18 @@ class Render {
|
||||
this.mindMap.keyCommand.addShortcut('Control+Down', () => {
|
||||
this.mindMap.execCommand('DOWN_NODE')
|
||||
})
|
||||
// 复制节点、剪切节点、粘贴节点的快捷键需开发者自行注册实现,可参考demo
|
||||
// 复制节点、
|
||||
this.mindMap.keyCommand.addShortcut('Control+c', () => {
|
||||
this.copy()
|
||||
})
|
||||
this.mindMap.keyCommand.addShortcut('Control+v', () => {
|
||||
this.onPaste()
|
||||
})
|
||||
// 剪切节点
|
||||
this.mindMap.keyCommand.addShortcut('Control+x', () => {
|
||||
this.cut()
|
||||
})
|
||||
// 粘贴节点
|
||||
this.mindMap.keyCommand.addShortcut('Control+v', () => {
|
||||
this.paste()
|
||||
})
|
||||
// 根节点居中显示
|
||||
this.mindMap.keyCommand.addShortcut('Control+Enter', () => {
|
||||
this.setRootNodeCenter()
|
||||
@@ -387,6 +386,13 @@ class Render {
|
||||
this.mindMap.keyCommand.restore()
|
||||
}
|
||||
|
||||
// 清空节点缓存池
|
||||
clearCache() {
|
||||
this.layout.lru.clear()
|
||||
this.nodeCache = {}
|
||||
this.lastNodeCache = {}
|
||||
}
|
||||
|
||||
// 渲染
|
||||
render(callback = () => {}, source) {
|
||||
// 如果当前还没有渲染完毕,不再触发渲染
|
||||
@@ -431,6 +437,9 @@ class Render {
|
||||
this.waitRenderingParams = []
|
||||
this.render(...params)
|
||||
} else {
|
||||
if (this.reRender) {
|
||||
this.reRender = false
|
||||
}
|
||||
// 触发一次保存,因为修改了渲染树的数据
|
||||
if (
|
||||
this.mindMap.richText &&
|
||||
@@ -866,6 +875,7 @@ class Render {
|
||||
// 复制节点
|
||||
copy() {
|
||||
this.beingCopyData = this.copyNode()
|
||||
if (!this.beingCopyData) return
|
||||
setDataToClipboard({
|
||||
simpleMindMap: true,
|
||||
data: this.beingCopyData
|
||||
@@ -883,17 +893,13 @@ class Render {
|
||||
})
|
||||
}
|
||||
|
||||
// 粘贴节点
|
||||
paste() {
|
||||
if (this.beingCopyData) {
|
||||
this.mindMap.execCommand('PASTE_NODE', this.beingCopyData)
|
||||
}
|
||||
}
|
||||
|
||||
// 粘贴事件
|
||||
async onPaste() {
|
||||
const { errorHandler, handleIsSplitByWrapOnPasteCreateNewNode } =
|
||||
this.mindMap.opt
|
||||
// 粘贴
|
||||
async paste() {
|
||||
const {
|
||||
errorHandler,
|
||||
handleIsSplitByWrapOnPasteCreateNewNode,
|
||||
handleNodePasteImg
|
||||
} = this.mindMap.opt
|
||||
// 读取剪贴板的文字和图片
|
||||
let text = null
|
||||
let img = null
|
||||
@@ -996,7 +1002,13 @@ class Render {
|
||||
// 存在图片,则添加到当前激活节点
|
||||
if (img) {
|
||||
try {
|
||||
let imgData = await loadImage(img)
|
||||
let imgData = null
|
||||
// 自定义图片处理函数
|
||||
if (handleNodePasteImg && typeof handleNodePasteImg === 'function') {
|
||||
imgData = await handleNodePasteImg(img)
|
||||
} else {
|
||||
imgData = await loadImage(img)
|
||||
}
|
||||
if (this.activeNodeList.length > 0) {
|
||||
this.activeNodeList.forEach(node => {
|
||||
this.mindMap.execCommand('SET_NODE_IMAGE', node, {
|
||||
@@ -1013,7 +1025,9 @@ class Render {
|
||||
}
|
||||
} else {
|
||||
// 粘贴节点数据
|
||||
this.paste()
|
||||
if (this.beingCopyData) {
|
||||
this.mindMap.execCommand('PASTE_NODE', this.beingCopyData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1205,7 +1219,7 @@ class Render {
|
||||
// 复制节点
|
||||
copyNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
return null
|
||||
}
|
||||
const nodeList = getTopAncestorsFomNodeList(this.activeNodeList)
|
||||
return nodeList.map(node => {
|
||||
@@ -1363,7 +1377,7 @@ class Render {
|
||||
0
|
||||
)
|
||||
this.mindMap.render(() => {
|
||||
this.mindMap.view.reset()
|
||||
this.setRootNodeCenter()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ export default class TextEdit {
|
||||
this.showTextEdit = false
|
||||
// 如果编辑过程中缩放画布了,那么缓存当前编辑的内容
|
||||
this.cacheEditingText = ''
|
||||
this.hasBodyMousedown = false
|
||||
this.bindEvent()
|
||||
}
|
||||
|
||||
@@ -38,7 +39,12 @@ export default class TextEdit {
|
||||
// 隐藏文本编辑框
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
this.mindMap.on('body_mousedown', () => {
|
||||
this.hasBodyMousedown = true
|
||||
})
|
||||
this.mindMap.on('body_click', () => {
|
||||
if (!this.hasBodyMousedown) return
|
||||
this.hasBodyMousedown = false
|
||||
// 隐藏文本编辑框
|
||||
if (this.mindMap.opt.isEndNodeTextEditOnClickOuter) {
|
||||
this.hideEditTextBox()
|
||||
@@ -126,6 +132,14 @@ export default class TextEdit {
|
||||
})
|
||||
}
|
||||
|
||||
// 获取当前文本编辑框是否处于显示状态,也就是是否处在文本编辑状态
|
||||
isShowTextEdit() {
|
||||
if (this.mindMap.richText) {
|
||||
return this.mindMap.richText.showTextEdit
|
||||
}
|
||||
return this.showTextEdit
|
||||
}
|
||||
|
||||
// 显示文本编辑框
|
||||
// isInserting:是否是刚创建的节点
|
||||
// isFromKeyDown:是否是在按键事件进入的编辑
|
||||
|
||||
@@ -165,6 +165,11 @@ class Node {
|
||||
this.top = 0
|
||||
}
|
||||
|
||||
// 节点被删除时需要复位的数据
|
||||
resetWhenDelete() {
|
||||
this._isMouseenter = false
|
||||
}
|
||||
|
||||
// 处理数据
|
||||
handleData(data) {
|
||||
data.data.expand = data.data.expand === false ? false : true
|
||||
@@ -182,7 +187,10 @@ class Node {
|
||||
}
|
||||
// 如果没有返回内容,那么还是使用内置的节点内容
|
||||
if (this._customNodeContent) {
|
||||
this._customNodeContent.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
this._customNodeContent.setAttribute(
|
||||
'xmlns',
|
||||
'http://www.w3.org/1999/xhtml'
|
||||
)
|
||||
return
|
||||
}
|
||||
this._imgData = this.createImgNode()
|
||||
@@ -694,6 +702,7 @@ class Node {
|
||||
// 销毁节点,不但会从画布删除,而且原节点直接置空,后续无法再插回画布
|
||||
destroy() {
|
||||
if (!this.group) return
|
||||
this.resetWhenDelete()
|
||||
this.group.remove()
|
||||
this.removeGeneralization()
|
||||
this.removeLine()
|
||||
@@ -825,9 +834,9 @@ class Node {
|
||||
this.renderer.layout.renderLine(
|
||||
this,
|
||||
this._lines,
|
||||
(line, node) => {
|
||||
(...args) => {
|
||||
// 添加样式
|
||||
this.styleLine(line, node)
|
||||
this.styleLine(...args)
|
||||
},
|
||||
this.style.getStyle('lineStyle', true)
|
||||
)
|
||||
@@ -882,19 +891,26 @@ class Node {
|
||||
}
|
||||
|
||||
// 设置连线样式
|
||||
styleLine(line, node) {
|
||||
let width =
|
||||
node.getSelfInhertStyle('lineWidth') || node.getStyle('lineWidth', true)
|
||||
let color =
|
||||
node.getSelfInhertStyle('lineColor') || node.getStyle('lineColor', true)
|
||||
let dasharray =
|
||||
node.getSelfInhertStyle('lineDasharray') ||
|
||||
node.getStyle('lineDasharray', true)
|
||||
this.style.line(line, {
|
||||
width,
|
||||
color,
|
||||
dasharray
|
||||
})
|
||||
styleLine(line, childNode, enableMarker) {
|
||||
const width =
|
||||
childNode.getSelfInhertStyle('lineWidth') ||
|
||||
childNode.getStyle('lineWidth', true)
|
||||
const color =
|
||||
childNode.getSelfInhertStyle('lineColor') ||
|
||||
childNode.getStyle('lineColor', true)
|
||||
const dasharray =
|
||||
childNode.getSelfInhertStyle('lineDasharray') ||
|
||||
childNode.getStyle('lineDasharray', true)
|
||||
this.style.line(
|
||||
line,
|
||||
{
|
||||
width,
|
||||
color,
|
||||
dasharray
|
||||
},
|
||||
enableMarker,
|
||||
childNode
|
||||
)
|
||||
}
|
||||
|
||||
// 移除连线
|
||||
|
||||
@@ -55,6 +55,9 @@ class Style {
|
||||
// 构造函数
|
||||
constructor(ctx) {
|
||||
this.ctx = ctx
|
||||
// 箭头图标
|
||||
this._markerPath = null
|
||||
this._marker = null
|
||||
}
|
||||
|
||||
// 合并样式
|
||||
@@ -190,8 +193,38 @@ class Style {
|
||||
}
|
||||
|
||||
// 连线
|
||||
line(node, { width, color, dasharray } = {}) {
|
||||
node.stroke({ width, color, dasharray }).fill({ color: 'none' })
|
||||
line(line, { width, color, dasharray } = {}, enableMarker, childNode) {
|
||||
line.stroke({ color, dasharray, width }).fill({ color: 'none' })
|
||||
// 可以显示箭头
|
||||
if (enableMarker) {
|
||||
const showMarker = this.merge('showLineMarker', true)
|
||||
const childNodeStyle = childNode.style
|
||||
// 显示箭头
|
||||
if (showMarker) {
|
||||
// 创建子节点箭头标记
|
||||
childNodeStyle._marker =
|
||||
childNodeStyle._marker || childNodeStyle.createMarker()
|
||||
// 设置样式
|
||||
childNodeStyle._markerPath.stroke({ color }).fill({ color })
|
||||
line.marker('end', childNodeStyle._marker)
|
||||
} else if (childNodeStyle._marker) {
|
||||
// 不显示箭头,则删除该子节点的箭头标记
|
||||
line.attr('marker-end', '')
|
||||
childNodeStyle._marker.remove()
|
||||
childNodeStyle._marker = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建箭头
|
||||
createMarker() {
|
||||
return this.ctx.lineDraw.marker(20, 20, add => {
|
||||
add.ref(8, 5)
|
||||
add.size(20, 20)
|
||||
add.attr('markerUnits', 'userSpaceOnUse')
|
||||
add.attr('orient', 'auto-start-reverse')
|
||||
this._markerPath = add.path('M0,0 L2,5 L0,10 L10,5 Z')
|
||||
})
|
||||
}
|
||||
|
||||
// 概要连线
|
||||
|
||||
@@ -37,7 +37,7 @@ class View {
|
||||
this.mindMap.event.on('drag', (e, event) => {
|
||||
// 按住ctrl键拖动为多选
|
||||
// 禁用拖拽
|
||||
if (e.ctrlKey || this.mindMap.opt.isDisableDrag) {
|
||||
if (e.ctrlKey || this.mindMap.opt.isDisableDrag) {
|
||||
return
|
||||
}
|
||||
if (this.firstDrag) {
|
||||
@@ -55,8 +55,8 @@ class View {
|
||||
this.firstDrag = true
|
||||
})
|
||||
// 放大缩小视图
|
||||
this.mindMap.event.on('mousewheel', (e, dir, event, isTouchPad) => {
|
||||
let {
|
||||
this.mindMap.event.on('mousewheel', (e, dirs, event, isTouchPad) => {
|
||||
const {
|
||||
customHandleMousewheel,
|
||||
mousewheelAction,
|
||||
mouseScaleCenterUseMousePosition,
|
||||
@@ -71,55 +71,61 @@ class View {
|
||||
) {
|
||||
return customHandleMousewheel(e)
|
||||
}
|
||||
// 鼠标滚轮事件控制缩放
|
||||
// 1.鼠标滚轮事件控制缩放
|
||||
if (mousewheelAction === CONSTANTS.MOUSE_WHEEL_ACTION.ZOOM || e.ctrlKey) {
|
||||
if (disableMouseWheelZoom) return
|
||||
const { x: clientX, y: clientY } = this.mindMap.toPos(
|
||||
e.clientX,
|
||||
e.clientY
|
||||
)
|
||||
let cx = mouseScaleCenterUseMousePosition ? clientX : undefined
|
||||
let cy = mouseScaleCenterUseMousePosition ? clientY : undefined
|
||||
switch (dir) {
|
||||
const cx = mouseScaleCenterUseMousePosition ? clientX : undefined
|
||||
const cy = mouseScaleCenterUseMousePosition ? clientY : undefined
|
||||
// 如果来自触控板,那么过滤掉左右的移动
|
||||
if (
|
||||
isTouchPad &&
|
||||
(dirs.includes(CONSTANTS.DIR.LEFT) ||
|
||||
dirs.includes(CONSTANTS.DIR.RIGHT))
|
||||
) {
|
||||
dirs = dirs.filter(dir => {
|
||||
return ![CONSTANTS.DIR.LEFT, CONSTANTS.DIR.RIGHT].includes(dir)
|
||||
})
|
||||
}
|
||||
switch (true) {
|
||||
// 鼠标滚轮,向上和向左,都是缩小
|
||||
case CONSTANTS.DIR.UP:
|
||||
case CONSTANTS.DIR.LEFT:
|
||||
case dirs.includes(CONSTANTS.DIR.UP || CONSTANTS.DIR.LEFT):
|
||||
mousewheelZoomActionReverse
|
||||
? this.enlarge(cx, cy, isTouchPad)
|
||||
: this.narrow(cx, cy, isTouchPad)
|
||||
break
|
||||
// 鼠标滚轮,向下和向右,都是放大
|
||||
case CONSTANTS.DIR.DOWN:
|
||||
case CONSTANTS.DIR.RIGHT:
|
||||
case dirs.includes(CONSTANTS.DIR.DOWN || CONSTANTS.DIR.RIGHT):
|
||||
mousewheelZoomActionReverse
|
||||
? this.narrow(cx, cy, isTouchPad)
|
||||
: this.enlarge(cx, cy, isTouchPad)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// 鼠标滚轮事件控制画布移动
|
||||
let step = mousewheelMoveStep
|
||||
if (isTouchPad) {
|
||||
step = 5
|
||||
// 2.鼠标滚轮事件控制画布移动
|
||||
const step = isTouchPad ? 5 : mousewheelMoveStep
|
||||
let mx = 0
|
||||
let my = 0
|
||||
// 上移
|
||||
if (dirs.includes(CONSTANTS.DIR.DOWN)) {
|
||||
my = -step
|
||||
}
|
||||
switch (dir) {
|
||||
// 上移
|
||||
case CONSTANTS.DIR.DOWN:
|
||||
this.translateY(-step)
|
||||
break
|
||||
// 下移
|
||||
case CONSTANTS.DIR.UP:
|
||||
this.translateY(step)
|
||||
break
|
||||
// 右移
|
||||
case CONSTANTS.DIR.LEFT:
|
||||
this.translateX(-step)
|
||||
break
|
||||
// 左移
|
||||
case CONSTANTS.DIR.RIGHT:
|
||||
this.translateX(step)
|
||||
break
|
||||
// 下移
|
||||
if (dirs.includes(CONSTANTS.DIR.UP)) {
|
||||
my = step
|
||||
}
|
||||
// 右移
|
||||
if (dirs.includes(CONSTANTS.DIR.LEFT)) {
|
||||
mx = step
|
||||
}
|
||||
// 左移
|
||||
if (dirs.includes(CONSTANTS.DIR.RIGHT)) {
|
||||
mx = -step
|
||||
}
|
||||
this.translateXY(mx, my)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -188,6 +194,9 @@ class View {
|
||||
|
||||
// 应用变换
|
||||
transform() {
|
||||
try {
|
||||
this.limitMindMapInCanvas()
|
||||
} catch (error) {}
|
||||
this.mindMap.draw.transform({
|
||||
origin: [0, 0],
|
||||
scale: this.scale,
|
||||
@@ -254,18 +263,17 @@ class View {
|
||||
|
||||
// 适应画布大小
|
||||
fit() {
|
||||
let { fitPadding } = this.mindMap.opt
|
||||
let draw = this.mindMap.draw
|
||||
let origTransform = draw.transform()
|
||||
let rect = draw.rbox()
|
||||
let drawWidth = rect.width / origTransform.scaleX
|
||||
let drawHeight = rect.height / origTransform.scaleY
|
||||
let drawRatio = drawWidth / drawHeight
|
||||
let { width: elWidth, height: elHeight } =
|
||||
this.mindMap.elRect
|
||||
const { fitPadding } = this.mindMap.opt
|
||||
const draw = this.mindMap.draw
|
||||
const origTransform = draw.transform()
|
||||
const rect = draw.rbox()
|
||||
const drawWidth = rect.width / origTransform.scaleX
|
||||
const drawHeight = rect.height / origTransform.scaleY
|
||||
const drawRatio = drawWidth / drawHeight
|
||||
let { width: elWidth, height: elHeight } = this.mindMap.elRect
|
||||
elWidth = elWidth - fitPadding * 2
|
||||
elHeight = elHeight - fitPadding * 2
|
||||
let elRatio = elWidth / elHeight
|
||||
const elRatio = elWidth / elHeight
|
||||
let newScale = 0
|
||||
let flag = ''
|
||||
if (drawWidth <= elWidth && drawHeight <= elHeight) {
|
||||
@@ -286,7 +294,10 @@ class View {
|
||||
newScale = newWidth / drawWidth
|
||||
}
|
||||
this.setScale(newScale)
|
||||
let newRect = draw.rbox()
|
||||
const newRect = draw.rbox()
|
||||
// 需要考虑画布容器距浏览器窗口左上角的距离
|
||||
newRect.x -= this.mindMap.elRect.left
|
||||
newRect.y -= this.mindMap.elRect.top
|
||||
let newX = 0
|
||||
let newY = 0
|
||||
if (flag === 1) {
|
||||
@@ -301,6 +312,73 @@ class View {
|
||||
}
|
||||
this.translateXY(newX, newY)
|
||||
}
|
||||
|
||||
// 将思维导图限制在画布内
|
||||
limitMindMapInCanvas() {
|
||||
const { isLimitMindMapInCanvasWhenHasScrollbar, isLimitMindMapInCanvas } =
|
||||
this.mindMap.opt
|
||||
// 如果注册了滚动条插件,那么使用isLimitMindMapInCanvasWhenHasScrollbar配置
|
||||
if (this.mindMap.scrollbar) {
|
||||
if (!isLimitMindMapInCanvasWhenHasScrollbar) return
|
||||
} else {
|
||||
// 否则使用isLimitMindMapInCanvas配置
|
||||
if (!isLimitMindMapInCanvas) return
|
||||
}
|
||||
|
||||
let { scale, left, top, right, bottom } = this.getPositionLimit()
|
||||
|
||||
// 如果缩放值改变了
|
||||
const scaleRatio = this.scale / scale
|
||||
left *= scaleRatio
|
||||
right *= scaleRatio
|
||||
top *= scaleRatio
|
||||
bottom *= scaleRatio
|
||||
|
||||
// 加上画布中心点距离
|
||||
const centerX = this.mindMap.width / 2
|
||||
const centerY = this.mindMap.height / 2
|
||||
const scaleOffset = this.scale - 1
|
||||
left -= scaleOffset * centerX
|
||||
right -= scaleOffset * centerX
|
||||
top -= scaleOffset * centerY
|
||||
bottom -= scaleOffset * centerY
|
||||
|
||||
// 判断是否超出边界
|
||||
if (this.x > left) {
|
||||
this.x = left
|
||||
}
|
||||
if (this.x < right) {
|
||||
this.x = right
|
||||
}
|
||||
if (this.y > top) {
|
||||
this.y = top
|
||||
}
|
||||
if (this.y < bottom) {
|
||||
this.y = bottom
|
||||
}
|
||||
}
|
||||
|
||||
// 计算图形四个方向的位置边界值
|
||||
getPositionLimit() {
|
||||
const { scaleX, scaleY } = this.mindMap.draw.transform()
|
||||
const drawRect = this.mindMap.draw.rbox()
|
||||
const rootRect = this.mindMap.renderer.root.group.rbox()
|
||||
const rootCenterOffset = this.mindMap.renderer.layout.getRootCenterOffset(
|
||||
rootRect.width,
|
||||
rootRect.height
|
||||
)
|
||||
const left = rootRect.x - drawRect.x - rootCenterOffset.x * scaleX
|
||||
const right = rootRect.x - drawRect.x2 - rootCenterOffset.x * scaleX
|
||||
const top = rootRect.y - drawRect.y - rootCenterOffset.y * scaleY
|
||||
const bottom = rootRect.y - drawRect.y2 - rootCenterOffset.y * scaleY
|
||||
return {
|
||||
scale: scaleX,
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default View
|
||||
|
||||
@@ -17,6 +17,8 @@ class Base {
|
||||
// 根节点
|
||||
this.root = null
|
||||
this.lru = new Lru(this.mindMap.opt.maxNodeCacheCount)
|
||||
// 当initRootNodePosition不为默认的值时,根节点的位置距默认的配置时根节点距离的差值
|
||||
this.rootNodeCenterOffset = null
|
||||
}
|
||||
|
||||
// 计算节点位置
|
||||
@@ -41,7 +43,7 @@ class Base {
|
||||
cacheNode(uid, node) {
|
||||
// 记录本次渲染时的节点
|
||||
this.renderer.nodeCache[uid] = node
|
||||
// 记录所有渲染时的节点
|
||||
// 缓存所有渲染过的节点
|
||||
this.lru.add(uid, node)
|
||||
}
|
||||
|
||||
@@ -70,11 +72,12 @@ class Base {
|
||||
// 创建节点实例
|
||||
createNode(data, parent, isRoot, layerIndex) {
|
||||
// 创建节点
|
||||
const uid = data.data.uid
|
||||
let newNode = null
|
||||
// 数据上保存了节点引用,那么直接复用节点
|
||||
if (data && data._node && !this.renderer.reRender) {
|
||||
newNode = data._node
|
||||
let isLayerTypeChange = this.checkIsLayerTypeChange(
|
||||
const isLayerTypeChange = this.checkIsLayerTypeChange(
|
||||
newNode.layerIndex,
|
||||
layerIndex
|
||||
)
|
||||
@@ -87,43 +90,49 @@ class Base {
|
||||
newNode.getSize()
|
||||
newNode.needLayout = true
|
||||
}
|
||||
} else if (this.lru.has(data.data.uid) && !this.renderer.reRender) {
|
||||
// 数据上没有保存节点引用,但是通过uid找到了缓存的节点,也可以复用
|
||||
newNode = this.lru.get(data.data.uid)
|
||||
} else if (
|
||||
(this.lru.has(uid) || this.renderer.lastNodeCache[uid]) &&
|
||||
!this.renderer.reRender
|
||||
) {
|
||||
// 节点数据上没有节点实例
|
||||
// 但是通过uid在节点缓存池中找到了缓存的节点
|
||||
// 或者在上一次渲染缓存对象中找到了节点
|
||||
// 也可以直接复用
|
||||
newNode = this.lru.get(uid) || this.renderer.lastNodeCache[uid]
|
||||
// 保存该节点上一次的数据
|
||||
let lastData = JSON.stringify(newNode.getData())
|
||||
let isLayerTypeChange = this.checkIsLayerTypeChange(
|
||||
const lastData = JSON.stringify(newNode.getData())
|
||||
const isLayerTypeChange = this.checkIsLayerTypeChange(
|
||||
newNode.layerIndex,
|
||||
layerIndex
|
||||
)
|
||||
newNode.reset()
|
||||
newNode.nodeData = newNode.handleData(data || {})
|
||||
newNode.layerIndex = layerIndex
|
||||
this.cacheNode(data.data.uid, newNode)
|
||||
this.cacheNode(uid, newNode)
|
||||
this.checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(newNode)
|
||||
data._node = newNode
|
||||
// 主题或主题配置改变了需要重新计算节点大小和布局
|
||||
let isResizeSource = this.checkIsNeedResizeSources()
|
||||
const isResizeSource = this.checkIsNeedResizeSources()
|
||||
// 节点数据改变了需要重新计算节点大小和布局
|
||||
let isNodeDataChange = lastData !== JSON.stringify(data.data)
|
||||
const isNodeDataChange = lastData !== JSON.stringify(data.data)
|
||||
if (isResizeSource || isNodeDataChange || isLayerTypeChange) {
|
||||
newNode.getSize()
|
||||
newNode.needLayout = true
|
||||
}
|
||||
} else {
|
||||
// 创建新节点
|
||||
let uid = data.data.uid || createUid()
|
||||
const newUid = uid || createUid()
|
||||
newNode = new Node({
|
||||
data,
|
||||
uid,
|
||||
uid: newUid,
|
||||
renderer: this.renderer,
|
||||
mindMap: this.mindMap,
|
||||
draw: this.draw,
|
||||
layerIndex
|
||||
})
|
||||
// uid保存到数据上,为了节点复用
|
||||
data.data.uid = uid
|
||||
this.cacheNode(uid, newNode)
|
||||
data.data.uid = newUid
|
||||
this.cacheNode(newUid, newNode)
|
||||
// 数据关联实际节点
|
||||
data._node = newNode
|
||||
if (data.data.isActive) {
|
||||
@@ -161,17 +170,21 @@ class Base {
|
||||
}
|
||||
}
|
||||
|
||||
// 定位节点到画布中间
|
||||
setNodeCenter(node) {
|
||||
let { initRootNodePosition } = this.mindMap.opt
|
||||
let { CENTER } = CONSTANTS.INIT_ROOT_NODE_POSITION
|
||||
if (
|
||||
!initRootNodePosition ||
|
||||
!Array.isArray(initRootNodePosition) ||
|
||||
initRootNodePosition.length < 2
|
||||
) {
|
||||
initRootNodePosition = [CENTER, CENTER]
|
||||
// 规范initRootNodePosition配置
|
||||
formatInitRootNodePosition(pos) {
|
||||
const { CENTER } = CONSTANTS.INIT_ROOT_NODE_POSITION
|
||||
if (!pos || !Array.isArray(pos) || pos.length < 2) {
|
||||
pos = [CENTER, CENTER]
|
||||
}
|
||||
return pos
|
||||
}
|
||||
|
||||
// 定位节点到画布中间
|
||||
setNodeCenter(node, position) {
|
||||
let { initRootNodePosition } = this.mindMap.opt
|
||||
initRootNodePosition = this.formatInitRootNodePosition(
|
||||
position || initRootNodePosition
|
||||
)
|
||||
node.left = this.formatPosition(
|
||||
initRootNodePosition[0],
|
||||
this.mindMap.width,
|
||||
@@ -184,6 +197,42 @@ class Base {
|
||||
)
|
||||
}
|
||||
|
||||
// 当initRootNodePosition配置不为默认的['center','center']时,计算当前配置和默认配置情况下,根节点位置的差值
|
||||
getRootCenterOffset(width, height) {
|
||||
// 因为根节点的大小不会影响这个差值,所以计算一次就足够了
|
||||
if (this.rootNodeCenterOffset) return this.rootNodeCenterOffset
|
||||
let { initRootNodePosition } = this.mindMap.opt
|
||||
const { CENTER } = CONSTANTS.INIT_ROOT_NODE_POSITION
|
||||
initRootNodePosition = this.formatInitRootNodePosition(initRootNodePosition)
|
||||
if (
|
||||
initRootNodePosition[0] === CENTER &&
|
||||
initRootNodePosition[1] === CENTER
|
||||
) {
|
||||
// 如果initRootNodePosition是默认的,那么不需要计算
|
||||
this.rootNodeCenterOffset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
} else {
|
||||
// 否则需要计算当前配置和默认配置的差值
|
||||
const tmpNode = {
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
const tmpNode2 = {
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
this.setNodeCenter(tmpNode, [CENTER, CENTER])
|
||||
this.setNodeCenter(tmpNode2)
|
||||
this.rootNodeCenterOffset = {
|
||||
x: tmpNode2.left - tmpNode.left,
|
||||
y: tmpNode2.top - tmpNode.top
|
||||
}
|
||||
}
|
||||
return this.rootNodeCenterOffset
|
||||
}
|
||||
|
||||
// 更新子节点属性
|
||||
updateChildren(children, prop, offset) {
|
||||
children.forEach(item => {
|
||||
@@ -394,6 +443,12 @@ class Base {
|
||||
getNodeActChildrenLength(node) {
|
||||
return node.nodeData.children && node.nodeData.children.length
|
||||
}
|
||||
|
||||
// 设置连线样式
|
||||
setLineStyle(style, line, path, childNode) {
|
||||
line.plot(path)
|
||||
style && style(line, childNode, true)
|
||||
}
|
||||
}
|
||||
|
||||
export default Base
|
||||
|
||||
@@ -233,8 +233,7 @@ class CatalogOrganization extends Base {
|
||||
`M ${x2},${y1 + s1} L ${x2},${y1 + s1 > y2 ? y2 + item.height : y2}` +
|
||||
nodeUseLineStylePath
|
||||
// 竖线
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
minx = Math.min(minx, x1)
|
||||
maxx = Math.max(maxx, x1)
|
||||
@@ -302,8 +301,7 @@ class CatalogOrganization extends Base {
|
||||
}`
|
||||
: ''
|
||||
path += nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
// 竖线
|
||||
if (len > 0) {
|
||||
|
||||
@@ -300,8 +300,7 @@ class Fishbone extends Base {
|
||||
// 水平线
|
||||
if (node.layerIndex > 1) {
|
||||
let path = `M ${x},${y} L ${item.left},${y}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
}
|
||||
})
|
||||
// 斜线
|
||||
|
||||
@@ -181,8 +181,7 @@ class LogicalStructure extends Base {
|
||||
let path = `M ${x1},${y1} L ${x1 + s1},${y1} L ${x1 + s1},${y2} L ${
|
||||
x2 + nodeUseLineStyleOffset
|
||||
},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -209,8 +208,7 @@ class LogicalStructure extends Base {
|
||||
? ` L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -242,8 +240,7 @@ class LogicalStructure extends Base {
|
||||
} else {
|
||||
path = this.cubicBezierPath(x1, y1, x2, y2) + nodeUseLineStylePath
|
||||
}
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -116,11 +116,7 @@ class MindMap extends Base {
|
||||
this.root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
if (
|
||||
node.getData('expand') &&
|
||||
node.children &&
|
||||
node.children.length
|
||||
) {
|
||||
if (node.getData('expand') && node.children && node.children.length) {
|
||||
let marginY = this.getMarginY(layerIndex + 1)
|
||||
let baseTop = node.top + node.height / 2 + marginY
|
||||
// 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半
|
||||
@@ -247,8 +243,7 @@ class MindMap extends Base {
|
||||
let path = `M ${x1},${y1} L ${x1 + _s},${y1} L ${x1 + _s},${y2} L ${
|
||||
x2 + nodeUseLineStyleOffset
|
||||
},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -287,8 +282,7 @@ class MindMap extends Base {
|
||||
}
|
||||
}
|
||||
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -332,8 +326,7 @@ class MindMap extends Base {
|
||||
} else {
|
||||
path = this.cubicBezierPath(x1, y1, x2, y2) + nodeUseLineStylePath
|
||||
}
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -384,7 +377,8 @@ class MindMap extends Base {
|
||||
x +
|
||||
(isLeft ? -generalizationNodeMargin : generalizationNodeMargin) -
|
||||
(isLeft ? item.generalizationNode.width : 0)
|
||||
item.generalizationNode.top = top + (bottom - top - item.generalizationNode.height) / 2
|
||||
item.generalizationNode.top =
|
||||
top + (bottom - top - item.generalizationNode.height) / 2
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -78,11 +78,7 @@ class OrganizationStructure extends Base {
|
||||
this.root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
if (
|
||||
node.getData('expand') &&
|
||||
node.children &&
|
||||
node.children.length
|
||||
) {
|
||||
if (node.getData('expand') && node.children && node.children.length) {
|
||||
let marginX = this.getMarginY(layerIndex + 1)
|
||||
// 第一个子节点的left值 = 该节点中心的left值 - 子节点的宽度之和的一半
|
||||
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
|
||||
@@ -175,8 +171,7 @@ class OrganizationStructure extends Base {
|
||||
? ` L ${item.left},${y2} L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -210,8 +205,7 @@ class OrganizationStructure extends Base {
|
||||
? ` L ${item.left},${y2} L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
let path = `M ${x2},${y1 + s1} L ${x2},${y2}` + nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
minx = Math.min(x1, minx)
|
||||
maxx = Math.max(x1, maxx)
|
||||
@@ -261,9 +255,9 @@ class OrganizationStructure extends Base {
|
||||
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
item.generalizationLine.plot(path)
|
||||
item.generalizationNode.top = bottom + generalizationNodeMargin
|
||||
item.generalizationNode.left = left + (right - left - item.generalizationNode.width) / 2
|
||||
item.generalizationNode.left =
|
||||
left + (right - left - item.generalizationNode.width) / 2
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 渲染展开收起按钮的隐藏占位元素
|
||||
|
||||
@@ -245,8 +245,7 @@ class Timeline extends Base {
|
||||
let x2 = item.left
|
||||
let y = node.top + node.height / 2
|
||||
let path = `M ${x1},${y} L ${x2},${y}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
prevBother = item
|
||||
})
|
||||
} else {
|
||||
@@ -264,8 +263,7 @@ class Timeline extends Base {
|
||||
}
|
||||
// 水平线
|
||||
let path = `M ${x},${y} L ${item.left},${y}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
// 竖线
|
||||
if (len > 0) {
|
||||
|
||||
@@ -246,8 +246,7 @@ class VerticalTimeline extends Base {
|
||||
let y2 = item.top
|
||||
let x = node.left + node.width / 2
|
||||
let path = `M ${x},${y1} L ${x},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
prevBother = item
|
||||
})
|
||||
} else {
|
||||
@@ -265,8 +264,7 @@ class VerticalTimeline extends Base {
|
||||
L ${nodeRight + offset},${nodeYCenter}
|
||||
L ${nodeRight + offset},${itemYCenter}
|
||||
L ${itemLeft},${itemYCenter}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
} else {
|
||||
let nodeLeft = node.left
|
||||
@@ -281,8 +279,7 @@ class VerticalTimeline extends Base {
|
||||
L ${nodeLeft - offset},${nodeYCenter}
|
||||
L ${nodeLeft - offset},${itemYCenter}
|
||||
L ${itemRight},${itemYCenter}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -306,8 +303,7 @@ class VerticalTimeline extends Base {
|
||||
let y2 = item.top
|
||||
let x = node.left + node.width / 2
|
||||
let path = `M ${x},${y1} L ${x},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
prevBother = item
|
||||
})
|
||||
} else {
|
||||
@@ -322,8 +318,7 @@ class VerticalTimeline extends Base {
|
||||
: item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = `M ${x1},${y1} L ${x2},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -346,8 +341,7 @@ class VerticalTimeline extends Base {
|
||||
let y2 = item.top
|
||||
let x = node.left + node.width / 2
|
||||
let path = `M ${x},${y1} L ${x},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
prevBother = item
|
||||
})
|
||||
} else {
|
||||
@@ -362,8 +356,7 @@ class VerticalTimeline extends Base {
|
||||
: item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = this.cubicBezierPath(x1, y1, x2, y2)
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
this.setLineStyle(style, lines[index], path, item)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -59,43 +59,70 @@ class AssociativeLine {
|
||||
|
||||
// 监听事件
|
||||
bindEvent() {
|
||||
// 节点树渲染完毕后渲染连接线
|
||||
this.renderAllLines = this.renderAllLines.bind(this)
|
||||
this.onDrawClick = this.onDrawClick.bind(this)
|
||||
this.onNodeClick = this.onNodeClick.bind(this)
|
||||
this.removeLine = this.removeLine.bind(this)
|
||||
this.addLine = this.addLine.bind(this)
|
||||
this.onMousemove = this.onMousemove.bind(this)
|
||||
this.onNodeDragging = this.onNodeDragging.bind(this)
|
||||
this.onNodeDragend = this.onNodeDragend.bind(this)
|
||||
this.onControlPointMouseup = this.onControlPointMouseup.bind(this)
|
||||
|
||||
// 节点树渲染完毕后渲染连接线
|
||||
this.mindMap.on('node_tree_render_end', this.renderAllLines)
|
||||
// 状态改变后重新渲染连接线
|
||||
this.mindMap.on('data_change', this.renderAllLines)
|
||||
// 监听画布和节点点击事件,用于清除当前激活的连接线
|
||||
this.mindMap.on('draw_click', () => {
|
||||
if (this.isControlPointMousedown) {
|
||||
return
|
||||
}
|
||||
this.clearActiveLine()
|
||||
})
|
||||
this.mindMap.on('node_click', node => {
|
||||
if (this.isCreatingLine) {
|
||||
this.completeCreateLine(node)
|
||||
} else {
|
||||
this.clearActiveLine()
|
||||
}
|
||||
})
|
||||
this.mindMap.on('draw_click', this.onDrawClick)
|
||||
this.mindMap.on('node_click', this.onNodeClick)
|
||||
// 注册删除快捷键
|
||||
this.mindMap.keyCommand.addShortcut(
|
||||
'Del|Backspace',
|
||||
this.removeLine.bind(this)
|
||||
)
|
||||
this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeLine)
|
||||
// 注册添加连接线的命令
|
||||
this.mindMap.command.add('ADD_ASSOCIATIVE_LINE', this.addLine.bind(this))
|
||||
this.mindMap.command.add('ADD_ASSOCIATIVE_LINE', this.addLine)
|
||||
// 监听鼠标移动事件
|
||||
this.mindMap.on('mousemove', this.onMousemove.bind(this))
|
||||
this.mindMap.on('mousemove', this.onMousemove)
|
||||
// 节点拖拽事件
|
||||
this.mindMap.on('node_dragging', this.onNodeDragging.bind(this))
|
||||
this.mindMap.on('node_dragend', this.onNodeDragend.bind(this))
|
||||
this.mindMap.on('node_dragging', this.onNodeDragging)
|
||||
this.mindMap.on('node_dragend', this.onNodeDragend)
|
||||
// 拖拽控制点
|
||||
this.mindMap.on('mouseup', this.onControlPointMouseup.bind(this))
|
||||
this.mindMap.on('mouseup', this.onControlPointMouseup)
|
||||
// 缩放事件
|
||||
this.mindMap.on('scale', this.onScale)
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
unBindEvent() {
|
||||
this.mindMap.off('node_tree_render_end', this.renderAllLines)
|
||||
this.mindMap.off('data_change', this.renderAllLines)
|
||||
this.mindMap.off('draw_click', this.onDrawClick)
|
||||
this.mindMap.off('node_click', this.onNodeClick)
|
||||
this.mindMap.keyCommand.removeShortcut('Del|Backspace', this.removeLine)
|
||||
this.mindMap.command.remove('ADD_ASSOCIATIVE_LINE', this.addLine)
|
||||
this.mindMap.off('mousemove', this.onMousemove)
|
||||
this.mindMap.off('node_dragging', this.onNodeDragging)
|
||||
this.mindMap.off('node_dragend', this.onNodeDragend)
|
||||
this.mindMap.off('mouseup', this.onControlPointMouseup)
|
||||
this.mindMap.off('scale', this.onScale)
|
||||
}
|
||||
|
||||
// 画布点击事件
|
||||
onDrawClick() {
|
||||
if (this.isControlPointMousedown) {
|
||||
return
|
||||
}
|
||||
this.clearActiveLine()
|
||||
}
|
||||
|
||||
// 节点点击事件
|
||||
onNodeClick(node) {
|
||||
if (this.isCreatingLine) {
|
||||
this.completeCreateLine(node)
|
||||
} else {
|
||||
this.clearActiveLine()
|
||||
}
|
||||
}
|
||||
|
||||
// 创建箭头
|
||||
createMarker() {
|
||||
return this.associativeLineDraw.marker(20, 20, add => {
|
||||
@@ -544,6 +571,16 @@ class AssociativeLine {
|
||||
this.associativeLineDraw.back() // 最底层
|
||||
this.associativeLineDraw.forward() // 连线层上面
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
}
|
||||
|
||||
AssociativeLine.instanceName = 'associativeLine'
|
||||
|
||||
@@ -55,51 +55,68 @@ class Drag extends Base {
|
||||
|
||||
// 绑定事件
|
||||
bindEvent() {
|
||||
this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this)
|
||||
this.mindMap.on('node_mousedown', (node, e) => {
|
||||
// 只读模式、不是鼠标左键按下、按下的是概要节点或根节点直接返回
|
||||
if (
|
||||
this.mindMap.opt.readonly ||
|
||||
e.which !== 1 ||
|
||||
node.isGeneralization ||
|
||||
node.isRoot
|
||||
) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
this.isMousedown = true
|
||||
// 记录鼠标按下时的节点
|
||||
this.mousedownNode = node
|
||||
// 记录鼠标按下的坐标
|
||||
const { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
})
|
||||
this.mindMap.on('mousemove', e => {
|
||||
if (this.mindMap.opt.readonly || !this.isMousedown) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
const { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseMoveX = x
|
||||
this.mouseMoveY = y
|
||||
// 还没开始移动时鼠标位移过小不认为是拖拽
|
||||
if (
|
||||
!this.isDragging &&
|
||||
Math.abs(x - this.mouseDownX) <= this.checkDragOffset &&
|
||||
Math.abs(y - this.mouseDownY) <= this.checkDragOffset
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.mindMap.emit('node_dragging')
|
||||
this.handleStartMove()
|
||||
this.onMove(x, y, e)
|
||||
})
|
||||
this.onNodeMousedown = this.onNodeMousedown.bind(this)
|
||||
this.onMousemove = this.onMousemove.bind(this)
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this)
|
||||
|
||||
this.mindMap.on('node_mousedown', this.onNodeMousedown)
|
||||
this.mindMap.on('mousemove', this.onMousemove)
|
||||
this.mindMap.on('node_mouseup', this.onMouseup)
|
||||
this.mindMap.on('mouseup', this.onMouseup)
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
unBindEvent() {
|
||||
this.mindMap.off('node_mousedown', this.onNodeMousedown)
|
||||
this.mindMap.off('mousemove', this.onMousemove)
|
||||
this.mindMap.off('node_mouseup', this.onMouseup)
|
||||
this.mindMap.off('mouseup', this.onMouseup)
|
||||
}
|
||||
|
||||
// 节点鼠标按下事件
|
||||
onNodeMousedown(node, e) {
|
||||
// 只读模式、不是鼠标左键按下、按下的是概要节点或根节点直接返回
|
||||
if (
|
||||
this.mindMap.opt.readonly ||
|
||||
e.which !== 1 ||
|
||||
node.isGeneralization ||
|
||||
node.isRoot
|
||||
) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
this.isMousedown = true
|
||||
// 记录鼠标按下时的节点
|
||||
this.mousedownNode = node
|
||||
// 记录鼠标按下的坐标
|
||||
const { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
}
|
||||
|
||||
// 鼠标移动事件
|
||||
onMousemove(e) {
|
||||
if (this.mindMap.opt.readonly || !this.isMousedown) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
const { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseMoveX = x
|
||||
this.mouseMoveY = y
|
||||
// 还没开始移动时鼠标位移过小不认为是拖拽
|
||||
if (
|
||||
!this.isDragging &&
|
||||
Math.abs(x - this.mouseDownX) <= this.checkDragOffset &&
|
||||
Math.abs(y - this.mouseDownY) <= this.checkDragOffset
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.mindMap.emit('node_dragging', this.mousedownNode)
|
||||
this.handleStartMove()
|
||||
this.onMove(x, y, e)
|
||||
}
|
||||
|
||||
// 鼠标松开事件
|
||||
onMouseup(e) {
|
||||
if (!this.isMousedown) {
|
||||
@@ -685,6 +702,16 @@ class Drag extends Base {
|
||||
return item.uid === node.uid || item.isAncestor(node)
|
||||
})
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
}
|
||||
|
||||
Drag.instanceName = 'drag'
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import drawBackgroundImageToCanvas from '../utils/simulateCSSBackgroundInCanvas'
|
||||
import { transformToMarkdown } from '../parse/toMarkdown'
|
||||
import { a4Size, ERROR_TYPES } from '../constants/constant'
|
||||
import { ERROR_TYPES } from '../constants/constant'
|
||||
|
||||
// 导出插件
|
||||
class Export {
|
||||
@@ -92,14 +92,7 @@ class Export {
|
||||
}
|
||||
|
||||
// svg转png
|
||||
svgToPng(
|
||||
svgSrc,
|
||||
transparent,
|
||||
checkRotate = () => {
|
||||
return false
|
||||
},
|
||||
compress
|
||||
) {
|
||||
svgToPng(svgSrc, transparent) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
// 跨域图片需要添加这个属性,否则画布被污染了无法导出图片
|
||||
@@ -113,36 +106,27 @@ class Export {
|
||||
)
|
||||
let imgWidth = img.width
|
||||
let imgHeight = img.height
|
||||
// 压缩图片
|
||||
if (compress) {
|
||||
const compressedSize = resizeImgSize(
|
||||
imgWidth,
|
||||
imgHeight,
|
||||
compress.width,
|
||||
compress.height
|
||||
)
|
||||
imgWidth = compressedSize[0]
|
||||
imgHeight = compressedSize[1]
|
||||
}
|
||||
// 如果宽比高长,那么旋转90度
|
||||
const needRotate = checkRotate(imgWidth, imgHeight)
|
||||
if (needRotate) {
|
||||
canvas.width = imgHeight * dpr
|
||||
canvas.height = imgWidth * dpr
|
||||
canvas.style.width = imgHeight + 'px'
|
||||
canvas.style.height = imgWidth + 'px'
|
||||
} else {
|
||||
canvas.width = imgWidth * dpr
|
||||
canvas.height = imgHeight * dpr
|
||||
canvas.style.width = imgWidth + 'px'
|
||||
canvas.style.height = imgHeight + 'px'
|
||||
// 检查是否超出canvas支持的像素上限
|
||||
const maxSize = 16384 / dpr
|
||||
const maxArea = maxSize * maxSize
|
||||
if (imgWidth * imgHeight > maxArea) {
|
||||
let newWidth = null
|
||||
let newHeight = null
|
||||
if (imgWidth > maxSize) {
|
||||
newWidth = maxArea / imgHeight
|
||||
} else if (imgHeight > maxSize) {
|
||||
newHeight = maxArea / imgWidth
|
||||
}
|
||||
const res = resizeImgSize(imgWidth, imgHeight, newWidth, newHeight)
|
||||
imgWidth = res[0]
|
||||
imgHeight = res[1]
|
||||
}
|
||||
canvas.width = imgWidth * dpr
|
||||
canvas.height = imgHeight * dpr
|
||||
canvas.style.width = imgWidth + 'px'
|
||||
canvas.style.height = imgHeight + 'px'
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.scale(dpr, dpr)
|
||||
if (needRotate) {
|
||||
ctx.rotate(0.5 * Math.PI)
|
||||
ctx.translate(0, -imgHeight)
|
||||
}
|
||||
// 绘制背景
|
||||
if (!transparent) {
|
||||
await this.drawBackgroundToCanvas(ctx, imgWidth, imgHeight)
|
||||
@@ -232,31 +216,20 @@ class Export {
|
||||
* 方法1.把svg的图片都转化成data:url格式,再转换
|
||||
* 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换
|
||||
*/
|
||||
async png(name, transparent = false, checkRotate, compress) {
|
||||
async png(name, transparent = false) {
|
||||
const { str } = await this.getSvgData()
|
||||
const svgUrl = await this.fixSvgStrAndToBlob(str)
|
||||
// 绘制到canvas上
|
||||
const res = await this.svgToPng(svgUrl, transparent, checkRotate, compress)
|
||||
const res = await this.svgToPng(svgUrl, transparent)
|
||||
return res
|
||||
}
|
||||
|
||||
// 导出为pdf
|
||||
async pdf(name, useMultiPageExport, maxImageWidth) {
|
||||
async pdf(name, transparent = false) {
|
||||
if (!this.mindMap.doExportPDF) {
|
||||
throw new Error('请注册ExportPDF插件')
|
||||
}
|
||||
const img = await this.png(
|
||||
'',
|
||||
false,
|
||||
(width, height) => {
|
||||
if (width <= a4Size.width && height && a4Size.height) return false
|
||||
return width / height > 1
|
||||
},
|
||||
{
|
||||
width: maxImageWidth || a4Size.width * 2
|
||||
}
|
||||
)
|
||||
await this.mindMap.doExportPDF.pdf(name, img, useMultiPageExport)
|
||||
const img = await this.png(name, transparent)
|
||||
await this.mindMap.doExportPDF.pdf(name, img)
|
||||
}
|
||||
|
||||
// 导出为xmind
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import JsPDF from '../utils/jspdf'
|
||||
import { a4Size } from '../constants/constant'
|
||||
|
||||
// 导出PDF插件,需要通过Export插件使用
|
||||
class ExportPDF {
|
||||
@@ -9,104 +8,20 @@ class ExportPDF {
|
||||
}
|
||||
|
||||
// 导出为pdf
|
||||
async pdf(name, img, useMultiPageExport = false) {
|
||||
if (useMultiPageExport) {
|
||||
await this.multiPageExport(name, img)
|
||||
} else {
|
||||
await this.onePageExport(name, img)
|
||||
}
|
||||
}
|
||||
|
||||
// 单页导出
|
||||
onePageExport(name, img) {
|
||||
async pdf(name, img) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let pdf = new JsPDF({
|
||||
unit: 'pt',
|
||||
format: 'a4',
|
||||
compress: true
|
||||
})
|
||||
let a4Ratio = a4Size.width / a4Size.height
|
||||
let image = new Image()
|
||||
const image = new Image()
|
||||
image.onload = () => {
|
||||
let imageWidth = image.width
|
||||
let imageHeight = image.height
|
||||
let imageRatio = imageWidth / imageHeight
|
||||
let w, h
|
||||
if (imageWidth <= a4Size.width && imageHeight <= a4Size.height) {
|
||||
// 使用图片原始宽高
|
||||
w = imageWidth
|
||||
h = imageHeight
|
||||
} else if (a4Ratio > imageRatio) {
|
||||
// 以a4Height为高度,缩放图片宽度
|
||||
w = imageRatio * a4Size.height
|
||||
h = a4Size.height
|
||||
} else {
|
||||
// 以a4Width为宽度,缩放图片高度
|
||||
w = a4Size.width
|
||||
h = a4Size.width / imageRatio
|
||||
}
|
||||
pdf.addImage(
|
||||
img,
|
||||
'PNG',
|
||||
(a4Size.width - w) / 2,
|
||||
(a4Size.height - h) / 2,
|
||||
w,
|
||||
h
|
||||
)
|
||||
pdf.save(name)
|
||||
resolve()
|
||||
}
|
||||
image.onerror = e => {
|
||||
reject(e)
|
||||
}
|
||||
image.src = img
|
||||
})
|
||||
}
|
||||
|
||||
// 多页导出
|
||||
multiPageExport(name, img) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let image = new Image()
|
||||
image.onload = () => {
|
||||
let imageWidth = image.width
|
||||
let imageHeight = image.height
|
||||
// 一页pdf显示高度
|
||||
let pageHeight = (imageWidth / a4Size.width) * a4Size.height
|
||||
// 未生成pdf的高度
|
||||
let leftHeight = imageHeight
|
||||
// 偏移
|
||||
let position = 0
|
||||
// a4纸的尺寸[595.28,841.89],图片在pdf中图片的宽高
|
||||
let imgWidth = a4Size.width
|
||||
let imgHeight = (a4Size.width / imageWidth) * imageHeight
|
||||
let pdf = new JsPDF({
|
||||
unit: 'pt',
|
||||
format: 'a4',
|
||||
compress: true
|
||||
const imageWidth = image.width
|
||||
const imageHeight = image.height
|
||||
const pdf = new JsPDF({
|
||||
unit: 'px',
|
||||
format: [imageWidth, imageHeight],
|
||||
compress: true,
|
||||
hotfixes: ['px_scaling'],
|
||||
orientation: imageWidth > imageHeight ? 'landscape' : 'portrait'
|
||||
})
|
||||
// 有两个高度需要区分,一个是图片的实际高度,和生成pdf的页面高度(841.89)
|
||||
// 当内容未超过pdf一页显示的范围,无需分页
|
||||
if (leftHeight < pageHeight) {
|
||||
pdf.addImage(
|
||||
img,
|
||||
'PNG',
|
||||
(a4Size.width - imgWidth) / 2,
|
||||
(a4Size.height - imgHeight) / 2,
|
||||
imgWidth,
|
||||
imgHeight
|
||||
)
|
||||
} else {
|
||||
// 分页
|
||||
while (leftHeight > 0) {
|
||||
pdf.addImage(img, 'PNG', 0, position, imgWidth, imgHeight)
|
||||
leftHeight -= pageHeight
|
||||
position -= a4Size.height
|
||||
// 避免添加空白页
|
||||
if (leftHeight > 0) {
|
||||
pdf.addPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
pdf.addImage(img, 'PNG', 0, 0, imageWidth, imageHeight)
|
||||
pdf.save(name)
|
||||
resolve()
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class Formula {
|
||||
// 给指定的节点插入指定公式
|
||||
insertFormulaToNode(node, formula) {
|
||||
let richTextPlugin = this.mindMap.richText
|
||||
richTextPlugin.showEditText(node)
|
||||
richTextPlugin.showEditText({ node })
|
||||
richTextPlugin.quill.insertEmbed(
|
||||
richTextPlugin.quill.getLength() - 1,
|
||||
'formula',
|
||||
|
||||
@@ -7,19 +7,61 @@ class KeyboardNavigation {
|
||||
constructor(opt) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.onKeyup = this.onKeyup.bind(this)
|
||||
this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.LEFT, () => {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.LEFT)
|
||||
})
|
||||
this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.UP, () => {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.UP)
|
||||
})
|
||||
this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.RIGHT, () => {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.RIGHT)
|
||||
})
|
||||
this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.DOWN, () => {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.DOWN)
|
||||
})
|
||||
|
||||
this.addShortcut()
|
||||
}
|
||||
|
||||
addShortcut() {
|
||||
this.onLeftKeyUp = this.onLeftKeyUp.bind(this)
|
||||
this.onUpKeyUp = this.onUpKeyUp.bind(this)
|
||||
this.onRightKeyUp = this.onRightKeyUp.bind(this)
|
||||
this.onDownKeyUp = this.onDownKeyUp.bind(this)
|
||||
|
||||
this.mindMap.keyCommand.addShortcut(
|
||||
CONSTANTS.KEY_DIR.LEFT,
|
||||
this.onLeftKeyUp
|
||||
)
|
||||
this.mindMap.keyCommand.addShortcut(CONSTANTS.KEY_DIR.UP, this.onUpKeyUp)
|
||||
this.mindMap.keyCommand.addShortcut(
|
||||
CONSTANTS.KEY_DIR.RIGHT,
|
||||
this.onRightKeyUp
|
||||
)
|
||||
this.mindMap.keyCommand.addShortcut(
|
||||
CONSTANTS.KEY_DIR.DOWN,
|
||||
this.onDownKeyUp
|
||||
)
|
||||
}
|
||||
|
||||
removeShortcut() {
|
||||
this.mindMap.keyCommand.removeShortcut(
|
||||
CONSTANTS.KEY_DIR.LEFT,
|
||||
this.onLeftKeyUp
|
||||
)
|
||||
this.mindMap.keyCommand.removeShortcut(CONSTANTS.KEY_DIR.UP, this.onUpKeyUp)
|
||||
this.mindMap.keyCommand.removeShortcut(
|
||||
CONSTANTS.KEY_DIR.RIGHT,
|
||||
this.onRightKeyUp
|
||||
)
|
||||
this.mindMap.keyCommand.removeShortcut(
|
||||
CONSTANTS.KEY_DIR.DOWN,
|
||||
this.onDownKeyUp
|
||||
)
|
||||
}
|
||||
|
||||
onLeftKeyUp() {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.LEFT)
|
||||
}
|
||||
|
||||
onUpKeyUp() {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.UP)
|
||||
}
|
||||
|
||||
onRightKeyUp() {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.RIGHT)
|
||||
}
|
||||
|
||||
onDownKeyUp() {
|
||||
this.onKeyup(CONSTANTS.KEY_DIR.DOWN)
|
||||
}
|
||||
|
||||
// 处理按键事件
|
||||
@@ -228,6 +270,16 @@ class KeyboardNavigation {
|
||||
y: (top + bottom) / 2
|
||||
}
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.removeShortcut()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.removeShortcut()
|
||||
}
|
||||
}
|
||||
|
||||
KeyboardNavigation.instanceName = 'keyboardNavigation'
|
||||
|
||||
@@ -96,8 +96,13 @@ class RichText {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.smm-richtext-node-wrap {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.smm-richtext-node-wrap p {
|
||||
font-family: auto;
|
||||
|
||||
}
|
||||
|
||||
.smm-richtext-node-edit-wrap p {
|
||||
@@ -255,8 +260,7 @@ class RichText {
|
||||
this.textEditNode.innerHTML = this.cacheEditingText || html
|
||||
} else {
|
||||
// 已经是富文本
|
||||
this.textEditNode.innerHTML =
|
||||
this.cacheEditingText || nodeText
|
||||
this.textEditNode.innerHTML = this.cacheEditingText || nodeText
|
||||
}
|
||||
this.initQuillEditor()
|
||||
document.querySelector('.ql-editor').style.minHeight = originHeight + 'px'
|
||||
@@ -372,6 +376,8 @@ class RichText {
|
||||
rectInfo,
|
||||
formatInfo
|
||||
)
|
||||
} else {
|
||||
this.mindMap.emit('rich_text_selection_change', false, null, null)
|
||||
}
|
||||
})
|
||||
this.quill.on('text-change', () => {
|
||||
|
||||
@@ -171,6 +171,10 @@ class Scrollbar {
|
||||
const t = this.mindMap.draw.transform()
|
||||
const drawRect = this.mindMap.draw.rbox()
|
||||
const rootRect = this.mindMap.renderer.root.group.rbox()
|
||||
const rootCenterOffset = this.mindMap.renderer.layout.getRootCenterOffset(
|
||||
rootRect.width,
|
||||
rootRect.height
|
||||
)
|
||||
if (type === CONSTANTS.SCROLL_BAR_DIR.VERTICAL) {
|
||||
// 滚动条新位置
|
||||
let oy = offset
|
||||
@@ -178,7 +182,7 @@ class Scrollbar {
|
||||
if (oy <= 0) {
|
||||
oy = 0
|
||||
}
|
||||
let max =
|
||||
const max =
|
||||
((100 - scrollbarData.vertical.height) / 100) *
|
||||
this.scrollbarWrapSize.height
|
||||
if (oy >= max) {
|
||||
@@ -193,7 +197,12 @@ class Scrollbar {
|
||||
// 内边距
|
||||
const paddingY = this.mindMap.height / 2
|
||||
// 图形新位置
|
||||
let chartTop = oyPx + yOffset - paddingY * t.scaleY + paddingY
|
||||
const chartTop =
|
||||
oyPx +
|
||||
yOffset -
|
||||
paddingY * t.scaleY +
|
||||
paddingY -
|
||||
rootCenterOffset.y * t.scaleY
|
||||
this.mindMap.view.translateYTo(chartTop)
|
||||
this.emitEvent({
|
||||
horizontal: scrollbarData.horizontal,
|
||||
@@ -209,7 +218,7 @@ class Scrollbar {
|
||||
if (ox <= 0) {
|
||||
ox = 0
|
||||
}
|
||||
let max =
|
||||
const max =
|
||||
((100 - scrollbarData.horizontal.width) / 100) *
|
||||
this.scrollbarWrapSize.width
|
||||
if (ox >= max) {
|
||||
@@ -217,14 +226,19 @@ class Scrollbar {
|
||||
}
|
||||
// 转换成百分比
|
||||
const oxPercentage = (ox / this.scrollbarWrapSize.width) * 100
|
||||
// 转换成相对于图形高度的距离
|
||||
// 转换成相对于图形宽度的距离
|
||||
const oxPx = (-oxPercentage / 100) * this.chartWidth
|
||||
// 节点中心点到图形最左边的距离
|
||||
const xOffset = rootRect.x - drawRect.x
|
||||
// 内边距
|
||||
const paddingX = this.mindMap.width / 2
|
||||
// 图形新位置
|
||||
let chartLeft = oxPx + xOffset - paddingX * t.scaleX + paddingX
|
||||
const chartLeft =
|
||||
oxPx +
|
||||
xOffset -
|
||||
paddingX * t.scaleX +
|
||||
paddingX -
|
||||
rootCenterOffset.x * t.scaleX
|
||||
this.mindMap.view.translateXTo(chartLeft)
|
||||
this.emitEvent({
|
||||
vertical: scrollbarData.vertical,
|
||||
@@ -247,6 +261,11 @@ class Scrollbar {
|
||||
this.updateMindMapView(type, offset)
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
|
||||
@@ -22,10 +22,19 @@ class Search {
|
||||
this.notResetSearchText = false
|
||||
// 是否自动跳转下一个匹配节点
|
||||
this.isJumpNext = false
|
||||
|
||||
this.bindEvent()
|
||||
}
|
||||
|
||||
bindEvent() {
|
||||
this.onDataChange = this.onDataChange.bind(this)
|
||||
this.mindMap.on('data_change', this.onDataChange)
|
||||
}
|
||||
|
||||
unBindEvent() {
|
||||
this.mindMap.off('data_change', this.onDataChange)
|
||||
}
|
||||
|
||||
// 节点数据改变了,需要重新搜索
|
||||
onDataChange() {
|
||||
if (this.isJumpNext) {
|
||||
@@ -177,6 +186,16 @@ class Search {
|
||||
total: this.matchNodeList.length
|
||||
})
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
}
|
||||
|
||||
Search.instanceName = 'search'
|
||||
|
||||
@@ -18,82 +18,99 @@ class Select {
|
||||
|
||||
// 绑定事件
|
||||
bindEvent() {
|
||||
this.checkInNodes = throttle(this.checkInNodes, 300, this)
|
||||
this.mindMap.on('mousedown', e => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
let { useLeftKeySelectionRightKeyDrag } = this.mindMap.opt
|
||||
if (
|
||||
!e.ctrlKey &&
|
||||
(useLeftKeySelectionRightKeyDrag ? e.which !== 1 : e.which !== 3)
|
||||
) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
this.isMousedown = true
|
||||
this.cacheActiveList = [...this.mindMap.renderer.activeNodeList]
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
this.createRect(x, y)
|
||||
})
|
||||
this.mindMap.on('mousemove', e => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseMoveX = x
|
||||
this.mouseMoveY = y
|
||||
if (
|
||||
Math.abs(x - this.mouseDownX) <= 10 &&
|
||||
Math.abs(y - this.mouseDownY) <= 10
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.clearAutoMoveTimer()
|
||||
this.onMove(
|
||||
e.clientX,
|
||||
e.clientY,
|
||||
() => {
|
||||
this.isSelecting = true
|
||||
// 绘制矩形
|
||||
this.rect.plot([
|
||||
[this.mouseDownX, this.mouseDownY],
|
||||
[this.mouseMoveX, this.mouseDownY],
|
||||
[this.mouseMoveX, this.mouseMoveY],
|
||||
[this.mouseDownX, this.mouseMoveY]
|
||||
])
|
||||
this.checkInNodes()
|
||||
},
|
||||
(dir, step) => {
|
||||
switch (dir) {
|
||||
case 'left':
|
||||
this.mouseDownX += step
|
||||
break
|
||||
case 'top':
|
||||
this.mouseDownY += step
|
||||
break
|
||||
case 'right':
|
||||
this.mouseDownX -= step
|
||||
break
|
||||
case 'bottom':
|
||||
this.mouseDownY -= step
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
this.onMousedown = this.onMousedown.bind(this)
|
||||
this.onMousemove = this.onMousemove.bind(this)
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
this.checkInNodes = throttle(this.checkInNodes, 300, this)
|
||||
|
||||
this.mindMap.on('mousedown', this.onMousedown)
|
||||
this.mindMap.on('mousemove', this.onMousemove)
|
||||
this.mindMap.on('mouseup', this.onMouseup)
|
||||
this.mindMap.on('node_mouseup', this.onMouseup)
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
unBindEvent() {
|
||||
this.mindMap.off('mousedown', this.onMousedown)
|
||||
this.mindMap.off('mousemove', this.onMousemove)
|
||||
this.mindMap.off('mouseup', this.onMouseup)
|
||||
this.mindMap.off('node_mouseup', this.onMouseup)
|
||||
}
|
||||
|
||||
// 鼠标按下
|
||||
onMousedown(e) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
let { useLeftKeySelectionRightKeyDrag } = this.mindMap.opt
|
||||
if (
|
||||
!e.ctrlKey &&
|
||||
(useLeftKeySelectionRightKeyDrag ? e.which !== 1 : e.which !== 3)
|
||||
) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
this.isMousedown = true
|
||||
this.cacheActiveList = [...this.mindMap.renderer.activeNodeList]
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
this.createRect(x, y)
|
||||
}
|
||||
|
||||
// 鼠标移动
|
||||
onMousemove(e) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseMoveX = x
|
||||
this.mouseMoveY = y
|
||||
if (
|
||||
Math.abs(x - this.mouseDownX) <= 10 &&
|
||||
Math.abs(y - this.mouseDownY) <= 10
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.clearAutoMoveTimer()
|
||||
this.onMove(
|
||||
e.clientX,
|
||||
e.clientY,
|
||||
() => {
|
||||
this.isSelecting = true
|
||||
// 绘制矩形
|
||||
this.rect.plot([
|
||||
[this.mouseDownX, this.mouseDownY],
|
||||
[this.mouseMoveX, this.mouseDownY],
|
||||
[this.mouseMoveX, this.mouseMoveY],
|
||||
[this.mouseDownX, this.mouseMoveY]
|
||||
])
|
||||
this.checkInNodes()
|
||||
},
|
||||
(dir, step) => {
|
||||
switch (dir) {
|
||||
case 'left':
|
||||
this.mouseDownX += step
|
||||
break
|
||||
case 'top':
|
||||
this.mouseDownY += step
|
||||
break
|
||||
case 'right':
|
||||
this.mouseDownX -= step
|
||||
break
|
||||
case 'bottom':
|
||||
this.mouseDownY -= step
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 结束框选
|
||||
onMouseup() {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
@@ -233,6 +250,16 @@ class Select {
|
||||
hasSelectRange() {
|
||||
return this.isSelecting
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
}
|
||||
|
||||
Select.instanceName = 'select'
|
||||
|
||||
@@ -12,6 +12,7 @@ class Watermark {
|
||||
this.text = '' // 水印文字
|
||||
this.textStyle = {} // 水印文字样式
|
||||
this.watermarkDraw = null // 容器
|
||||
this.isInExport = false // 是否是在导出过程中
|
||||
this.maxLong = this.getMaxLong()
|
||||
this.updateWatermark(this.mindMap.opt.watermarkConfig || {})
|
||||
this.bindEvent()
|
||||
@@ -72,11 +73,18 @@ class Watermark {
|
||||
this.textStyle = Object.assign(this.textStyle, textStyle || {})
|
||||
}
|
||||
|
||||
// 清除水印
|
||||
clear() {
|
||||
if (this.watermarkDraw) this.watermarkDraw.clear()
|
||||
}
|
||||
|
||||
// 绘制水印
|
||||
// 非精确绘制,会绘制一些超出可视区域的水印
|
||||
draw() {
|
||||
// 清空之前的水印
|
||||
if (this.watermarkDraw) this.watermarkDraw.clear()
|
||||
this.clear()
|
||||
// 如果是仅导出需要水印,那么非导出中不渲染
|
||||
const { onlyExport } = this.mindMap.opt.watermarkConfig
|
||||
if (onlyExport && !this.isInExport) return
|
||||
// 如果没有水印数据,那么水印容器也删除掉
|
||||
if (!this.hasWatermark()) {
|
||||
this.removeContainer()
|
||||
|
||||
@@ -20,6 +20,8 @@ export default {
|
||||
lineStyle: 'straight', // 针对logicalStructure、mindMap两种结构。曲线(curve)、直线(straight)、直连(direct)
|
||||
// 曲线连接时,根节点和其他节点的连接线样式保持统一,默认根节点为 ( 型,其他节点为 { 型,设为true后,都为 { 型
|
||||
rootLineKeepSameInCurve: true,
|
||||
// 连线尾部是否显示标记,目前只支持箭头
|
||||
showLineMarker: false,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
@@ -159,7 +161,8 @@ const nodeSizeIndependenceList = [
|
||||
'backgroundRepeat',
|
||||
'backgroundPosition',
|
||||
'backgroundSize',
|
||||
'rootLineKeepSameInCurve'
|
||||
'rootLineKeepSameInCurve',
|
||||
'showLineMarker'
|
||||
]
|
||||
export const checkIsNodeSizeIndependenceConfig = config => {
|
||||
let keys = Object.keys(config)
|
||||
|
||||
@@ -7,16 +7,24 @@ export default class Lru {
|
||||
}
|
||||
|
||||
add(key, value) {
|
||||
const isExist = this.has(key)
|
||||
// 如果该key之前不存在,并且现在数量已经超出最大值,则不再继续添加
|
||||
if (!isExist && this.size >= this.max) {
|
||||
return false
|
||||
}
|
||||
// 已经存在则可以更新,因为不影响数量
|
||||
// 如果该key是否已经存在,则先删除
|
||||
this.delete(key)
|
||||
// 添加
|
||||
this.pool.set(key, value)
|
||||
this.size++
|
||||
// 如果数量超出最大值,则删除最早的
|
||||
if (this.size > this.max) {
|
||||
let keys = this.pool.keys()
|
||||
let last = keys.next()
|
||||
this.delete(last.value)
|
||||
}
|
||||
// 删除最早的没啥意义,详见:https://github.com/wanglin2/mind-map/issues/467
|
||||
// if (this.size > this.max) {
|
||||
// let keys = this.pool.keys()
|
||||
// let last = keys.next()
|
||||
// this.delete(last.value)
|
||||
// }
|
||||
return true
|
||||
}
|
||||
|
||||
delete(key) {
|
||||
@@ -35,4 +43,9 @@ export default class Lru {
|
||||
return this.pool.get(key)
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.size = 0
|
||||
this.pool = new Map()
|
||||
}
|
||||
}
|
||||
|
||||
BIN
web/src/assets/avatar/继龙.jpg
Normal file
BIN
web/src/assets/avatar/继龙.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
@@ -11,6 +11,7 @@ export default {
|
||||
width: 'Width',
|
||||
style: 'Style',
|
||||
lineOfOutline: 'Line of outline',
|
||||
showArrow: 'Is show arrow',
|
||||
nodePadding: 'Node padding',
|
||||
nodeMargin: 'Node margin',
|
||||
horizontal: 'Horizontal',
|
||||
@@ -27,6 +28,7 @@ export default {
|
||||
enableFreeDrag: 'Enable node free drag',
|
||||
watermark: 'Watermark',
|
||||
showWatermark: 'Is show watermark',
|
||||
onlyExport: 'Only export',
|
||||
watermarkDefaultText: 'Watermark text',
|
||||
watermarkText: 'Watermark text',
|
||||
watermarkTextColor: 'Text color',
|
||||
|
||||
@@ -11,6 +11,7 @@ export default {
|
||||
width: '粗细',
|
||||
style: '风格',
|
||||
lineOfOutline: '概要的连线',
|
||||
showArrow: '是否显示箭头',
|
||||
nodePadding: '节点内边距',
|
||||
nodeMargin: '节点外边距',
|
||||
horizontal: '水平',
|
||||
@@ -28,6 +29,7 @@ export default {
|
||||
watermark: '水印',
|
||||
showWatermark: '是否显示水印',
|
||||
watermarkDefaultText: '水印文字',
|
||||
onlyExport: '是否仅在导出时显示',
|
||||
watermarkText: '水印文字',
|
||||
watermarkTextColor: '文字颜色',
|
||||
watermarkLineSpacing: '水印行间距',
|
||||
|
||||
@@ -18,6 +18,7 @@ let APIList = [
|
||||
'constructor',
|
||||
'node',
|
||||
'render',
|
||||
'textEdit',
|
||||
'view',
|
||||
'keyCommand',
|
||||
'command',
|
||||
|
||||
@@ -1,5 +1,67 @@
|
||||
# Changelog
|
||||
|
||||
## 0.9.2
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fix the issue of no line breaks when node text contains consecutive numbers or letters.
|
||||
>
|
||||
> 2.Fix the issue of duplicate node drawing when importing files with the same UID as existing nodes on the current canvas.
|
||||
>
|
||||
> 3.Fix the issue of duplicate rendering of nodes caused by forward and backward when the number of nodes exceeds the maximum number of cache pools.
|
||||
>
|
||||
> 4.Fix the issue of the canvas moving in the opposite direction when scrolling horizontally with the mouse or touchpad.
|
||||
>
|
||||
> 5.Fix the issue where the mouse in flag is not reset when a node is destroyed.
|
||||
>
|
||||
> 6.Fix the issue of incorrect position calculation in the scrollbar plugin when the 'initRootNodePosition' configuration is not set to the default '[center, center]'.
|
||||
>
|
||||
> 7.Fix the issue where dragging the canvas cannot stop when the mouse is released on the node.
|
||||
>
|
||||
> 8.Fix the issue of errors in the position calculated by the view. fit method when the canvas container is not 0 from the top left corner of the browser window.
|
||||
>
|
||||
> 9.Fix the issue where the watermark in the exported image does not fully cover the entire image when there are a large number of nodes.
|
||||
>
|
||||
> 10.Fix the issue of inserting formula errors.
|
||||
>
|
||||
> 11.Fix the issue of losing the selected text status when the mouse moves out of the editing box while selecting text in the node text editing state.
|
||||
>
|
||||
> 12.When repairing node rich text editing, Fix the issue 'rich_text_selection_change' event is not triggered when the text selection range is 'null'.
|
||||
>
|
||||
> 13.Fix the issue of no 'node' instance in the 'node_dragging' event callback.
|
||||
>
|
||||
> 14.Fix the issue of too many nodes and the canvas size being too large to export PNG.
|
||||
|
||||
New:
|
||||
|
||||
> 1.Modify the mousewheel event, change the dir flag to dirs, support storing multiple directions, and optimize the dual finger movement operation of the touchpad.
|
||||
>
|
||||
> 2.The TextEdit class adds the isShowTextEdit method to determine whether the current node is in an editing state.
|
||||
>
|
||||
> 3.Change the paste method of the render class to support pasting clipboard data.
|
||||
>
|
||||
> 4.Add a configuration option to restrict mind map graphics within the canvas.
|
||||
>
|
||||
> 5.When registering the scrollbar plugin, it supports configuring whether to restrict the mind map within the canvas.
|
||||
>
|
||||
> 6.Folding all nodes will move the mind map root node to the center of the canvas.
|
||||
>
|
||||
> 7.Support the configuration option of displaying watermarks only during export.
|
||||
>
|
||||
> 8.When pasting images from the clipboard at a node, custom processing functions are supported to upload the images to your server.
|
||||
>
|
||||
> 9.Refactoring the export logic of the PDF, the exported PDF size is no longer a fixed A4, but the size of the mind map, while deleting the configuration for pagination export.
|
||||
>
|
||||
> 10.Node connections support displaying arrows as a field for the theme.
|
||||
>
|
||||
> 11.The maximum number of historical records is adjusted to 500 by default.
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.Support configuration to display watermarks only during export.
|
||||
>
|
||||
> 2.Basic style configuration line supports displaying arrows.
|
||||
|
||||
## 0.9.1-fix.2
|
||||
|
||||
Fix:
|
||||
|
||||
@@ -1,6 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.9.2</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fix the issue of no line breaks when node text contains consecutive numbers or letters.</p>
|
||||
<p>2.Fix the issue of duplicate node drawing when importing files with the same UID as existing nodes on the current canvas.</p>
|
||||
<p>3.Fix the issue of duplicate rendering of nodes caused by forward and backward when the number of nodes exceeds the maximum number of cache pools.</p>
|
||||
<p>4.Fix the issue of the canvas moving in the opposite direction when scrolling horizontally with the mouse or touchpad.</p>
|
||||
<p>5.Fix the issue where the mouse in flag is not reset when a node is destroyed.</p>
|
||||
<p>6.Fix the issue of incorrect position calculation in the scrollbar plugin when the 'initRootNodePosition' configuration is not set to the default '[center, center]'.</p>
|
||||
<p>7.Fix the issue where dragging the canvas cannot stop when the mouse is released on the node.</p>
|
||||
<p>8.Fix the issue of errors in the position calculated by the view. fit method when the canvas container is not 0 from the top left corner of the browser window.</p>
|
||||
<p>9.Fix the issue where the watermark in the exported image does not fully cover the entire image when there are a large number of nodes.</p>
|
||||
<p>10.Fix the issue of inserting formula errors.</p>
|
||||
<p>11.Fix the issue of losing the selected text status when the mouse moves out of the editing box while selecting text in the node text editing state.</p>
|
||||
<p>12.When repairing node rich text editing, Fix the issue 'rich_text_selection_change' event is not triggered when the text selection range is 'null'.</p>
|
||||
<p>13.Fix the issue of no 'node' instance in the 'node_dragging' event callback.</p>
|
||||
<p>14.Fix the issue of too many nodes and the canvas size being too large to export PNG.</p>
|
||||
</blockquote>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.Modify the mousewheel event, change the dir flag to dirs, support storing multiple directions, and optimize the dual finger movement operation of the touchpad.</p>
|
||||
<p>2.The TextEdit class adds the isShowTextEdit method to determine whether the current node is in an editing state.</p>
|
||||
<p>3.Change the paste method of the render class to support pasting clipboard data.</p>
|
||||
<p>4.Add a configuration option to restrict mind map graphics within the canvas.</p>
|
||||
<p>5.When registering the scrollbar plugin, it supports configuring whether to restrict the mind map within the canvas.</p>
|
||||
<p>6.Folding all nodes will move the mind map root node to the center of the canvas.</p>
|
||||
<p>7.Support the configuration option of displaying watermarks only during export.</p>
|
||||
<p>8.When pasting images from the clipboard at a node, custom processing functions are supported to upload the images to your server.</p>
|
||||
<p>9.Refactoring the export logic of the PDF, the exported PDF size is no longer a fixed A4, but the size of the mind map, while deleting the configuration for pagination export.</p>
|
||||
<p>10.Node connections support displaying arrows as a field for the theme.</p>
|
||||
<p>11.The maximum number of historical records is adjusted to 500 by default.</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.Support configuration to display watermarks only during export.</p>
|
||||
<p>2.Basic style configuration line supports displaying arrows.</p>
|
||||
</blockquote>
|
||||
<h2>0.9.1-fix.2</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
|
||||
@@ -61,7 +61,7 @@ const mindMap = new MindMap({
|
||||
| nodeTextEditZIndex(v0.5.5+) | Number | 3000 | | z-index of node text edit box elements |
|
||||
| nodeNoteTooltipZIndex(v0.5.5+) | Number | 3000 | z-index of floating layer elements in node comments | |
|
||||
| isEndNodeTextEditOnClickOuter(v0.5.5+) | Boolean | true | Whether to end the editing status of node text when clicking on an area outside the canvas | |
|
||||
| maxHistoryCount(v0.5.6+) | Number | 1000 | | Maximum number of history records |
|
||||
| maxHistoryCount(v0.5.6+) | Number | 1000(v0.9.2+ changed 500) | | Maximum number of history records |
|
||||
| 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 | |
|
||||
@@ -105,6 +105,9 @@ const mindMap = new MindMap({
|
||||
| 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 |
|
||||
|
||||
### Data structure
|
||||
|
||||
@@ -156,6 +159,7 @@ If you want to add custom fields, you can add them to the same level as 'data' a
|
||||
| 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
|
||||
|
||||
@@ -381,7 +385,7 @@ Listen to an event. Event list:
|
||||
| mousemove | el element mouse move event | e (event object), this (Event event class instance) |
|
||||
| drag | If it is a drag event while holding down the left button | e (event object), this (Event event class instance) |
|
||||
| mouseup | el element mouse up event | e (event object), this (Event event class instance) |
|
||||
| mousewheel | Mouse scroll event | e (event object), dir (up or down scroll), this (Event event class instance) 、isTouchPad(v0.6.1+, Is it an event triggered by the touchpad) |
|
||||
| mousewheel | Mouse scroll event | e (event object), dir (up or down scroll. v0.9.2+ changed to dirs, array type, which supports saving multiple directions simultaneously), this (Event event class instance) 、isTouchPad(v0.6.1+, Is it an event triggered by the touchpad) |
|
||||
| contextmenu | svg canvas right mouse button menu event | e (event object) |
|
||||
| node_click | Node click event | this (node instance), e (event object) |
|
||||
| node_mousedown | Node mouse down event | this (node instance), e (event object) |
|
||||
@@ -414,6 +418,8 @@ Listen to an event. Event list:
|
||||
| set_data(v0.7.3+) | Triggered when the setData method is called to dynamically set mind map data | data(New Mind Map Data) |
|
||||
| resize(v0.8.0+) | Triggered after the container size changes, actually when the 'resize' method of the mind map instance is called | |
|
||||
| beforeDestroy(v0.9.0+) | Triggered before destroying the mind map, i.e. triggered by calling the destroy method | |
|
||||
| body_mousedown(v0.9.2+) | Mousedown event of document.body | e(event object) |
|
||||
| body_click | Click event of document.body | e(event object) |
|
||||
|
||||
### emit(event, ...args)
|
||||
|
||||
@@ -507,7 +513,7 @@ redo. All commands are as follows:
|
||||
| EXPAND_ALL | Expand all nodes | |
|
||||
| UNEXPAND_ALL | Collapse all nodes | |
|
||||
| UNEXPAND_TO_LEVEL (v0.2.8+) | Expand to a specified level | level (the level to expand to, 1, 2, 3...) |
|
||||
| SET_NODE_DATA | Update node data, that is, update the data in the data object of the node data object | node (the node to set), data (object, the data to update, e.g. `{expand: true}`) |
|
||||
| SET_NODE_DATA | Update node data, that is, update the data in the data object of the node data object. Note that this command will not trigger view updates | node (the node to set), data (object, the data to update, e.g. `{expand: true}`) |
|
||||
| SET_NODE_TEXT | Set node text | node (the node to set), text (the new text for the node), richText(v0.4.0+, If you want to set a rich text character, you need to set it to `true`)、resetRichText(v0.6.10+Do you want to reset rich text? The default is false. If true is passed, the style of the rich text node will be reset) |
|
||||
| SET_NODE_IMAGE | Set Node Image | node (node to set), imgData (object, image information, structured as: `{url, title, width, height}`, the width and height of the image must be passed) |
|
||||
| SET_NODE_ICON | Set Node Icon | node (node to set), icons (array, predefined image names array, available icons can be obtained in the nodeIconList list in the [icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js) file, icon name is type_name, such as ['priority_1']) |
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
<tr>
|
||||
<td>maxHistoryCount(v0.5.6+)</td>
|
||||
<td>Number</td>
|
||||
<td>1000</td>
|
||||
<td>1000(v0.9.2+ changed 500)</td>
|
||||
<td></td>
|
||||
<td>Maximum number of history records</td>
|
||||
</tr>
|
||||
@@ -595,6 +595,27 @@
|
||||
<td>Image address, the default image displayed when node image loading fails</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>handleNodePasteImg(v0.9.2+)</td>
|
||||
<td>null or Function</td>
|
||||
<td>null</td>
|
||||
<td>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} }</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvas(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>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</td>
|
||||
<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>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Data structure</h3>
|
||||
@@ -674,6 +695,12 @@
|
||||
<td>{color: '#999', opacity: 0.5, fontSize: 14}</td>
|
||||
<td>Watermark text style</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onlyExport(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>Is only add watermarks during export</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Icon Configuration</h3>
|
||||
@@ -910,7 +937,7 @@ poor performance and should be used sparingly.</p>
|
||||
<tr>
|
||||
<td>mousewheel</td>
|
||||
<td>Mouse scroll event</td>
|
||||
<td>e (event object), dir (up or down scroll), this (Event event class instance) 、isTouchPad(v0.6.1+, Is it an event triggered by the touchpad)</td>
|
||||
<td>e (event object), dir (up or down scroll. v0.9.2+ changed to dirs, array type, which supports saving multiple directions simultaneously), this (Event event class instance) 、isTouchPad(v0.6.1+, Is it an event triggered by the touchpad)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>contextmenu</td>
|
||||
@@ -1072,6 +1099,16 @@ poor performance and should be used sparingly.</p>
|
||||
<td>Triggered before destroying the mind map, i.e. triggered by calling the destroy method</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>body_mousedown(v0.9.2+)</td>
|
||||
<td>Mousedown event of document.body</td>
|
||||
<td>e(event object)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>body_click</td>
|
||||
<td>Click event of document.body</td>
|
||||
<td>e(event object)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>emit(event, ...args)</h3>
|
||||
@@ -1219,7 +1256,7 @@ redo. All commands are as follows:</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SET_NODE_DATA</td>
|
||||
<td>Update node data, that is, update the data in the data object of the node data object</td>
|
||||
<td>Update node data, that is, update the data in the data object of the node data object. Note that this command will not trigger view updates</td>
|
||||
<td>node (the node to set), data (object, the data to update, e.g. <code>{expand: true}</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -48,9 +48,9 @@ a.click()
|
||||
|
||||
- `rotateWhenWidthLongerThenHeight`: v0.6.15+, V0.7.0+abandoned, Boolean, false, Automatically rotate 90 degrees when the image has a width to height ratio
|
||||
|
||||
- `checkRotate`: v0.7.0+, Function, You can pass a function that takes two parameters, the width and height of the image, and returns true or false. True represents that the image needs to be rotated by 90 degrees
|
||||
- `checkRotate`: v0.7.0+, (v0.9.2+obsolete), Function, You can pass a function that takes two parameters, the width and height of the image, and returns true or false. True represents that the image needs to be rotated by 90 degrees
|
||||
|
||||
- `compress`:v0.8.1+,null | { width, height }, The parameter for compressing images. In some cases, the length and width of the exported image may be very large. If you want to reduce it, you can use this parameter to control it. Only one width or height can be provided, and it will be scaled proportionally
|
||||
- `compress`:v0.8.1+, (v0.9.2+obsolete),null | { width, height }, The parameter for compressing images. In some cases, the length and width of the exported image may be very large. If you want to reduce it, you can use this parameter to control it. Only one width or height can be provided, and it will be scaled proportionally
|
||||
|
||||
Exports as `png`.
|
||||
|
||||
@@ -74,15 +74,19 @@ svg(
|
||||
|
||||
Exports as `svg`.
|
||||
|
||||
### pdf(name, useMultiPageExport, maxImageWidth)
|
||||
### pdf(name, transparent = false)
|
||||
|
||||
> v0.8.1:pdf(name, useMultiPageExport, maxImageWidth)
|
||||
|
||||
> v0.2.1+
|
||||
|
||||
- `name`:File name
|
||||
|
||||
- `useMultiPageExport`: v0.6.15+, Boolean, false, Whether to export multiple pages, default to single page
|
||||
- `useMultiPageExport`: v0.6.15+, (v0.9.2+obsolete), Boolean, false, Whether to export multiple pages, default to single page
|
||||
|
||||
- `maxImageWidth`:v0.8.1+,null | Number,The default is twice the width of A4 paper, which is a parameter for compressing images. In some cases, the length and width of the image may be very large, resulting in a very large PDF volume. Therefore, if you want to reduce the volume, you can use this parameter to control the maximum width of the image
|
||||
- `maxImageWidth`:v0.8.1+, (v0.9.2+obsolete),null | Number,The default is twice the width of A4 paper, which is a parameter for compressing images. In some cases, the length and width of the image may be very large, resulting in a very large PDF volume. Therefore, if you want to reduce the volume, you can use this parameter to control the maximum width of the image
|
||||
|
||||
- `transparent`:v0.9.2+,Boolean,default is false,Specify whether the background of the exported image is transparent
|
||||
|
||||
Export as `pdf`. Unlike other export methods, this method does not return data and directly triggers the download.
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ a.click()
|
||||
<p><code>rotateWhenWidthLongerThenHeight</code>: v0.6.15+, V0.7.0+abandoned, Boolean, false, Automatically rotate 90 degrees when the image has a width to height ratio</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>checkRotate</code>: v0.7.0+, Function, You can pass a function that takes two parameters, the width and height of the image, and returns true or false. True represents that the image needs to be rotated by 90 degrees</p>
|
||||
<p><code>checkRotate</code>: v0.7.0+, (v0.9.2+obsolete), Function, You can pass a function that takes two parameters, the width and height of the image, and returns true or false. True represents that the image needs to be rotated by 90 degrees</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>compress</code>:v0.8.1+,null | { width, height }, The parameter for compressing images. In some cases, the length and width of the exported image may be very large. If you want to reduce it, you can use this parameter to control it. Only one width or height can be provided, and it will be scaled proportionally</p>
|
||||
<p><code>compress</code>:v0.8.1+, (v0.9.2+obsolete),null | { width, height }, The parameter for compressing images. In some cases, the length and width of the exported image may be very large. If you want to reduce it, you can use this parameter to control it. Only one width or height can be provided, and it will be scaled proportionally</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Exports as <code>png</code>.</p>
|
||||
@@ -69,7 +69,10 @@ a.click()
|
||||
)
|
||||
</code></pre>
|
||||
<p>Exports as <code>svg</code>.</p>
|
||||
<h3>pdf(name, useMultiPageExport, maxImageWidth)</h3>
|
||||
<h3>pdf(name, transparent = false)</h3>
|
||||
<blockquote>
|
||||
<p>v0.8.1:pdf(name, useMultiPageExport, maxImageWidth)</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>v0.2.1+</p>
|
||||
</blockquote>
|
||||
@@ -78,10 +81,13 @@ a.click()
|
||||
<p><code>name</code>:File name</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>useMultiPageExport</code>: v0.6.15+, Boolean, false, Whether to export multiple pages, default to single page</p>
|
||||
<p><code>useMultiPageExport</code>: v0.6.15+, (v0.9.2+obsolete), Boolean, false, Whether to export multiple pages, default to single page</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>maxImageWidth</code>:v0.8.1+,null | Number,The default is twice the width of A4 paper, which is a parameter for compressing images. In some cases, the length and width of the image may be very large, resulting in a very large PDF volume. Therefore, if you want to reduce the volume, you can use this parameter to control the maximum width of the image</p>
|
||||
<p><code>maxImageWidth</code>:v0.8.1+, (v0.9.2+obsolete),null | Number,The default is twice the width of A4 paper, which is a parameter for compressing images. In some cases, the length and width of the image may be very large, resulting in a very large PDF volume. Therefore, if you want to reduce the volume, you can use this parameter to control the maximum width of the image</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>transparent</code>:v0.9.2+,Boolean,default is false,Specify whether the background of the exported image is transparent</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Export as <code>pdf</code>. Unlike other export methods, this method does not return data and directly triggers the download.</p>
|
||||
|
||||
@@ -265,4 +265,8 @@ Open source is not easy. If this project is helpful to you, you can invite the a
|
||||
<img src="../../../../assets/avatar/HaHN.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>HaHN</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>
|
||||
@@ -221,6 +221,10 @@ full screen, support mini map</li>
|
||||
<img src="../../../../assets/avatar/HaHN.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>HaHN</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>
|
||||
|
||||
@@ -217,7 +217,7 @@ if `key` is not passed, return the `data` object
|
||||
### setData(data)
|
||||
|
||||
Set the value of the specified key in the data object of the node's real data
|
||||
nodeData, `SET_NODE_DATA` command's shortcut method
|
||||
nodeData, `SET_NODE_DATA` command's shortcut method. This method and command will not update the view, so if you want to modify the text, use the 'setText' method or use the command pointing to the text.
|
||||
|
||||
### setText(text, richText)
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ default <code>false</code></p>
|
||||
if <code>key</code> is not passed, return the <code>data</code> object</p>
|
||||
<h3>setData(data)</h3>
|
||||
<p>Set the value of the specified key in the data object of the node's real data
|
||||
nodeData, <code>SET_NODE_DATA</code> command's shortcut method</p>
|
||||
nodeData, <code>SET_NODE_DATA</code> command's shortcut method. This method and command will not update the view, so if you want to modify the text, use the 'setText' method or use the command pointing to the text.</p>
|
||||
<h3>setText(text, richText)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -11,7 +11,13 @@ Gets the current list of active nodes.
|
||||
|
||||
### root
|
||||
|
||||
Gets the root node of the node tree.
|
||||
Node tree, also known as the mind map node instance tree.
|
||||
|
||||
### renderTree
|
||||
|
||||
The rendering tree, also known as the data tree of the mind map.
|
||||
|
||||
### layout
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -114,15 +120,6 @@ Search for the index of a node in the active list.
|
||||
|
||||
Get the position index of a node among its siblings.
|
||||
|
||||
### removeOneNode(node)
|
||||
|
||||
Delete a specific node.
|
||||
|
||||
### copyNode()
|
||||
|
||||
Copy a node, the active node is the node to be operated on, if there are
|
||||
multiple active nodes, only the first node will be operated on.
|
||||
|
||||
### setNodeDataRender(node, data, notRender)
|
||||
|
||||
- `notRender`: v0.6.9+, `Boolean`, Default is `false`, Do not trigger rendering.
|
||||
@@ -179,16 +176,36 @@ Find the corresponding node instance based on the uid.
|
||||
|
||||
> v0.6.8+
|
||||
|
||||
Copy nodes. After calling this method, the current activated node data will be stored. Multiple activated nodes will only operate on the first node, and subsequent calls to the 'paste()' method can be pasted.
|
||||
Copy nodes. After calling this method, the current activated node data will be stored. and subsequent calls to the 'paste()' method can be pasted.
|
||||
|
||||
If the browser and protocol (https) support 'js' to manipulate clipboard data, the copied node data will also be added to the user's clipboard.
|
||||
|
||||
### cut()
|
||||
|
||||
> v0.6.8+
|
||||
|
||||
Cut a node. After calling this method, the currently active node will be cut and the node data will be stored. Multiple nodes will only operate on the first node, and subsequent calls to the 'paste()' method can be pasted.
|
||||
Cut a node. After calling this method, the currently active node will be cut and the node data will be stored. and subsequent calls to the 'paste()' method can be pasted.
|
||||
|
||||
If the browser and protocol (https) support 'js' to manipulate clipboard data, the copied node data will also be added to the user's clipboard.
|
||||
|
||||
### paste()
|
||||
|
||||
> v0.6.8+
|
||||
|
||||
Pasting nodes can be done by calling the 'copy()' or 'cut()' method after calling it. This method does not support pasting data from the user's clipboard. Please use the built-in 'Ctrl+v' shortcut key.
|
||||
Pasting nodes can be done by calling the 'copy()' or 'cut()' method after calling it.
|
||||
|
||||
If the browser and protocol (https) support 'js' to manipulate clipboard data, data copied from other places can also be pasted. For example, you can paste' simple mind map 'nodes across browsers. If it is non' simple mind map 'node data, the text and images in the clipboard will be extracted and pasted. The text will be pasted as a child node by default, and the images will be added to the current node by default.
|
||||
|
||||
### clearCache()
|
||||
|
||||
> v0.9.2+
|
||||
|
||||
Empty the node cache pool.
|
||||
|
||||
### emitNodeActiveEvent(node = null, activeNodeList = [...this.activeNodeList])
|
||||
|
||||
- `node`:The node activated this time
|
||||
|
||||
- `activeNodeList`:All currently activated nodes
|
||||
|
||||
Dispatch node activation event, which triggers `node_active` event.
|
||||
@@ -7,7 +7,10 @@ accessed through <code>mindMap.renderer</code>.</p>
|
||||
<h3>activeNodeList</h3>
|
||||
<p>Gets the current list of active nodes.</p>
|
||||
<h3>root</h3>
|
||||
<p>Gets the root node of the node tree.</p>
|
||||
<p>Node tree, also known as the mind map node instance tree.</p>
|
||||
<h3>renderTree</h3>
|
||||
<p>The rendering tree, also known as the data tree of the mind map.</p>
|
||||
<h3>layout</h3>
|
||||
<h2>Methods</h2>
|
||||
<h3>highlightNode(node, range)</h3>
|
||||
<blockquote>
|
||||
@@ -93,11 +96,6 @@ disable the enter key and delete key related shortcuts to prevent conflicts.</p>
|
||||
<p>Search for the index of a node in the active list.</p>
|
||||
<h3>getNodeIndex(node)</h3>
|
||||
<p>Get the position index of a node among its siblings.</p>
|
||||
<h3>removeOneNode(node)</h3>
|
||||
<p>Delete a specific node.</p>
|
||||
<h3>copyNode()</h3>
|
||||
<p>Copy a node, the active node is the node to be operated on, if there are
|
||||
multiple active nodes, only the first node will be operated on.</p>
|
||||
<h3>setNodeDataRender(node, data, notRender)</h3>
|
||||
<ul>
|
||||
<li><code>notRender</code>: v0.6.9+, <code>Boolean</code>, Default is <code>false</code>, Do not trigger rendering.</li>
|
||||
@@ -151,17 +149,35 @@ is an object, e.g. <code>{text: 'I am new text'}</code>.</p>
|
||||
<blockquote>
|
||||
<p>v0.6.8+</p>
|
||||
</blockquote>
|
||||
<p>Copy nodes. After calling this method, the current activated node data will be stored. Multiple activated nodes will only operate on the first node, and subsequent calls to the 'paste()' method can be pasted.</p>
|
||||
<p>Copy nodes. After calling this method, the current activated node data will be stored. and subsequent calls to the 'paste()' method can be pasted.</p>
|
||||
<p>If the browser and protocol (https) support 'js' to manipulate clipboard data, the copied node data will also be added to the user's clipboard.</p>
|
||||
<h3>cut()</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.8+</p>
|
||||
</blockquote>
|
||||
<p>Cut a node. After calling this method, the currently active node will be cut and the node data will be stored. Multiple nodes will only operate on the first node, and subsequent calls to the 'paste()' method can be pasted.</p>
|
||||
<p>Cut a node. After calling this method, the currently active node will be cut and the node data will be stored. and subsequent calls to the 'paste()' method can be pasted.</p>
|
||||
<p>If the browser and protocol (https) support 'js' to manipulate clipboard data, the copied node data will also be added to the user's clipboard.</p>
|
||||
<h3>paste()</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.8+</p>
|
||||
</blockquote>
|
||||
<p>Pasting nodes can be done by calling the 'copy()' or 'cut()' method after calling it. This method does not support pasting data from the user's clipboard. Please use the built-in 'Ctrl+v' shortcut key.</p>
|
||||
<p>Pasting nodes can be done by calling the 'copy()' or 'cut()' method after calling it.</p>
|
||||
<p>If the browser and protocol (https) support 'js' to manipulate clipboard data, data copied from other places can also be pasted. For example, you can paste' simple mind map 'nodes across browsers. If it is non' simple mind map 'node data, the text and images in the clipboard will be extracted and pasted. The text will be pasted as a child node by default, and the images will be added to the current node by default.</p>
|
||||
<h3>clearCache()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.2+</p>
|
||||
</blockquote>
|
||||
<p>Empty the node cache pool.</p>
|
||||
<h3>emitNodeActiveEvent(node = null, activeNodeList = [...this.activeNodeList])</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>node</code>:The node activated this time</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>activeNodeList</code>:All currently activated nodes</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Dispatch node activation event, which triggers <code>node_active</code> event.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
23
web/src/pages/Doc/en/textEdit/index.md
Normal file
23
web/src/pages/Doc/en/textEdit/index.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# TextEdit instance
|
||||
|
||||
Node text editing instance. It can be obtained through `mindMap.renderer.textEdit`.
|
||||
|
||||
## Methods
|
||||
|
||||
### isShowTextEdit()
|
||||
|
||||
Get whether the current text editing box is in a display state, that is, whether it is in a text editing state.
|
||||
|
||||
### hideEditTextBox()
|
||||
|
||||
Hiding the text editing box will set the content of the current text editing box as node text.
|
||||
|
||||
### registerTmpShortcut()
|
||||
|
||||
Register temporary shortcut keys, which means editing can be completed through the Enter and Tab keys.
|
||||
|
||||
### show({ node})
|
||||
|
||||
- `node`:Node instance to enter for editing
|
||||
|
||||
Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.
|
||||
29
web/src/pages/Doc/en/textEdit/index.vue
Normal file
29
web/src/pages/Doc/en/textEdit/index.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>TextEdit instance</h1>
|
||||
<p>Node text editing instance. It can be obtained through <code>mindMap.renderer.textEdit</code>.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>isShowTextEdit()</h3>
|
||||
<p>Get whether the current text editing box is in a display state, that is, whether it is in a text editing state.</p>
|
||||
<h3>hideEditTextBox()</h3>
|
||||
<p>Hiding the text editing box will set the content of the current text editing box as node text.</p>
|
||||
<h3>registerTmpShortcut()</h3>
|
||||
<p>Register temporary shortcut keys, which means editing can be completed through the Enter and Tab keys.</p>
|
||||
<h3>show({ node})</h3>
|
||||
<ul>
|
||||
<li><code>node</code>:Node instance to enter for editing</li>
|
||||
</ul>
|
||||
<p>Manually enable node editing. By default, it will enter node editing when double clicking or pressing F2 on the node.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -498,4 +498,8 @@ Check if a cache exists.
|
||||
|
||||
#### get(key)
|
||||
|
||||
Gets the value of a cache.
|
||||
Gets the value of a cache.
|
||||
|
||||
> v0.9.2+
|
||||
|
||||
Empty the cache pool.
|
||||
@@ -397,6 +397,10 @@ drawBackgroundImageToCanvas(ctx, width, height, img, {
|
||||
<p>Check if a cache exists.</p>
|
||||
<h4>get(key)</h4>
|
||||
<p>Gets the value of a cache.</p>
|
||||
<blockquote>
|
||||
<p>v0.9.2+</p>
|
||||
</blockquote>
|
||||
<p>Empty the cache pool.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,6 +11,8 @@ through `mindMap.view`
|
||||
|
||||
Zoom the mind map to fit the canvas.
|
||||
|
||||
Note that this method cannot be called immediately after calling the 'setData' and 'setFullData' methods, and needs to listen to the 'node_tree_render_end' event calls 'fit'.
|
||||
|
||||
### translateX(step)
|
||||
|
||||
Translate in the `x` direction, `step`: number of pixels to translate
|
||||
|
||||
@@ -9,6 +9,7 @@ through <code>mindMap.view</code></p>
|
||||
<p>v0.6.0+</p>
|
||||
</blockquote>
|
||||
<p>Zoom the mind map to fit the canvas.</p>
|
||||
<p>Note that this method cannot be called immediately after calling the 'setData' and 'setFullData' methods, and needs to listen to the 'node_tree_render_end' event calls 'fit'.</p>
|
||||
<h3>translateX(step)</h3>
|
||||
<p>Translate in the <code>x</code> direction, <code>step</code>: number of pixels to translate</p>
|
||||
<h3>translateY(step)</h3>
|
||||
|
||||
@@ -48,4 +48,10 @@ mindMap.watermark.updateWatermark({
|
||||
|
||||
> v0.3.2+
|
||||
|
||||
Gets whether the watermark exists.
|
||||
Gets whether the watermark exists.
|
||||
|
||||
### clear()
|
||||
|
||||
> v0.9.2+
|
||||
|
||||
Clear watermark.
|
||||
@@ -37,6 +37,11 @@ MindMap.usePlugin(Watermark)
|
||||
<p>v0.3.2+</p>
|
||||
</blockquote>
|
||||
<p>Gets whether the watermark exists.</p>
|
||||
<h3>clear()</h3>
|
||||
<blockquote>
|
||||
<p>v0.9.2+</p>
|
||||
</blockquote>
|
||||
<p>Clear watermark.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -41,6 +41,7 @@ export default [
|
||||
{ path: 'miniMap', title: 'MiniMap插件' },
|
||||
{ path: 'node', title: 'Node实例' },
|
||||
{ path: 'render', title: 'Render实例' },
|
||||
{ path: 'textEdit', title: 'TextEdit实例' },
|
||||
{ path: 'richText', title: 'RichText插件' },
|
||||
{ path: 'select', title: 'Select 插件 ' },
|
||||
{ path: 'start', title: '开始' },
|
||||
@@ -83,6 +84,7 @@ export default [
|
||||
{ path: 'miniMap', title: 'MiniMap plugin' },
|
||||
{ path: 'node', title: 'Node instance' },
|
||||
{ path: 'render', title: 'Render instance' },
|
||||
{ path: 'textEdit', title: 'TextEdit instance' },
|
||||
{ path: 'richText', title: 'RichText plugin' },
|
||||
{ path: 'select', title: 'Select plugin' },
|
||||
{ path: 'start', title: 'Start' },
|
||||
|
||||
@@ -1,5 +1,68 @@
|
||||
# Changelog
|
||||
|
||||
## 0.9.2
|
||||
|
||||
修复:
|
||||
|
||||
> 1.修复节点文本含有连续的数字或字母时没有换行的问题。
|
||||
>
|
||||
> 2.修复导入含有和当前画布已有节点uid相同的文件时会重复绘制节点的问题。
|
||||
>
|
||||
> 3.修复当节点数量超出了缓存池的最大数量时,前进回退会导致节点重复渲染的问题。
|
||||
>
|
||||
> 4.修复鼠标或触控板水平滚动时画布移动方向相反的问题。
|
||||
>
|
||||
> 5.修复节点被销毁时鼠标移入标志没有复位的问题。
|
||||
>
|
||||
> 6.修复滚动条插件在initRootNodePosition配置不为默认的[center,center]时位置计算错误的问题。
|
||||
>
|
||||
> 7.修复拖拽画布时鼠标在节点上面松开时拖拽无法停止的问题。
|
||||
>
|
||||
> 8.修复当画布容器距浏览器窗口左上角不为0时,view.fit方法计算出来的位置有误差的问题。
|
||||
>
|
||||
> 9.修复当节点数量比较多时,导出的图片中水印没有完全覆盖整个图片的问题。
|
||||
>
|
||||
> 10.修复插入公式报错的问题。
|
||||
>
|
||||
> 11.修复节点文本编辑状态中鼠标选择文本时移出编辑框,文字选中状态会丢失的问题。
|
||||
>
|
||||
> 12.修复节点富文本编辑时,文本选中范围为null时没有触发rich_text_selection_change事件的问题。
|
||||
>
|
||||
> 13.修复node_dragging事件回参里没有node实例的问题。
|
||||
>
|
||||
> 14.修复节点数量过多,画布尺寸过大无法导出png的问题。
|
||||
|
||||
|
||||
新增:
|
||||
|
||||
> 1.修改mousewheel事件,dir标志修改为dirs,支持存储多个方向,优化触控板的双指移动操作。
|
||||
>
|
||||
> 2.TextEdit类增加isShowTextEdit方法判断当前是否处在节点编辑状态。
|
||||
>
|
||||
> 3.Render类的paste方法改为支持粘贴剪贴板的数据。
|
||||
>
|
||||
> 4.新增将思维导图图形限制在画布内的配置选项。
|
||||
>
|
||||
> 5.注册了滚动条插件的情况下,支持配置是否将思维导图限制在画布内。
|
||||
>
|
||||
> 6.收起所有节点操作会将思维导图根节点移至画布中心。
|
||||
>
|
||||
> 7.支持仅在导出时显示水印的配置选项。
|
||||
>
|
||||
> 8.在节点粘贴剪贴板中的图片时,支持自定义处理函数,可以将图片上传到你的服务器。
|
||||
>
|
||||
> 9.重构pdf的导出逻辑,导出的pdf尺寸不再是固定的a4,而是思维导图的尺寸,同时删除分页导出的配置。
|
||||
>
|
||||
> 10.节点连线支持显示箭头,作为主题的一个字段。
|
||||
>
|
||||
> 11.最大历史记录数量默认调整为500。
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.支持配置仅在导出时显示水印。
|
||||
>
|
||||
> 2.基础样式配置连线支持显示箭头。
|
||||
|
||||
## 0.9.1-fix.2
|
||||
|
||||
修复:
|
||||
|
||||
@@ -1,6 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.9.2</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
<p>1.修复节点文本含有连续的数字或字母时没有换行的问题。</p>
|
||||
<p>2.修复导入含有和当前画布已有节点uid相同的文件时会重复绘制节点的问题。</p>
|
||||
<p>3.修复当节点数量超出了缓存池的最大数量时,前进回退会导致节点重复渲染的问题。</p>
|
||||
<p>4.修复鼠标或触控板水平滚动时画布移动方向相反的问题。</p>
|
||||
<p>5.修复节点被销毁时鼠标移入标志没有复位的问题。</p>
|
||||
<p>6.修复滚动条插件在initRootNodePosition配置不为默认的[center,center]时位置计算错误的问题。</p>
|
||||
<p>7.修复拖拽画布时鼠标在节点上面松开时拖拽无法停止的问题。</p>
|
||||
<p>8.修复当画布容器距浏览器窗口左上角不为0时,view.fit方法计算出来的位置有误差的问题。</p>
|
||||
<p>9.修复当节点数量比较多时,导出的图片中水印没有完全覆盖整个图片的问题。</p>
|
||||
<p>10.修复插入公式报错的问题。</p>
|
||||
<p>11.修复节点文本编辑状态中鼠标选择文本时移出编辑框,文字选中状态会丢失的问题。</p>
|
||||
<p>12.修复节点富文本编辑时,文本选中范围为null时没有触发rich_text_selection_change事件的问题。</p>
|
||||
<p>13.修复node_dragging事件回参里没有node实例的问题。</p>
|
||||
<p>14.修复节点数量过多,画布尺寸过大无法导出png的问题。</p>
|
||||
</blockquote>
|
||||
<p>新增:</p>
|
||||
<blockquote>
|
||||
<p>1.修改mousewheel事件,dir标志修改为dirs,支持存储多个方向,优化触控板的双指移动操作。</p>
|
||||
<p>2.TextEdit类增加isShowTextEdit方法判断当前是否处在节点编辑状态。</p>
|
||||
<p>3.Render类的paste方法改为支持粘贴剪贴板的数据。</p>
|
||||
<p>4.新增将思维导图图形限制在画布内的配置选项。</p>
|
||||
<p>5.注册了滚动条插件的情况下,支持配置是否将思维导图限制在画布内。</p>
|
||||
<p>6.收起所有节点操作会将思维导图根节点移至画布中心。</p>
|
||||
<p>7.支持仅在导出时显示水印的配置选项。</p>
|
||||
<p>8.在节点粘贴剪贴板中的图片时,支持自定义处理函数,可以将图片上传到你的服务器。</p>
|
||||
<p>9.重构pdf的导出逻辑,导出的pdf尺寸不再是固定的a4,而是思维导图的尺寸,同时删除分页导出的配置。</p>
|
||||
<p>10.节点连线支持显示箭头,作为主题的一个字段。</p>
|
||||
<p>11.最大历史记录数量默认调整为500。</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.支持配置仅在导出时显示水印。</p>
|
||||
<p>2.基础样式配置连线支持显示箭头。</p>
|
||||
</blockquote>
|
||||
<h2>0.9.1-fix.2</h2>
|
||||
<p>修复:</p>
|
||||
<blockquote>
|
||||
|
||||
@@ -61,7 +61,7 @@ const mindMap = new MindMap({
|
||||
| nodeTextEditZIndex(v0.5.5+) | Number | 3000 | 节点文本编辑框元素的z-index |
|
||||
| nodeNoteTooltipZIndex(v0.5.5+) | Number | 3000 | 节点备注浮层元素的z-index |
|
||||
| isEndNodeTextEditOnClickOuter(v0.5.5+) | Boolean | true | 是否在点击了画布外的区域时结束节点文本的编辑状态 |
|
||||
| maxHistoryCount(v0.5.6+) | Number | 1000 | 最大历史记录数 |
|
||||
| maxHistoryCount(v0.5.6+) | Number | 1000(v0.9.2+改为500) | 最大历史记录数 |
|
||||
| alwaysShowExpandBtn(v0.5.8+) | Boolean | false | 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示 |
|
||||
| iconList(v0.5.8+) | Array | [] | 扩展节点可插入的图标,数组的每一项为一个对象,对象详细结构请参考下方【图标配置】表格 |
|
||||
| maxNodeCacheCount(v0.5.10+) | Number | 1000 | 节点最大缓存数量。为了优化性能,内部会维护一个节点缓存池,用来复用节点,通过该属性可以指定池的最大缓存数量 |
|
||||
@@ -105,6 +105,9 @@ const mindMap = new MindMap({
|
||||
| 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配置不再起作用 |
|
||||
|
||||
### 数据结构
|
||||
|
||||
@@ -156,6 +159,7 @@ const mindMap = new MindMap({
|
||||
| textSpacing | Number | 100 | 同一行水印之间的间距 |
|
||||
| angle | Number | 30 | 水印的倾斜角度,范围:[0, 90] |
|
||||
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | 水印文字样式 |
|
||||
| onlyExport(v0.9.2+) | Boolean | false | 是否仅在导出时添加水印 |
|
||||
|
||||
### 图标配置
|
||||
|
||||
@@ -379,7 +383,7 @@ mindMap.setTheme('主题名称')
|
||||
| mousemove | el元素的鼠标移动事件 | e(事件对象)、this(Event事件类实例) |
|
||||
| drag | 如果是按住左键拖动的话会触发拖动事件 | e(事件对象)、this(Event事件类实例) |
|
||||
| mouseup | el元素的鼠标松开事件 | e(事件对象)、this(Event事件类实例) |
|
||||
| mousewheel | 鼠标滚动事件 | e(事件对象)、dir(向上up还是向下down滚动)、this(Event事件类实例)、isTouchPad(v0.6.1+,是否是触控板触发的事件) |
|
||||
| mousewheel | 鼠标滚动事件 | e(事件对象)、dir(向上up还是向下down滚动。v0.9.2+已改为dirs,数组类型,即支持同时保存多个方向)、this(Event事件类实例)、isTouchPad(v0.6.1+,是否是触控板触发的事件) |
|
||||
| contextmenu | svg画布的鼠标右键菜单事件 | e(事件对象) |
|
||||
| node_click | 节点的单击事件 | this(节点实例)、e(事件对象) |
|
||||
| node_mousedown | 节点的鼠标按下事件 | this(节点实例)、e(事件对象) |
|
||||
@@ -411,6 +415,8 @@ mindMap.setTheme('主题名称')
|
||||
| set_data(v0.7.3+) | 调用了setData方法动态设置思维导图数据时触发 | data(新的思维导图数据) |
|
||||
| resize(v0.8.0+) | 容器尺寸改变后触发,实际上是当思维导图实例的`resize`方法被调用后触发 | |
|
||||
| beforeDestroy(v0.9.0+) | 思维导图销毁前触发,即调用了destroy方法触发 | |
|
||||
| body_mousedown(v0.9.2+) | document.body的鼠标按下事件 | e(事件对象) |
|
||||
| body_click | document.body的点击事件 | e(事件对象) |
|
||||
|
||||
### emit(event, ...args)
|
||||
|
||||
@@ -502,7 +508,7 @@ mindMap.updateConfig({
|
||||
| EXPAND_ALL | 展开所有节点 | |
|
||||
| UNEXPAND_ALL | 收起所有节点 | |
|
||||
| UNEXPAND_TO_LEVEL(v0.2.8+) | 展开到指定层级 | level(要展开到的层级,1、2、3...) |
|
||||
| SET_NODE_DATA | 更新节点数据,即更新节点数据对象里`data`对象的数据 | node(要设置的节点)、data(对象,要更新的数据,如`{expand: true}`) |
|
||||
| SET_NODE_DATA | 更新节点数据,即更新节点数据对象里`data`对象的数据,注意这个命令不会触发视图的更新 | node(要设置的节点)、data(对象,要更新的数据,如`{expand: true}`) |
|
||||
| SET_NODE_TEXT | 设置节点文本 | node(要设置的节点)、text(要设置的文本字符串,换行可以使用`\n`)、richText(v0.4.0+,如果要设置的是富文本字符,需要设为`true`)、resetRichText(v0.6.10+是否要复位富文本,默认为false,如果传true那么会重置富文本节点的样式) |
|
||||
| SET_NODE_IMAGE | 设置节点图片 | node(要设置的节点)、imgData(对象,图片信息,结构为:`{url, title, width, height}`,图片的宽高必须要传) |
|
||||
| SET_NODE_ICON | 设置节点图标 | node(要设置的节点)、icons(数组,预定义的图片名称组成的数组,可用图标可在[icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件里的`nodeIconList`列表里获取到,图标名称为`type_name`,如`['priority_1']`) |
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
<tr>
|
||||
<td>maxHistoryCount(v0.5.6+)</td>
|
||||
<td>Number</td>
|
||||
<td>1000</td>
|
||||
<td>1000(v0.9.2+改为500)</td>
|
||||
<td>最大历史记录数</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -513,6 +513,24 @@
|
||||
<td></td>
|
||||
<td>图片地址,当节点图片加载失败时显示的默认图片</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>handleNodePasteImg(v0.9.2+)</td>
|
||||
<td>null 或 Function</td>
|
||||
<td>null</td>
|
||||
<td>在节点上粘贴剪贴板中的图片的处理方法,默认是转换为data:url数据插入到节点中,你可以通过该方法来将图片数据上传到服务器,实现保存图片的url。可以传递一个异步方法,接收Blob类型的图片数据,需要返回指定结构:{ url, size: {width, height} }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvas(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否将思维导图限制在画布内。比如向右拖动时,思维导图图形的最左侧到达画布中心时将无法继续向右拖动,其他同理</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isLimitMindMapInCanvasWhenHasScrollbar(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>当注册了滚动条插件(Scrollbar)时,是否将思维导图限制在画布内,isLimitMindMapInCanvas配置不再起作用</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>数据结构</h3>
|
||||
@@ -592,6 +610,12 @@
|
||||
<td>{color: '#999', opacity: 0.5, fontSize: 14}</td>
|
||||
<td>水印文字样式</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onlyExport(v0.9.2+)</td>
|
||||
<td>Boolean</td>
|
||||
<td>false</td>
|
||||
<td>是否仅在导出时添加水印</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>图标配置</h3>
|
||||
@@ -826,7 +850,7 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<tr>
|
||||
<td>mousewheel</td>
|
||||
<td>鼠标滚动事件</td>
|
||||
<td>e(事件对象)、dir(向上up还是向下down滚动)、this(Event事件类实例)、isTouchPad(v0.6.1+,是否是触控板触发的事件)</td>
|
||||
<td>e(事件对象)、dir(向上up还是向下down滚动。v0.9.2+已改为dirs,数组类型,即支持同时保存多个方向)、this(Event事件类实例)、isTouchPad(v0.6.1+,是否是触控板触发的事件)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>contextmenu</td>
|
||||
@@ -983,6 +1007,16 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<td>思维导图销毁前触发,即调用了destroy方法触发</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>body_mousedown(v0.9.2+)</td>
|
||||
<td>document.body的鼠标按下事件</td>
|
||||
<td>e(事件对象)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>body_click</td>
|
||||
<td>document.body的点击事件</td>
|
||||
<td>e(事件对象)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>emit(event, ...args)</h3>
|
||||
@@ -1132,7 +1166,7 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SET_NODE_DATA</td>
|
||||
<td>更新节点数据,即更新节点数据对象里<code>data</code>对象的数据</td>
|
||||
<td>更新节点数据,即更新节点数据对象里<code>data</code>对象的数据,注意这个命令不会触发视图的更新</td>
|
||||
<td>node(要设置的节点)、data(对象,要更新的数据,如<code>{expand: true}</code>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 结构
|
||||
|
||||
`simple-mind-map`目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)、verticalTimeline(v0.6.6+竖向时间轴)。
|
||||
`simple-mind-map`目前支持的结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)、verticalTimeline(v0.6.6+竖向时间轴)。
|
||||
|
||||
可以在实例化`simple-mind-map`时通过选项指定使用的结构:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>结构</h1>
|
||||
<p><code>simple-mind-map</code>目前支持四种结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)、verticalTimeline(v0.6.6+竖向时间轴)。</p>
|
||||
<p><code>simple-mind-map</code>目前支持的结构:logicalStructure(逻辑结构图)、mindMap(思维导图)、organizationStructure(组织结构图)、catalogOrganization(目录组织图)、timeline(时间轴)、timeline2(时间轴2)、fishbone(鱼骨图)、verticalTimeline(v0.6.6+竖向时间轴)。</p>
|
||||
<p>可以在实例化<code>simple-mind-map</code>时通过选项指定使用的结构:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">new</span> MindMap({
|
||||
<span class="hljs-comment">// ...</span>
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
name: '插入同级节点',
|
||||
value: 'Enter'
|
||||
},
|
||||
{
|
||||
name: '插入父节点',
|
||||
value: 'Shift + Tab'
|
||||
},
|
||||
{
|
||||
name: '上移节点',
|
||||
value: 'Ctrl + ↑'
|
||||
@@ -35,6 +39,10 @@
|
||||
name: '删除节点',
|
||||
value: 'Delete | Backspace'
|
||||
},
|
||||
{
|
||||
name: '仅删除当前节点',
|
||||
value: 'Shift + Backspace'
|
||||
},
|
||||
{
|
||||
name: '复制节点',
|
||||
value: 'Ctrl + C'
|
||||
@@ -89,8 +97,16 @@
|
||||
value: 'Ctrl + -'
|
||||
},
|
||||
{
|
||||
name: '恢复默认',
|
||||
name: '放大缩小',
|
||||
value: 'Ctrl + 鼠标滚动'
|
||||
},
|
||||
{
|
||||
name: '回到根节点',
|
||||
value: 'Ctrl + Enter'
|
||||
},
|
||||
{
|
||||
name: '适应画布',
|
||||
value: 'Ctrl + i'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user