Compare commits

..

39 Commits

Author SHA1 Message Date
wanglin2
e4fab73017 Demo打包 2023-09-27 18:25:55 +08:00
wanglin2
20f67efd58 Demo:修复公式侧边栏组件导致的侧边栏自动关闭问题 2023-09-27 16:44:29 +08:00
wanglin2
8c3d66eb3c Feat:创建节点、复制节点时给新节点数据创建uid 2023-09-27 13:38:15 +08:00
wanglin2
a4f6006efd Fix:修复isSameObject工具方法逻辑错误的问题 2023-09-27 11:02:37 +08:00
wanglin2
1d297350cc Fix:修复工具方法getType返回错误的问题 2023-09-27 09:03:40 +08:00
wanglin2
07650f8978 Doc update 2023-09-26 09:19:58 +08:00
wanglin2
b26e5625ce 打包 2023-09-24 22:14:10 +08:00
wanglin2
1e38731ecb Doc update 2023-09-24 22:03:06 +08:00
wanglin2
ef9b9804cb 打包0.7.2 2023-09-23 16:35:13 +08:00
wanglin2
9fe321a127 Doc update 2023-09-23 16:28:17 +08:00
wanglin2
464e57d019 Doc update 2023-09-23 15:48:05 +08:00
wanglin2
50f125471e Feat:插入公式命令支持传入指定的节点 2023-09-23 15:22:26 +08:00
wanglin2
6bbee4a5cc Demo:节点标签输入适配新颜色生成逻辑 2023-09-23 10:52:04 +08:00
wanglin2
5052c0427a 优化节点标签代码 2023-09-23 10:51:30 +08:00
街角小林
9528631ed1 Merge pull request #347 from wanghao1993/tag_color
feat: 修改tag颜色,可以自定义tag颜色,没有自定义的tag颜色,那么就根据内容生成
2023-09-23 10:34:49 +08:00
街角小林
2a816f62fa Merge branch 'feature' into tag_color 2023-09-23 10:34:38 +08:00
wanglin2
8596e3356d Fix:修复非富文本模式下文本中存在<>&字符时再次编辑时部分文本会消失的问题 2023-09-23 10:22:57 +08:00
Isaac Wang1 汪浩
7422af7f3b feat: 修改tag颜色,可以自定义tag颜色,没有自定义的tag颜色,那么就根据内容生成 2023-09-22 19:36:34 +08:00
wanglin2
0f047da78b update 2023-09-22 17:54:26 +08:00
wanglin2
f866abb34c 优化图标合并相关逻辑 2023-09-22 17:13:09 +08:00
wanglin2
01d7e36990 恢复意外的合并部分 2023-09-22 16:44:57 +08:00
街角小林
a9493b9c16 Merge pull request #345 from wanghao1993/feature/icon-merge
Feature/icon merge
2023-09-22 16:29:03 +08:00
街角小林
a59a283d74 Merge branch 'feature' into feature/icon-merge 2023-09-22 16:28:47 +08:00
wanglin2
aafcba8bb7 Demo:支持数学公式 2023-09-22 16:12:40 +08:00
wanglin2
11ea7d452c Feat:新增数学公式插件 2023-09-22 16:11:33 +08:00
Isaac Wang1 汪浩
47d21d85fb feat: build 2023-09-22 14:01:02 +08:00
wanglin2
518b7642a0 Demo:修复复制知犀思维导图多个节点时无法粘贴的问题 2023-09-22 10:57:32 +08:00
wanglin2
a9ea4b8e33 Feat:1.新增同时插入多个同级节点、多个子节点的命令;2.复制、剪切操作支持同时操作多个节点;3.新增对插入同级节点、子节点的命令插入的第四个参数数据的处理 2023-09-22 10:00:44 +08:00
wanglin2
443465eb86 Feat:将节点唯一标识由id全部改为uid 2023-09-22 08:57:00 +08:00
wanghao1993
e1172c8d0d fix: text 是空的时候会报错 2023-09-21 23:33:06 +08:00
wanglin2
7a2605fdad Feat:支持同时对多个节点插入兄弟节点;对根节点调用插入兄弟节点的命令时不再创建子节点 2023-09-21 16:27:26 +08:00
wanglin2
a97d549d69 Feat:优化子节点的插入:1.同时对多个节点插入子节点时,不进入编辑状态;2.新插入的子节点自动进入激活状态 2023-09-21 15:58:22 +08:00
wanglin2
fcf48ca3dc Fix:增加一些边界判断 2023-09-21 15:10:17 +08:00
wanglin2
c0ad18cff8 Feat:存在激活节点时点击关联线可直接激活关联线 2023-09-21 09:53:35 +08:00
wanglin2
73e7855575 Feat:1.双击关联线进入关联线文本编辑模式;2.关联线文本为默认文本的话不保存 2023-09-21 09:51:46 +08:00
wanglin2
69ef7faf49 Feat:优化drag插件,支持同时拖动多个节点 2023-09-21 09:02:45 +08:00
wanglin2
036f845968 Feat:支持移动多个节点 2023-09-21 09:01:37 +08:00
wanglin2
740e2e3410 Fix:修复多选节点时选区未包含节点边界时节点不会被选中的问题 2023-09-21 09:00:25 +08:00
wanghao1993
ba44f69f9f fix: icon 合并错误 2023-09-20 00:00:48 +08:00
110 changed files with 4490 additions and 2349 deletions

View File

@@ -25,17 +25,19 @@ Github[releases](https://github.com/wanglin2/mind-map/releases)。
百度云盘:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
> 客户端版本会落后于在线版本,尝试最新功能请优先使用在线版。
# 特性
- [x] 插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积
- [x] 支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构
- [x] 内置多种主题,允许高度自定义样式,支持注册新主题
- [x] 节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要
- [x] 节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式
- [x] 节点支持拖拽(拖拽移动、自由调整)、多种节点形状,支持使用 DDM 完全自定义节点内容
- [x] 支持画布拖动、缩放
- [x] 支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式
- [x] 支持导出为`json``png``svg``pdf``markdown``xmind`,支持从`json``xmind``markdown`导入
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条
- [x] 提供丰富的配置,满足各种场景各种使用习惯
# 安装
@@ -183,4 +185,8 @@ const mindMap = new MindMap({
<img src="./web/src/assets/avatar/敏.jpg" style="width: 50px;height: 50px;" />
<span>敏</span>
</span>
<span>
<img src="./web/src/assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;" />
<span>沐风牧草</span>
</span>
</p>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="icon" href="dist/logo.ico"><title>思绪思维导图</title><script>// 自定义静态资源的路径
window.externalPublicPath = './dist/'
// 接管应用
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?3d449dfd2d4c7693c086" rel="stylesheet"><link href="dist/css/app.css?3d449dfd2d4c7693c086" 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?009f4c7305e0f9f13b31" rel="stylesheet"><link href="dist/css/app.css?009f4c7305e0f9f13b31" 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?3d449dfd2d4c7693c086"></script><script src="dist/js/app.js?3d449dfd2d4c7693c086"></script></body></html>
}</script><script src="dist/js/chunk-vendors.js?009f4c7305e0f9f13b31"></script><script src="dist/js/app.js?009f4c7305e0f9f13b31"></script></body></html>

View File

@@ -14,6 +14,7 @@ import TouchEvent from './src/plugins/TouchEvent.js'
import Search from './src/plugins/Search.js'
import Painter from './src/plugins/Painter.js'
import Scrollbar from './src/plugins/Scrollbar.js'
import Formula from './src/plugins/Formula.js'
import xmind from './src/parse/xmind.js'
import markdown from './src/parse/markdown.js'
import icons from './src/svg/icons.js'
@@ -43,5 +44,6 @@ MindMap.usePlugin(MiniMap)
.usePlugin(Search)
.usePlugin(Painter)
.usePlugin(Scrollbar)
.usePlugin(Formula)
export default MindMap

View File

@@ -1,11 +1,11 @@
{
"name": "simple-mind-map",
"version": "0.6.15-fix.2",
"version": "0.7.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.6.15-fix.2",
"version": "0.7.2",
"license": "MIT",
"dependencies": {
"@svgdotjs/svg.js": "^3.0.16",
@@ -13,8 +13,10 @@
"eventemitter3": "^4.0.7",
"jspdf": "^2.5.1",
"jszip": "^3.10.1",
"katex": "^0.16.8",
"mdast-util-from-markdown": "^1.3.0",
"quill": "^1.3.6",
"tern": "^0.24.3",
"uuid": "^9.0.0",
"xml-js": "^1.6.11"
},
@@ -187,6 +189,36 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/acorn-loose": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-6.1.0.tgz",
"integrity": "sha512-FHhXoiF0Uch3IqsrnPpWwCtiv5PYvipTpT1k9lDMgQVVYc9iDuSl5zdJV358aI8twfHCYMFBRVYvAVki9wC/ng==",
"dependencies": {
"acorn": "^6.2.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-loose/node_modules/acorn": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
"integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-walk": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -247,8 +279,7 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
@@ -263,7 +294,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -371,11 +401,18 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"engines": {
"node": ">= 12"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/core-js": {
"version": "3.27.1",
@@ -523,6 +560,31 @@
"integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==",
"optional": true
},
"node_modules/enhanced-resolve": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz",
"integrity": "sha512-n6e4bsCpzsP0OB76X+vEWhySUQI8GHPVFVK+3QkX35tbryy2WoeGeK5kQ+oxzgDVHjIZyz5fyS60Mi3EpQLc0Q==",
"dependencies": {
"graceful-fs": "^4.1.2",
"memory-fs": "^0.3.0",
"object-assign": "^4.0.1",
"tapable": "^0.2.3"
},
"engines": {
"node": ">=0.6"
}
},
"node_modules/errno": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
"dependencies": {
"prr": "~1.0.1"
},
"bin": {
"errno": "cli.js"
}
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -796,8 +858,7 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/function-bind": {
"version": "1.1.1",
@@ -829,7 +890,6 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -872,6 +932,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
@@ -990,7 +1055,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -1148,6 +1212,21 @@
"setimmediate": "^1.0.5"
}
},
"node_modules/katex": {
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
"integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
"funding": [
"https://opencollective.com/katex",
"https://github.com/sponsors/katex"
],
"dependencies": {
"commander": "^8.3.0"
},
"bin": {
"katex": "cli.js"
}
},
"node_modules/kleur": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
@@ -1233,6 +1312,15 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/memory-fs": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz",
"integrity": "sha512-QTNXnl79X97kZ9jJk/meJrtDuvgvRakX5LU7HZW1L7MsXHuSTwoMIzN9tOLLH3Xfsj/gbsSqX/ovnsqz246zKQ==",
"dependencies": {
"errno": "^0.1.3",
"readable-stream": "^2.0.1"
}
},
"node_modules/micromark": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-3.1.0.tgz",
@@ -1659,7 +1747,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -1686,6 +1773,14 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
@@ -1713,7 +1808,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
}
@@ -1800,7 +1894,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1849,6 +1942,11 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
"integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="
},
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -2140,6 +2238,50 @@
"node": ">=12.0.0"
}
},
"node_modules/tapable": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz",
"integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/tern": {
"version": "0.24.3",
"resolved": "https://registry.npmjs.org/tern/-/tern-0.24.3.tgz",
"integrity": "sha512-Z8uvtdWIlFn1GWy0HW5FhZ8VDryZwoJUdnjZU25C7/PBOltLIn1uv+WF3rVq6S1761YbsmbZYRP/l0ZJBCkvrw==",
"dependencies": {
"acorn": "^6.0.0",
"acorn-loose": "^6.0.0",
"acorn-walk": "^6.0.0",
"enhanced-resolve": "^2.2.2",
"glob": "^7.1.1",
"minimatch": "^3.0.3",
"resolve-from": "2.0.0"
},
"bin": {
"tern": "bin/tern"
}
},
"node_modules/tern/node_modules/acorn": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
"integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/tern/node_modules/resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
@@ -2266,8 +2408,7 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/xml-js": {
"version": "1.6.11",
@@ -2418,6 +2559,26 @@
"dev": true,
"requires": {}
},
"acorn-loose": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-6.1.0.tgz",
"integrity": "sha512-FHhXoiF0Uch3IqsrnPpWwCtiv5PYvipTpT1k9lDMgQVVYc9iDuSl5zdJV358aI8twfHCYMFBRVYvAVki9wC/ng==",
"requires": {
"acorn": "^6.2.0"
},
"dependencies": {
"acorn": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
"integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ=="
}
}
},
"acorn-walk": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2459,8 +2620,7 @@
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"base64-arraybuffer": {
"version": "1.0.2",
@@ -2472,7 +2632,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2549,11 +2708,15 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"commander": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"core-js": {
"version": "3.27.1",
@@ -2660,6 +2823,25 @@
"integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==",
"optional": true
},
"enhanced-resolve": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz",
"integrity": "sha512-n6e4bsCpzsP0OB76X+vEWhySUQI8GHPVFVK+3QkX35tbryy2WoeGeK5kQ+oxzgDVHjIZyz5fyS60Mi3EpQLc0Q==",
"requires": {
"graceful-fs": "^4.1.2",
"memory-fs": "^0.3.0",
"object-assign": "^4.0.1",
"tapable": "^0.2.3"
}
},
"errno": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
"integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
"requires": {
"prr": "~1.0.1"
}
},
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -2872,8 +3054,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"function-bind": {
"version": "1.1.1",
@@ -2899,7 +3080,6 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -2927,6 +3107,11 @@
"type-fest": "^0.20.2"
}
},
"graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
@@ -3009,7 +3194,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -3131,6 +3315,14 @@
"setimmediate": "^1.0.5"
}
},
"katex": {
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
"integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
"requires": {
"commander": "^8.3.0"
}
},
"kleur": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
@@ -3196,6 +3388,15 @@
"@types/mdast": "^3.0.0"
}
},
"memory-fs": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz",
"integrity": "sha512-QTNXnl79X97kZ9jJk/meJrtDuvgvRakX5LU7HZW1L7MsXHuSTwoMIzN9tOLLH3Xfsj/gbsSqX/ovnsqz246zKQ==",
"requires": {
"errno": "^0.1.3",
"readable-stream": "^2.0.1"
}
},
"micromark": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/micromark/-/micromark-3.1.0.tgz",
@@ -3412,7 +3613,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -3433,6 +3633,11 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
@@ -3451,7 +3656,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"requires": {
"wrappy": "1"
}
@@ -3516,8 +3720,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
},
"path-key": {
"version": "3.1.1",
@@ -3548,6 +3751,11 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
"integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@@ -3752,6 +3960,37 @@
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
"optional": true
},
"tapable": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz",
"integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A=="
},
"tern": {
"version": "0.24.3",
"resolved": "https://registry.npmjs.org/tern/-/tern-0.24.3.tgz",
"integrity": "sha512-Z8uvtdWIlFn1GWy0HW5FhZ8VDryZwoJUdnjZU25C7/PBOltLIn1uv+WF3rVq6S1761YbsmbZYRP/l0ZJBCkvrw==",
"requires": {
"acorn": "^6.0.0",
"acorn-loose": "^6.0.0",
"acorn-walk": "^6.0.0",
"enhanced-resolve": "^2.2.2",
"glob": "^7.1.1",
"minimatch": "^3.0.3",
"resolve-from": "2.0.0"
},
"dependencies": {
"acorn": {
"version": "6.4.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
"integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ=="
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ=="
}
}
},
"text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
@@ -3847,8 +4086,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"xml-js": {
"version": "1.6.11",

View File

@@ -1,6 +1,6 @@
{
"name": "simple-mind-map",
"version": "0.7.1-fix.2",
"version": "0.7.2",
"description": "一个简单的web在线思维导图",
"authors": [
{
@@ -13,6 +13,7 @@
}
],
"types": "./types/index.d.ts",
"typings": "./types/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
@@ -31,6 +32,7 @@
"eventemitter3": "^4.0.7",
"jspdf": "^2.5.1",
"jszip": "^3.10.1",
"katex": "^0.16.8",
"mdast-util-from-markdown": "^1.3.0",
"quill": "^1.3.6",
"tern": "^0.24.3",

View File

@@ -1,27 +1,3 @@
// 标签颜色列表
export const tagColorList = [
{
color: 'rgb(77, 65, 0)',
background: 'rgb(255, 244, 179)'
},
{
color: 'rgb(0, 50, 77)',
background: 'rgb(179, 229, 255)'
},
{
color: 'rgb(77, 0, 73)',
background: 'rgb(255, 179, 251)'
},
{
color: 'rgb(57, 77, 0)',
background: 'rgb(236, 255, 179)'
},
{
color: 'rgb(0, 77, 47)',
background: 'rgb(179, 255, 226)'
}
]
// 主题列表
export const themeList = [
{
@@ -365,7 +341,7 @@ export const cssContent = `
stroke-width: 1;
}
.smm-node:hover .smm-hover-node{
.smm-node:not(.smm-node-dragging):hover .smm-hover-node{
display: block;
}

View File

@@ -188,5 +188,21 @@ export const defaultOpt = {
// 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动
autoMoveWhenMouseInEdgeOnDrag: true,
// 是否首次加载fit view
fit: false
fit: false,
// 拖拽多个节点时随鼠标移动的示意矩形的样式配置
dragMultiNodeRectConfig: {
width: 40,
height: 20,
fill: '' // 填充颜色,如果不传默认使用连线的颜色
},
// 节点拖拽时新位置的示意矩形的填充颜色,如果不传默认使用连线的颜色
dragPlaceholderRectFill: '',
// 节点拖拽时的透明度配置
dragOpacityConfig: {
cloneNodeOpacity: 0.5, // 跟随鼠标移动的克隆节点或矩形的透明度
beingDragNodeOpacity: 0.3 // 被拖拽节点的透明度
},
// 自定义标签的颜色
// {pass: 'green, unpass: 'red'}
tagsColorMap: {}
}

View File

@@ -13,7 +13,13 @@ import {
walk,
bfsWalk,
loadImage,
isUndef
isUndef,
getTopAncestorsFomNodeList,
addDataToAppointNodes,
createUidForAppointNodes,
formatDataToArray,
getNodeIndex,
createUid
} from '../../utils'
import { shapeList } from './node/Shape'
import { lineStyleProps } from '../../themes/default'
@@ -40,7 +46,6 @@ const layouts = {
}
// 渲染
class Render {
// 构造函数
constructor(opt = {}) {
@@ -132,9 +137,18 @@ class Render {
// 插入同级节点
this.insertNode = this.insertNode.bind(this)
this.mindMap.command.add('INSERT_NODE', this.insertNode)
// 插入多个同级节点
this.insertMultiNode = this.insertMultiNode.bind(this)
this.mindMap.command.add('INSERT_MULTI_NODE', this.insertMultiNode)
// 插入子节点
this.insertChildNode = this.insertChildNode.bind(this)
this.mindMap.command.add('INSERT_CHILD_NODE', this.insertChildNode)
// 插入多个子节点
this.insertMultiChildNode = this.insertMultiChildNode.bind(this)
this.mindMap.command.add(
'INSERT_MULTI_CHILD_NODE',
this.insertMultiChildNode
)
// 上移节点
this.upNode = this.upNode.bind(this)
this.mindMap.command.add('UP_NODE', this.upNode)
@@ -202,6 +216,9 @@ class Render {
// 设置节点标签
this.setNodeTag = this.setNodeTag.bind(this)
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
// 设置节点公式
this.insertFormula = this.insertFormula.bind(this)
this.mindMap.command.add('INSERT_FORMULA', this.insertFormula)
// 添加节点概要
this.addGeneralization = this.addGeneralization.bind(this)
this.mindMap.command.add('ADD_GENERALIZATION', this.addGeneralization)
@@ -386,15 +403,6 @@ class Render {
})
}
// 获取节点在同级里的索引位置
getNodeIndex(node) {
return node.parent
? node.parent.children.findIndex(item => {
return item.uid === node.uid
})
: 0
}
// 全选
selectAll() {
walk(
@@ -439,58 +447,120 @@ class Render {
}
}
// 规范指定节点数据
formatAppointNodes(appointNodes) {
if (!appointNodes) return []
return Array.isArray(appointNodes) ? appointNodes : [appointNodes]
}
// 插入同级节点,多个节点只会操作第一个节点
// 插入同级节点
insertNode(
openEdit = true,
appointNodes = [],
appointData = null,
appointChildren = []
) {
appointNodes = this.formatAppointNodes(appointNodes)
appointNodes = formatDataToArray(appointNodes)
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
return
}
this.textEdit.hideEditTextBox()
let {
const {
defaultInsertSecondLevelNodeText,
defaultInsertBelowSecondLevelNodeText
} = this.mindMap.opt
let list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
let first = list[0]
if (first.isGeneralization) {
return
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
const handleMultiNodes = list.length > 1
const isRichText = !!this.mindMap.richText
const params = {
expand: true,
richText: isRichText,
resetRichText: isRichText,
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
}
if (first.isRoot) {
this.insertChildNode(openEdit, appointNodes, appointData)
} else {
let text =
first.layerIndex === 1
? defaultInsertSecondLevelNodeText
: defaultInsertBelowSecondLevelNodeText
if (first.layerIndex === 1) {
first.parent.destroy()
// 动态指定的子节点数据也需要添加相关属性
appointChildren = addDataToAppointNodes(appointChildren, {
...params
})
const needDestroyNodeList = {}
list.forEach(node => {
if (node.isGeneralization || node.isRoot) {
return
}
let index = this.getNodeIndex(first)
let isRichText = !!this.mindMap.richText
first.parent.nodeData.children.splice(index + 1, 0, {
inserting: openEdit,
const parent = node.parent
const isOneLayer = node.layerIndex === 1
// 插入二级节点时根节点需要重新渲染
if (isOneLayer && !needDestroyNodeList[parent.uid]) {
needDestroyNodeList[parent.uid] = parent
}
// 新插入节点的默认文本
const text = isOneLayer
? defaultInsertSecondLevelNodeText
: defaultInsertBelowSecondLevelNodeText
// 计算插入位置
const index = parent.nodeData.children.findIndex(item => {
return item.data.uid === node.uid
})
const newNodeData = {
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式,
data: {
text: text,
expand: true,
richText: isRichText,
resetRichText: isRichText,
...params,
uid: createUid(),
...(appointData || {})
},
children: [...appointChildren]
})
this.mindMap.render()
children: [...createUidForAppointNodes(appointChildren)]
}
parent.nodeData.children.splice(index + 1, 0, newNodeData)
})
Object.keys(needDestroyNodeList).forEach(key => {
needDestroyNodeList[key].destroy()
})
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
if (handleMultiNodes || !openEdit) {
this.clearActive()
}
this.mindMap.render()
}
// 插入多个同级节点
insertMultiNode(appointNodes, nodeList) {
if (!nodeList || nodeList.length <= 0) return
appointNodes = formatDataToArray(appointNodes)
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
return
}
this.textEdit.hideEditTextBox()
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
const isRichText = !!this.mindMap.richText
const params = {
expand: true,
richText: isRichText,
resetRichText: isRichText,
isActive: true
}
nodeList = addDataToAppointNodes(nodeList, params)
const needDestroyNodeList = {}
list.forEach(node => {
if (node.isGeneralization || node.isRoot) {
return
}
const parent = node.parent
const isOneLayer = node.layerIndex === 1
// 插入二级节点时根节点需要重新渲染
if (isOneLayer && !needDestroyNodeList[parent.uid]) {
needDestroyNodeList[parent.uid] = parent
}
// 计算插入位置
const index = parent.nodeData.children.findIndex(item => {
return item.data.uid === node.uid
})
const newNodeList = createUidForAppointNodes(simpleDeepClone(nodeList))
parent.nodeData.children.splice(
index + 1,
0,
...newNodeList
)
})
Object.keys(needDestroyNodeList).forEach(key => {
needDestroyNodeList[key].destroy()
})
this.clearActive()
this.mindMap.render()
}
// 插入子节点
@@ -500,16 +570,28 @@ class Render {
appointData = null,
appointChildren = []
) {
appointNodes = this.formatAppointNodes(appointNodes)
appointNodes = formatDataToArray(appointNodes)
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
return
}
this.textEdit.hideEditTextBox()
let {
const {
defaultInsertSecondLevelNodeText,
defaultInsertBelowSecondLevelNodeText
} = this.mindMap.opt
let list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
const handleMultiNodes = list.length > 1
const isRichText = !!this.mindMap.richText
const params = {
expand: true,
richText: isRichText,
resetRichText: isRichText,
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
}
// 动态指定的子节点数据也需要添加相关属性
appointChildren = addDataToAppointNodes(appointChildren, {
...params
})
list.forEach(node => {
if (node.isGeneralization) {
return
@@ -517,27 +599,66 @@ class Render {
if (!node.nodeData.children) {
node.nodeData.children = []
}
let text = node.isRoot
const text = node.isRoot
? defaultInsertSecondLevelNodeText
: defaultInsertBelowSecondLevelNodeText
let isRichText = !!this.mindMap.richText
node.nodeData.children.push({
inserting: openEdit,
const newNode = {
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式
data: {
text: text,
expand: true,
richText: isRichText,
resetRichText: isRichText,
uid: createUid(),
...params,
...(appointData || {})
},
children: [...appointChildren]
})
children: [...createUidForAppointNodes(appointChildren)]
}
node.nodeData.children.push(newNode)
// 插入子节点时自动展开子节点
node.nodeData.data.expand = true
if (node.isRoot) {
node.destroy()
}
})
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
if (handleMultiNodes || !openEdit) {
this.clearActive()
}
this.mindMap.render()
}
// 插入多个子节点
insertMultiChildNode(appointNodes, childList) {
if (!childList || childList.length <= 0) return
appointNodes = formatDataToArray(appointNodes)
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
return
}
this.textEdit.hideEditTextBox()
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
const isRichText = !!this.mindMap.richText
const params = {
expand: true,
richText: isRichText,
resetRichText: isRichText,
isActive: true
}
childList = addDataToAppointNodes(childList, params)
list.forEach(node => {
if (node.isGeneralization) {
return
}
if (!node.nodeData.children) {
node.nodeData.children = []
}
childList = createUidForAppointNodes(childList)
node.nodeData.children.push(...childList)
// 插入子节点时自动展开子节点
node.nodeData.data.expand = true
if (node.isRoot) {
node.destroy()
}
})
this.clearActive()
this.mindMap.render()
}
@@ -598,19 +719,19 @@ class Render {
// 复制节点
copy() {
this.beingCopyData = this.copyNode()
this.setCoptyDataToClipboard(this.beingCopyData)
this.setCopyDataToClipboard(this.beingCopyData)
}
// 剪切节点
cut() {
this.mindMap.execCommand('CUT_NODE', copyData => {
this.beingCopyData = copyData
this.setCoptyDataToClipboard(copyData)
this.setCopyDataToClipboard(copyData)
})
}
// 将粘贴或剪切的数据设置到用户剪切板中
setCoptyDataToClipboard(data) {
setCopyDataToClipboard(data) {
if (navigator.clipboard) {
navigator.clipboard.writeText(
JSON.stringify({
@@ -701,13 +822,9 @@ class Render {
}
if (smmData) {
this.mindMap.execCommand(
'INSERT_CHILD_NODE',
false,
'INSERT_MULTI_CHILD_NODE',
[],
{
...smmData.data
},
[...smmData.children]
Array.isArray(smmData) ? smmData : [smmData]
)
} else {
this.mindMap.execCommand('INSERT_CHILD_NODE', false, [], {
@@ -741,86 +858,70 @@ class Render {
// 将节点移动到另一个节点的前面
insertBefore(node, exist) {
if (node.isRoot) {
return
}
// 如果是二级节点变成了下级节点,或是下级节点变成了二级节点,节点样式需要更新
let nodeLayerChanged =
(node.layerIndex === 1 && exist.layerIndex !== 1) ||
(node.layerIndex !== 1 && exist.layerIndex === 1)
// 移动节点
let nodeParent = node.parent
let nodeBorthers = nodeParent.children
let nodeIndex = nodeBorthers.findIndex(item => {
return item.uid === node.uid
})
if (nodeIndex === -1) {
return
}
nodeBorthers.splice(nodeIndex, 1)
nodeParent.nodeData.children.splice(nodeIndex, 1)
// 目标节点
let existParent = exist.parent
let existBorthers = existParent.children
let existIndex = existBorthers.findIndex(item => {
return item.uid === exist.uid
})
if (existIndex === -1) {
return
}
existBorthers.splice(existIndex, 0, node)
existParent.nodeData.children.splice(existIndex, 0, node.nodeData)
this.mindMap.render(() => {
if (nodeLayerChanged) {
node.reRender()
}
})
this.insertTo(node, exist, 'before')
}
// 将节点移动到另一个节点的后面
insertAfter(node, exist) {
if (node.isRoot) {
return
}
// 如果是二级节点变成了下级节点,或是下级节点变成了二级节点,节点样式需要更新
let nodeLayerChanged =
(node.layerIndex === 1 && exist.layerIndex !== 1) ||
(node.layerIndex !== 1 && exist.layerIndex === 1)
// 移动节点
let nodeParent = node.parent
let nodeBorthers = nodeParent.children
let nodeIndex = nodeBorthers.findIndex(item => {
return item.uid === node.uid
})
if (nodeIndex === -1) {
return
}
nodeBorthers.splice(nodeIndex, 1)
nodeParent.nodeData.children.splice(nodeIndex, 1)
this.insertTo(node, exist, 'after')
}
// 目标节点
let existParent = exist.parent
let existBorthers = existParent.children
let existIndex = existBorthers.findIndex(item => {
return item.uid === exist.uid
// 将节点移动到另一个节点的前面或后面
insertTo(node, exist, dir = 'before') {
let nodeList = formatDataToArray(node)
nodeList = nodeList.filter(item => {
return !item.isRoot
})
if (existIndex === -1) {
return
if (dir === 'after') {
nodeList.reverse()
}
existIndex++
existBorthers.splice(existIndex, 0, node)
existParent.nodeData.children.splice(existIndex, 0, node.nodeData)
this.mindMap.render(() => {
if (nodeLayerChanged) {
node.reRender()
nodeList.forEach(item => {
this.checkNodeLayerChange(item, exist)
// 移动节点
let nodeParent = item.parent
let nodeBorthers = nodeParent.children
let nodeIndex = nodeBorthers.findIndex(item2 => {
return item.uid === item2.uid
})
if (nodeIndex === -1) {
return
}
nodeBorthers.splice(nodeIndex, 1)
nodeParent.nodeData.children.splice(nodeIndex, 1)
// 目标节点
let existParent = exist.parent
let existBorthers = existParent.children
let existIndex = existBorthers.findIndex(item2 => {
return item2.uid === exist.uid
})
if (existIndex === -1) {
return
}
if (dir === 'after') {
existIndex++
}
existBorthers.splice(existIndex, 0, item)
existParent.nodeData.children.splice(existIndex, 0, item.nodeData)
})
this.mindMap.render()
}
// 如果是富文本模式,那么某些层级变化需要更新样式
checkNodeLayerChange(node, toNode) {
if (this.mindMap.richText) {
let nodeLayerChanged =
(node.layerIndex === 1 && toNode.layerIndex !== 1) ||
(node.layerIndex !== 1 && toNode.layerIndex === 1)
if (nodeLayerChanged) {
node.nodeData.data.resetRichText = true
}
}
}
// 移除节点
removeNode(appointNodes = []) {
appointNodes = this.formatAppointNodes(appointNodes)
appointNodes = formatDataToArray(appointNodes)
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
return
}
@@ -892,32 +993,40 @@ class Render {
// 移除某个指定节点
removeOneNode(node) {
let index = this.getNodeIndex(node)
let index = getNodeIndex(node)
node.remove()
node.parent.children.splice(index, 1)
node.parent.nodeData.children.splice(index, 1)
}
// 复制节点,多个节点只会操作第一个节点
// 复制节点
copyNode() {
if (this.activeNodeList.length <= 0) {
return
}
return copyNodeTree({}, this.activeNodeList[0], true)
const nodeList = getTopAncestorsFomNodeList(this.activeNodeList)
return nodeList.map(node => {
return copyNodeTree({}, node, true)
})
}
// 剪切节点,多个节点只会操作第一个节点
// 剪切节点
cutNode(callback) {
if (this.activeNodeList.length <= 0) {
return
}
let node = this.activeNodeList[0]
if (node.isRoot) {
return null
}
let copyData = copyNodeTree({}, node, true)
this.removeActiveNode(node)
this.removeOneNode(node)
const nodeList = getTopAncestorsFomNodeList(this.activeNodeList).filter(
node => {
return !node.isRoot
}
)
const copyData = nodeList.map(node => {
return copyNodeTree({}, node, true)
})
nodeList.forEach(node => {
this.removeActiveNode(node)
this.removeOneNode(node)
})
this.mindMap.emit('node_active', null, [...this.activeNodeList])
this.mindMap.render()
if (callback && typeof callback === 'function') {
@@ -925,16 +1034,19 @@ class Render {
}
}
// 移动一个节点作为另一个节点的子节点
// 移动节点作为另一个节点的子节点
moveNodeTo(node, toNode) {
if (node.isRoot) {
return
}
// let copyData = copyNodeTree({}, node, false, true)
this.removeActiveNode(node)
this.removeOneNode(node)
let nodeList = formatDataToArray(node)
nodeList = nodeList.filter(item => {
return !item.isRoot
})
nodeList.forEach(item => {
this.checkNodeLayerChange(item, toNode)
this.removeActiveNode(item)
this.removeOneNode(item)
toNode.nodeData.children.push(item.nodeData)
})
this.mindMap.emit('node_active', null, [...this.activeNodeList])
toNode.nodeData.children.push(node.nodeData)
this.mindMap.render()
if (toNode.isRoot) {
toNode.destroy()
@@ -943,11 +1055,16 @@ class Render {
// 粘贴节点到节点
pasteNode(data) {
if (this.activeNodeList.length <= 0 || !data) {
data = formatDataToArray(data)
if (this.activeNodeList.length <= 0 || data.length <= 0) {
return
}
this.activeNodeList.forEach(item => {
item.nodeData.children.push(simpleDeepClone(data))
this.activeNodeList.forEach(node => {
node.nodeData.children.push(
...data.map(item => {
return simpleDeepClone(item)
})
)
})
this.mindMap.render()
}
@@ -1171,6 +1288,17 @@ class Render {
})
}
// 设置节点公式
insertFormula(formula, appointNodes = []) {
// 只在富文本模式下可用并且需要注册Formula插件
if (!this.mindMap.richText || !this.mindMap.formula) return
appointNodes = formatDataToArray(appointNodes)
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
list.forEach(node => {
this.mindMap.formula.insertFormulaToNode(node, formula)
})
}
// 添加节点概要
addGeneralization(data) {
if (this.activeNodeList.length <= 0) {

View File

@@ -1,4 +1,10 @@
import { getStrWithBrFromHtml, checkNodeOuter } from '../../utils'
import {
getStrWithBrFromHtml,
checkNodeOuter,
focusInput,
selectAllInput,
htmlEscape
} from '../../utils'
import { ERROR_TYPES } from '../../constants/constant'
// 节点文字编辑类
@@ -167,9 +173,11 @@ export default class TextEdit {
let scale = this.mindMap.view.scale
let lineHeight = node.style.merge('lineHeight')
let fontSize = node.style.merge('fontSize')
let textLines = (this.cacheEditingText || node.nodeData.data.text).split(
/\n/gim
)
let textLines = (this.cacheEditingText || node.nodeData.data.text)
.split(/\n/gim)
.map(item => {
return htmlEscape(item)
})
let isMultiLine = node._textData.node.attr('data-ismultiLine') === 'true'
node.style.domText(this.textEditNode, scale, isMultiLine)
this.textEditNode.style.zIndex = nodeTextEditZIndex
@@ -188,35 +196,16 @@ export default class TextEdit {
this.showTextEdit = true
// 选中文本
// if (!this.cacheEditingText) {
// this.selectNodeText()
// selectAllInput(this.textEditNode)
// }
if (isInserting || (selectTextOnEnterEditText && !isFromKeyDown)) {
this.selectNodeText()
selectAllInput(this.textEditNode)
} else {
this.focus()
focusInput(this.textEditNode)
}
this.cacheEditingText = ''
}
// 聚焦
focus() {
let selection = window.getSelection()
let range = document.createRange()
range.selectNodeContents(this.textEditNode)
range.collapse()
selection.removeAllRanges()
selection.addRange(range)
}
// 选中文本
selectNodeText() {
let selection = window.getSelection()
let range = document.createRange()
range.selectNodeContents(this.textEditNode)
selection.removeAllRanges()
selection.addRange(range)
}
// 获取当前正在编辑的内容
getEditText() {
return getStrWithBrFromHtml(this.textEditNode.innerHTML)

View File

@@ -14,7 +14,7 @@ class Node {
constructor(opt = {}) {
// 节点数据
this.nodeData = this.handleData(opt.data || {})
// id
// uid
this.uid = opt.uid
// 控制实例
this.mindMap = opt.mindMap
@@ -440,12 +440,14 @@ class Node {
this.mindMap.emit('node_mouseup', this, e)
})
this.group.on('mouseenter', e => {
if (this.isDrag) return
this._isMouseenter = true
// 显示展开收起按钮
this.showExpandBtn()
this.mindMap.emit('node_mouseenter', this, e)
})
this.group.on('mouseleave', e => {
if (!this._isMouseenter) return
this._isMouseenter = false
this.hideExpandBtn()
this.mindMap.emit('node_mouseleave', this, e)
@@ -701,6 +703,61 @@ class Node {
}
}
// 设置节点透明度
// 包括连接线和下级节点
setOpacity(val) {
// 自身及连线
this.group.opacity(val)
this._lines.forEach(line => {
line.opacity(val)
})
// 子节点
this.children.forEach(item => {
item.setOpacity(val)
})
// 概要节点
if (this._generalizationNode) {
this._generalizationLine.opacity(val)
this._generalizationNode.group.opacity(val)
}
}
// 隐藏子节点
hideChildren() {
this._lines.forEach(item => {
item.hide()
})
if (this.children && this.children.length) {
this.children.forEach(item => {
item.hide()
})
}
}
// 显示子节点
showChildren() {
this._lines.forEach(item => {
item.show()
})
if (this.children && this.children.length) {
this.children.forEach(item => {
item.show()
})
}
}
// 被拖拽中
startDrag() {
this.isDrag = true
this.group.addClass('smm-node-dragging')
}
// 拖拽结束
endDrag() {
this.isDrag = false
this.group.removeClass('smm-node-dragging')
}
// 连线
renderLine(deep = false) {
if (this.nodeData.data.expand === false) {

View File

@@ -1,5 +1,7 @@
import { tagColorList } from '../../../constants/constant'
import { checkIsNodeStyleDataKey } from '../../../utils/index'
import {
checkIsNodeStyleDataKey,
generateColorByContent
} from '../../../utils/index'
const rootProp = ['paddingX', 'paddingY']
const backgroundStyleProps = [
@@ -163,10 +165,10 @@ class Style {
}
// 标签文字
tagText(node, index) {
tagText(node) {
node
.fill({
color: tagColorList[index].color
color: '#fff'
})
.css({
'font-size': '12px'
@@ -174,9 +176,9 @@ class Style {
}
// 标签矩形
tagRect(node, index) {
tagRect(node, text, color) {
node.fill({
color: tagColorList[index].background
color: color || generateColorByContent(text.node.textContent)
})
}

View File

@@ -3,7 +3,8 @@ import {
resizeImgSize,
removeHtmlStyle,
addHtmlStyle,
checkIsRichText
checkIsRichText,
isUndef
} from '../../../utils'
import { Image, SVG, A, G, Rect, Text, ForeignObject } from '@svgdotjs/svg.js'
import iconsSvg from '../../../svg/icons'
@@ -164,7 +165,10 @@ function createTextNode() {
let lineHeight = this.getStyle('lineHeight', false)
// 文本超长自动换行
let textStyle = this.style.getTextFontStyle()
let textArr = this.nodeData.data.text.split(/\n/gim)
let textArr = []
if (!isUndef(this.nodeData.data.text)) {
textArr = String(this.nodeData.data.text).split(/\n/gim)
}
let maxWidth = this.mindMap.opt.textAutoWrapWidth
let isMultiLine = false
textArr.forEach((item, index) => {
@@ -249,12 +253,15 @@ function createTagNode() {
tagData.slice(0, this.mindMap.opt.maxTag).forEach((item, index) => {
let tag = new G()
// 标签文本
let text = new Text().text(item).x(8).cy(10)
let text = new Text().text(item).x(8).cy(8)
this.style.tagText(text, index)
let { width } = text.bbox()
// 标签矩形
let rect = new Rect().size(width + 16, 20)
this.style.tagRect(rect, index)
// 先从自定义的颜色中获取颜色,没有的话就按照内容生成
const tagsColorList = this.mindMap.opt.tagsColorMap || {}
const color = tagsColorList[text.node.textContent]
this.style.tagRect(rect, text, color)
tag.add(rect).add(text)
nodes.push({
node: tag,

View File

@@ -136,6 +136,7 @@ function renderExpandBtn() {
this._expandBtn.on('dblclick', e => {
e.stopPropagation()
})
this._expandBtn.addClass('smm-expand-btn')
this.group.add(this._expandBtn)
}
this._showExpandBtn = true

View File

@@ -149,8 +149,8 @@ class AssociativeLine {
) {
nodeToIds.set(cur, data.associativeLineTargets)
}
if (data.id) {
idToNode.set(data.id, cur)
if (data.uid) {
idToNode.set(data.uid, cur)
}
},
() => {},
@@ -158,8 +158,8 @@ class AssociativeLine {
0
)
nodeToIds.forEach((ids, node) => {
ids.forEach((id, index) => {
let toNode = idToNode.get(id)
ids.forEach((uid, index) => {
let toNode = idToNode.get(uid)
if (!node || !toNode) return
const associativeLinePoint = (node.nodeData.data.associativeLinePoint ||
[])[index]
@@ -234,6 +234,11 @@ class AssociativeLine {
controlPoints
})
})
// 双击进入关联线文本编辑状态
clickPath.dblclick(() => {
if (!this.activeLine) return
this.showEditTextBox(text)
})
// 渲染关联线文字
this.renderText(this.getText(node, toNode), path, text)
this.lineList.push([path, clickPath, text, node, toNode])
@@ -252,28 +257,25 @@ class AssociativeLine {
}) {
let { associativeLineActiveColor } = this.mindMap.themeConfig
// 如果当前存在激活节点,那么取消激活节点
if (this.mindMap.renderer.activeNodeList.length > 0) {
this.clearActiveNodes()
} else {
// 否则清除当前的关联线的激活状态,如果有的话
this.clearActiveLine()
// 保存当前激活的关联线信息
this.activeLine = [path, clickPath, text, node, toNode]
// 让不可见的点击线显示
clickPath.stroke({ color: associativeLineActiveColor })
// 如果没有输入过关联线文字,那么显示默认文字
if (!this.getText(node, toNode)) {
this.renderText(this.mindMap.opt.defaultAssociativeLineText, path, text)
}
// 渲染控制点和连线
this.renderControls(
startPoint,
endPoint,
controlPoints[0],
controlPoints[1]
)
this.mindMap.emit('associative_line_click', path, clickPath, node, toNode)
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
// 否则清除当前的关联线的激活状态,如果有的话
this.clearActiveLine()
// 保存当前激活的关联线信息
this.activeLine = [path, clickPath, text, node, toNode]
// 让不可见的点击线显示
clickPath.stroke({ color: associativeLineActiveColor })
// 如果没有输入过关联线文字,那么显示默认文字
if (!this.getText(node, toNode)) {
this.renderText(this.mindMap.opt.defaultAssociativeLineText, path, text)
}
// 渲染控制点和连线
this.renderControls(
startPoint,
endPoint,
controlPoints[0],
controlPoints[1]
)
this.mindMap.emit('associative_line_click', path, clickPath, node, toNode)
}
// 移除所有连接线
@@ -395,21 +397,21 @@ class AssociativeLine {
addLine(fromNode, toNode) {
if (!fromNode || !toNode) return
// 目标节点如果没有id则生成一个id
let id = toNode.nodeData.data.id
if (!id) {
id = uuid()
let uid = toNode.nodeData.data.uid
if (!uid) {
uid = uuid()
this.mindMap.execCommand('SET_NODE_DATA', toNode, {
id
uid
})
}
// 将目标节点id保存起来
let list = fromNode.nodeData.data.associativeLineTargets || []
// 连线节点是否存在相同的id,存在则阻止添加关联线
const sameLine = list.some(item => item === id)
const sameLine = list.some(item => item === uid)
if (sameLine) {
return
}
list.push(id)
list.push(uid)
// 保存控制点
let [startPoint, endPoint] = computeNodePoints(fromNode, toNode)
let controlPoints = computeCubicBezierPathPoints(
@@ -458,7 +460,7 @@ class AssociativeLine {
let newAssociativeLineText = {}
if (associativeLineText) {
Object.keys(associativeLineText).forEach(item => {
if (item !== toNode.nodeData.data.id) {
if (item !== toNode.nodeData.data.uid) {
newAssociativeLineText[item] = associativeLineText[item]
}
})
@@ -483,13 +485,6 @@ class AssociativeLine {
})
}
// 清除当前激活的节点
clearActiveNodes() {
if (this.mindMap.renderer.activeNodeList.length > 0) {
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
}
}
// 清除激活的线
clearActiveLine() {
if (this.activeLine) {

View File

@@ -1,4 +1,4 @@
import { bfsWalk, throttle } from '../utils'
import { bfsWalk, throttle, getTopAncestorsFomNodeList } from '../utils'
import Base from '../layouts/Base'
// 节点拖动插件
@@ -13,10 +13,14 @@ class Drag extends Base {
// 复位
reset() {
// 是否正在跳转中
this.isDragging = false
// 鼠标按下的节点
this.mousedownNode = null
// 被拖拽中的节点列表
this.beingDragNodeList = []
// 当前画布节点列表
this.nodeList = []
// 当前拖拽节点
this.node = null
// 当前重叠节点
this.overlapNode = null
// 当前上一个同级节点
@@ -27,16 +31,11 @@ class Drag extends Base {
this.drawTransform = null
// 克隆节点
this.clone = null
// 连接线
this.line = null
// 同级位置占位符
this.placeholder = null
// 鼠标按下位置和节点左上角的偏移量
this.offsetX = 0
this.offsetY = 0
// 克隆节点左上角的坐标
this.cloneNodeLeft = 0
this.cloneNodeTop = 0
// 当前鼠标是否按下
this.isMousedown = false
// 拖拽的鼠标位置变量
@@ -53,45 +52,42 @@ class Drag extends Base {
bindEvent() {
this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this)
this.mindMap.on('node_mousedown', (node, e) => {
if (this.mindMap.opt.readonly || node.isGeneralization) {
return
}
if (e.which !== 1 || node.isRoot) {
return
}
e.preventDefault()
// 计算鼠标按下的位置距离节点左上角的距离
this.drawTransform = this.mindMap.draw.transform()
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
this.offsetX = x - (node.left * scaleX + translateX)
this.offsetY = y - (node.top * scaleY + translateY)
this.node = node
this.isMousedown = true
this.mouseDownX = x
this.mouseDownY = y
this.nodeTreeToList()
})
this.mindMap.on('mousemove', e => {
if (this.mindMap.opt.readonly) {
return
}
if (!this.isMousedown) {
return
}
this.mindMap.emit('node_dragging', this.node)
e.preventDefault()
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
this.mouseMoveX = x
this.mouseMoveY = y
// 只读模式、不是鼠标左键按下、按下的是概要节点或根节点直接返回
if (
Math.abs(x - this.mouseDownX) <= this.checkDragOffset &&
Math.abs(y - this.mouseDownY) <= this.checkDragOffset &&
!this.node.isDrag
this.mindMap.opt.readonly ||
e.which !== 1 ||
node.isGeneralization ||
node.isRoot
) {
return
}
this.mindMap.renderer.clearAllActive()
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.onMouseup = this.onMouseup.bind(this)
@@ -105,9 +101,12 @@ class Drag extends Base {
return
}
this.isMousedown = false
let _nodeIsDrag = this.node.isDrag
this.node.isDrag = false
this.node.show()
// 恢复被拖拽节点的临时设置
this.beingDragNodeList.forEach(node => {
node.setOpacity(1)
node.showChildren()
node.endDrag()
})
this.removeCloneNode()
let overlapNodeUid = this.overlapNode
? this.overlapNode.nodeData.data.uid
@@ -117,17 +116,33 @@ class Drag extends Base {
// 存在重叠子节点,则移动作为其子节点
if (this.overlapNode) {
this.mindMap.renderer.setNodeActive(this.overlapNode, false)
this.mindMap.execCommand('MOVE_NODE_TO', this.node, this.overlapNode)
this.mindMap.execCommand(
'MOVE_NODE_TO',
this.beingDragNodeList,
this.overlapNode
)
} else if (this.prevNode) {
// 存在前一个相邻节点,作为其下一个兄弟节点
this.mindMap.renderer.setNodeActive(this.prevNode, false)
this.mindMap.execCommand('INSERT_AFTER', this.node, this.prevNode)
this.mindMap.execCommand(
'INSERT_AFTER',
this.beingDragNodeList,
this.prevNode
)
} else if (this.nextNode) {
// 存在下一个相邻节点,作为其前一个兄弟节点
this.mindMap.renderer.setNodeActive(this.nextNode, false)
this.mindMap.execCommand('INSERT_BEFORE', this.node, this.nextNode)
} else if (_nodeIsDrag && this.mindMap.opt.enableFreeDrag) {
// 自定义位置
this.mindMap.execCommand(
'INSERT_BEFORE',
this.beingDragNodeList,
this.nextNode
)
} else if (
this.clone &&
this.mindMap.opt.enableFreeDrag &&
this.beingDragNodeList.length === 1
) {
// 如果只拖拽了一个节点,那么设置自定义位置
let { x, y } = this.mindMap.toPos(
e.clientX - this.offsetX,
e.clientY - this.offsetY
@@ -135,11 +150,16 @@ class Drag extends Base {
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
x = (x - translateX) / scaleX
y = (y - translateY) / scaleY
this.node.left = x
this.node.top = y
this.node.customLeft = x
this.node.customTop = y
this.mindMap.execCommand('SET_NODE_CUSTOM_POSITION', this.node, x, y)
this.mousedownNode.left = x
this.mousedownNode.top = y
this.mousedownNode.customLeft = x
this.mousedownNode.customTop = y
this.mindMap.execCommand(
'SET_NODE_CUSTOM_POSITION',
this.mousedownNode,
x,
y
)
this.mindMap.render()
}
this.reset()
@@ -150,24 +170,131 @@ class Drag extends Base {
})
}
// 拖动中
onMove(x, y, e) {
if (!this.isMousedown) {
return
}
// 更新克隆节点的位置
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
let cloneNodeLeft = x - this.offsetX
let cloneNodeTop = y - this.offsetY
x = (cloneNodeLeft - translateX) / scaleX
y = (cloneNodeTop - translateY) / scaleY
let t = this.clone.transform()
this.clone.translate(x - t.translateX, y - t.translateY)
// 检测新位置
this.checkOverlapNode()
// 如果注册了多选节点插件,那么复用它的边缘自动移动画布功能
if (this.mindMap.opt.autoMoveWhenMouseInEdgeOnDrag && this.mindMap.select) {
this.drawTransform = this.mindMap.draw.transform()
this.mindMap.select.clearAutoMoveTimer()
this.mindMap.select.onMove(e.clientX, e.clientY)
}
}
// 开始拖拽时初始化一些数据
handleStartMove() {
if (!this.isDragging) {
this.isDragging = true
// 鼠标按下的节点
let node = this.mousedownNode
// 计算鼠标按下的位置距离节点左上角的距离
this.drawTransform = this.mindMap.draw.transform()
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
this.offsetX = this.mouseDownX - (node.left * scaleX + translateX)
this.offsetY = this.mouseDownY - (node.top * scaleY + translateY)
// 如果鼠标按下的节点是激活节点,那么保存当前所有激活的节点
if (node.nodeData.data.isActive) {
// 找出这些激活节点中的最顶层节点
this.beingDragNodeList = getTopAncestorsFomNodeList(
// 过滤掉根节点和概要节点
this.mindMap.renderer.activeNodeList.filter(item => {
return !item.isRoot && !item.isGeneralization
})
)
} else {
// 否则只拖拽按下的节点
this.beingDragNodeList = [node]
}
// 将节点树转为节点数组
this.nodeTreeToList()
// 创建克隆节点
this.createCloneNode()
// 清除当前所有激活的节点
this.mindMap.renderer.clearAllActive()
}
}
// 节点由树转换成数组,从子节点到根节点
nodeTreeToList() {
const list = []
bfsWalk(this.mindMap.renderer.root, node => {
// 过滤掉当前被拖拽的节点
if (this.checkIsInBeingDragNodeList(node)) {
return
}
if (!list[node.layerIndex]) {
list[node.layerIndex] = []
}
list[node.layerIndex].push(node)
})
this.nodeList = list.reduceRight((res, cur) => {
return [...res, ...cur]
}, [])
}
// 创建克隆节点
createCloneNode() {
if (!this.clone) {
// 节点
this.clone = this.node.group.clone()
this.clone.opacity(0.5)
const {
dragMultiNodeRectConfig,
dragPlaceholderRectFill,
dragOpacityConfig
} = this.mindMap.opt
const {
width: rectWidth,
height: rectHeight,
fill: rectFill
} = dragMultiNodeRectConfig
const node = this.beingDragNodeList[0]
const lineColor = node.style.merge('lineColor', true)
// 如果当前被拖拽的节点数量大于1那么创建一个矩形示意
if (this.beingDragNodeList.length > 1) {
this.clone = this.draw
.rect()
.size(rectWidth, rectHeight)
.radius(rectHeight / 2)
.fill({
color: rectFill || lineColor
})
this.offsetX = rectWidth / 2
this.offsetY = rectHeight / 2
} else {
// 否则克隆当前的节点
this.clone = node.group.clone()
// 删除展开收起按钮元素
const expandEl = this.clone.findOne('.smm-expand-btn')
if (expandEl) {
expandEl.remove()
}
this.mindMap.draw.add(this.clone)
}
this.clone.opacity(dragOpacityConfig.cloneNodeOpacity)
this.clone.css('z-index', 99999)
this.node.isDrag = true
this.node.hide()
// 连接线
this.line = this.draw.path()
this.line.opacity(0.5)
this.node.styleLine(this.line, this.node)
// 同级位置占位符
// 同级位置提示元素
this.placeholder = this.draw.rect().fill({
color: this.node.style.merge('lineColor', true)
color: dragPlaceholderRectFill || lineColor
})
// 当前被拖拽的节点的临时设置
this.beingDragNodeList.forEach(node => {
// 降低透明度
node.setOpacity(dragOpacityConfig.beingDragNodeOpacity)
// 隐藏连线及下级节点
node.hideChildren()
// 设置拖拽状态
node.startDrag()
})
this.mindMap.draw.add(this.clone)
}
}
@@ -177,42 +304,9 @@ class Drag extends Base {
return
}
this.clone.remove()
this.line.remove()
this.placeholder.remove()
}
// 拖动中
onMove(x, y, e) {
if (!this.isMousedown) {
return
}
this.createCloneNode()
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
this.cloneNodeLeft = x - this.offsetX
this.cloneNodeTop = y - this.offsetY
x = (this.cloneNodeLeft - translateX) / scaleX
y = (this.cloneNodeTop - translateY) / scaleY
let t = this.clone.transform()
this.clone.translate(x - t.translateX, y - t.translateY)
// 连接线
let parent = this.node.parent
this.line.plot(
this.quadraticCurvePath(
parent.left + parent.width / 2,
parent.top + parent.height / 2,
x + this.node.width / 2,
y + this.node.height / 2
)
)
this.checkOverlapNode()
// 如果注册了多选节点插件,那么复用它的边缘自动移动画布功能
if (this.mindMap.opt.autoMoveWhenMouseInEdgeOnDrag && this.mindMap.select) {
this.drawTransform = this.mindMap.draw.transform()
this.mindMap.select.clearAutoMoveTimer()
this.mindMap.select.onMove(e.clientX, e.clientY)
}
}
// 检测重叠节点
checkOverlapNode() {
if (!this.drawTransform || !this.placeholder) {
@@ -226,9 +320,6 @@ class Drag extends Base {
if (node.nodeData.data.isActive) {
this.mindMap.renderer.setNodeActive(node, false)
}
if (node.uid === this.node.uid || this.node.isParent(node)) {
return
}
if (this.overlapNode || (this.prevNode && this.nextNode)) {
return
}
@@ -484,7 +575,7 @@ class Drag extends Base {
if (node.layerIndex === 1) {
sameDir = item.dir === node.dir
}
return item !== this.node && sameDir
return sameDir && !this.checkIsInBeingDragNodeList(item)
})
: []
this.handleVerticalCheck(node, checkList)
@@ -535,7 +626,7 @@ class Drag extends Base {
handleFishbone(node) {
let checkList = node.parent
? node.parent.children.filter(item => {
return item !== this.node && item.layerIndex > 1
return item.layerIndex > 1 && !this.checkIsInBeingDragNodeList(item)
})
: []
if (node.layerIndex === 1) {
@@ -553,8 +644,8 @@ class Drag extends Base {
// 获取节点的兄弟节点列表通用方法
commonGetNodeCheckList(node) {
return node.parent
? node.parent.children.filter(item => {
return item !== this.node
? [...node.parent.children].filter(item => {
return !this.checkIsInBeingDragNodeList(item)
})
: []
}
@@ -585,18 +676,11 @@ class Drag extends Base {
}
}
// 节点由树转换成数组,从子节点到根节点
nodeTreeToList() {
const list = []
bfsWalk(this.mindMap.renderer.root, node => {
if (!list[node.layerIndex]) {
list[node.layerIndex] = []
}
list[node.layerIndex].push(node)
// 检查某个节点是否在被拖拽节点内
checkIsInBeingDragNodeList(node) {
return !!this.beingDragNodeList.find(item => {
return item.uid === node.uid || item.isParent(node)
})
this.nodeList = list.reduceRight((res, cur) => {
return [...res, ...cur]
}, [])
}
}

View File

@@ -41,7 +41,7 @@ class Export {
let task = imageList.map(async item => {
let imgUlr = item.attr('href') || item.attr('xlink:href')
// 已经是data:URL形式不用转换
if (/^data:/.test(imgUlr)) {
if (/^data:/.test(imgUlr) || imgUlr === 'none') {
return
}
let imgData = await imgToDataUrl(imgUlr)

View File

@@ -0,0 +1,53 @@
import katex from 'katex'
import Quill from 'quill'
// 数学公式支持插件
// 该插件在富文本模式下可用
class Formula {
// 构造函数
constructor(opt) {
this.opt = opt
this.mindMap = opt.mindMap
window.katex = katex
this.extendQuill()
}
// 修改formula格式工具
extendQuill() {
const QuillFormula = Quill.import('formats/formula')
class CustomFormulaBlot extends QuillFormula {
static create(value) {
let node = super.create(value)
if (typeof value === 'string') {
katex.render(value, node, {
throwOnError: false,
errorColor: '#f00',
output: 'mathml' // 增加该配置,默认只输出公式
})
node.setAttribute('data-value', value)
}
return node
}
}
Quill.register('formats/formula', CustomFormulaBlot, true)
}
// 给指定的节点插入指定公式
insertFormulaToNode(node, formula) {
let richTextPlugin = this.mindMap.richText
richTextPlugin.showEditText(node)
richTextPlugin.quill.insertEmbed(
richTextPlugin.quill.getLength() - 1,
'formula',
formula
)
richTextPlugin.setTextStyleIfNotRichText(richTextPlugin.node)
richTextPlugin.hideEditText([node])
}
}
Formula.instanceName = 'formula'
export default Formula

View File

@@ -5,7 +5,8 @@ import {
walk,
getTextFromHtml,
isWhite,
getVisibleColorFromTheme
getVisibleColorFromTheme,
isUndef
} from '../utils'
import { CONSTANTS } from '../constants/constant'
@@ -237,7 +238,10 @@ class RichText {
}
if (!node.nodeData.data.richText) {
// 还不是富文本的情况
let text = node.nodeData.data.text.split(/\n/gim).join('<br>')
let text = ''
if (!isUndef(node.nodeData.data.text)) {
text = String(node.nodeData.data.text).split(/\n/gim).join('<br>')
}
let html = `<p>${text}</p>`
this.textEditNode.innerHTML = this.cacheEditingText || html
} else {
@@ -616,7 +620,7 @@ class RichText {
// 处理导入数据
handleSetData(data) {
let walk = root => {
if (!root.data.richText) {
if (root.data && !root.data.richText) {
root.data.richText = true
root.data.resetRichText = true
}

View File

@@ -1,4 +1,4 @@
import { bfsWalk, throttle } from '../utils'
import { bfsWalk, throttle, checkTwoRectIsOverlap } from '../utils'
// 节点选择插件
class Select {
@@ -210,24 +210,19 @@ class Select {
left = left * scaleX + translateX
top = top * scaleY + translateY
if (
((left >= minx && left <= maxx) || (right >= minx && right <= maxx)) &&
((top >= miny && top <= maxy) || (bottom >= miny && bottom <= maxy))
checkTwoRectIsOverlap(minx, maxx, miny, maxy, left, right, top, bottom)
) {
// this.mindMap.batchExecution.push('activeNode' + node.uid, () => {
if (node.nodeData.data.isActive) {
return
}
this.mindMap.renderer.setNodeActive(node, true)
this.mindMap.renderer.addActiveNode(node)
// })
} else if (node.nodeData.data.isActive) {
// this.mindMap.batchExecution.push('activeNode' + node.uid, () => {
if (!node.nodeData.data.isActive) {
return
}
this.mindMap.renderer.setNodeActive(node, false)
this.mindMap.renderer.removeActiveNode(node)
// })
}
})
}

View File

@@ -1,5 +1,9 @@
import { Text } from '@svgdotjs/svg.js'
import { getStrWithBrFromHtml } from '../../utils/index'
import {
getStrWithBrFromHtml,
focusInput,
selectAllInput
} from '../../utils/index'
// 创建文字节点
function createText(data) {
@@ -36,7 +40,7 @@ function showEditTextBox(g) {
this.mindMap.keyCommand.addShortcut('Enter', () => {
this.hideEditTextBox()
})
// 输入框元素没有创建过,则先创建
if (!this.textEditNode) {
this.textEditNode = document.createElement('div')
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
@@ -55,20 +59,27 @@ function showEditTextBox(g) {
associativeLineTextFontFamily,
associativeLineTextLineHeight
} = this.mindMap.themeConfig
let { defaultAssociativeLineText, nodeTextEditZIndex } = this.mindMap.opt
let scale = this.mindMap.view.scale
let [, , , node, toNode] = this.activeLine
let textLines = (
this.getText(node, toNode) || this.mindMap.opt.defaultAssociativeLineText
).split(/\n/gim)
let text = this.getText(node, toNode)
let textLines = (text || defaultAssociativeLineText).split(/\n/gim)
this.textEditNode.style.fontFamily = associativeLineTextFontFamily
this.textEditNode.style.fontSize = associativeLineTextFontSize * scale + 'px'
this.textEditNode.style.lineHeight =
textLines.length > 1 ? associativeLineTextLineHeight : 'normal'
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
this.textEditNode.style.zIndex = nodeTextEditZIndex
this.textEditNode.innerHTML = textLines.join('<br>')
this.textEditNode.style.display = 'block'
this.updateTextEditBoxPos(g)
this.showTextEdit = true
// 如果是默认文本要全选输入框
if (text === '' || text === defaultAssociativeLineText) {
selectAllInput(this.textEditNode)
} else {
// 否则聚焦即可
focusInput(this.textEditNode)
}
}
// 处理画布缩放
@@ -94,10 +105,13 @@ function hideEditTextBox() {
}
let [path, , text, node, toNode] = this.activeLine
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
// 如果是默认文本,那么不保存
let isDefaultText = str === this.mindMap.opt.defaultAssociativeLineText
str = isDefaultText ? '' : str
this.mindMap.execCommand('SET_NODE_DATA', node, {
associativeLineText: {
...(node.nodeData.data.associativeLineText || {}),
[toNode.nodeData.data.id]: str
[toNode.nodeData.data.uid]: str
}
})
this.textEditNode.style.display = 'none'
@@ -113,7 +127,7 @@ function getText(node, toNode) {
if (!obj) {
return ''
}
return obj[toNode.nodeData.data.id] || ''
return obj[toNode.nodeData.data.uid] || ''
}
// 渲染关联线文字

View File

@@ -1,7 +1,7 @@
// 获取目标节点在起始节点的目标数组中的索引
export const getAssociativeLineTargetIndex = (node, toNode) => {
return node.nodeData.data.associativeLineTargets.findIndex(item => {
return item === toNode.nodeData.data.id
return item === toNode.nodeData.data.uid
})
}

View File

@@ -1,3 +1,5 @@
import { mergerIconList } from '../utils'
// 超链接图标
const hyperlink =
'<svg t="1624174958075" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7982" ><path d="M435.484444 251.733333v68.892445L295.822222 320.682667a168.504889 168.504889 0 0 0-2.844444 336.952889h142.506666v68.892444H295.822222a237.397333 237.397333 0 0 1 0-474.794667h139.662222z m248.945778 0a237.397333 237.397333 0 0 1 0 474.851556H544.654222v-69.006222l139.776 0.056889a168.504889 168.504889 0 0 0 2.844445-336.952889H544.597333V251.676444h139.776z m-25.827555 203.946667a34.474667 34.474667 0 0 1 0 68.892444H321.649778a34.474667 34.474667 0 0 1 0-68.892444h336.952889z" p-id="7983"></path></svg>'
@@ -281,12 +283,21 @@ export const nodeIconList = [
// 获取nodeIconList icon内容
const getNodeIconListIcon = (name, extendIconList = []) => {
let arr = name.split('_')
let typeData = [...nodeIconList, ...extendIconList].find(item => {
const iconList = mergerIconList([...nodeIconList, ...extendIconList])
let typeData = iconList.find(item => {
return item.type === arr[0]
})
return typeData.list.find(item => {
return item.name === arr[1]
}).icon
if (typeData) {
let typeName = typeData.list.find(item => {
return item.name === arr[1]
})
if (typeName) {
return typeName.icon
}
return ''
} else {
return ''
}
}
export default {

View File

@@ -1,6 +1,6 @@
import { v4 as uuidv4 } from 'uuid'
import { nodeDataNoStylePropList } from '../constants/constant'
import MersenneTwister from './mersenneTwister'
// 深度优先遍历树
export const walk = (
root,
@@ -170,9 +170,10 @@ export const copyNodeTree = (
keepId = false
) => {
tree.data = simpleDeepClone(root.nodeData ? root.nodeData.data : root.data)
// 去除节点id因为节点id不能重复
if (tree.data.id && !keepId) delete tree.data.id
if (tree.data.uid) delete tree.data.uid
// 重新创建节点uid因为节点uid不能重复
if (!keepId) {
tree.data.uid = createUid()
}
if (removeActiveState) {
tree.data.isActive = false
}
@@ -465,7 +466,7 @@ export const removeHTMLEntities = str => {
// 获取一个数据的类型
export const getType = data => {
return Object.prototype.toString.call(data).slice(7, -1)
return Object.prototype.toString.call(data).slice(8, -1)
}
// 判断一个数据是否是null和undefined和空字符串
@@ -669,3 +670,204 @@ export const checkIsNodeStyleDataKey = key => {
}
return false
}
// 合并图标数组
// const data = [
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },
// { type: 'priority', name: '优先级图标', list: [{ name: '2', icon: 'c' }, { name: 3, icon: 'd' }] },
// ];
// mergerIconList(data) 结果
// [
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'c' }, { name: 3, icon: 'd' }] },
// ]
export const mergerIconList = list => {
return list.reduce((result, item) => {
const existingItem = result.find(x => x.type === item.type)
if (existingItem) {
item.list.forEach(newObj => {
const existingObj = existingItem.list.find(x => x.name === newObj.name)
if (existingObj) {
existingObj.icon = newObj.icon
} else {
existingItem.list.push(newObj)
}
})
} else {
result.push({ ...item })
}
return result
}, [])
}
// 从节点实例列表里找出顶层的节点
export const getTopAncestorsFomNodeList = list => {
let res = []
list.forEach(node => {
if (
!list.find(item => {
return item.uid !== node.uid && item.isParent(node)
})
) {
res.push(node)
}
})
return res
}
// 判断两个矩形是否重叠
export const checkTwoRectIsOverlap = (
minx1,
maxx1,
miny1,
maxy1,
minx2,
maxx2,
miny2,
maxy2
) => {
return maxx1 > minx2 && maxx2 > minx1 && maxy1 > miny2 && maxy2 > miny1
}
// 聚焦指定输入框
export const focusInput = el => {
let selection = window.getSelection()
let range = document.createRange()
range.selectNodeContents(el)
range.collapse()
selection.removeAllRanges()
selection.addRange(range)
}
// 聚焦全选指定输入框
export const selectAllInput = el => {
let selection = window.getSelection()
let range = document.createRange()
range.selectNodeContents(el)
selection.removeAllRanges()
selection.addRange(range)
}
// 给指定的节点列表树数据添加附加数据,会修改原数据
export const addDataToAppointNodes = (appointNodes, data = {}) => {
const walk = list => {
list.forEach(node => {
node.data = {
...node.data,
...data
}
if (node.children && node.children.length > 0) {
walk(node.children)
}
})
}
walk(appointNodes)
return appointNodes
}
// 给指定的节点列表树数据添加uid如果不存在的话会修改原数据
export const createUidForAppointNodes = appointNodes => {
const walk = list => {
list.forEach(node => {
if (!node.data) {
node.data = {}
}
if (isUndef(node.data.uid)) {
node.data.uid = createUid()
}
if (node.children && node.children.length > 0) {
walk(node.children)
}
})
}
walk(appointNodes)
return appointNodes
}
// 传入一个数据,如果该数据是数组,那么返回该数组,否则返回一个以该数据为成员的数组
export const formatDataToArray = data => {
if (!data) return []
return Array.isArray(data) ? data : [data]
}
// 获取节点在同级里的位置索引
export const getNodeIndex = node => {
return node.parent
? node.parent.children.findIndex(item => {
return item.uid === node.uid
})
: 0
}
// 根据内容生成颜色
export const generateColorByContent = str => {
let hash = 0
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash)
}
// 这里使用伪随机数的原因是因为
// 1. 如果字符串的内容差不多根据hash生产的颜色就比较相近不好区分比如v1.1 v1.2,所以需要加入随机数来使得颜色能够区分开
// 2. 普通的随机数每次数值不一样,就会导致每次新增标签原来的标签颜色就会发生改变,所以加入了这个方法,使得内容不变随机数也不变
const rng = new MersenneTwister(hash)
const h = rng.genrand_int32() % 360
return 'hsla(' + h + ', 50%, 50%, 1)'
}
// html转义
export const htmlEscape = str => {
;[
['&', '&amp;'],
['<', '&lt;'],
['>', '&gt;']
].forEach(item => {
str = str.replace(new RegExp(item[0], 'g'), item[1])
})
return str
}
// 判断两个对象是否相同,只处理对象或数组
export const isSameObject = (a, b) => {
const type = getType(a)
// a、b类型不一致那么肯定不相同
if (type !== getType(b)) return false
// 如果都是对象
if (type === 'Object') {
const keysa = Object.keys(a)
const keysb = Object.keys(b)
// 对象字段数量不一样,肯定不相同
if (keysa.length !== keysb.length) return false
// 字段数量一样,那么需要遍历字段进行判断
for (let i = 0; i < keysa.length; i++) {
const key = keysa[i]
// b没有a的一个字段那么肯定不相同
if (!keysb.includes(key)) return false
// 字段名称一样,那么需要递归判断它们的值
const isSame = isSameObject(a[key], b[key])
if (!isSame) {
return false
}
}
return true
} else if (type === 'Array') {
// 如果都是数组
// 数组长度不一样,肯定不相同
if (a.length !== b.length) return false
// 长度一样,那么需要遍历进行判断
for (let i = 0; i < a.length; i++) {
const itema = a[i]
const itemb = b[i]
const typea = getType(itema)
const typeb = getType(itemb)
if (typea !== typeb) return false
const isSame = isSameObject(itema, itemb)
if (!isSame) {
return false
}
}
return true
} else {
// 其他类型,直接全等判断
return a === b
}
}

View File

@@ -0,0 +1,65 @@
/**
* @description 为了保证相同的内容每次生成的随机数都是一样的我们可以使用一个伪随机数生成器PRNG并使用内容的哈希值作为种子。以下是一个使用Mersenne Twister算法的PRNG的实现
*
* @param {*} seed
*/
export default function MersenneTwister(seed) {
this.N = 624
this.M = 397
this.MATRIX_A = 0x9908b0df
this.UPPER_MASK = 0x80000000
this.LOWER_MASK = 0x7fffffff
this.mt = new Array(this.N)
this.mti = this.N + 1
this.init_genrand(seed)
}
MersenneTwister.prototype.init_genrand = function (s) {
this.mt[0] = s >>> 0
for (this.mti = 1; this.mti < this.N; this.mti++) {
s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30)
this.mt[this.mti] =
((((s & 0xffff0000) >>> 16) * 1812433253) << 16) +
(s & 0x0000ffff) * 1812433253 +
this.mti
this.mt[this.mti] >>>= 0
}
}
MersenneTwister.prototype.genrand_int32 = function () {
var y
var mag01 = new Array(0x0, this.MATRIX_A)
if (this.mti >= this.N) {
var kk
if (this.mti == this.N + 1) this.init_genrand(5489)
for (kk = 0; kk < this.N - this.M; kk++) {
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK)
this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]
}
for (; kk < this.N - 1; kk++) {
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK)
this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]
}
y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK)
this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]
this.mti = 0
}
y = this.mt[this.mti++]
y ^= y >>> 11
y ^= (y << 7) & 0x9d2c5680
y ^= (y << 15) & 0xefc60000
y ^= y >>> 18
return y >>> 0
}

View File

@@ -1,166 +1,172 @@
export default MindMap
export default MindMap;
declare class MindMap {
/**
*
* @param {defaultOpt} opt
*/
constructor(opt?: {
readonly: boolean
layout: string
fishboneDeg: number
theme: string
themeConfig: {}
scaleRatio: number
mouseScaleCenterUseMousePosition: boolean
maxTag: number
expandBtnSize: number
imgTextMargin: number
textContentMargin: number
selectTranslateStep: number
selectTranslateLimit: number
customNoteContentShow: any
enableFreeDrag: boolean
watermarkConfig: {
text: string
lineSpacing: number
textSpacing: number
angle: number
textStyle: {
color: string
opacity: number
fontSize: number
}
}
textAutoWrapWidth: number
customHandleMousewheel: any
mousewheelAction: string
mousewheelMoveStep: number
mousewheelZoomActionReverse: boolean
defaultInsertSecondLevelNodeText: string
defaultInsertBelowSecondLevelNodeText: string
expandBtnStyle: {
color: string
fill: string
fontSize: number
strokeColor: string
}
expandBtnIcon: {
open: string
close: string
}
expandBtnNumHandler: (num: any) => any
isShowExpandNum: boolean
enableShortcutOnlyWhenMouseInSvg: boolean
initRootNodePosition: any
exportPaddingX: number
exportPaddingY: number
nodeTextEditZIndex: number
nodeNoteTooltipZIndex: number
isEndNodeTextEditOnClickOuter: boolean
maxHistoryCount: number
alwaysShowExpandBtn: boolean
iconList: any[]
maxNodeCacheCount: number
defaultAssociativeLineText: string
fitPadding: number
enableCtrlKeyNodeSelection: boolean
useLeftKeySelectionRightKeyDrag: boolean
beforeTextEdit: any
isUseCustomNodeContent: boolean
customCreateNodeContent: any
customInnerElsAppendTo: any
nodeDragPlaceholderMaxSize: number
enableAutoEnterTextEditWhenKeydown: boolean
richTextEditFakeInPlace: boolean
customHandleClipboardText: any
disableMouseWheelZoom: boolean
errorHandler: (code: any, error: any) => void
resetCss: string
enableDblclickReset: boolean
minExportImgCanvasScale: number
hoverRectColor: string
hoverRectPadding: number
selectTextOnEnterEditText: boolean
deleteNodeActive: boolean
autoMoveWhenMouseInEdgeOnDrag: boolean
})
opt: any
el: any
elRect: any
width: any
height: any
cssEl: HTMLStyleElement
svg: any
draw: any
event: Event
keyCommand: KeyCommand
command: Command
renderer: Render
view: View
batchExecution: BatchExecution
handleOpt(opt: any): any
addCss(): void
removeCss(): void
render(callback: any, source?: string): void
reRender(callback: any, source?: string): void
resize(): void
on(event: any, fn: any): void
emit(event: any, ...args: any[]): void
off(event: any, fn: any): void
initCache(): void
initTheme(): void
themeConfig: any
setTheme(theme: any): void
getTheme(): any
setThemeConfig(config: any): void
getCustomThemeConfig(): any
getThemeConfig(prop: any): any
getConfig(prop: any): any
updateConfig(opt?: {}): void
getLayout(): any
setLayout(layout: any): void
execCommand(...args: any[]): void
setData(data: any): void
setFullData(data: any): void
getData(withConfig: any): any
export(...args: any[]): Promise<any>
toPos(
x: any,
y: any
): {
x: number
y: number
}
setMode(mode: any): void
getSvgData({
paddingX,
paddingY
}?: {
paddingX?: number
paddingY?: number
}): {
svg: any
svgHTML: any
rect: any
origWidth: any
origHeight: any
scaleX: any
scaleY: any
}
addPlugin(plugin: any, opt: any): void
removePlugin(plugin: any): void
initPlugin(plugin: any): void
destroy(): void
/**
*
* @param {defaultOpt} opt
*/
constructor(opt?: {
readonly: boolean;
layout: string;
fishboneDeg: number;
theme: string;
themeConfig: {};
scaleRatio: number;
mouseScaleCenterUseMousePosition: boolean;
maxTag: number;
expandBtnSize: number;
imgTextMargin: number;
textContentMargin: number;
selectTranslateStep: number;
selectTranslateLimit: number;
customNoteContentShow: any;
enableFreeDrag: boolean;
watermarkConfig: {
text: string;
lineSpacing: number;
textSpacing: number;
angle: number;
textStyle: {
color: string;
opacity: number;
fontSize: number;
};
};
textAutoWrapWidth: number;
customHandleMousewheel: any;
mousewheelAction: string;
mousewheelMoveStep: number;
mousewheelZoomActionReverse: boolean;
defaultInsertSecondLevelNodeText: string;
defaultInsertBelowSecondLevelNodeText: string;
expandBtnStyle: {
color: string;
fill: string;
fontSize: number;
strokeColor: string;
};
expandBtnIcon: {
open: string;
close: string;
};
expandBtnNumHandler: (num: any) => any;
isShowExpandNum: boolean;
enableShortcutOnlyWhenMouseInSvg: boolean;
initRootNodePosition: any;
exportPaddingX: number;
exportPaddingY: number;
nodeTextEditZIndex: number;
nodeNoteTooltipZIndex: number;
isEndNodeTextEditOnClickOuter: boolean;
maxHistoryCount: number;
alwaysShowExpandBtn: boolean;
iconList: any[];
maxNodeCacheCount: number;
defaultAssociativeLineText: string;
fitPadding: number;
enableCtrlKeyNodeSelection: boolean;
useLeftKeySelectionRightKeyDrag: boolean;
beforeTextEdit: any;
isUseCustomNodeContent: boolean;
customCreateNodeContent: any;
customInnerElsAppendTo: any;
nodeDragPlaceholderMaxSize: number;
enableAutoEnterTextEditWhenKeydown: boolean;
richTextEditFakeInPlace: boolean;
customHandleClipboardText: any;
disableMouseWheelZoom: boolean;
errorHandler: (code: any, error: any) => void;
resetCss: string;
enableDblclickReset: boolean;
minExportImgCanvasScale: number;
hoverRectColor: string;
hoverRectPadding: number;
selectTextOnEnterEditText: boolean;
deleteNodeActive: boolean;
autoMoveWhenMouseInEdgeOnDrag: boolean;
fit: boolean;
dragMultiNodeRectConfig: {
width: number;
height: number;
fill: string;
};
dragPlaceholderRectFill: string;
dragOpacityConfig: {
cloneNodeOpacity: number;
beingDragNodeOpacity: number;
};
tagsColorMap: {};
});
opt: any;
el: any;
elRect: any;
width: any;
height: any;
cssEl: HTMLStyleElement;
svg: any;
draw: any;
event: Event;
keyCommand: KeyCommand;
command: Command;
renderer: Render;
view: View;
batchExecution: BatchExecution;
handleOpt(opt: any): any;
addCss(): void;
removeCss(): void;
render(callback: any, source?: string): void;
reRender(callback: any, source?: string): void;
resize(): void;
on(event: any, fn: any): void;
emit(event: any, ...args: any[]): void;
off(event: any, fn: any): void;
initCache(): void;
initTheme(): void;
themeConfig: any;
setTheme(theme: any): void;
getTheme(): any;
setThemeConfig(config: any): void;
getCustomThemeConfig(): any;
getThemeConfig(prop: any): any;
getConfig(prop: any): any;
updateConfig(opt?: {}): void;
getLayout(): any;
setLayout(layout: any): void;
execCommand(...args: any[]): void;
setData(data: any): void;
setFullData(data: any): void;
getData(withConfig: any): any;
export(...args: any[]): Promise<any>;
toPos(x: any, y: any): {
x: number;
y: number;
};
setMode(mode: any): void;
getSvgData({ paddingX, paddingY }?: {
paddingX?: number;
paddingY?: number;
}): {
svg: any;
svgHTML: any;
rect: any;
origWidth: any;
origHeight: any;
scaleX: any;
scaleY: any;
};
addPlugin(plugin: any, opt: any): void;
removePlugin(plugin: any): void;
initPlugin(plugin: any): void;
destroy(): void;
}
declare namespace MindMap {
let pluginList: any[]
function usePlugin(plugin: any, opt?: {}): typeof MindMap
function hasPlugin(plugin: any): number
function defineTheme(name: any, config?: {}): Error
let pluginList: any[];
function usePlugin(plugin: any, opt?: {}): typeof MindMap;
function hasPlugin(plugin: any): number;
function defineTheme(name: any, config?: {}): Error;
}
import Event from './src/core/event/Event'
import KeyCommand from './src/core/command/KeyCommand'
import Command from './src/core/command/Command'
import Render from './src/core/render/Render'
import View from './src/core/view/View'
import BatchExecution from './src/utils/BatchExecution'
import Event from './src/core/event/Event';
import KeyCommand from './src/core/command/KeyCommand';
import Command from './src/core/command/Command';
import Render from './src/core/render/Render';
import View from './src/core/view/View';
import BatchExecution from './src/utils/BatchExecution';

View File

@@ -1,113 +1,109 @@
export const tagColorList: {
color: string
background: string
}[]
export const themeList: {
name: string
value: string
dark: boolean
}[]
name: string;
value: string;
dark: boolean;
}[];
export namespace CONSTANTS {
let CHANGE_THEME: string
let CHANGE_LAYOUT: string
let SET_DATA: string
let TRANSFORM_TO_NORMAL_NODE: string
namespace MODE {
let READONLY: string
let EDIT: string
}
namespace LAYOUT {
let LOGICAL_STRUCTURE: string
let MIND_MAP: string
let ORGANIZATION_STRUCTURE: string
let CATALOG_ORGANIZATION: string
let TIMELINE: string
let TIMELINE2: string
let FISHBONE: string
let VERTICAL_TIMELINE: string
}
namespace DIR {
let UP: string
let LEFT: string
let DOWN: string
let RIGHT: string
}
namespace KEY_DIR {
let LEFT_1: string
export { LEFT_1 as LEFT }
let UP_1: string
export { UP_1 as UP }
let RIGHT_1: string
export { RIGHT_1 as RIGHT }
let DOWN_1: string
export { DOWN_1 as DOWN }
}
namespace SHAPE {
let RECTANGLE: string
let DIAMOND: string
let PARALLELOGRAM: string
let ROUNDED_RECTANGLE: string
let OCTAGONAL_RECTANGLE: string
let OUTER_TRIANGULAR_RECTANGLE: string
let INNER_TRIANGULAR_RECTANGLE: string
let ELLIPSE: string
let CIRCLE: string
}
namespace MOUSE_WHEEL_ACTION {
let ZOOM: string
let MOVE: string
}
namespace INIT_ROOT_NODE_POSITION {
let LEFT_2: string
export { LEFT_2 as LEFT }
export let TOP: string
let RIGHT_2: string
export { RIGHT_2 as RIGHT }
export let BOTTOM: string
export let CENTER: string
}
namespace LAYOUT_GROW_DIR {
let LEFT_3: string
export { LEFT_3 as LEFT }
let TOP_1: string
export { TOP_1 as TOP }
let RIGHT_3: string
export { RIGHT_3 as RIGHT }
let BOTTOM_1: string
export { BOTTOM_1 as BOTTOM }
}
namespace PASTE_TYPE {
let CLIP_BOARD: string
let CANVAS: string
}
namespace SCROLL_BAR_DIR {
let VERTICAL: string
let HORIZONTAL: string
}
let CHANGE_THEME: string;
let CHANGE_LAYOUT: string;
let SET_DATA: string;
let TRANSFORM_TO_NORMAL_NODE: string;
namespace MODE {
let READONLY: string;
let EDIT: string;
}
namespace LAYOUT {
let LOGICAL_STRUCTURE: string;
let MIND_MAP: string;
let ORGANIZATION_STRUCTURE: string;
let CATALOG_ORGANIZATION: string;
let TIMELINE: string;
let TIMELINE2: string;
let FISHBONE: string;
let VERTICAL_TIMELINE: string;
}
namespace DIR {
let UP: string;
let LEFT: string;
let DOWN: string;
let RIGHT: string;
}
namespace KEY_DIR {
let LEFT_1: string;
export { LEFT_1 as LEFT };
let UP_1: string;
export { UP_1 as UP };
let RIGHT_1: string;
export { RIGHT_1 as RIGHT };
let DOWN_1: string;
export { DOWN_1 as DOWN };
}
namespace SHAPE {
let RECTANGLE: string;
let DIAMOND: string;
let PARALLELOGRAM: string;
let ROUNDED_RECTANGLE: string;
let OCTAGONAL_RECTANGLE: string;
let OUTER_TRIANGULAR_RECTANGLE: string;
let INNER_TRIANGULAR_RECTANGLE: string;
let ELLIPSE: string;
let CIRCLE: string;
}
namespace MOUSE_WHEEL_ACTION {
let ZOOM: string;
let MOVE: string;
}
namespace INIT_ROOT_NODE_POSITION {
let LEFT_2: string;
export { LEFT_2 as LEFT };
export let TOP: string;
let RIGHT_2: string;
export { RIGHT_2 as RIGHT };
export let BOTTOM: string;
export let CENTER: string;
}
namespace LAYOUT_GROW_DIR {
let LEFT_3: string;
export { LEFT_3 as LEFT };
let TOP_1: string;
export { TOP_1 as TOP };
let RIGHT_3: string;
export { RIGHT_3 as RIGHT };
let BOTTOM_1: string;
export { BOTTOM_1 as BOTTOM };
}
namespace PASTE_TYPE {
let CLIP_BOARD: string;
let CANVAS: string;
}
namespace SCROLL_BAR_DIR {
let VERTICAL: string;
let HORIZONTAL: string;
}
}
export const initRootNodePositionMap: {
[x: string]: number
}
[x: string]: number;
};
export const layoutList: {
name: string
value: string
}[]
export const layoutValueList: string[]
export const nodeDataNoStylePropList: string[]
name: string;
value: string;
}[];
export const layoutValueList: string[];
export const nodeDataNoStylePropList: string[];
export namespace commonCaches {
let measureCustomNodeContentSizeEl: any
let measureRichtextNodeTextSizeEl: any
let measureCustomNodeContentSizeEl: any;
let measureRichtextNodeTextSizeEl: any;
}
export namespace ERROR_TYPES {
let READ_CLIPBOARD_ERROR: string
let PARSE_PASTE_DATA_ERROR: string
let CUSTOM_HANDLE_CLIPBOARD_TEXT_ERROR: string
let LOAD_CLIPBOARD_IMAGE_ERROR: string
let BEFORE_TEXT_EDIT_ERROR: string
let EXPORT_ERROR: string
let READ_CLIPBOARD_ERROR: string;
let PARSE_PASTE_DATA_ERROR: string;
let CUSTOM_HANDLE_CLIPBOARD_TEXT_ERROR: string;
let LOAD_CLIPBOARD_IMAGE_ERROR: string;
let BEFORE_TEXT_EDIT_ERROR: string;
let EXPORT_ERROR: string;
}
export namespace a4Size {
let width: number
let height: number
let width: number;
let height: number;
}
export const cssContent: '\n /* 鼠标hover和激活时渲染的矩形 */\n .smm-hover-node{\n display: none;\n opacity: 0.6;\n stroke-width: 1;\n }\n\n .smm-node:hover .smm-hover-node{\n display: block;\n }\n\n .smm-node.active .smm-hover-node{\n display: block;\n opacity: 1;\n stroke-width: 2;\n }\n'
export const cssContent: "\n /* 鼠标hover和激活时渲染的矩形 */\n .smm-hover-node{\n display: none;\n opacity: 0.6;\n stroke-width: 1;\n }\n\n .smm-node:not(.smm-node-dragging):hover .smm-hover-node{\n display: block;\n }\n\n .smm-node.active .smm-hover-node{\n display: block;\n opacity: 1;\n stroke-width: 2;\n }\n";

View File

@@ -1,82 +1,95 @@
export namespace defaultOpt {
let readonly: boolean
let layout: string
let fishboneDeg: number
let theme: string
let themeConfig: {}
let scaleRatio: number
let mouseScaleCenterUseMousePosition: boolean
let maxTag: number
let expandBtnSize: number
let imgTextMargin: number
let textContentMargin: number
let selectTranslateStep: number
let selectTranslateLimit: number
let customNoteContentShow: any
let enableFreeDrag: boolean
namespace watermarkConfig {
let text: string
let lineSpacing: number
let textSpacing: number
let angle: number
namespace textStyle {
let color: string
let opacity: number
let fontSize: number
let readonly: boolean;
let layout: string;
let fishboneDeg: number;
let theme: string;
let themeConfig: {};
let scaleRatio: number;
let mouseScaleCenterUseMousePosition: boolean;
let maxTag: number;
let expandBtnSize: number;
let imgTextMargin: number;
let textContentMargin: number;
let selectTranslateStep: number;
let selectTranslateLimit: number;
let customNoteContentShow: any;
let enableFreeDrag: boolean;
namespace watermarkConfig {
let text: string;
let lineSpacing: number;
let textSpacing: number;
let angle: number;
namespace textStyle {
let color: string;
let opacity: number;
let fontSize: number;
}
}
}
let textAutoWrapWidth: number
let customHandleMousewheel: any
let mousewheelAction: string
let mousewheelMoveStep: number
let mousewheelZoomActionReverse: boolean
let defaultInsertSecondLevelNodeText: string
let defaultInsertBelowSecondLevelNodeText: string
namespace expandBtnStyle {
let color_1: string
export { color_1 as color }
export let fill: string
let fontSize_1: number
export { fontSize_1 as fontSize }
export let strokeColor: string
}
namespace expandBtnIcon {
let open: string
let close: string
}
function expandBtnNumHandler(num: any): any
let isShowExpandNum: boolean
let enableShortcutOnlyWhenMouseInSvg: boolean
let initRootNodePosition: any
let exportPaddingX: number
let exportPaddingY: number
let nodeTextEditZIndex: number
let nodeNoteTooltipZIndex: number
let isEndNodeTextEditOnClickOuter: boolean
let maxHistoryCount: number
let alwaysShowExpandBtn: boolean
let iconList: any[]
let maxNodeCacheCount: number
let defaultAssociativeLineText: string
let fitPadding: number
let enableCtrlKeyNodeSelection: boolean
let useLeftKeySelectionRightKeyDrag: boolean
let beforeTextEdit: any
let isUseCustomNodeContent: boolean
let customCreateNodeContent: any
let customInnerElsAppendTo: any
let nodeDragPlaceholderMaxSize: number
let enableAutoEnterTextEditWhenKeydown: boolean
let richTextEditFakeInPlace: boolean
let customHandleClipboardText: any
let disableMouseWheelZoom: boolean
function errorHandler(code: any, error: any): void
let resetCss: string
let enableDblclickReset: boolean
let minExportImgCanvasScale: number
let hoverRectColor: string
let hoverRectPadding: number
let selectTextOnEnterEditText: boolean
let deleteNodeActive: boolean
let autoMoveWhenMouseInEdgeOnDrag: boolean
let textAutoWrapWidth: number;
let customHandleMousewheel: any;
let mousewheelAction: string;
let mousewheelMoveStep: number;
let mousewheelZoomActionReverse: boolean;
let defaultInsertSecondLevelNodeText: string;
let defaultInsertBelowSecondLevelNodeText: string;
namespace expandBtnStyle {
let color_1: string;
export { color_1 as color };
export let fill: string;
let fontSize_1: number;
export { fontSize_1 as fontSize };
export let strokeColor: string;
}
namespace expandBtnIcon {
let open: string;
let close: string;
}
function expandBtnNumHandler(num: any): any;
let isShowExpandNum: boolean;
let enableShortcutOnlyWhenMouseInSvg: boolean;
let initRootNodePosition: any;
let exportPaddingX: number;
let exportPaddingY: number;
let nodeTextEditZIndex: number;
let nodeNoteTooltipZIndex: number;
let isEndNodeTextEditOnClickOuter: boolean;
let maxHistoryCount: number;
let alwaysShowExpandBtn: boolean;
let iconList: any[];
let maxNodeCacheCount: number;
let defaultAssociativeLineText: string;
let fitPadding: number;
let enableCtrlKeyNodeSelection: boolean;
let useLeftKeySelectionRightKeyDrag: boolean;
let beforeTextEdit: any;
let isUseCustomNodeContent: boolean;
let customCreateNodeContent: any;
let customInnerElsAppendTo: any;
let nodeDragPlaceholderMaxSize: number;
let enableAutoEnterTextEditWhenKeydown: boolean;
let richTextEditFakeInPlace: boolean;
let customHandleClipboardText: any;
let disableMouseWheelZoom: boolean;
function errorHandler(code: any, error: any): void;
let resetCss: string;
let enableDblclickReset: boolean;
let minExportImgCanvasScale: number;
let hoverRectColor: string;
let hoverRectPadding: number;
let selectTextOnEnterEditText: boolean;
let deleteNodeActive: boolean;
let autoMoveWhenMouseInEdgeOnDrag: boolean;
let fit: boolean;
namespace dragMultiNodeRectConfig {
export let width: number;
export let height: number;
let fill_1: string;
export { fill_1 as fill };
}
let dragPlaceholderRectFill: string;
namespace dragOpacityConfig {
let cloneNodeOpacity: number;
let beingDragNodeOpacity: number;
}
let tagsColorMap: {};
}

View File

@@ -1,19 +1,19 @@
export default Command
export default Command;
declare class Command {
constructor(opt?: {})
opt: {}
mindMap: any
commands: {}
history: any[]
activeHistoryIndex: number
addHistory(): void
clearHistory(): void
registerShortcutKeys(): void
exec(name: any, ...args: any[]): void
add(name: any, fn: any): void
remove(name: any, fn: any): void
back(step?: number): any
forward(step?: number): any
getCopyData(): any
removeDataUid(data: any): any
constructor(opt?: {});
opt: {};
mindMap: any;
commands: {};
history: any[];
activeHistoryIndex: number;
addHistory(): void;
clearHistory(): void;
registerShortcutKeys(): void;
exec(name: any, ...args: any[]): void;
add(name: any, fn: any): void;
remove(name: any, fn: any): void;
back(step?: number): any;
forward(step?: number): any;
getCopyData(): any;
removeDataUid(data: any): any;
}

View File

@@ -1,26 +1,26 @@
export default class KeyCommand {
constructor(opt: any)
opt: any
mindMap: any
shortcutMap: {}
shortcutMapCache: {}
isPause: boolean
isInSvg: boolean
pause(): void
recovery(): void
save(): void
restore(): void
bindEvent(): void
checkKey(e: any, key: any): boolean
getOriginEventCodeArr(e: any): any[]
hasCombinationKey(e: any): any
getKeyCodeArr(key: any): any[]
/**
* Enter
* Tab | Insert
* Shift + a
*/
addShortcut(key: any, fn: any): void
removeShortcut(key: any, fn: any): void
getShortcutFn(key: any): any[]
constructor(opt: any);
opt: any;
mindMap: any;
shortcutMap: {};
shortcutMapCache: {};
isPause: boolean;
isInSvg: boolean;
pause(): void;
recovery(): void;
save(): void;
restore(): void;
bindEvent(): void;
checkKey(e: any, key: any): boolean;
getOriginEventCodeArr(e: any): any[];
hasCombinationKey(e: any): any;
getKeyCodeArr(key: any): any[];
/**
* Enter
* Tab | Insert
* Shift + a
*/
addShortcut(key: any, fn: any): void;
removeShortcut(key: any, fn: any): void;
getShortcutFn(key: any): any[];
}

View File

@@ -1,42 +1,42 @@
export const keyMap: {
Backspace: number
Tab: number
Enter: number
Shift: number
Control: number
Alt: number
CapsLock: number
Esc: number
Spacebar: number
PageUp: number
PageDown: number
End: number
Home: number
Insert: number
Left: number
Up: number
Right: number
Down: number
Del: number
NumLock: number
Cmd: number
CmdFF: number
F1: number
F2: number
F3: number
F4: number
F5: number
F6: number
F7: number
F8: number
F9: number
F10: number
F11: number
F12: number
'`': number
'=': number
'-': number
'/': number
'.': number
}
export function isKey(e: any, key: any): boolean
Backspace: number;
Tab: number;
Enter: number;
Shift: number;
Control: number;
Alt: number;
CapsLock: number;
Esc: number;
Spacebar: number;
PageUp: number;
PageDown: number;
End: number;
Home: number;
Insert: number;
Left: number;
Up: number;
Right: number;
Down: number;
Del: number;
NumLock: number;
Cmd: number;
CmdFF: number;
F1: number;
F2: number;
F3: number;
F4: number;
F5: number;
F6: number;
F7: number;
F8: number;
F9: number;
F10: number;
F11: number;
F12: number;
'`': number;
'=': number;
'-': number;
'/': number;
'.': number;
};
export function isKey(e: any, key: any): boolean;

View File

@@ -1,35 +1,35 @@
export default Event
export default Event;
declare class Event {
constructor(opt?: {})
opt: {}
mindMap: any
isLeftMousedown: boolean
isRightMousedown: boolean
isMiddleMousedown: boolean
mousedownPos: {
x: number
y: number
}
mousemovePos: {
x: number
y: number
}
mousemoveOffset: {
x: number
y: number
}
bindFn(): void
onBodyClick(e: any): void
onDrawClick(e: any): void
onMousedown(e: any): void
onMousemove(e: any): void
onMouseup(e: any): void
onMousewheel(e: any): void
onContextmenu(e: any): void
onSvgMousedown(e: any): void
onKeyup(e: any): void
onMouseenter(e: any): void
onMouseleave(e: any): void
bind(): void
unbind(): void
constructor(opt?: {});
opt: {};
mindMap: any;
isLeftMousedown: boolean;
isRightMousedown: boolean;
isMiddleMousedown: boolean;
mousedownPos: {
x: number;
y: number;
};
mousemovePos: {
x: number;
y: number;
};
mousemoveOffset: {
x: number;
y: number;
};
bindFn(): void;
onBodyClick(e: any): void;
onDrawClick(e: any): void;
onMousedown(e: any): void;
onMousemove(e: any): void;
onMouseup(e: any): void;
onMousewheel(e: any): void;
onContextmenu(e: any): void;
onSvgMousedown(e: any): void;
onKeyup(e: any): void;
onMouseenter(e: any): void;
onMouseleave(e: any): void;
bind(): void;
unbind(): void;
}

View File

@@ -1,107 +1,95 @@
export default Render
export default Render;
declare class Render {
constructor(opt?: {})
opt: {}
mindMap: any
themeConfig: any
draw: any
renderTree: any
reRender: boolean
isRendering: boolean
hasWaitRendering: boolean
nodeCache: {}
lastNodeCache: {}
renderSource: string
activeNodeList: any[]
root: any
textEdit: TextEdit
lastBeingCopyData: any
beingCopyData: any
beingPasteText: string
beingPasteImgSize: number
currentBeingPasteType: string
setLayout(): void
layout:
| MindMap
| CatalogOrganization
| OrganizationStructure
| Timeline
| VerticalTimeline
bindEvent(): void
registerCommands(): void
selectAll(): void
back(step: any): void
forward(step: any): void
insertNode(
openEdit?: boolean,
appointNodes?: any[],
appointData?: any,
appointChildren?: any[]
): void
insertChildNode(
openEdit?: boolean,
appointNodes?: any[],
appointData?: any,
appointChildren?: any[]
): void
upNode(): void
downNode(): void
insertAfter(node: any, exist: any): void
insertBefore(node: any, exist: any): void
moveNodeTo(node: any, toNode: any): void
removeNode(appointNodes?: any[]): void
pasteNode(data: any): void
cutNode(callback: any): any
setNodeStyle(node: any, prop: any, value: any): void
setNodeStyles(node: any, style: any): void
setNodeActive(node: any, active: any): void
clearAllActive(): void
setNodeExpand(node: any, expand: any): void
expandAllNode(): void
unexpandAllNode(): void
expandToLevel(level: any): void
setNodeData(node: any, data: any): void
setNodeText(node: any, text: any, richText: any, resetRichText: any): void
setNodeImage(node: any, data: any): void
setNodeIcon(node: any, icons: any): void
setNodeHyperlink(node: any, link: any, title?: string): void
setNodeNote(node: any, note: any): void
setNodeTag(node: any, tag: any): void
addGeneralization(data: any): void
removeGeneralization(): void
setNodeCustomPosition(node: any, left?: any, top?: any): void
resetLayout(): void
setNodeShape(node: any, shape: any): void
goTargetNode(node: any, callback?: () => void): void
registerShortcutKeys(): void
insertNodeWrap: () => void
toggleActiveExpand(): void
removeNodeWrap: () => void
copy(): void
cut(): void
startTextEdit(): void
endTextEdit(): void
render(callback: () => void, source: any): void
clearActive(): void
addActiveNode(node: any): void
removeActiveNode(node: any): void
findActiveNodeIndex(node: any): number
getNodeIndex(node: any): any
formatAppointNodes(appointNodes: any): any[]
setCoptyDataToClipboard(data: any): void
paste(): void
onPaste(): Promise<void>
removeOneNode(node: any): void
copyNode(): any
toggleNodeExpand(node: any): void
setNodeDataRender(node: any, data: any, notRender?: boolean): void
moveNodeToCenter(node: any): void
expandToNodeUid(uid: any, callback?: () => void): void
findNodeByUid(uid: any): any
constructor(opt?: {});
opt: {};
mindMap: any;
themeConfig: any;
draw: any;
renderTree: any;
reRender: boolean;
isRendering: boolean;
hasWaitRendering: boolean;
nodeCache: {};
lastNodeCache: {};
renderSource: string;
activeNodeList: any[];
root: any;
textEdit: TextEdit;
lastBeingCopyData: any;
beingCopyData: any;
beingPasteText: string;
beingPasteImgSize: number;
currentBeingPasteType: string;
setLayout(): void;
layout: MindMap | CatalogOrganization | OrganizationStructure | Timeline | VerticalTimeline;
bindEvent(): void;
registerCommands(): void;
selectAll(): void;
back(step: any): void;
forward(step: any): void;
insertNode(openEdit?: boolean, appointNodes?: any[], appointData?: any, appointChildren?: any[]): void;
insertMultiNode(appointNodes: any, nodeList: any): void;
insertChildNode(openEdit?: boolean, appointNodes?: any[], appointData?: any, appointChildren?: any[]): void;
insertMultiChildNode(appointNodes: any, childList: any): void;
upNode(): void;
downNode(): void;
insertAfter(node: any, exist: any): void;
insertBefore(node: any, exist: any): void;
moveNodeTo(node: any, toNode: any): void;
removeNode(appointNodes?: any[]): void;
pasteNode(data: any): void;
cutNode(callback: any): void;
setNodeStyle(node: any, prop: any, value: any): void;
setNodeStyles(node: any, style: any): void;
setNodeActive(node: any, active: any): void;
clearAllActive(): void;
setNodeExpand(node: any, expand: any): void;
expandAllNode(): void;
unexpandAllNode(): void;
expandToLevel(level: any): void;
setNodeData(node: any, data: any): void;
setNodeText(node: any, text: any, richText: any, resetRichText: any): void;
setNodeImage(node: any, data: any): void;
setNodeIcon(node: any, icons: any): void;
setNodeHyperlink(node: any, link: any, title?: string): void;
setNodeNote(node: any, note: any): void;
setNodeTag(node: any, tag: any): void;
insertFormula(formula: any, appointNodes?: any[]): void;
addGeneralization(data: any): void;
removeGeneralization(): void;
setNodeCustomPosition(node: any, left?: any, top?: any): void;
resetLayout(): void;
setNodeShape(node: any, shape: any): void;
goTargetNode(node: any, callback?: () => void): void;
registerShortcutKeys(): void;
insertNodeWrap: () => void;
toggleActiveExpand(): void;
removeNodeWrap: () => void;
copy(): void;
cut(): void;
startTextEdit(): void;
endTextEdit(): void;
render(callback: () => void, source: any): void;
clearActive(): void;
addActiveNode(node: any): void;
removeActiveNode(node: any): void;
findActiveNodeIndex(node: any): number;
setCopyDataToClipboard(data: any): void;
paste(): void;
onPaste(): Promise<void>;
insertTo(node: any, exist: any, dir?: string): void;
checkNodeLayerChange(node: any, toNode: any): void;
removeOneNode(node: any): void;
copyNode(): any;
toggleNodeExpand(node: any): void;
setNodeDataRender(node: any, data: any, notRender?: boolean): void;
moveNodeToCenter(node: any): void;
expandToNodeUid(uid: any, callback?: () => void): void;
findNodeByUid(uid: any): any;
}
import TextEdit from './TextEdit'
import MindMap from '../../layouts/MindMap'
import CatalogOrganization from '../../layouts/CatalogOrganization'
import OrganizationStructure from '../../layouts/OrganizationStructure'
import Timeline from '../../layouts/Timeline'
import VerticalTimeline from '../../layouts/VerticalTimeline'
import TextEdit from './TextEdit';
import MindMap from '../../layouts/MindMap';
import CatalogOrganization from '../../layouts/CatalogOrganization';
import OrganizationStructure from '../../layouts/OrganizationStructure';
import Timeline from '../../layouts/Timeline';
import VerticalTimeline from '../../layouts/VerticalTimeline';

View File

@@ -1,29 +1,17 @@
export default class TextEdit {
constructor(renderer: any)
renderer: any
mindMap: any
currentNode: any
textEditNode: HTMLDivElement
showTextEdit: boolean
cacheEditingText: string
bindEvent(): void
show(
node: any,
e: any,
isInserting?: boolean,
isFromKeyDown?: boolean
): Promise<void>
onScale(): void
checkIsAutoEnterTextEditKey(e: any): boolean
registerTmpShortcut(): void
showEditTextBox(
node: any,
rect: any,
isInserting: any,
isFromKeyDown: any
): void
focus(): void
selectNodeText(): void
getEditText(): any
hideEditTextBox(): any
constructor(renderer: any);
renderer: any;
mindMap: any;
currentNode: any;
textEditNode: HTMLDivElement;
showTextEdit: boolean;
cacheEditingText: string;
bindEvent(): void;
show(node: any, e: any, isInserting?: boolean, isFromKeyDown?: boolean): Promise<void>;
onScale(): void;
checkIsAutoEnterTextEditKey(e: any): boolean;
registerTmpShortcut(): void;
showEditTextBox(node: any, rect: any, isInserting: any, isFromKeyDown: any): void;
getEditText(): any;
hideEditTextBox(): any;
}

View File

@@ -1,116 +1,118 @@
export default Node
export default Node;
declare class Node {
constructor(opt?: {})
nodeData: any
uid: any
mindMap: any
renderer: any
draw: any
style: Style
shapeInstance: Shape
shapePadding: {
paddingX: number
paddingY: number
}
isRoot: any
isGeneralization: any
generalizationBelongNode: any
layerIndex: any
width: any
height: any
_left: any
_top: any
customLeft: any
customTop: any
isDrag: boolean
parent: any
children: any
group: any
shapeNode: any
hoverNode: any
_customNodeContent: any
_imgData: any
_iconData: any
_textData: any
_hyperlinkData: any
_tagData: any
_noteData: any
noteEl: any
_expandBtn: any
_lastExpandBtnType: any
_showExpandBtn: boolean
_openExpandNode: any
_closeExpandNode: any
_fillExpandNode: any
_lines: any[]
_generalizationLine: any
_generalizationNode: any
_unVisibleRectRegionNode: any
_isMouseenter: boolean
_rectInfo: {
imgContentWidth: number
imgContentHeight: number
textContentWidth: number
textContentHeight: number
}
_generalizationNodeWidth: number
_generalizationNodeHeight: number
textContentItemMargin: any
blockContentMargin: any
expandBtnSize: any
isMultipleChoice: boolean
needLayout: boolean
isHide: boolean
set left(arg: any)
get left(): any
set top(arg: any)
get top(): any
reset(): void
handleData(data: any): any
createNodeData(): void
getSize(): boolean
getNodeRect(): {
width: any
height: any
}
layout(): void
bindGroupEvent(): void
active(e: any): void
update(): void
getNodePosInClient(
_left: any,
_top: any
): {
left: any
top: any
}
reRender(): boolean
updateNodeActive(): void
render(callback?: () => void): void
remove(): void
destroy(): void
hide(): void
show(): void
renderLine(deep?: boolean): void
getShape(): any
hasCustomPosition(): boolean
ancestorHasCustomPosition(): boolean
addChildren(node: any): void
styleLine(line: any, node: any): void
removeLine(): void
isParent(node: any): boolean
isBrother(node: any): any
getPaddingVale(): {
paddingX: any
paddingY: any
}
getStyle(prop: any, root: any): any
getSelfStyle(prop: any): any
getParentSelfStyle(prop: any): any
getSelfInhertStyle(prop: any): any
getBorderWidth(): any
getData(key: any): any
hasCustomStyle(): boolean
constructor(opt?: {});
nodeData: any;
uid: any;
mindMap: any;
renderer: any;
draw: any;
style: Style;
shapeInstance: Shape;
shapePadding: {
paddingX: number;
paddingY: number;
};
isRoot: any;
isGeneralization: any;
generalizationBelongNode: any;
layerIndex: any;
width: any;
height: any;
_left: any;
_top: any;
customLeft: any;
customTop: any;
isDrag: boolean;
parent: any;
children: any;
group: any;
shapeNode: any;
hoverNode: any;
_customNodeContent: any;
_imgData: any;
_iconData: any;
_textData: any;
_hyperlinkData: any;
_tagData: any;
_noteData: any;
noteEl: any;
_expandBtn: any;
_lastExpandBtnType: any;
_showExpandBtn: boolean;
_openExpandNode: any;
_closeExpandNode: any;
_fillExpandNode: any;
_lines: any[];
_generalizationLine: any;
_generalizationNode: any;
_unVisibleRectRegionNode: any;
_isMouseenter: boolean;
_rectInfo: {
imgContentWidth: number;
imgContentHeight: number;
textContentWidth: number;
textContentHeight: number;
};
_generalizationNodeWidth: number;
_generalizationNodeHeight: number;
textContentItemMargin: any;
blockContentMargin: any;
expandBtnSize: any;
isMultipleChoice: boolean;
needLayout: boolean;
isHide: boolean;
set left(arg: any);
get left(): any;
set top(arg: any);
get top(): any;
reset(): void;
handleData(data: any): any;
createNodeData(): void;
getSize(): boolean;
getNodeRect(): {
width: any;
height: any;
};
layout(): void;
bindGroupEvent(): void;
active(e: any): void;
update(): void;
getNodePosInClient(_left: any, _top: any): {
left: any;
top: any;
};
reRender(): boolean;
updateNodeActive(): void;
render(callback?: () => void): void;
remove(): void;
destroy(): void;
hide(): void;
show(): void;
setOpacity(val: any): void;
hideChildren(): void;
showChildren(): void;
startDrag(): void;
endDrag(): void;
renderLine(deep?: boolean): void;
getShape(): any;
hasCustomPosition(): boolean;
ancestorHasCustomPosition(): boolean;
addChildren(node: any): void;
styleLine(line: any, node: any): void;
removeLine(): void;
isParent(node: any): boolean;
isBrother(node: any): any;
getPaddingVale(): {
paddingX: any;
paddingY: any;
};
getStyle(prop: any, root: any): any;
getSelfStyle(prop: any): any;
getParentSelfStyle(prop: any): any;
getSelfInhertStyle(prop: any): any;
getBorderWidth(): any;
getData(key: any): any;
hasCustomStyle(): boolean;
}
import Style from './Style'
import Shape from './Shape'
import Style from './Style';
import Shape from './Shape';

View File

@@ -1,28 +1,23 @@
export default class Shape {
constructor(node: any)
node: any
getShapePadding(
width: any,
height: any,
paddingX: any,
paddingY: any
): {
paddingX: number
paddingY: number
}
createShape(): any
getNodeSize(): {
width: any
height: any
}
createRect(): any
createDiamond(): any
createParallelogram(): any
createRoundedRectangle(): any
createOctagonalRectangle(): any
createOuterTriangularRectangle(): any
createInnerTriangularRectangle(): any
createEllipse(): any
createCircle(): any
constructor(node: any);
node: any;
getShapePadding(width: any, height: any, paddingX: any, paddingY: any): {
paddingX: number;
paddingY: number;
};
createShape(): any;
getNodeSize(): {
width: any;
height: any;
};
createRect(): any;
createDiamond(): any;
createParallelogram(): any;
createRoundedRectangle(): any;
createOctagonalRectangle(): any;
createOuterTriangularRectangle(): any;
createInnerTriangularRectangle(): any;
createEllipse(): any;
createCircle(): any;
}
export const shapeList: string[]
export const shapeList: string[];

View File

@@ -1,43 +1,36 @@
export default Style
export default Style;
declare class Style {
static setBackgroundStyle(el: any, themeConfig: any): void
static removeBackgroundStyle(el: any): void
constructor(ctx: any)
ctx: any
merge(prop: any, root: any): any
getStyle(prop: any, root: any): any
getSelfStyle(prop: any): any
rect(node: any): void
shape(node: any): void
text(node: any): void
createStyleText(): string
getTextFontStyle(): {
italic: boolean
bold: any
fontSize: any
fontFamily: any
}
domText(node: any, fontSizeScale: number, isMultiLine: any): void
tagText(node: any, index: any): void
tagRect(node: any, index: any): void
iconNode(node: any): void
line(
node: any,
{
width,
color,
dasharray
}?: {
width: any
color: any
dasharray: any
}
): void
generalizationLine(node: any): void
iconBtn(node: any, node2: any, fillNode: any): void
hasCustomStyle(): boolean
hoverNode(node: any): void
static setBackgroundStyle(el: any, themeConfig: any): void;
static removeBackgroundStyle(el: any): void;
constructor(ctx: any);
ctx: any;
merge(prop: any, root: any): any;
getStyle(prop: any, root: any): any;
getSelfStyle(prop: any): any;
rect(node: any): void;
shape(node: any): void;
text(node: any): void;
createStyleText(): string;
getTextFontStyle(): {
italic: boolean;
bold: any;
fontSize: any;
fontFamily: any;
};
domText(node: any, fontSizeScale: number, isMultiLine: any): void;
tagText(node: any): void;
tagRect(node: any, text: any, color: any): void;
iconNode(node: any): void;
line(node: any, { width, color, dasharray }?: {
width: any;
color: any;
dasharray: any;
}): void;
generalizationLine(node: any): void;
iconBtn(node: any, node2: any, fillNode: any): void;
hasCustomStyle(): boolean;
hoverNode(node: any): void;
}
declare namespace Style {
let cacheStyle: any
let cacheStyle: any;
}

View File

@@ -1,23 +1,23 @@
declare namespace _default {
export { setData }
export { setText }
export { setImage }
export { setIcon }
export { setHyperlink }
export { setNote }
export { setTag }
export { setShape }
export { setStyle }
export { setStyles }
export { setData };
export { setText };
export { setImage };
export { setIcon };
export { setHyperlink };
export { setNote };
export { setTag };
export { setShape };
export { setStyle };
export { setStyles };
}
export default _default
declare function setData(data?: {}): void
declare function setText(text: any, richText: any, resetRichText: any): void
declare function setImage(imgData: any): void
declare function setIcon(icons: any): void
declare function setHyperlink(link: any, title: any): void
declare function setNote(note: any): void
declare function setTag(tag: any): void
declare function setShape(shape: any): void
declare function setStyle(prop: any, value: any): void
declare function setStyles(style: any): void
export default _default;
declare function setData(data?: {}): void;
declare function setText(text: any, richText: any, resetRichText: any): void;
declare function setImage(imgData: any): void;
declare function setIcon(icons: any): void;
declare function setHyperlink(link: any, title: any): void;
declare function setNote(note: any): void;
declare function setTag(tag: any): void;
declare function setShape(shape: any): void;
declare function setStyle(prop: any, value: any): void;
declare function setStyles(style: any): void;

View File

@@ -1,45 +1,45 @@
declare namespace _default {
export { createImgNode }
export { getImgShowSize }
export { createIconNode }
export { createRichTextNode }
export { createTextNode }
export { createHyperlinkNode }
export { createTagNode }
export { createNoteNode }
export { measureCustomNodeContentSize }
export { isUseCustomNodeContent }
export { createImgNode };
export { getImgShowSize };
export { createIconNode };
export { createRichTextNode };
export { createTextNode };
export { createHyperlinkNode };
export { createTagNode };
export { createNoteNode };
export { measureCustomNodeContentSize };
export { isUseCustomNodeContent };
}
export default _default
export default _default;
declare function createImgNode(): {
node: any
width: any
height: any
}
declare function getImgShowSize(): any
declare function createIconNode(): any
node: any;
width: any;
height: any;
};
declare function getImgShowSize(): any;
declare function createIconNode(): any;
declare function createRichTextNode(): {
node: any
width: any
height: any
}
declare function createTextNode(): any
node: any;
width: any;
height: any;
};
declare function createTextNode(): any;
declare function createHyperlinkNode(): {
node: any
width: any
height: any
}
declare function createTagNode(): any[]
node: any;
width: any;
height: any;
};
declare function createTagNode(): any[];
declare function createNoteNode(): {
node: any
width: any
height: any
}
node: any;
width: any;
height: any;
};
declare class createNoteNode {
noteEl: HTMLDivElement
noteEl: HTMLDivElement;
}
declare function measureCustomNodeContentSize(content: any): {
width: any
height: any
}
declare function isUseCustomNodeContent(): boolean
width: any;
height: any;
};
declare function isUseCustomNodeContent(): boolean;

View File

@@ -1,34 +1,34 @@
declare namespace _default {
export { createExpandNodeContent }
export { updateExpandBtnNode }
export { updateExpandBtnPos }
export { renderExpandBtn }
export { removeExpandBtn }
export { showExpandBtn }
export { hideExpandBtn }
export { sumNode }
export { createExpandNodeContent };
export { updateExpandBtnNode };
export { updateExpandBtnPos };
export { renderExpandBtn };
export { removeExpandBtn };
export { showExpandBtn };
export { hideExpandBtn };
export { sumNode };
}
export default _default
declare function createExpandNodeContent(): void
export default _default;
declare function createExpandNodeContent(): void;
declare class createExpandNodeContent {
_openExpandNode: any
_closeExpandNode: any
_fillExpandNode: any
_openExpandNode: any;
_closeExpandNode: any;
_fillExpandNode: any;
}
declare function updateExpandBtnNode(): void
declare function updateExpandBtnNode(): void;
declare class updateExpandBtnNode {
_lastExpandBtnType: boolean
_lastExpandBtnType: boolean;
}
declare function updateExpandBtnPos(): void
declare function renderExpandBtn(): void
declare function updateExpandBtnPos(): void;
declare function renderExpandBtn(): void;
declare class renderExpandBtn {
_expandBtn: any
_showExpandBtn: boolean
_expandBtn: any;
_showExpandBtn: boolean;
}
declare function removeExpandBtn(): void
declare function removeExpandBtn(): void;
declare class removeExpandBtn {
_showExpandBtn: boolean
_showExpandBtn: boolean;
}
declare function showExpandBtn(): void
declare function hideExpandBtn(): void
declare function sumNode(data?: any[]): any
declare function showExpandBtn(): void;
declare function hideExpandBtn(): void;
declare function sumNode(data?: any[]): any;

View File

@@ -1,18 +1,18 @@
declare namespace _default {
export { renderExpandBtnPlaceholderRect }
export { clearExpandBtnPlaceholderRect }
export { updateExpandBtnPlaceholderRect }
export { renderExpandBtnPlaceholderRect };
export { clearExpandBtnPlaceholderRect };
export { updateExpandBtnPlaceholderRect };
}
export default _default
declare function renderExpandBtnPlaceholderRect(): void
export default _default;
declare function renderExpandBtnPlaceholderRect(): void;
declare class renderExpandBtnPlaceholderRect {
_unVisibleRectRegionNode: any
_unVisibleRectRegionNode: any;
}
declare function clearExpandBtnPlaceholderRect(): void
declare function clearExpandBtnPlaceholderRect(): void;
declare class clearExpandBtnPlaceholderRect {
_unVisibleRectRegionNode: any
_unVisibleRectRegionNode: any;
}
declare function updateExpandBtnPlaceholderRect(): void
declare function updateExpandBtnPlaceholderRect(): void;
declare class updateExpandBtnPlaceholderRect {
needRerenderExpandBtnPlaceholderRect: boolean
needRerenderExpandBtnPlaceholderRect: boolean;
}

View File

@@ -1,32 +1,32 @@
declare namespace _default {
export { checkHasGeneralization }
export { createGeneralizationNode }
export { updateGeneralization }
export { renderGeneralization }
export { removeGeneralization }
export { hideGeneralization }
export { showGeneralization }
export { checkHasGeneralization };
export { createGeneralizationNode };
export { updateGeneralization };
export { renderGeneralization };
export { removeGeneralization };
export { hideGeneralization };
export { showGeneralization };
}
export default _default
declare function checkHasGeneralization(): boolean
declare function createGeneralizationNode(): void
export default _default;
declare function checkHasGeneralization(): boolean;
declare function createGeneralizationNode(): void;
declare class createGeneralizationNode {
_generalizationLine: any
_generalizationNode: Node
_generalizationNodeWidth: any
_generalizationNodeHeight: any
_generalizationLine: any;
_generalizationNode: Node;
_generalizationNodeWidth: any;
_generalizationNodeHeight: any;
}
declare function updateGeneralization(): void
declare function renderGeneralization(): void
declare function updateGeneralization(): void;
declare function renderGeneralization(): void;
declare class renderGeneralization {
_generalizationNodeWidth: number
_generalizationNodeHeight: number
_generalizationNodeWidth: number;
_generalizationNodeHeight: number;
}
declare function removeGeneralization(): void
declare function removeGeneralization(): void;
declare class removeGeneralization {
_generalizationLine: any
_generalizationNode: any
_generalizationLine: any;
_generalizationNode: any;
}
declare function hideGeneralization(): void
declare function showGeneralization(): void
import Node from './Node'
declare function hideGeneralization(): void;
declare function showGeneralization(): void;
import Node from './Node';

View File

@@ -1,36 +1,36 @@
export default View
export default View;
declare class View {
constructor(opt?: {})
opt: {}
mindMap: any
scale: number
sx: number
sy: number
x: number
y: number
firstDrag: boolean
bind(): void
getTransformData(): {
transform: any
state: {
scale: number
x: number
y: number
sx: number
sy: number
}
}
setTransformData(viewData: any): void
translateXY(x: any, y: any): void
translateX(step: any): void
translateXTo(x: any): void
translateY(step: any): void
translateYTo(y: any): void
transform(): void
reset(): void
narrow(cx: any, cy: any, isTouchPad: any): void
enlarge(cx: any, cy: any, isTouchPad: any): void
scaleInCenter(scale: any, cx: any, cy: any): void
setScale(scale: any, cx: any, cy: any): void
fit(): void
constructor(opt?: {});
opt: {};
mindMap: any;
scale: number;
sx: number;
sy: number;
x: number;
y: number;
firstDrag: boolean;
bind(): void;
getTransformData(): {
transform: any;
state: {
scale: number;
x: number;
y: number;
sx: number;
sy: number;
};
};
setTransformData(viewData: any): void;
translateXY(x: any, y: any): void;
translateX(step: any): void;
translateXTo(x: any): void;
translateY(step: any): void;
translateYTo(y: any): void;
transform(): void;
reset(): void;
narrow(cx: any, cy: any, isTouchPad: any): void;
enlarge(cx: any, cy: any, isTouchPad: any): void;
scaleInCenter(scale: any, cx: any, cy: any): void;
setScale(scale: any, cx: any, cy: any): void;
fit(): void;
}

View File

@@ -1,46 +1,43 @@
export default Base
export default Base;
declare class Base {
constructor(renderer: any)
renderer: any
mindMap: any
draw: any
root: any
lru: Lru
doLayout(): void
renderLine(): void
renderExpandBtn(): void
renderGeneralization(): void
cacheNode(uid: any, node: any): void
checkIsNeedResizeSources(): boolean
checkIsLayerTypeChange(oldIndex: any, newIndex: any): boolean
checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(node: any): void
createNode(data: any, parent: any, isRoot: any, layerIndex: any): any
formatPosition(value: any, size: any, nodeSize: any): number
setNodeCenter(node: any): void
updateChildren(children: any, prop: any, offset: any): void
updateChildrenPro(children: any, props: any): void
getNodeAreaWidth(node: any, withGeneralization?: boolean): number
quadraticCurvePath(x1: any, y1: any, x2: any, y2: any): string
cubicBezierPath(x1: any, y1: any, x2: any, y2: any): string
getMarginX(layerIndex: any): any
getMarginY(layerIndex: any): any
getNodeWidthWithGeneralization(node: any): number
getNodeHeightWithGeneralization(node: any): number
/**
* dir生长方向h水平、v垂直
* isLeft是否向左生长
*/
getNodeBoundaries(
node: any,
dir: any
): {
left: any
right: any
top: any
bottom: any
generalizationLineMargin: any
generalizationNodeMargin: any
}
getNodeActChildrenLength(node: any): any
constructor(renderer: any);
renderer: any;
mindMap: any;
draw: any;
root: any;
lru: Lru;
doLayout(): void;
renderLine(): void;
renderExpandBtn(): void;
renderGeneralization(): void;
cacheNode(uid: any, node: any): void;
checkIsNeedResizeSources(): boolean;
checkIsLayerTypeChange(oldIndex: any, newIndex: any): boolean;
checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(node: any): void;
createNode(data: any, parent: any, isRoot: any, layerIndex: any): any;
formatPosition(value: any, size: any, nodeSize: any): number;
setNodeCenter(node: any): void;
updateChildren(children: any, prop: any, offset: any): void;
updateChildrenPro(children: any, props: any): void;
getNodeAreaWidth(node: any, withGeneralization?: boolean): number;
quadraticCurvePath(x1: any, y1: any, x2: any, y2: any): string;
cubicBezierPath(x1: any, y1: any, x2: any, y2: any): string;
getMarginX(layerIndex: any): any;
getMarginY(layerIndex: any): any;
getNodeWidthWithGeneralization(node: any): number;
getNodeHeightWithGeneralization(node: any): number;
/**
* dir生长方向h水平、v垂直
* isLeft是否向左生长
*/
getNodeBoundaries(node: any, dir: any): {
left: any;
right: any;
top: any;
bottom: any;
generalizationLineMargin: any;
generalizationNodeMargin: any;
};
getNodeActChildrenLength(node: any): any;
}
import Lru from '../utils/Lru'
import Lru from '../utils/Lru';

View File

@@ -1,21 +1,15 @@
export default CatalogOrganization
export default CatalogOrganization;
declare class CatalogOrganization extends Base {
constructor(opt?: {})
doLayout(callback: any): void
computedBaseValue(): void
computedLeftTopValue(): void
adjustLeftTopValue(): void
updateBrothersLeft(node: any, addWidth: any): void
updateBrothersTop(node: any, addHeight: any): void
renderLine(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt?: {});
doLayout(callback: any): void;
computedBaseValue(): void;
computedLeftTopValue(): void;
adjustLeftTopValue(): void;
updateBrothersLeft(node: any, addWidth: any): void;
updateBrothersTop(node: any, addHeight: any): void;
renderLine(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,25 +1,19 @@
export default Fishbone
export default Fishbone;
declare class Fishbone extends Base {
constructor(opt?: {})
indent: number
childIndent: number
doLayout(callback: any): void
computedBaseValue(): void
computedLeftTopValue(): void
adjustLeftTopValue(): void
getNodeAreaHeight(node: any): number
updateBrothersLeft(node: any): void
updateBrothersTop(node: any, addHeight: any): void
checkIsTop(node: any): boolean
renderLine(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt?: {});
indent: number;
childIndent: number;
doLayout(callback: any): void;
computedBaseValue(): void;
computedLeftTopValue(): void;
adjustLeftTopValue(): void;
getNodeAreaHeight(node: any): number;
updateBrothersLeft(node: any): void;
updateBrothersTop(node: any, addHeight: any): void;
checkIsTop(node: any): boolean;
renderLine(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,23 +1,17 @@
export default LogicalStructure
export default LogicalStructure;
declare class LogicalStructure extends Base {
constructor(opt?: {})
doLayout(callback: any): void
computedBaseValue(): void
computedTopValue(): void
adjustTopValue(): void
updateBrothers(node: any, addHeight: any): void
renderLine(node: any, lines: any, style: any, lineStyle: any): void
renderLineStraight(node: any, lines: any, style: any): any[]
renderLineDirect(node: any, lines: any, style: any): any[]
renderLineCurve(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt?: {});
doLayout(callback: any): void;
computedBaseValue(): void;
computedTopValue(): void;
adjustTopValue(): void;
updateBrothers(node: any, addHeight: any): void;
renderLine(node: any, lines: any, style: any, lineStyle: any): void;
renderLineStraight(node: any, lines: any, style: any): any[];
renderLineDirect(node: any, lines: any, style: any): any[];
renderLineCurve(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,23 +1,17 @@
export default MindMap
export default MindMap;
declare class MindMap extends Base {
constructor(opt?: {})
doLayout(callback: any): void
computedBaseValue(): void
computedTopValue(): void
adjustTopValue(): void
updateBrothers(node: any, leftAddHeight: any, rightAddHeight: any): void
renderLine(node: any, lines: any, style: any, lineStyle: any): void
renderLineStraight(node: any, lines: any, style: any): any[]
renderLineDirect(node: any, lines: any, style: any): any[]
renderLineCurve(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt?: {});
doLayout(callback: any): void;
computedBaseValue(): void;
computedTopValue(): void;
adjustTopValue(): void;
updateBrothers(node: any, leftAddHeight: any, rightAddHeight: any): void;
renderLine(node: any, lines: any, style: any, lineStyle: any): void;
renderLineStraight(node: any, lines: any, style: any): any[];
renderLineDirect(node: any, lines: any, style: any): any[];
renderLineCurve(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,22 +1,16 @@
export default OrganizationStructure
export default OrganizationStructure;
declare class OrganizationStructure extends Base {
constructor(opt?: {})
doLayout(callback: any): void
computedBaseValue(): void
computedLeftValue(): void
adjustLeftValue(): void
updateBrothers(node: any, addWidth: any): void
renderLine(node: any, lines: any, style: any, lineStyle: any): void
renderLineDirect(node: any, lines: any, style: any): any[]
renderLineStraight(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt?: {});
doLayout(callback: any): void;
computedBaseValue(): void;
computedLeftValue(): void;
adjustLeftValue(): void;
updateBrothers(node: any, addWidth: any): void;
renderLine(node: any, lines: any, style: any, lineStyle: any): void;
renderLineDirect(node: any, lines: any, style: any): any[];
renderLineStraight(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,23 +1,17 @@
export default Timeline
export default Timeline;
declare class Timeline extends Base {
constructor(opt: {}, layout: any)
layout: any
doLayout(callback: any): void
computedBaseValue(): void
computedLeftTopValue(): void
adjustLeftTopValue(): void
getNodeAreaHeight(node: any): number
updateBrothersLeft(node: any): void
updateBrothersTop(node: any, addHeight: any): void
renderLine(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt: {}, layout: any);
layout: any;
doLayout(callback: any): void;
computedBaseValue(): void;
computedLeftTopValue(): void;
adjustLeftTopValue(): void;
getNodeAreaHeight(node: any): number;
updateBrothersLeft(node: any): void;
updateBrothersTop(node: any, addHeight: any): void;
renderLine(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,25 +1,19 @@
export default VerticalTimeline
export default VerticalTimeline;
declare class VerticalTimeline extends Base {
constructor(opt: {}, layout: any)
layout: any
doLayout(callback: any): void
computedBaseValue(): void
computedTopValue(): void
adjustLeftTopValue(): void
updateBrothers(node: any, addHeight: any): void
updateBrothersTop(node: any, addHeight: any): void
renderLine(node: any, lines: any, style: any, lineStyle: any): void
renderLineStraight(node: any, lines: any, style: any): any[]
renderLineDirect(node: any, lines: any, style: any): any[]
renderLineCurve(node: any, lines: any, style: any): any[]
renderExpandBtn(node: any, btn: any): void
renderGeneralization(node: any, gLine: any, gNode: any): void
renderExpandBtnRect(
rect: any,
expandBtnSize: any,
width: any,
height: any,
node: any
): void
constructor(opt: {}, layout: any);
layout: any;
doLayout(callback: any): void;
computedBaseValue(): void;
computedTopValue(): void;
adjustLeftTopValue(): void;
updateBrothers(node: any, addHeight: any): void;
updateBrothersTop(node: any, addHeight: any): void;
renderLine(node: any, lines: any, style: any, lineStyle: any): void;
renderLineStraight(node: any, lines: any, style: any): any[];
renderLineDirect(node: any, lines: any, style: any): any[];
renderLineCurve(node: any, lines: any, style: any): any[];
renderExpandBtn(node: any, btn: any): void;
renderGeneralization(node: any, gLine: any, gNode: any): void;
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
}
import Base from './Base'
import Base from './Base';

View File

@@ -1,137 +1,77 @@
declare namespace _default {
namespace top {
function renderExpandBtn({
node,
btn,
expandBtnSize,
translateX,
translateY,
width,
height
}: {
node: any
btn: any
expandBtnSize: any
translateX: any
translateY: any
width: any
height: any
}): void
function renderLine({
node,
line,
top,
x,
lineLength,
height,
expandBtnSize,
maxy,
ctx
}: {
node: any
line: any
top: any
x: any
lineLength: any
height: any
expandBtnSize: any
maxy: any
ctx: any
}): void
function computedLeftTopValue({
layerIndex,
node,
ctx
}: {
layerIndex: any
node: any
ctx: any
}): void
function adjustLeftTopValueBefore({
node,
parent,
ctx,
layerIndex
}: {
node: any
parent: any
ctx: any
layerIndex: any
}): void
function adjustLeftTopValueAfter({
parent,
node,
ctx
}: {
parent: any
node: any
ctx: any
}): void
}
namespace bottom {
function renderExpandBtn({
node,
btn,
expandBtnSize,
translateX,
translateY,
width,
height
}: {
node: any
btn: any
expandBtnSize: any
translateX: any
translateY: any
width: any
height: any
}): void
function renderLine({
node,
line,
top,
x,
lineLength,
height,
miny,
ctx
}: {
node: any
line: any
top: any
x: any
lineLength: any
height: any
miny: any
ctx: any
}): void
function computedLeftTopValue({
layerIndex,
node,
ctx
}: {
layerIndex: any
node: any
ctx: any
}): void
function adjustLeftTopValueBefore({
node,
ctx,
layerIndex
}: {
node: any
ctx: any
layerIndex: any
}): void
function adjustLeftTopValueAfter({
parent,
node,
ctx
}: {
parent: any
node: any
ctx: any
}): void
}
namespace top {
function renderExpandBtn({ node, btn, expandBtnSize, translateX, translateY, width, height }: {
node: any;
btn: any;
expandBtnSize: any;
translateX: any;
translateY: any;
width: any;
height: any;
}): void;
function renderLine({ node, line, top, x, lineLength, height, expandBtnSize, maxy, ctx }: {
node: any;
line: any;
top: any;
x: any;
lineLength: any;
height: any;
expandBtnSize: any;
maxy: any;
ctx: any;
}): void;
function computedLeftTopValue({ layerIndex, node, ctx }: {
layerIndex: any;
node: any;
ctx: any;
}): void;
function adjustLeftTopValueBefore({ node, parent, ctx, layerIndex }: {
node: any;
parent: any;
ctx: any;
layerIndex: any;
}): void;
function adjustLeftTopValueAfter({ parent, node, ctx }: {
parent: any;
node: any;
ctx: any;
}): void;
}
namespace bottom {
function renderExpandBtn({ node, btn, expandBtnSize, translateX, translateY, width, height }: {
node: any;
btn: any;
expandBtnSize: any;
translateX: any;
translateY: any;
width: any;
height: any;
}): void;
function renderLine({ node, line, top, x, lineLength, height, miny, ctx }: {
node: any;
line: any;
top: any;
x: any;
lineLength: any;
height: any;
miny: any;
ctx: any;
}): void;
function computedLeftTopValue({ layerIndex, node, ctx }: {
layerIndex: any;
node: any;
ctx: any;
}): void;
function adjustLeftTopValueBefore({ node, ctx, layerIndex }: {
node: any;
ctx: any;
layerIndex: any;
}): void;
function adjustLeftTopValueAfter({ parent, node, ctx }: {
parent: any;
node: any;
ctx: any;
}): void;
}
}
export default _default
export default _default;

View File

@@ -1,11 +1,11 @@
declare namespace _default {
export { open }
export { close }
export { remove }
export { imgAdjust }
export { open };
export { close };
export { remove };
export { imgAdjust };
}
export default _default
declare const open: '<svg t="1618141562310" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13476" width="200" height="200"><path d="M475.136 327.168v147.968h-147.968v74.24h147.968v147.968h74.24v-147.968h147.968v-74.24h-147.968v-147.968h-74.24z m36.864-222.208c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13477"></path></svg>'
declare const close: '<svg t="1618141589243" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13611" width="200" height="200"><path d="M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13612"></path><path d="M252.928 474.624h518.144v74.24h-518.144z" p-id="13613"></path></svg>'
declare const remove: '<svg width="14px" height="14px" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13611" width="200" height="200"><path fill="#ffffff" d="M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13612"></path><path fill="#ffffff" d="M252.928 474.624h518.144v74.24h-518.144z" p-id="13613"></path></svg>'
declare const imgAdjust: '<svg width="12px" height="12px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M1008.128 614.4a25.6 25.6 0 0 0-27.648 5.632l-142.848 142.848L259.072 186.88 401.92 43.52A25.6 25.6 0 0 0 384 0h-358.4a25.6 25.6 0 0 0-25.6 25.6v358.4a25.6 25.6 0 0 0 43.52 17.92l143.36-142.848 578.048 578.048-142.848 142.848a25.6 25.6 0 0 0 17.92 43.52h358.4a25.6 25.6 0 0 0 25.6-25.6v-358.4a25.6 25.6 0 0 0-15.872-25.088z" /></svg>'
export default _default;
declare const open: "<svg t=\"1618141562310\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13476\" width=\"200\" height=\"200\"><path d=\"M475.136 327.168v147.968h-147.968v74.24h147.968v147.968h74.24v-147.968h147.968v-74.24h-147.968v-147.968h-74.24z m36.864-222.208c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z\" p-id=\"13477\"></path></svg>";
declare const close: "<svg t=\"1618141589243\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13611\" width=\"200\" height=\"200\"><path d=\"M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z\" p-id=\"13612\"></path><path d=\"M252.928 474.624h518.144v74.24h-518.144z\" p-id=\"13613\"></path></svg>";
declare const remove: "<svg width=\"14px\" height=\"14px\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13611\" width=\"200\" height=\"200\"><path fill=\"#ffffff\" d=\"M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z\" p-id=\"13612\"></path><path fill=\"#ffffff\" d=\"M252.928 474.624h518.144v74.24h-518.144z\" p-id=\"13613\"></path></svg>";
declare const imgAdjust: "<svg width=\"12px\" height=\"12px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#ffffff\" d=\"M1008.128 614.4a25.6 25.6 0 0 0-27.648 5.632l-142.848 142.848L259.072 186.88 401.92 43.52A25.6 25.6 0 0 0 384 0h-358.4a25.6 25.6 0 0 0-25.6 25.6v358.4a25.6 25.6 0 0 0 43.52 17.92l143.36-142.848 578.048 578.048-142.848 142.848a25.6 25.6 0 0 0 17.92 43.52h358.4a25.6 25.6 0 0 0 25.6-25.6v-358.4a25.6 25.6 0 0 0-15.872-25.088z\" /></svg>";

View File

@@ -1,18 +1,18 @@
export const nodeIconList: {
name: string
type: string
list: {
name: string
icon: string
}[]
}[]
name: string;
type: string;
list: {
name: string;
icon: string;
}[];
}[];
declare namespace _default {
export { hyperlink }
export { note }
export { nodeIconList }
export { getNodeIconListIcon }
export { hyperlink };
export { note };
export { nodeIconList };
export { getNodeIconListIcon };
}
export default _default
declare const hyperlink: '<svg t="1624174958075" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7982" ><path d="M435.484444 251.733333v68.892445L295.822222 320.682667a168.504889 168.504889 0 0 0-2.844444 336.952889h142.506666v68.892444H295.822222a237.397333 237.397333 0 0 1 0-474.794667h139.662222z m248.945778 0a237.397333 237.397333 0 0 1 0 474.851556H544.654222v-69.006222l139.776 0.056889a168.504889 168.504889 0 0 0 2.844445-336.952889H544.597333V251.676444h139.776z m-25.827555 203.946667a34.474667 34.474667 0 0 1 0 68.892444H321.649778a34.474667 34.474667 0 0 1 0-68.892444h336.952889z" p-id="7983"></path></svg>'
declare const note: '<svg t="1624195132675" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8792" ><path d="M152.768 985.984 152.768 49.856l434.56 0 66.816 0 234.048 267.392 0 66.816 0 601.92L152.768 985.984 152.768 985.984zM654.144 193.088l0 124.16 108.736 0L654.144 193.088 654.144 193.088zM821.312 384.064l-167.168 0L587.328 384.064 587.328 317.312 587.328 116.736 219.584 116.736 219.584 919.04l601.728 0L821.312 384.064 821.312 384.064zM386.688 517.888 319.808 517.888 319.808 450.944l66.816 0L386.624 517.888 386.688 517.888zM386.688 651.584 319.808 651.584 319.808 584.704l66.816 0L386.624 651.584 386.688 651.584zM386.688 785.344 319.808 785.344l0-66.88 66.816 0L386.624 785.344 386.688 785.344zM721.024 517.888 453.632 517.888 453.632 450.944l267.392 0L721.024 517.888 721.024 517.888zM654.144 651.584 453.632 651.584 453.632 584.704l200.512 0L654.144 651.584 654.144 651.584zM620.672 785.344l-167.04 0 0-66.88 167.04 0L620.672 785.344 620.672 785.344z" p-id="8793"></path></svg>'
declare function getNodeIconListIcon(name: any, extendIconList?: any[]): any
export default _default;
declare const hyperlink: "<svg t=\"1624174958075\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"7982\" ><path d=\"M435.484444 251.733333v68.892445L295.822222 320.682667a168.504889 168.504889 0 0 0-2.844444 336.952889h142.506666v68.892444H295.822222a237.397333 237.397333 0 0 1 0-474.794667h139.662222z m248.945778 0a237.397333 237.397333 0 0 1 0 474.851556H544.654222v-69.006222l139.776 0.056889a168.504889 168.504889 0 0 0 2.844445-336.952889H544.597333V251.676444h139.776z m-25.827555 203.946667a34.474667 34.474667 0 0 1 0 68.892444H321.649778a34.474667 34.474667 0 0 1 0-68.892444h336.952889z\" p-id=\"7983\"></path></svg>";
declare const note: "<svg t=\"1624195132675\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"8792\" ><path d=\"M152.768 985.984 152.768 49.856l434.56 0 66.816 0 234.048 267.392 0 66.816 0 601.92L152.768 985.984 152.768 985.984zM654.144 193.088l0 124.16 108.736 0L654.144 193.088 654.144 193.088zM821.312 384.064l-167.168 0L587.328 384.064 587.328 317.312 587.328 116.736 219.584 116.736 219.584 919.04l601.728 0L821.312 384.064 821.312 384.064zM386.688 517.888 319.808 517.888 319.808 450.944l66.816 0L386.624 517.888 386.688 517.888zM386.688 651.584 319.808 651.584 319.808 584.704l66.816 0L386.624 651.584 386.688 651.584zM386.688 785.344 319.808 785.344l0-66.88 66.816 0L386.624 785.344 386.688 785.344zM721.024 517.888 453.632 517.888 453.632 450.944l267.392 0L721.024 517.888 721.024 517.888zM654.144 651.584 453.632 651.584 453.632 584.704l200.512 0L654.144 651.584 654.144 651.584zM620.672 785.344l-167.04 0 0-66.88 167.04 0L620.672 785.344 620.672 785.344z\" p-id=\"8793\"></path></svg>";
declare function getNodeIconListIcon(name: any, extendIconList?: any[]): any;

View File

@@ -1,143 +1,143 @@
declare namespace _default {
let paddingX: number
let paddingY: number
let imgMaxWidth: number
let imgMaxHeight: number
let iconSize: number
let lineWidth: number
let lineColor: string
let lineDasharray: string
let lineStyle: string
let rootLineKeepSameInCurve: boolean
let generalizationLineWidth: number
let generalizationLineColor: string
let generalizationLineMargin: number
let generalizationNodeMargin: number
let associativeLineWidth: number
let associativeLineColor: string
let associativeLineActiveWidth: number
let associativeLineActiveColor: string
let associativeLineTextColor: string
let associativeLineTextFontSize: number
let associativeLineTextLineHeight: number
let associativeLineTextFontFamily: string
let backgroundColor: string
let backgroundImage: string
let backgroundRepeat: string
let backgroundPosition: string
let backgroundSize: string
let nodeUseLineStyle: boolean
namespace root {
let shape: string
let fillColor: string
let fontFamily: string
let color: string
let fontSize: number
let fontWeight: string
let fontStyle: string
let lineHeight: number
let borderColor: string
let borderWidth: number
let borderDasharray: string
let borderRadius: number
let textDecoration: string
}
namespace second {
let shape_1: string
export { shape_1 as shape }
export let marginX: number
export let marginY: number
let fillColor_1: string
export { fillColor_1 as fillColor }
let fontFamily_1: string
export { fontFamily_1 as fontFamily }
let color_1: string
export { color_1 as color }
let fontSize_1: number
export { fontSize_1 as fontSize }
let fontWeight_1: string
export { fontWeight_1 as fontWeight }
let fontStyle_1: string
export { fontStyle_1 as fontStyle }
let lineHeight_1: number
export { lineHeight_1 as lineHeight }
let borderColor_1: string
export { borderColor_1 as borderColor }
let borderWidth_1: number
export { borderWidth_1 as borderWidth }
let borderDasharray_1: string
export { borderDasharray_1 as borderDasharray }
let borderRadius_1: number
export { borderRadius_1 as borderRadius }
let textDecoration_1: string
export { textDecoration_1 as textDecoration }
}
namespace node {
let shape_2: string
export { shape_2 as shape }
let marginX_1: number
export { marginX_1 as marginX }
let marginY_1: number
export { marginY_1 as marginY }
let fillColor_2: string
export { fillColor_2 as fillColor }
let fontFamily_2: string
export { fontFamily_2 as fontFamily }
let color_2: string
export { color_2 as color }
let fontSize_2: number
export { fontSize_2 as fontSize }
let fontWeight_2: string
export { fontWeight_2 as fontWeight }
let fontStyle_2: string
export { fontStyle_2 as fontStyle }
let lineHeight_2: number
export { lineHeight_2 as lineHeight }
let borderColor_2: string
export { borderColor_2 as borderColor }
let borderWidth_2: number
export { borderWidth_2 as borderWidth }
let borderRadius_2: number
export { borderRadius_2 as borderRadius }
let borderDasharray_2: string
export { borderDasharray_2 as borderDasharray }
let textDecoration_2: string
export { textDecoration_2 as textDecoration }
}
namespace generalization {
let shape_3: string
export { shape_3 as shape }
let marginX_2: number
export { marginX_2 as marginX }
let marginY_2: number
export { marginY_2 as marginY }
let fillColor_3: string
export { fillColor_3 as fillColor }
let fontFamily_3: string
export { fontFamily_3 as fontFamily }
let color_3: string
export { color_3 as color }
let fontSize_3: number
export { fontSize_3 as fontSize }
let fontWeight_3: string
export { fontWeight_3 as fontWeight }
let fontStyle_3: string
export { fontStyle_3 as fontStyle }
let lineHeight_3: number
export { lineHeight_3 as lineHeight }
let borderColor_3: string
export { borderColor_3 as borderColor }
let borderWidth_3: number
export { borderWidth_3 as borderWidth }
let borderDasharray_3: string
export { borderDasharray_3 as borderDasharray }
let borderRadius_3: number
export { borderRadius_3 as borderRadius }
let textDecoration_3: string
export { textDecoration_3 as textDecoration }
}
let paddingX: number;
let paddingY: number;
let imgMaxWidth: number;
let imgMaxHeight: number;
let iconSize: number;
let lineWidth: number;
let lineColor: string;
let lineDasharray: string;
let lineStyle: string;
let rootLineKeepSameInCurve: boolean;
let generalizationLineWidth: number;
let generalizationLineColor: string;
let generalizationLineMargin: number;
let generalizationNodeMargin: number;
let associativeLineWidth: number;
let associativeLineColor: string;
let associativeLineActiveWidth: number;
let associativeLineActiveColor: string;
let associativeLineTextColor: string;
let associativeLineTextFontSize: number;
let associativeLineTextLineHeight: number;
let associativeLineTextFontFamily: string;
let backgroundColor: string;
let backgroundImage: string;
let backgroundRepeat: string;
let backgroundPosition: string;
let backgroundSize: string;
let nodeUseLineStyle: boolean;
namespace root {
let shape: string;
let fillColor: string;
let fontFamily: string;
let color: string;
let fontSize: number;
let fontWeight: string;
let fontStyle: string;
let lineHeight: number;
let borderColor: string;
let borderWidth: number;
let borderDasharray: string;
let borderRadius: number;
let textDecoration: string;
}
namespace second {
let shape_1: string;
export { shape_1 as shape };
export let marginX: number;
export let marginY: number;
let fillColor_1: string;
export { fillColor_1 as fillColor };
let fontFamily_1: string;
export { fontFamily_1 as fontFamily };
let color_1: string;
export { color_1 as color };
let fontSize_1: number;
export { fontSize_1 as fontSize };
let fontWeight_1: string;
export { fontWeight_1 as fontWeight };
let fontStyle_1: string;
export { fontStyle_1 as fontStyle };
let lineHeight_1: number;
export { lineHeight_1 as lineHeight };
let borderColor_1: string;
export { borderColor_1 as borderColor };
let borderWidth_1: number;
export { borderWidth_1 as borderWidth };
let borderDasharray_1: string;
export { borderDasharray_1 as borderDasharray };
let borderRadius_1: number;
export { borderRadius_1 as borderRadius };
let textDecoration_1: string;
export { textDecoration_1 as textDecoration };
}
namespace node {
let shape_2: string;
export { shape_2 as shape };
let marginX_1: number;
export { marginX_1 as marginX };
let marginY_1: number;
export { marginY_1 as marginY };
let fillColor_2: string;
export { fillColor_2 as fillColor };
let fontFamily_2: string;
export { fontFamily_2 as fontFamily };
let color_2: string;
export { color_2 as color };
let fontSize_2: number;
export { fontSize_2 as fontSize };
let fontWeight_2: string;
export { fontWeight_2 as fontWeight };
let fontStyle_2: string;
export { fontStyle_2 as fontStyle };
let lineHeight_2: number;
export { lineHeight_2 as lineHeight };
let borderColor_2: string;
export { borderColor_2 as borderColor };
let borderWidth_2: number;
export { borderWidth_2 as borderWidth };
let borderRadius_2: number;
export { borderRadius_2 as borderRadius };
let borderDasharray_2: string;
export { borderDasharray_2 as borderDasharray };
let textDecoration_2: string;
export { textDecoration_2 as textDecoration };
}
namespace generalization {
let shape_3: string;
export { shape_3 as shape };
let marginX_2: number;
export { marginX_2 as marginX };
let marginY_2: number;
export { marginY_2 as marginY };
let fillColor_3: string;
export { fillColor_3 as fillColor };
let fontFamily_3: string;
export { fontFamily_3 as fontFamily };
let color_3: string;
export { color_3 as color };
let fontSize_3: number;
export { fontSize_3 as fontSize };
let fontWeight_3: string;
export { fontWeight_3 as fontWeight };
let fontStyle_3: string;
export { fontStyle_3 as fontStyle };
let lineHeight_3: number;
export { lineHeight_3 as lineHeight };
let borderColor_3: string;
export { borderColor_3 as borderColor };
let borderWidth_3: number;
export { borderWidth_3 as borderWidth };
let borderDasharray_3: string;
export { borderDasharray_3 as borderDasharray };
let borderRadius_3: number;
export { borderRadius_3 as borderRadius };
let textDecoration_3: string;
export { textDecoration_3 as textDecoration };
}
}
export default _default
export const supportActiveStyle: string[]
export function checkIsNodeSizeIndependenceConfig(config: any): boolean
export const lineStyleProps: string[]
export default _default;
export const supportActiveStyle: string[];
export function checkIsNodeSizeIndependenceConfig(config: any): boolean;
export const lineStyleProps: string[];

View File

@@ -1,8 +1,8 @@
export default BatchExecution
export default BatchExecution;
declare class BatchExecution {
has: {}
queue: any[]
nextTick: any
push(name: any, fn: any): void
flush(): void
has: {};
queue: any[];
nextTick: any;
push(name: any, fn: any): void;
flush(): void;
}

View File

@@ -1,10 +1,10 @@
export default class CRU {
constructor(max: any)
max: any
size: number
pool: Map<any, any>
add(key: any, value: any): void
delete(key: any): void
has(key: any): boolean
get(key: any): any
export default class Lru {
constructor(max: any);
max: any;
size: number;
pool: Map<any, any>;
add(key: any, value: any): void;
delete(key: any): void;
has(key: any): boolean;
get(key: any): any;
}

View File

@@ -1,113 +1,69 @@
export function walk(
root: any,
parent: any,
beforeCallback: any,
afterCallback: any,
isRoot: any,
layerIndex?: number,
index?: number
): void
export function bfsWalk(root: any, callback: any): void
export function resizeImgSizeByOriginRatio(
width: any,
height: any,
newWidth: any,
newHeight: any
): any[]
export function resizeImgSize(
width: any,
height: any,
maxWidth: any,
maxHeight: any
): any[]
export function resizeImg(
imgUrl: any,
maxWidth: any,
maxHeight: any
): Promise<any>
export function getStrWithBrFromHtml(str: any): any
export function simpleDeepClone(data: any): any
export function copyRenderTree(
tree: any,
root: any,
removeActiveState?: boolean
): any
export function copyNodeTree(
tree: any,
root: any,
removeActiveState?: boolean,
keepId?: boolean
): any
export function imgToDataUrl(src: any): Promise<any>
export function parseDataUrl(data: any): any
export function downloadFile(file: any, fileName: any): void
export function throttle(
fn: any,
time: number,
ctx: any
): (...args: any[]) => void
export function asyncRun(taskList: any, callback?: () => void): void
export function degToRad(deg: any): number
export function camelCaseToHyphen(str: any): any
export function measureText(
text: any,
{
italic,
bold,
fontSize,
fontFamily
}: {
italic: any
bold: any
fontSize: any
fontFamily: any
}
): {
width: any
height: any
}
export function joinFontStr({
italic,
bold,
fontSize,
fontFamily
}: {
italic: any
bold: any
fontSize: any
fontFamily: any
}): string
export function nextTick(fn: any, ctx: any): () => void
export function checkNodeOuter(
mindMap: any,
node: any
): {
isOuter: boolean
offsetLeft: number
offsetTop: number
}
export function getTextFromHtml(html: any): any
export function readBlob(blob: any): Promise<any>
export function nodeToHTML(node: any): any
export function getImageSize(src: any): Promise<any>
export function createUid(): any
export function loadImage(imgFile: any): Promise<any>
export function removeHTMLEntities(str: any): any
export function getType(data: any): any
export function isUndef(data: any): boolean
export function removeHtmlStyle(html: any): any
export function addHtmlStyle(html: any, tag: any, style: any): any
export function checkIsRichText(str: any): boolean
export function replaceHtmlText(
html: any,
searchText: any,
replaceText: any
): any
export function isWhite(color: any): boolean
export function isTransparent(color: any): boolean
export function getVisibleColorFromTheme(themeConfig: any): any
export function nodeRichTextToTextWithWrap(html: any): string
export function textToNodeRichTextWithWrap(html: any): string
export function isMobile(): boolean
export function getObjectChangedProps(oldObject: any, newObject: any): {}
export function checkIsNodeStyleDataKey(key: any): boolean
export function walk(root: any, parent: any, beforeCallback: any, afterCallback: any, isRoot: any, layerIndex?: number, index?: number): void;
export function bfsWalk(root: any, callback: any): void;
export function resizeImgSizeByOriginRatio(width: any, height: any, newWidth: any, newHeight: any): any[];
export function resizeImgSize(width: any, height: any, maxWidth: any, maxHeight: any): any[];
export function resizeImg(imgUrl: any, maxWidth: any, maxHeight: any): Promise<any>;
export function getStrWithBrFromHtml(str: any): any;
export function simpleDeepClone(data: any): any;
export function copyRenderTree(tree: any, root: any, removeActiveState?: boolean): any;
export function copyNodeTree(tree: any, root: any, removeActiveState?: boolean, keepId?: boolean): any;
export function imgToDataUrl(src: any): Promise<any>;
export function parseDataUrl(data: any): any;
export function downloadFile(file: any, fileName: any): void;
export function throttle(fn: any, time: number, ctx: any): (...args: any[]) => void;
export function asyncRun(taskList: any, callback?: () => void): void;
export function degToRad(deg: any): number;
export function camelCaseToHyphen(str: any): any;
export function measureText(text: any, { italic, bold, fontSize, fontFamily }: {
italic: any;
bold: any;
fontSize: any;
fontFamily: any;
}): {
width: any;
height: any;
};
export function joinFontStr({ italic, bold, fontSize, fontFamily }: {
italic: any;
bold: any;
fontSize: any;
fontFamily: any;
}): string;
export function nextTick(fn: any, ctx: any): () => void;
export function checkNodeOuter(mindMap: any, node: any): {
isOuter: boolean;
offsetLeft: number;
offsetTop: number;
};
export function getTextFromHtml(html: any): any;
export function readBlob(blob: any): Promise<any>;
export function nodeToHTML(node: any): any;
export function getImageSize(src: any): Promise<any>;
export function createUid(): any;
export function loadImage(imgFile: any): Promise<any>;
export function removeHTMLEntities(str: any): any;
export function getType(data: any): any;
export function isUndef(data: any): boolean;
export function removeHtmlStyle(html: any): any;
export function addHtmlStyle(html: any, tag: any, style: any): any;
export function checkIsRichText(str: any): boolean;
export function replaceHtmlText(html: any, searchText: any, replaceText: any): any;
export function isWhite(color: any): boolean;
export function isTransparent(color: any): boolean;
export function getVisibleColorFromTheme(themeConfig: any): any;
export function nodeRichTextToTextWithWrap(html: any): string;
export function textToNodeRichTextWithWrap(html: any): string;
export function isMobile(): boolean;
export function getObjectChangedProps(oldObject: any, newObject: any): {};
export function checkIsNodeStyleDataKey(key: any): boolean;
export function mergerIconList(list: any): any;
export function getTopAncestorsFomNodeList(list: any): any[];
export function checkTwoRectIsOverlap(minx1: any, maxx1: any, miny1: any, maxy1: any, minx2: any, maxx2: any, miny2: any, maxy2: any): boolean;
export function focusInput(el: any): void;
export function selectAllInput(el: any): void;
export function addDataToAppointNodes(appointNodes: any, data?: {}): any;
export function createUidForAppointNodes(appointNodes: any): any;
export function formatDataToArray(data: any): any[];
export function getNodeIndex(node: any): any;
export function generateColorByContent(str: any): string;
export function htmlEscape(str: any): any;

View File

@@ -0,0 +1,23 @@
/**
* @description 为了保证相同的内容每次生成的随机数都是一样的我们可以使用一个伪随机数生成器PRNG并使用内容的哈希值作为种子。以下是一个使用Mersenne Twister算法的PRNG的实现
*
* @param {*} seed
*/
export default function MersenneTwister(seed: any): void;
export default class MersenneTwister {
/**
* @description 为了保证相同的内容每次生成的随机数都是一样的我们可以使用一个伪随机数生成器PRNG并使用内容的哈希值作为种子。以下是一个使用Mersenne Twister算法的PRNG的实现
*
* @param {*} seed
*/
constructor(seed: any);
N: number;
M: number;
MATRIX_A: number;
UPPER_MASK: number;
LOWER_MASK: number;
mt: any[];
mti: number;
init_genrand(s: any): void;
genrand_int32(): number;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
src: url('iconfont.woff2?t=1691822758372') format('woff2'),
url('iconfont.woff?t=1691822758372') format('woff'),
url('iconfont.ttf?t=1691822758372') format('truetype');
src: url('iconfont.woff2?t=1695365666344') format('woff2'),
url('iconfont.woff?t=1695365666344') format('woff'),
url('iconfont.ttf?t=1695365666344') format('truetype');
}
.iconfont {
@@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
.icongongshi:before {
content: "\e617";
}
.icontouming:before {
content: "\e60c";
}

View File

@@ -1,60 +1,83 @@
// 布局结构图片映射
export const layoutImgMap = {
logicalStructure: require('../assets/img/structures/logicalStructure.png'),
mindMap: require('../assets/img/structures/mindMap.png'),
organizationStructure: require('../assets/img/structures/organizationStructure.png'),
catalogOrganization: require('../assets/img/structures/catalogOrganization.png'),
timeline: require('../assets/img/structures/timeline.png'),
timeline2: require('../assets/img/structures/timeline2.png'),
fishbone: require('../assets/img/structures/fishbone.png'),
verticalTimeline: require('../assets/img/structures/verticalTimeline.png'),
logicalStructure: require('../assets/img/structures/logicalStructure.png'),
mindMap: require('../assets/img/structures/mindMap.png'),
organizationStructure: require('../assets/img/structures/organizationStructure.png'),
catalogOrganization: require('../assets/img/structures/catalogOrganization.png'),
timeline: require('../assets/img/structures/timeline.png'),
timeline2: require('../assets/img/structures/timeline2.png'),
fishbone: require('../assets/img/structures/fishbone.png'),
verticalTimeline: require('../assets/img/structures/verticalTimeline.png')
}
// 主题图片映射
export const themeMap = {
default: require('../assets/img/themes/default.jpg'),
classic: require('../assets/img/themes/classic.jpg'),
minions: require('../assets/img/themes/minions.jpg'),
pinkGrape: require('../assets/img/themes/pinkGrape.jpg'),
mint: require('../assets/img/themes/mint.jpg'),
gold: require('../assets/img/themes/gold.jpg'),
vitalityOrange: require('../assets/img/themes/vitalityOrange.jpg'),
greenLeaf: require('../assets/img/themes/greenLeaf.jpg'),
dark2: require('../assets/img/themes/dark2.jpg'),
skyGreen: require('../assets/img/themes/skyGreen.jpg'),
classic2: require('../assets/img/themes/classic2.jpg'),
classic3: require('../assets/img/themes/classic3.jpg'),
classic4: require('../assets/img/themes/classic4.jpg'),
classicGreen: require('../assets/img/themes/classicGreen.jpg'),
classicBlue: require('../assets/img/themes/classicBlue.jpg'),
blueSky: require('../assets/img/themes/blueSky.jpg'),
brainImpairedPink: require('../assets/img/themes/brainImpairedPink.jpg'),
dark: require('../assets/img/themes/dark.jpg'),
earthYellow: require('../assets/img/themes/earthYellow.jpg'),
freshGreen: require('../assets/img/themes/freshGreen.jpg'),
freshRed: require('../assets/img/themes/freshRed.jpg'),
romanticPurple: require('../assets/img/themes/romanticPurple.jpg'),
simpleBlack: require('../assets/img/themes/simpleBlack.jpg'),
courseGreen: require('../assets/img/themes/courseGreen.jpg'),
coffee: require('../assets/img/themes/coffee.jpg'),
redSpirit: require('../assets/img/themes/redSpirit.jpg'),
blackHumour: require('../assets/img/themes/blackHumour.jpg'),
lateNightOffice: require('../assets/img/themes/lateNightOffice.jpg'),
blackGold: require('../assets/img/themes/blackGold.jpg'),
autumn: require('../assets/img/themes/autumn.jpg'),
avocado: require('../assets/img/themes/avocado.jpg'),
orangeJuice: require('../assets/img/themes/orangeJuice.jpg'),
oreo: require('../assets/img/themes/oreo.jpg'),
shallowSea: require('../assets/img/themes/shallowSea.jpg'),
lemonBubbles: require('../assets/img/themes/lemonBubbles.jpg'),
rose: require('../assets/img/themes/rose.jpg'),
seaBlueLine: require('../assets/img/themes/seaBlueLine.jpg'),
neonLamp: require('../assets/img/themes/neonLamp.jpg'),
darkNightLceBlade: require('../assets/img/themes/darkNightLceBlade.jpg'),
morandi: require('../assets/img/themes/morandi.jpg'),
classic5: require('../assets/img/themes/classic5.jpg'),
dark3: require('../assets/img/themes/dark3.jpg'),
dark4: require('../assets/img/themes/dark4.jpg'),
cactus: require('../assets/img/themes/cactus.jpg'),
default: require('../assets/img/themes/default.jpg'),
classic: require('../assets/img/themes/classic.jpg'),
minions: require('../assets/img/themes/minions.jpg'),
pinkGrape: require('../assets/img/themes/pinkGrape.jpg'),
mint: require('../assets/img/themes/mint.jpg'),
gold: require('../assets/img/themes/gold.jpg'),
vitalityOrange: require('../assets/img/themes/vitalityOrange.jpg'),
greenLeaf: require('../assets/img/themes/greenLeaf.jpg'),
dark2: require('../assets/img/themes/dark2.jpg'),
skyGreen: require('../assets/img/themes/skyGreen.jpg'),
classic2: require('../assets/img/themes/classic2.jpg'),
classic3: require('../assets/img/themes/classic3.jpg'),
classic4: require('../assets/img/themes/classic4.jpg'),
classicGreen: require('../assets/img/themes/classicGreen.jpg'),
classicBlue: require('../assets/img/themes/classicBlue.jpg'),
blueSky: require('../assets/img/themes/blueSky.jpg'),
brainImpairedPink: require('../assets/img/themes/brainImpairedPink.jpg'),
dark: require('../assets/img/themes/dark.jpg'),
earthYellow: require('../assets/img/themes/earthYellow.jpg'),
freshGreen: require('../assets/img/themes/freshGreen.jpg'),
freshRed: require('../assets/img/themes/freshRed.jpg'),
romanticPurple: require('../assets/img/themes/romanticPurple.jpg'),
simpleBlack: require('../assets/img/themes/simpleBlack.jpg'),
courseGreen: require('../assets/img/themes/courseGreen.jpg'),
coffee: require('../assets/img/themes/coffee.jpg'),
redSpirit: require('../assets/img/themes/redSpirit.jpg'),
blackHumour: require('../assets/img/themes/blackHumour.jpg'),
lateNightOffice: require('../assets/img/themes/lateNightOffice.jpg'),
blackGold: require('../assets/img/themes/blackGold.jpg'),
autumn: require('../assets/img/themes/autumn.jpg'),
avocado: require('../assets/img/themes/avocado.jpg'),
orangeJuice: require('../assets/img/themes/orangeJuice.jpg'),
oreo: require('../assets/img/themes/oreo.jpg'),
shallowSea: require('../assets/img/themes/shallowSea.jpg'),
lemonBubbles: require('../assets/img/themes/lemonBubbles.jpg'),
rose: require('../assets/img/themes/rose.jpg'),
seaBlueLine: require('../assets/img/themes/seaBlueLine.jpg'),
neonLamp: require('../assets/img/themes/neonLamp.jpg'),
darkNightLceBlade: require('../assets/img/themes/darkNightLceBlade.jpg'),
morandi: require('../assets/img/themes/morandi.jpg'),
classic5: require('../assets/img/themes/classic5.jpg'),
dark3: require('../assets/img/themes/dark3.jpg'),
dark4: require('../assets/img/themes/dark4.jpg'),
cactus: require('../assets/img/themes/cactus.jpg')
}
// 公式列表
export const formulaList = [
'a^2',
'a_2',
'a^{2+2}',
'a_{i,j}',
'x_2^3',
'\\overbrace{1+2+\\cdots+100}',
'\\sum_{k=1}^N k^2',
'\\lim_{n \\to \\infty}x_n',
'\\int_{-N}^{N} e^x\\, dx',
'\\sqrt{3}',
'\\sqrt[n]{3}',
'\\sin\\theta',
'\\log X',
'\\log_{10}',
'\\log_\\alpha X',
'\\lim_{t\\to n}T',
'\\frac{1}{2}=0.5',
'\\binom{n}{k}',
'\\begin{matrix}x & y \\\\z & v\\end{matrix}',
'\\begin{cases}3x + 5y + z \\\\7x - 2y + 4z \\\\-6x + 3y + 2z\\end{cases}'
]

File diff suppressed because one or more lines are too long

View File

@@ -103,11 +103,13 @@ export default {
markdownFile: 'markdown file',
tips: 'tips: .smm and .json file can be import',
isTransparent: 'Background is transparent',
pngTips: 'tips: Exporting pictures in rich text mode is time-consuming. It is recommended to export to svg format',
pngTips:
'tips: Exporting pictures in rich text mode is time-consuming. It is recommended to export to svg format',
svgTips: 'tips: Exporting pictures in rich text mode is time-consuming',
transformingDomToImages: 'Converting nodes: ',
notifyTitle: 'Info',
notifyMessage: 'If the download is not triggered, check whether it is blocked by the browser',
notifyMessage:
'If the download is not triggered, check whether it is blocked by the browser',
paddingX: 'Padding x',
paddingY: 'Padding y',
useMultiPageExport: 'Export multi page'
@@ -213,15 +215,19 @@ export default {
export: 'Export',
shortcutKey: 'Shortcut key',
associativeLine: 'Associative line',
painter: 'Painter'
painter: 'Painter',
formula: 'Formula'
},
edit: {
newFeatureNoticeTitle: 'New feature reminder',
newFeatureNoticeMessage: 'This update supports node rich text editing, But there are some defects, The most important impact is that the time to export the image is proportional to the number of nodes, Therefore, if you are more dependent on export requirements, you can use【Base style】-【Other config】-【Enable node rich text editing】Set to turn off rich text editing mode.'
newFeatureNoticeMessage:
'This update supports node rich text editing, But there are some defects, The most important impact is that the time to export the image is proportional to the number of nodes, Therefore, if you are more dependent on export requirements, you can use【Base style】-【Other config】-【Enable node rich text editing】Set to turn off rich text editing mode.'
},
mouseAction: {
tip1: 'Current: Left click to drag the canvas, right click to box select nodes',
tip2: 'Current: Left click to box select nodes, right click to drag the canvas',
tip1:
'Current: Left click to drag the canvas, right click to box select nodes',
tip2:
'Current: Left click to box select nodes, right click to drag the canvas'
},
search: {
searchPlaceholder: 'Please enter the search content',
@@ -229,5 +235,16 @@ export default {
replace: 'Replace',
replaceAll: 'Replace all',
cancel: 'Cancel'
},
nodeIconSidebar: {
title: 'Icon/Sticker',
icon: 'Icon',
sticker: 'Sticker'
},
formulaSidebar: {
title: 'Formula',
placeholder: 'Please enter LaText syntax',
confirm: 'Confirm',
common: 'Common formulas'
}
}

View File

@@ -213,15 +213,17 @@ export default {
export: '导出',
shortcutKey: '快捷键',
associativeLine: '关联线',
painter: '格式刷'
painter: '格式刷',
formula: '公式'
},
edit: {
newFeatureNoticeTitle: '新特性提醒',
newFeatureNoticeMessage: '本次更新支持了节点富文本编辑,但是存在一定缺陷,最主要的影响是导出为图片的时间和节点数量成正比,所以对导出需求比较依赖的话可以通过【基础样式】-【其他配置】-【是否开启节点富文本编辑】设置关掉富文本编辑模式。'
newFeatureNoticeMessage:
'本次更新支持了节点富文本编辑,但是存在一定缺陷,最主要的影响是导出为图片的时间和节点数量成正比,所以对导出需求比较依赖的话可以通过【基础样式】-【其他配置】-【是否开启节点富文本编辑】设置关掉富文本编辑模式。'
},
mouseAction: {
tip1: '当前:左键拖动画布,右键框选节点',
tip2: '当前:左键框选节点,右键拖动画布',
tip2: '当前:左键框选节点,右键拖动画布'
},
search: {
searchPlaceholder: '请输入查找内容',
@@ -229,5 +231,16 @@ export default {
replace: '替换',
replaceAll: '全部替换',
cancel: '取消'
},
nodeIconSidebar: {
title: '图标/贴纸',
icon: '图标',
sticker: '贴纸'
},
formulaSidebar: {
title: '公式',
placeholder: '请输入 LaText 语法',
confirm: '完成',
common: '常用公式'
}
}

View File

@@ -35,6 +35,7 @@ let APIList = [
'search',
'painter',
'scrollbar',
'formula',
'xmind',
'markdown',
'utils'

View File

@@ -2,16 +2,24 @@
<div class="headerContainer">
<div class="left">
<div class="title" @click="toIndex">
<img src="../../../assets/img/logo2.png" alt="">
<img src="../../../assets/img/logo2.png" alt="" />
SimpleMindMap
</div>
</div>
<div class="center">
<div class="btn" @click="toIndex">{{ index }}</div>
<div class="btn" @click="toDemo">{{ demoName }}</div>
<div class="btn" @click="toHelp" :class="{ active: docType === 'help' }">
{{ helpDoc }}
</div>
<div class="btn" @click="toDev" :class="{ active: docType === 'doc' }">
{{ devDoc }}
</div>
<el-dropdown
trigger="click"
placement="bottom-start"
@command="handleCommand"
v-if="docType === 'doc'"
>
<span class="translateBtn">
{{ currentLangName }}<i class="el-icon-arrow-down el-icon--right"></i>
@@ -41,6 +49,7 @@ import t from '../i18n'
export default {
data() {
return {
docType: '',
lang: '',
currentLangName: '',
otherLangList: []
@@ -49,7 +58,16 @@ export default {
computed: {
demoName() {
return t('demo', this.lang)
}
},
helpDoc() {
return t('help', this.lang)
},
devDoc() {
return t('dev', this.lang)
},
index() {
return t('index', this.lang)
},
},
watch: {
$route() {
@@ -61,6 +79,12 @@ export default {
},
methods: {
init() {
// 当前文档类型
let docType = /^\/([^\/]+)\//.exec(this.$route.path)
if (docType && docType[1]) {
this.docType = docType[1]
}
// 当前文档语言
let lang = /^\/doc\/([^\/]+)\//.exec(this.$route.path)
if (lang && lang[1]) {
this.lang = lang[1]
@@ -87,6 +111,15 @@ export default {
return `/doc/${path}/`
})
this.$router.push(url)
},
toHelp() {
this.lang = 'zh'
this.$router.replace('/help/zh/')
},
toDev() {
this.$router.replace('/doc/zh/')
}
}
}
@@ -137,6 +170,10 @@ export default {
&:hover {
color: #1ea59a;
}
&.active {
color: #1ea59a;
}
}
.translateBtn {

View File

@@ -1,5 +1,43 @@
# Changelog
## 0.7.2
Fix:
> 1.Fixed the issue of nodes not being selected when the selection area does not include node boundaries when multiple nodes are selected.
>
> 2.Fix the issue of errors when node text is not a string.
>
> 3.Fix the issue of some text disappearing when edited again when there are<>&characters in the text in non rich text mode.
New:
> 1.Supports inserting mathematical formulas.
>
> 2.Supports dragging and moving multiple nodes simultaneously.
>
> 3.Supports copying and cutting multiple nodes simultaneously.
>
> 4.The node label color has been changed to be generated based on the label content, meaning that the same label content will generate the same color.
>
> 5.Optimize the insertion of child nodes: 1. When inserting child nodes into multiple nodes simultaneously, do not enter the editing state; 2. The newly inserted child node automatically enters the active state.
>
> 6.Optimize the insertion of sibling nodes: 1. Support the simultaneous insertion of sibling nodes into multiple nodes; 2. When calling the command to insert sibling nodes on the root node, no child nodes will be created.
>
> 7.Add a command to simultaneously insert multiple peers and multiple child nodes.
>
> 8.Changing the unique identifier of nodes from id to uid mainly affects the associated lines, which may not display properly in previous versions.
>
> 9.Optimize the logic of icon merging and support the expansion of icons under the internal classification of the library.
>
> 10.Associate line: 1. Double click the associate line to enter associate line text editing mode; If the associated line text is the default text, it will not be saved; 3. When there are active nodes, clicking on the associated line can directly activate the associated line.
Demo:
> 1.Fixed an issue where multiple nodes in the Zhixi mind map cannot be pasted when copying.
>
> 2.Add a sidebar for formula editing.
## 0.7.1-fix.2
Fix: 1.Fix the issue of plugin registration method chain call reporting errors.

View File

@@ -1,6 +1,31 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.7.2</h2>
<p>Fix:</p>
<blockquote>
<p>1.Fixed the issue of nodes not being selected when the selection area does not include node boundaries when multiple nodes are selected.</p>
<p>2.Fix the issue of errors when node text is not a string.</p>
<p>3.Fix the issue of some text disappearing when edited again when there are&lt;&gt;&amp;characters in the text in non rich text mode.</p>
</blockquote>
<p>New:</p>
<blockquote>
<p>1.Supports inserting mathematical formulas.</p>
<p>2.Supports dragging and moving multiple nodes simultaneously.</p>
<p>3.Supports copying and cutting multiple nodes simultaneously.</p>
<p>4.The node label color has been changed to be generated based on the label content, meaning that the same label content will generate the same color.</p>
<p>5.Optimize the insertion of child nodes: 1. When inserting child nodes into multiple nodes simultaneously, do not enter the editing state; 2. The newly inserted child node automatically enters the active state.</p>
<p>6.Optimize the insertion of sibling nodes: 1. Support the simultaneous insertion of sibling nodes into multiple nodes; 2. When calling the command to insert sibling nodes on the root node, no child nodes will be created.</p>
<p>7.Add a command to simultaneously insert multiple peers and multiple child nodes.</p>
<p>8.Changing the unique identifier of nodes from id to uid mainly affects the associated lines, which may not display properly in previous versions.</p>
<p>9.Optimize the logic of icon merging and support the expansion of icons under the internal classification of the library.</p>
<p>10.Associate line: 1. Double click the associate line to enter associate line text editing mode; If the associated line text is the default text, it will not be saved; 3. When there are active nodes, clicking on the associated line can directly activate the associated line.</p>
</blockquote>
<p>Demo:</p>
<blockquote>
<p>1.Fixed an issue where multiple nodes in the Zhixi mind map cannot be pasted when copying.</p>
<p>2.Add a sidebar for formula editing.</p>
</blockquote>
<h2>0.7.1-fix.2</h2>
<p>Fix: 1.Fix the issue of plugin registration method chain call reporting errors.</p>
<p>New:</p>

View File

@@ -0,0 +1,82 @@
# Client
This project also provides a client version using [Electron](https://www.electronjs.org/) Development. Supports 'Windows', 'Mac', and 'Linux'.
Currently, the function is relatively simple:
1. Support creating and opening files for editing;
2. Support viewing the list of recently edited files;
3. Support the copying, deletion, and renaming of files;
## Download
> The client version may lag behind the online version. To try new features, please prioritize using the online version.
You can directly download the corresponding client for installation and use, and two download addresses are provided:
Github[releases](https://github.com/wanglin2/mind-map/releases)。
Baidu cloud disk[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
## Development
If necessary, you can also conduct secondary development.
### clone
```bash
git clone https://github.com/wanglin2/mind-map.git
cd mind-map
git checkout electron
```
### Start serve
Execute in the project root directory:
```bash
cd simple-mind-map
npm i
npm link
cd ..
cd web
npm i
npm link simple-mind-map
npm run electron:serve
```
### Packaging client
You need at least two computers, one 'Windows' and one 'Mac'.
Packaging 'Windows' application:
```bash
npm run electron:build-win
```
Packaging 'Mac' application:
```bash
npm run electron:build-mac
```
Packaging 'Linux' application:
```bash
npm run electron:build-linux
```
Packaging all applications:
```bash
npm run electron:build-all
```
Automatically pack according to your computer system:
```bash
npm run electron:build
```

View File

@@ -0,0 +1,71 @@
<template>
<div>
<h1>Client</h1>
<p>This project also provides a client version using <a href="https://www.electronjs.org/">Electron</a> Development. Supports 'Windows', 'Mac', and 'Linux'.</p>
<p>Currently, the function is relatively simple:</p>
<ol>
<li>
<p>Support creating and opening files for editing;</p>
</li>
<li>
<p>Support viewing the list of recently edited files;</p>
</li>
<li>
<p>Support the copying, deletion, and renaming of files;</p>
</li>
</ol>
<h2>Download</h2>
<blockquote>
<p>The client version may lag behind the online version. To try new features, please prioritize using the online version.</p>
</blockquote>
<p>You can directly download the corresponding client for installation and use, and two download addresses are provided:</p>
<p>Github<a href="https://github.com/wanglin2/mind-map/releases">releases</a></p>
<p>Baidu cloud disk<a href="https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3">地址</a></p>
<h2>Development</h2>
<p>If necessary, you can also conduct secondary development.</p>
<h3>clone</h3>
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
<span class="hljs-built_in">cd</span> mind-map
git checkout electron
</code></pre>
<h3>Start serve</h3>
<p>Execute in the project root directory:</p>
<pre class="hljs"><code><span class="hljs-built_in">cd</span> simple-mind-map
npm i
npm link
<span class="hljs-built_in">cd</span> ..
<span class="hljs-built_in">cd</span> web
npm i
npm link simple-mind-map
npm run electron:serve
</code></pre>
<h3>Packaging client</h3>
<p>You need at least two computers, one 'Windows' and one 'Mac'.</p>
<p>Packaging 'Windows' application:</p>
<pre class="hljs"><code>npm run electron:build-win
</code></pre>
<p>Packaging 'Mac' application:</p>
<pre class="hljs"><code>npm run electron:build-mac
</code></pre>
<p>Packaging 'Linux' application:</p>
<pre class="hljs"><code>npm run electron:build-linux
</code></pre>
<p>Packaging all applications:</p>
<pre class="hljs"><code>npm run electron:build-all
</code></pre>
<p>Automatically pack according to your computer system:</p>
<pre class="hljs"><code>npm run electron:build
</code></pre>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@@ -90,6 +90,10 @@ const mindMap = new MindMap({
| deleteNodeActivev0.7.1+ | Boolean | true | Enable the function of automatically activating adjacent nodes or parent nodes after deleting nodes | |
| autoMoveWhenMouseInEdgeOnDragv0.7.1+ | Boolean | true | Whether to enable automatic canvas movement when the mouse moves to the edge of the canvas while dragging nodes | |
| fitv0.7.1-fix.2+ | Boolean | false | Is the first rendering scaled to fit the canvas size | |
| dragMultiNodeRectConfigv0.7.2+ | Object | { width: 40, height: 20, fill: '' } | The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle | |
| dragPlaceholderRectFillv0.7.2+ | String | | The filling color of the schematic rectangle for the new position when dragging nodes. If not transmitted, the default color for the connected line is used | |
| dragOpacityConfigv0.7.2+ | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node | |
| tagsColorMapv0.7.2+ | Object | {} | The color of a custom node label can be transferred to an object, where key is the label content to be assigned a color, and value is the color of the label content. If not transferred internally, a corresponding color will be generated based on the label content | |
### Data structure
@@ -381,7 +385,7 @@ redo. All commands are as follows:
| SELECT_ALL | Select all | |
| BACK | Go back a specified number of steps | step (the number of steps to go back, default is 1) |
| FORWARD | Go forward a specified number of steps | step (the number of steps to go forward, default is 1) |
| INSERT_NODE | Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective | openEditv0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true` 、 appointNodesv0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array、 appointDataOptional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildrenv0.6.14+, Optional, Specify the child nodes of the newly created node, array type |
| INSERT_NODE | Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effectivev0.7.2+Supports simultaneous insertion of sibling nodes into multiple active nodes | openEditv0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true` 、 appointNodesv0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array、 appointDataOptional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildrenv0.6.14+, Optional, Specify the child nodes of the newly created node, array type |
| INSERT_CHILD_NODE | Insert a child node, the active node or appoint node will be the operation node | openEditv0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`)、 appointNodesv0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array、 appointDataOptional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildrenv0.6.14+, Optional, Specify the child nodes of the newly created node, array type |
| UP_NODE | Move node up, the active node will be the operation node. If there are multiple active nodes, only the first one will be effective. Using this command on the root node or the first node in the list will be invalid | |
| DOWN_NODE | Move node down, the active node will be the operation node. If there are multiple active nodes, only the first one will be effective. Using this command on the root node or the last node in the list will be invalid | |
@@ -402,15 +406,18 @@ redo. All commands are as follows:
| SET_NODE_HYPERLINK | Set Node Hyperlink | node (node to set), link (hyperlink address), title (hyperlink name, optional) |
| SET_NODE_NOTE | Set Node Note | node (node to set), note (note text) |
| SET_NODE_TAG | Set Node Tag | node (node to set), tag (string array, built-in color information can be obtained in [constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js)) |
| INSERT_AFTER (v0.1.5+) | Move Node to After Another Node | node (node to move), exist (target node) |
| INSERT_BEFORE (v0.1.5+) | Move Node to Before Another Node | node (node to move), exist (target node) |
| MOVE_NODE_TO (v0.1.5+) | Move a node as a child of another node | node (the node to move), toNode (the target node) |
| INSERT_AFTER (v0.1.5+) | Move Node to After Another Node | node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node) |
| INSERT_BEFORE (v0.1.5+) | Move Node to Before Another Node | node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node) |
| MOVE_NODE_TO (v0.1.5+) | Move a node as a child of another node | node (the node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), toNode (the target node) |
| ADD_GENERALIZATION (v0.2.0+) | Add a node summary | data (the data for the summary, in object format, all numerical fields of the node are supported, default is `{text: 'summary'}`) |
| REMOVE_GENERALIZATION (v0.2.0+) | Remove a node summary | |
| SET_NODE_CUSTOM_POSITION (v0.2.0+) | Set a custom position for a node | node (the node to set), left (custom x coordinate, default is undefined), top (custom y coordinate, default is undefined) |
| RESET_LAYOUT (v0.2.0+) | Arrange layout with one click | |
| SET_NODE_SHAPE (v0.2.4+) | Set the shape of a node | node (the node to set), shape (the shape, all shapes: [Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js)) |
| GO_TARGET_NODEv0.6.7+ | Navigate to a node, and if the node is collapsed, it will automatically expand to that node | nodeNode instance or node uid to locate、callbackv0.6.9+, Callback function after positioning completion |
| INSERT_MULTI_NODEv0.7.2+ | Insert multiple sibling nodes into the specified node at the same time, with the operating node being the currently active node or the specified node | appointNodesOptional, specify nodes, specify multiple nodes to pass an array, nodeListData list of newly inserted nodes, array type |
| INSERT_MULTI_CHILD_NODEv0.7.2+ | Insert multiple child nodes into the specified node simultaneously, with the operation node being the currently active node or the specified node | appointNodesOptional, specify nodes, specify multiple nodes to pass an array, childListData list of newly inserted nodes, array type |
| INSERT_FORMULAv0.7.2+ | Insert mathematical formulas into nodes, operate on the currently active node or specified node | formulaMathematical formula to insert, LaText syntax, appointNodesOptional, specify the node to insert the formula into. Multiple nodes can be passed as arrays, otherwise it defaults to the currently active node |
### setData(data)

View File

@@ -490,6 +490,34 @@
<td>Is the first rendering scaled to fit the canvas size</td>
<td></td>
</tr>
<tr>
<td>dragMultiNodeRectConfigv0.7.2+</td>
<td>Object</td>
<td>{ width: 40, height: 20, fill: '' }</td>
<td>The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle</td>
<td></td>
</tr>
<tr>
<td>dragPlaceholderRectFillv0.7.2+</td>
<td>String</td>
<td></td>
<td>The filling color of the schematic rectangle for the new position when dragging nodes. If not transmitted, the default color for the connected line is used</td>
<td></td>
</tr>
<tr>
<td>dragOpacityConfigv0.7.2+</td>
<td>Object</td>
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
<td>The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node</td>
<td></td>
</tr>
<tr>
<td>tagsColorMapv0.7.2+</td>
<td>Object</td>
<td>{}</td>
<td>The color of a custom node label can be transferred to an object, where key is the label content to be assigned a color, and value is the color of the label content. If not transferred internally, a corresponding color will be generated based on the label content</td>
<td></td>
</tr>
</tbody>
</table>
<h3>Data structure</h3>
@@ -961,7 +989,7 @@ redo. All commands are as follows:</p>
</tr>
<tr>
<td>INSERT_NODE</td>
<td>Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective</td>
<td>Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effectivev0.7.2+Supports simultaneous insertion of sibling nodes into multiple active nodes</td>
<td>openEditv0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is <code>true</code> 、 appointNodesv0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array、 appointDataOptional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> )、 appointChildrenv0.6.14+, Optional, Specify the child nodes of the newly created node, array type</td>
</tr>
<tr>
@@ -1067,17 +1095,17 @@ redo. All commands are as follows:</p>
<tr>
<td>INSERT_AFTER (v0.1.5+)</td>
<td>Move Node to After Another Node</td>
<td>node (node to move), exist (target node)</td>
<td>node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node)</td>
</tr>
<tr>
<td>INSERT_BEFORE (v0.1.5+)</td>
<td>Move Node to Before Another Node</td>
<td>node (node to move), exist (target node)</td>
<td>node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node)</td>
</tr>
<tr>
<td>MOVE_NODE_TO (v0.1.5+)</td>
<td>Move a node as a child of another node</td>
<td>node (the node to move), toNode (the target node)</td>
<td>node (the node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), toNode (the target node)</td>
</tr>
<tr>
<td>ADD_GENERALIZATION (v0.2.0+)</td>
@@ -1109,6 +1137,21 @@ redo. All commands are as follows:</p>
<td>Navigate to a node, and if the node is collapsed, it will automatically expand to that node</td>
<td>nodeNode instance or node uid to locate、callbackv0.6.9+, Callback function after positioning completion</td>
</tr>
<tr>
<td>INSERT_MULTI_NODEv0.7.2+</td>
<td>Insert multiple sibling nodes into the specified node at the same time, with the operating node being the currently active node or the specified node</td>
<td>appointNodesOptional, specify nodes, specify multiple nodes to pass an array, nodeListData list of newly inserted nodes, array type</td>
</tr>
<tr>
<td>INSERT_MULTI_CHILD_NODEv0.7.2+</td>
<td>Insert multiple child nodes into the specified node simultaneously, with the operation node being the currently active node or the specified node</td>
<td>appointNodesOptional, specify nodes, specify multiple nodes to pass an array, childListData list of newly inserted nodes, array type</td>
</tr>
<tr>
<td>INSERT_FORMULAv0.7.2+</td>
<td>Insert mathematical formulas into nodes, operate on the currently active node or specified node</td>
<td>formulaMathematical formula to insert, LaText syntax, appointNodesOptional, specify the node to insert the formula into. Multiple nodes can be passed as arrays, otherwise it defaults to the currently active node</td>
</tr>
</tbody>
</table>
<h3>setData(data)</h3>

View File

@@ -0,0 +1,36 @@
# Formula plugin
> v0.7.2+
> This plugin is only supported in rich text mode, so it needs to be used after registering the RichText plugin
This plugin is used to support inserting formulas into nodes.
## Register
```js
import MindMap from 'simple-mind-map'
import Formula from 'simple-mind-map/src/plugins/Formula.js'
MindMap.usePlugin(Formula)
```
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.formula`.
## Usage
After registering the plugin, you can use the command 'INSERT_FORMULA' to insert the specified formula for the node:
```js
mindMap.execCommand('INSERT_FORMULA', 'a^2')
```
The above command will insert the 'a^2' formula into the currently active node.
If you want to assign a formula to a node or nodes, you can pass the second parameter:
```js
mindMap.execCommand('INSERT_FORMULA', 'a^2', [Node])
```
Pass in the specified node instance through the second parameter.

View File

@@ -0,0 +1,39 @@
<template>
<div>
<h1>Formula plugin</h1>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<blockquote>
<p>This plugin is only supported in rich text mode, so it needs to be used after registering the RichText plugin</p>
</blockquote>
<p>This plugin is used to support inserting formulas into nodes.</p>
<h2>Register</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> Formula <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/plugins/Formula.js&#x27;</span>
MindMap.usePlugin(Formula)
</code></pre>
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.formula</code>.</p>
<h2>Usage</h2>
<p>After registering the plugin, you can use the command 'INSERT_FORMULA' to insert the specified formula for the node:</p>
<pre class="hljs"><code>mindMap.execCommand(<span class="hljs-string">&#x27;INSERT_FORMULA&#x27;</span>, <span class="hljs-string">&#x27;a^2&#x27;</span>)
</code></pre>
<p>The above command will insert the 'a^2' formula into the currently active node.</p>
<p>If you want to assign a formula to a node or nodes, you can pass the second parameter:</p>
<pre class="hljs"><code>mindMap.execCommand(<span class="hljs-string">&#x27;INSERT_FORMULA&#x27;</span>, <span class="hljs-string">&#x27;a^2&#x27;</span>, [Node])
</code></pre>
<p>Pass in the specified node instance through the second parameter.</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@@ -11,12 +11,12 @@
- [x] Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume
- [x] Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures
- [x] Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes
- [x] Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, and summaries
- [x] Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas
- [x] Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM
- [x] Support canvas dragging and scaling
- [x] Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection
- [x] Supoorts to export as `json``png``svg``pdf``markdown``xmind`, support import from `json``xmind``markdown`
- [x] Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, and watermarks
- [x] Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar
- [x] Provide rich configurations to meet various scenarios and usage habits
## Repository Catalog Introduction
@@ -62,6 +62,8 @@ The folder containing the packaged resources for the `web` folder.
[My first Electron application](https://juejin.cn/post/7233012756314701884)
[Explore how to export HTML and SVG as images](https://juejin.cn/post/7276712861514170409)
## Special Note
This project can be used for learning and reference. Please deeply experience whether it can meet your needs when using it for actual projects.
@@ -70,7 +72,7 @@ This project may not have fully tested every function point, so there may be bug
If you have suggestions or find bugs, you can submit [issues](https://github.com/wanglin2/mind-map/issues) here.
The built-in themes and icons in the project come from:
The built-in themes and icons in the project part come from:
[Baidu Mind Map](https://naotu.baidu.com/)
@@ -90,7 +92,7 @@ There are many other online mind mapping products similar to Zhixi, such as [Git
`kityminder-core` is an open source brain mapping tool developed by Baidu. It has powerful functions and good performance, but it is no longer maintained. Therefore, the code is relatively old, and the interface beauty is relatively ordinary. In addition, bugs can only be fixed by yourself, and the functions can only be developed by yourself. It has high requirements for front-end development capabilities.
3.[jsmind](https://github.com/hizzgdev/jsmind)、[Mind-elixir](https://github.com/ssshooter/mind-elixir-core)、[my-mind](https://github.com/ondras/my-mind)、[blink-mind](https://github.com/awehook/blink-mind)、[remind](https://github.com/luvsic3/remind)、[vue3-mindmap](https://github.com/hellowuxin/vue3-mindmap)、[ZMindMap](https://github.com/zyascend/ZMindMap)...
3.[jsmind](https://github.com/hizzgdev/jsmind)、[Mind-elixir](https://github.com/ssshooter/mind-elixir-core)、[my-mind](https://github.com/ondras/my-mind)、[blink-mind](https://github.com/awehook/blink-mind)、[remind](https://github.com/luvsic3/remind)、[vue3-mindmap](https://github.com/hellowuxin/vue3-mindmap)、[ZMindMap](https://github.com/zyascend/ZMindMap)、[mindmaptree](https://github.com/RockyRen/mindmaptree)...
These open-source mind maps are also good, each with its own characteristics, but they also have certain drawbacks, such as stopping updates, average interface aesthetics, less functionality, relying on a certain framework, and so on.
@@ -204,4 +206,8 @@ Open source is not easy. If this project is helpful to you, you can invite the a
<img src="../../../../assets/avatar/敏.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>敏</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>沐风牧草</p>
</div>
</div>

View File

@@ -8,16 +8,16 @@
</blockquote>
<h2>Features</h2>
<ul>
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, and summaries</label></li>
<li><input type="checkbox" id="checkbox34" checked="true" /><label for="checkbox34">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
<li><input type="checkbox" id="checkbox35" checked="true" /><label for="checkbox35">Support canvas dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox36" checked="true" /><label for="checkbox36">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
<li><input type="checkbox" id="checkbox37" checked="true" /><label for="checkbox37">Supoorts to export as </label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code>, support import from <code>json</code><code>xmind</code><code>markdown</code></li>
<li><input type="checkbox" id="checkbox38" checked="true" /><label for="checkbox38">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, and watermarks</label></li>
<li><input type="checkbox" id="checkbox39" checked="true" /><label for="checkbox39">Provide rich configurations to meet various scenarios and usage habits</label></li>
<li><input type="checkbox" id="checkbox15" checked="true" /><label for="checkbox15">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Support canvas dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Supoorts to export as </label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code>, support import from <code>json</code><code>xmind</code><code>markdown</code></li>
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Provide rich configurations to meet various scenarios and usage habits</label></li>
</ul>
<h2>Repository Catalog Introduction</h2>
<p>1.<code>simple-mind-map</code></p>
@@ -27,16 +27,16 @@ frameworks such as Vue and React, or without a framework.</p>
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
<ul>
<li><input type="checkbox" id="checkbox40" checked="true" /><label for="checkbox40">Toolbar, which supports inserting and deleting nodes, and editing node</label>
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Toolbar, which supports inserting and deleting nodes, and editing node</label>
images, icons, hyperlinks, notes, tags, and summaries</li>
<li><input type="checkbox" id="checkbox41" checked="true" /><label for="checkbox41">Sidebar, with panels for basic style settings, node style settings,</label>
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Sidebar, with panels for basic style settings, node style settings,</label>
outline, theme selection, and structure selection</li>
<li><input type="checkbox" id="checkbox42" checked="true" /><label for="checkbox42">Import and export functionality; data is saved in the browser's local</label>
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Import and export functionality; data is saved in the browser's local</label>
storage by default, but it also supports creating, opening, and editing
local files on the computer directly</li>
<li><input type="checkbox" id="checkbox43" checked="true" /><label for="checkbox43">Right-click menu, which supports operations such as expanding, collapsing,</label>
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Right-click menu, which supports operations such as expanding, collapsing,</label>
and organizing layout</li>
<li><input type="checkbox" id="checkbox44" checked="true" /><label for="checkbox44">Bottom bar, which supports node and word count statistics, switching</label>
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Bottom bar, which supports node and word count statistics, switching</label>
between edit and read-only modes, zooming in and out, and switching to
full screen, support mini map</li>
</ul>
@@ -49,11 +49,12 @@ full screen, support mini map</li>
<p><a href="https://juejin.cn/post/7199666255883927612">When you press the direction key, how does the TV find the next focus</a></p>
<p><a href="https://juejin.cn/post/7204854015463538744">How to simulate the background image style of css in canvas</a></p>
<p><a href="https://juejin.cn/post/7233012756314701884">My first Electron application</a></p>
<p><a href="https://juejin.cn/post/7276712861514170409">Explore how to export HTML and SVG as images</a></p>
<h2>Special Note</h2>
<p>This project can be used for learning and reference. Please deeply experience whether it can meet your needs when using it for actual projects.</p>
<p>This project may not have fully tested every function point, so there may be bugs. In addition, when the number of nodes is very large, there may be some performance issues. Because everyone can accept different levels of congestion, you can test the maximum number of nodes yourself.</p>
<p>If you have suggestions or find bugs, you can submit <a href="https://github.com/wanglin2/mind-map/issues">issues</a> here.</p>
<p>The built-in themes and icons in the project come from:</p>
<p>The built-in themes and icons in the project part come from:</p>
<p><a href="https://naotu.baidu.com/">Baidu Mind Map</a></p>
<p><a href="https://www.zhixi.com/">Zhixi Mind Map</a></p>
<p>Respect the copyright, and do not use the theme and icons directly for commercial projects.</p>
@@ -63,7 +64,7 @@ full screen, support mini map</li>
<p>There are many other online mind mapping products similar to Zhixi, such as <a href="https://gitmind.cn/">GitMind</a><a href="http://www.mindline.cn/">MindLine</a><a href="https://www.mindmeister.com/zh">MinMeister</a><a href="https://mubu.com/">Mubu</a> and so on, There are many searches on search engines, but these products either require fees or are developed by small companies, and their stability and sustainability cannot be guaranteed. Of course, the most crucial thing is that they are not open-source.</p>
<p>2.<a href="https://github.com/fex-team/kityminder-core">kityminder-core</a></p>
<p><code>kityminder-core</code> is an open source brain mapping tool developed by Baidu. It has powerful functions and good performance, but it is no longer maintained. Therefore, the code is relatively old, and the interface beauty is relatively ordinary. In addition, bugs can only be fixed by yourself, and the functions can only be developed by yourself. It has high requirements for front-end development capabilities.</p>
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a><a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a><a href="https://github.com/ondras/my-mind">my-mind</a><a href="https://github.com/awehook/blink-mind">blink-mind</a><a href="https://github.com/luvsic3/remind">remind</a><a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a><a href="https://github.com/zyascend/ZMindMap">ZMindMap</a>...</p>
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a><a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a><a href="https://github.com/ondras/my-mind">my-mind</a><a href="https://github.com/awehook/blink-mind">blink-mind</a><a href="https://github.com/luvsic3/remind">remind</a><a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a><a href="https://github.com/zyascend/ZMindMap">ZMindMap</a><a href="https://github.com/RockyRen/mindmaptree">mindmaptree</a>...</p>
<p>These open-source mind maps are also good, each with its own characteristics, but they also have certain drawbacks, such as stopping updates, average interface aesthetics, less functionality, relying on a certain framework, and so on.</p>
<p>In summary, in open-source mind maps, it is difficult to find a better choice than <code>simple-mind-map</code>. Of course, <code>simple-mind-map</code> is far from being the best, and it also has many shortcomings, as you saw in the previous [special note]. However, <code>simple-mind-map</code> has always been in a fast iteration process, and we welcome you to join and improve it together.</p>
<h2>Browser Compatibility</h2>
@@ -163,6 +164,10 @@ full screen, support mini map</li>
<img src="../../../../assets/avatar/敏.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p></p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>沐风牧草</p>
</div>
</div>
</div>
</template>

View File

@@ -56,6 +56,26 @@ Whether the node is currently being dragged
## Methods
### setOpacity(val)
> v0.7.2+
- `val`: Opacity value0-1
Set node transparency, including connecting lines and child nodes.
### hideChildren()
> v0.7.2+
Hide subordinate nodes.
### showChildren()
> v0.7.2+
Display subordinate nodes.
### hasCustomStyle()
> v0.6.2+

View File

@@ -31,6 +31,24 @@
</blockquote>
<p>Whether the node is currently being dragged</p>
<h2>Methods</h2>
<h3>setOpacity(val)</h3>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>val</code>: Opacity value0-1</li>
</ul>
<p>Set node transparency, including connecting lines and child nodes.</p>
<h3>hideChildren()</h3>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<p>Hide subordinate nodes.</p>
<h3>showChildren()</h3>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<p>Display subordinate nodes.</p>
<h3>hasCustomStyle()</h3>
<blockquote>
<p>v0.6.2+</p>

View File

@@ -1,4 +1,12 @@
# Participate in translation
# Contribute
## Participate in development
If you want to contribute code, you can 'fork' this project and switch to the 'feature' branch for development. After development and testing, you can submit the 'pr' to the 'feature' branch of this project. When submitting, please try to submit functional files as much as possible. Do not submit unnecessary files.
Before development, it is best to create a new 'issue' to describe the new features you want to add. We can have sufficient communication first, and when submitting a 'pr', please provide a detailed description of the features you are developing.
## Participate in translation
> Thanks for the first version English translation provided by [Emircan ERKUL](https://github.com/emircanerkul).
>

View File

@@ -1,6 +1,10 @@
<template>
<div>
<h1>Participate in translation</h1>
<h1>Contribute</h1>
<h2>Participate in development</h2>
<p>If you want to contribute code, you can 'fork' this project and switch to the 'feature' branch for development. After development and testing, you can submit the 'pr' to the 'feature' branch of this project. When submitting, please try to submit functional files as much as possible. Do not submit unnecessary files.</p>
<p>Before development, it is best to create a new 'issue' to describe the new features you want to add. We can have sufficient communication first, and when submitting a 'pr', please provide a detailed description of the features you are developing.</p>
<h2>Participate in translation</h2>
<blockquote>
<p>Thanks for the first version English translation provided by <a href="https://github.com/emircanerkul">Emircan ERKUL</a>.</p>
<p>Due to limited energy, most translations currently use machine translation, so accuracy is inevitably problematic.</p>

View File

@@ -250,6 +250,107 @@ Convert the wrapped text of `<br>` into node rich text content in the form of `<
Determine if it is a mobile environment.
#### getTopAncestorsFomNodeList(list)
> v0.7.2+
- `list`: Arrray, Node instance list.
Find the top-level node list from the node instance list.
#### checkTwoRectIsOverlap(minx1, maxx1, miny1, maxy1, minx2, maxx2, miny2, maxy2)
> v0.7.2+
The parameter is the position of two rectangles.
Determine if two rectangles overlap.
#### focusInput(el)
> v0.7.2+
- `el`: DOM nodes, elements that can be focused, typically input box elements.
Focus on the specified input box.
#### selectAllInput(el)
> v0.7.2+
- `el`: DOM nodes, elements that can be focused, typically input box elements.
Focus and select all specified input boxes.
#### addDataToAppointNodes(appointNodes, data = {})
> v0.7.2+
- `appointNodes`Node instance list, array type.
- `data`The data to be attached to all nodes in the specified node instance list tree.
Adding additional data to the specified node list tree data will modify the original data.
#### createUidForAppointNodes(appointNodes)
> v0.7.2+
- `appointNodes`Node instance list, array type.
Adding a uid to the specified node list tree data (if the uid does not exist) will modify the original data.
#### getNodeIndex(node)
> v0.7.2+
- `node`Node instance.
Gets the position index of a node within its peers.
#### mergerIconList(list)
> v0.7.2+
- `list`The array of node icons to be merged into the library.
```js
// const data = [
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },
// { type: 'priority', name: '优先级图标', list: [{ name: '2', icon: 'c' }, { name: 3, icon: 'd' }] },
// ];
// mergerIconList(data) result:
// [
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'c' }, { name: 3, icon: 'd' }] },
// ]
```
Merge icon arrays.
#### htmlEscape(str)
> v0.7.2+
- `str`String.
Escape the incoming string, currently escaping the following three characters:
```
& -> &amp;
< -> &lt;
> -> &gt;
```
#### generateColorByContent(str)
> v0.7.2+
- `str`String.
Generate colors based on incoming content, and the same content will generate the same color.
## Simulate CSS background in Canvas
Import:

View File

@@ -179,6 +179,104 @@ and copying the <code>data</code> of the data object, example:</p>
<p>v0.6.13+</p>
</blockquote>
<p>Determine if it is a mobile environment.</p>
<h4>getTopAncestorsFomNodeList(list)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>list</code>: Arrray, Node instance list.</li>
</ul>
<p>Find the top-level node list from the node instance list.</p>
<h4>checkTwoRectIsOverlap(minx1, maxx1, miny1, maxy1, minx2, maxx2, miny2, maxy2)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<p>The parameter is the position of two rectangles.</p>
<p>Determine if two rectangles overlap.</p>
<h4>focusInput(el)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>el</code>: DOM nodes, elements that can be focused, typically input box elements.</li>
</ul>
<p>Focus on the specified input box.</p>
<h4>selectAllInput(el)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>el</code>: DOM nodes, elements that can be focused, typically input box elements.</li>
</ul>
<p>Focus and select all specified input boxes.</p>
<h4>addDataToAppointNodes(appointNodes, data = {})</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li>
<p><code>appointNodes</code>Node instance list, array type.</p>
</li>
<li>
<p><code>data</code>The data to be attached to all nodes in the specified node instance list tree.</p>
</li>
</ul>
<p>Adding additional data to the specified node list tree data will modify the original data.</p>
<h4>createUidForAppointNodes(appointNodes)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>appointNodes</code>Node instance list, array type.</li>
</ul>
<p>Adding a uid to the specified node list tree data (if the uid does not exist) will modify the original data.</p>
<h4>getNodeIndex(node)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>node</code>Node instance.</li>
</ul>
<p>Gets the position index of a node within its peers.</p>
<h4>mergerIconList(list)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>list</code>The array of node icons to be merged into the library.</li>
</ul>
<pre class="hljs"><code><span class="hljs-comment">// const data = [</span>
<span class="hljs-comment">// { type: &#x27;priority&#x27;, name: &#x27;优先级图标&#x27;, list: [{ name: &#x27;1&#x27;, icon: &#x27;a&#x27; }, { name: 2, icon: &#x27;b&#x27; }] },</span>
<span class="hljs-comment">// { type: &#x27;priority&#x27;, name: &#x27;优先级图标&#x27;, list: [{ name: &#x27;2&#x27;, icon: &#x27;c&#x27; }, { name: 3, icon: &#x27;d&#x27; }] },</span>
<span class="hljs-comment">// ];</span>
<span class="hljs-comment">// mergerIconList(data) result:</span>
<span class="hljs-comment">// [</span>
<span class="hljs-comment">// { type: &#x27;priority&#x27;, name: &#x27;优先级图标&#x27;, list: [{ name: &#x27;1&#x27;, icon: &#x27;a&#x27; }, { name: 2, icon: &#x27;c&#x27; }, { name: 3, icon: &#x27;d&#x27; }] },</span>
<span class="hljs-comment">// ]</span>
</code></pre>
<p>Merge icon arrays.</p>
<h4>htmlEscape(str)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>str</code>String.</li>
</ul>
<p>Escape the incoming string, currently escaping the following three characters:</p>
<pre class="hljs"><code>&amp; -&gt; &amp;amp;
&lt; -&gt; &amp;lt;
&gt; -&gt; &amp;gt;
</code></pre>
<h4>generateColorByContent(str)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>str</code>String.</li>
</ul>
<p>Generate colors based on incoming content, and the same content will generate the same color.</p>
<h2>Simulate CSS background in Canvas</h2>
<p>Import:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/utils/simulateCSSBackgroundInCanvas&#x27;</span>

View File

@@ -6,7 +6,19 @@ const data = {
demo: {
zh: '在线示例',
en: 'Online Demo'
}
},
help: {
zh: '帮助文档',
en: 'Help doc'
},
dev: {
zh: '开发文档',
en: 'Dev doc'
},
index: {
zh: '首页',
en: 'Home'
},
}
const t = (str, lang) => {

View File

@@ -43,7 +43,7 @@ export default [
{ path: 'richText', title: 'RichText插件' },
{ path: 'select', title: 'Select 插件 ' },
{ path: 'start', title: '开始' },
{ path: 'translate', title: '参与翻译' },
{ path: 'translate', title: '贡献' },
{ path: 'utils', title: '内置工具方法' },
{ path: 'view', title: 'View实例' },
{ path: 'watermark', title: 'Watermark插件' },
@@ -56,6 +56,7 @@ export default [
{ path: 'painter', title: 'Painter插件' },
{ path: 'painter', title: 'Painter插件' },
{ path: 'scrollbar', title: 'Scrollbar插件' },
{ path: 'formula', title: 'Formula插件' },
{ path: 'help1', title: '概要/关联线' },
{ path: 'help2', title: '客户端' },
{ path: 'help3', title: '打开预览在线文件' },
@@ -83,7 +84,7 @@ export default [
{ path: 'richText', title: 'RichText plugin' },
{ path: 'select', title: 'Select plugin' },
{ path: 'start', title: 'Start' },
{ path: 'translate', title: 'Participate in translation' },
{ path: 'translate', title: 'Contribute' },
{ path: 'utils', title: 'Utility Methods' },
{ path: 'view', title: 'View instance' },
{ path: 'watermark', title: 'Watermark plugin' },
@@ -93,7 +94,9 @@ export default [
{ path: 'nodeImgAdjust', title: 'NodeImgAdjust plugin' },
{ path: 'search', title: 'Search plugin' },
{ path: 'painter', title: 'Painter plugin' },
{ path: 'scrollbar', title: 'Scrollbar plugin' }
{ path: 'scrollbar', title: 'Scrollbar plugin' },
{ path: 'formula', title: 'Formula plugin' },
{ path: 'client', title: 'Client' }
]
}
]

View File

@@ -1,5 +1,43 @@
# Changelog
## 0.7.2
修复:
> 1.修复多选节点时选区未包含节点边界时节点不会被选中的问题。
>
> 2.修复节点文本不为字符串时报错的问题。
>
> 3.修复非富文本模式下文本中存在<>&字符时再次编辑时部分文本会消失的问题。
新增:
> 1.支持插入数学公式。
>
> 2.支持同时拖拽移动多个节点。
>
> 3.支持同时复制、剪切多个节点。
>
> 4.节点标签颜色改为根据标签内容生成,即同样的标签内容会生成相同的颜色。
>
> 5.优化子节点的插入1.同时对多个节点插入子节点时不进入编辑状态2.新插入的子节点自动进入激活状态。
>
> 6.优化兄弟节点的插入1.支持同时对多个节点插入兄弟节点2.对根节点调用插入兄弟节点的命令时不再创建子节点。
>
> 7.新增同时插入多个同级节点、多个子节点的命令。
>
> 8.将节点唯一标识由id全部改为uid主要影响关联线之前版本的关联线可能无法正常显示。
>
> 9.优化图标合并逻辑,支持扩展库内部分类下的图标。
>
> 10.关联线1.双击关联线进入关联线文本编辑模式2.关联线文本为默认文本的话不保存3.存在激活节点时点击关联线可直接激活关联线。
Demo
> 1.修复复制知犀思维导图多个节点时无法粘贴的问题。
>
> 2.新增公式编辑的侧边栏。
## 0.7.1-fix.2
修复1.修复插件注册方法链式调用报错的问题。

View File

@@ -1,6 +1,31 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.7.2</h2>
<p>修复</p>
<blockquote>
<p>1.修复多选节点时选区未包含节点边界时节点不会被选中的问题</p>
<p>2.修复节点文本不为字符串时报错的问题</p>
<p>3.修复非富文本模式下文本中存在&lt;&gt;&amp;字符时再次编辑时部分文本会消失的问题</p>
</blockquote>
<p>新增</p>
<blockquote>
<p>1.支持插入数学公式</p>
<p>2.支持同时拖拽移动多个节点</p>
<p>3.支持同时复制剪切多个节点</p>
<p>4.节点标签颜色改为根据标签内容生成即同样的标签内容会生成相同的颜色</p>
<p>5.优化子节点的插入1.同时对多个节点插入子节点时不进入编辑状态2.新插入的子节点自动进入激活状态</p>
<p>6.优化兄弟节点的插入1.支持同时对多个节点插入兄弟节点2.对根节点调用插入兄弟节点的命令时不再创建子节点</p>
<p>7.新增同时插入多个同级节点多个子节点的命令</p>
<p>8.将节点唯一标识由id全部改为uid主要影响关联线之前版本的关联线可能无法正常显示</p>
<p>9.优化图标合并逻辑支持扩展库内部分类下的图标</p>
<p>10.关联线1.双击关联线进入关联线文本编辑模式2.关联线文本为默认文本的话不保存3.存在激活节点时点击关联线可直接激活关联线</p>
</blockquote>
<p>Demo</p>
<blockquote>
<p>1.修复复制知犀思维导图多个节点时无法粘贴的问题</p>
<p>2.新增公式编辑的侧边栏</p>
</blockquote>
<h2>0.7.1-fix.2</h2>
<p>修复1.修复插件注册方法链式调用报错的问题</p>
<p>新增</p>

View File

@@ -12,6 +12,8 @@
## 下载
> 客户端版本会落后于在线版本,要尝试新功能请优先使用在线版。
你可以直接下载对应的客户端安装使用,提供了两个下载地址:
Github[releases](https://github.com/wanglin2/mind-map/releases)。

View File

@@ -7,6 +7,9 @@
<p>2.支持查看最近编辑文件列表</p>
<p>3.支持文件的复制删除重命名</p>
<h2>下载</h2>
<blockquote>
<p>客户端版本会落后于在线版本要尝试新功能请优先使用在线版</p>
</blockquote>
<p>你可以直接下载对应的客户端安装使用提供了两个下载地址</p>
<p>Github<a href="https://github.com/wanglin2/mind-map/releases">releases</a></p>
<p>百度云盘<a href="https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3">地址</a></p>

View File

@@ -22,74 +22,78 @@ const mindMap = new MindMap({
## 实例化选项
| 字段名称 | 类型 | 默认值 | 描述 | 是否必填 |
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ | -------- |
| el | Element | | 容器元素必须为DOM元素 | 是 |
| data | Object | {} | 思维导图数据,可参考下方【数据结构】介绍 | |
| layout | String | logicalStructure | 布局类型可选列表logicalStructure逻辑结构图、mindMap思维导图、catalogOrganization目录组织图、organizationStructure组织结构图、timelinev0.5.4+时间轴、timeline2v0.5.4+上下交替型时间轴、fishbonev0.5.4+,鱼骨图) | |
| fishboneDegv0.5.4+ | Number | 45 | 设置鱼骨结构图的斜线角度 | |
| theme | String | default | 主题可选列表default默认、classic脑图经典、minions小黄人、pinkGrape粉红葡萄、mint薄荷、gold金色vip、vitalityOrange活力橙、greenLeaf绿叶、dark2暗色2、skyGreen天清绿、classic2脑图经典2、classic3脑图经典3、classic4脑图经典4v0.2.0+、classicGreen经典绿、classicBlue经典蓝、blueSky天空蓝、brainImpairedPink脑残粉、dark暗色、earthYellow泥土黄、freshGreen清新绿、freshRed清新红、romanticPurple浪漫紫、simpleBlackv0.5.4+简约黑、courseGreenv0.5.4+课程绿、coffeev0.5.4+咖啡、redSpiritv0.5.4+红色精神、blackHumourv0.5.4+黑色幽默、lateNightOfficev0.5.4+深夜办公室、blackGoldv0.5.4+黑金、avocadov.5.10-fix.2+牛油果、autumnv.5.10-fix.2+秋天、orangeJuicev.5.10-fix.2+橙汁) | |
| themeConfig | Object | {} | 主题配置,会和所选择的主题进行合并,可用字段可参考:[default.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js) | |
| scaleRatio | Number | 0.1 | 放大缩小的增量比例 | |
| maxTag | Number | 5 | 节点里最多显示的标签数量,多余的会被丢弃 | |
| exportPadding | Number | 20 | 导出图片时的内边距 | |
| imgTextMargin | Number | 5 | 节点里图片和文字的间距 | |
| textContentMargin | Number | 2 | 节点里各种文字信息的间距,如图标和文字的间距 | |
| selectTranslateStep | Number | 3 | 多选节点时鼠标移动到边缘时的画布移动偏移量 | |
| selectTranslateLimit | Number | 20 | 多选节点时鼠标移动距边缘多少距离时开始偏移 | |
| customNoteContentShowv0.1.6+ | Object | null | 自定义节点备注内容显示Object类型结构为{show: (noteContent, left, top) => {// 你的显示节点备注逻辑 }, hide: () => {// 你的隐藏节点备注逻辑 }} | |
| readonlyv0.1.7+ | Boolean | false | 是否是只读模式 | |
| enableFreeDragv0.2.4+ | Boolean | false | 是否开启节点自由拖拽 | |
| watermarkConfigv0.2.4+ | Object | | 水印配置,详细配置请参考下方表格【水印配置】 | |
| textAutoWrapWidthv0.3.4+ | Number | 500 | 节点内每行文本达到该宽度后自动换行 | |
| customHandleMousewheelv0.4.3+ | Function | null | 自定义鼠标滚轮事件处理,可以传一个函数,回调参数为事件对象 | |
| mousewheelActionv0.4.3+ | String | zoom | 鼠标滚轮的行为,`zoom`(放大缩小)、`move`(上下移动)。如果`customHandleMousewheel`传了自定义函数,这个属性不生效 | |
| mousewheelMoveStepv0.4.3+ | Number | 100 | 当`mousewheelAction`设为`move`时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位`px` | |
| mousewheelZoomActionReversev0.6.5+ | Boolean | false | 当mousewheelAction设为zoom时默认向前滚动是缩小向后滚动是放大如果该属性设为true那么会反过来 | |
| defaultInsertSecondLevelNodeTextv0.4.7+ | String | 二级节点 | 默认插入的二级节点的文字 | |
| defaultInsertBelowSecondLevelNodeTextv0.4.7+ | String | 分支主题 | 默认插入的二级以下节点的文字 | |
| expandBtnStylev0.5.0+ | Object | { color: '#808080', fill: '#fff', fontSize: 13, strokeColor: '#333333' } | 展开收起按钮的颜色fontSize及strokeColor字段为0.7.0+版本新增的,用于设置收起时显示节点数量的文字样式) | |
| expandBtnIconv0.5.0+ | Object | { open: '', close: '' } | 自定义展开收起按钮的图标可以传图标的svg字符串 | |
| expandBtnNumHandlerv0.7.0+ | Function | | 用于自定义收起时显示节点数量的内容接收一个参数代表收起的节点实例需要返回一个数字或字符串代表最终显示的内容比如你可以当数量大于99时显示99+ | |
| isShowExpandNumv0.7.0+ | Boolean | true | 节点收起时是否显示收起的数量 | |
| enableShortcutOnlyWhenMouseInSvgv0.5.1+ | Boolean | true | 是否只有当鼠标在画布内才响应快捷键事件 | |
| enableNodeTransitionMovev0.5.1+v0.6.7+已去除该特性) | Boolean | true | 是否开启节点动画过渡 | |
| nodeTransitionMoveDurationv0.5.1+v0.6.7+已去除该特性) | Number | 300 | 如果开启节点动画过渡可以通过该属性设置过渡的时间单位ms | |
| initRootNodePositionv0.5.3+ | Array | null | 初始根节点的位置,可传一个数组,默认为`['center', 'center']`,代表根节点处于画布中心位置,除了`center`,关键词还可以设置`left``top``right``bottom`,除了可以传关键词,数组的每项还可以传递一个数字,代表具体的像素,可以传递一个百分比字符串,比如`['40%', '60%']`,代表水平位置在画布宽度的`40%`的位置,垂直位置在画布高度的`60%`的位置 | |
| exportPaddingXv0.5.5+ | Number | 10 | 导出png、svg、pdf时的图形水平内边距 | |
| exportPaddingYv0.5.5+ | Number | 10 | 导出png、svg、pdf时的图形垂直内边距 | |
| nodeTextEditZIndexv0.5.5+ | Number | 3000 | 节点文本编辑框元素的z-index | |
| nodeNoteTooltipZIndexv0.5.5+ | Number | 3000 | 节点备注浮层元素的z-index | |
| isEndNodeTextEditOnClickOuterv0.5.5+ | Boolean | true | 是否在点击了画布外的区域时结束节点文本的编辑状态 | |
| maxHistoryCountv0.5.6+ | Number | 1000 | 最大历史记录数 | |
| alwaysShowExpandBtnv0.5.8+ | Boolean | false | 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示 | |
| iconListv0.5.8+ | Array | [] | 扩展节点可插入的图标,数组的每一项为一个对象,对象详细结构请参考下方【图标配置】表格 | |
| maxNodeCacheCountv0.5.10+ | Number | 1000 | 节点最大缓存数量。为了优化性能,内部会维护一个节点缓存池,用来复用节点,通过该属性可以指定池的最大缓存数量 | |
| defaultAssociativeLineTextv0.5.11+ | String | 关联 | 关联线默认文字 | |
| fitPaddingv0.6.0+ | Number | 50 | 思维导图适应画布大小时的内边距单位px | |
| enableCtrlKeyNodeSelectionv0.6.0+ | Boolean | true | 是否开启按住ctrl键多选节点的功能 | |
| useLeftKeySelectionRightKeyDragv0.6.0+ | Boolean | false | 设置为左键多选节点,右键拖动画布 | |
| beforeTextEditv0.6.0+ | Function/null | null | 节点即将进入编辑前的回调方法如果该方法返回true以外的值那么将取消编辑函数可以返回一个值或一个Promise回调参数为节点实例 | |
| isUseCustomNodeContentv0.6.3+ | Boolean | false | 是否自定义节点内容 | |
| customCreateNodeContentv0.6.3+ | Function/null | null | 如果`isUseCustomNodeContent`设为`true`,那么需要使用该选项传入一个方法,接收节点实例`node`为参数(如果要获取该节点的数据,可以通过`node.nodeData.data`需要返回自定义节点内容元素也就是DOM节点如果某个节点不需要自定义那么返回`null`即可 | |
| mouseScaleCenterUseMousePositionv0.6.4-fix.1+ | Boolean | true | 鼠标缩放是否以鼠标当前位置为中心点,否则以画布中心点 | |
| customInnerElsAppendTov0.6.12+ | null/HTMLElement | null | 指定内部一些元素节点文本编辑元素、节点备注显示元素、关联线文本编辑元素、节点图片调整按钮元素添加到的位置默认添加到document.body下 | |
| nodeDragPlaceholderMaxSizev0.6.12+ | Number | 20 | 拖拽元素时,指示元素新位置的块的最大高度 | |
| enableCreateHiddenInputv0.6.13+v0.6.14+版本已去除该特性) | Boolean | true | 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态 | |
| enableAutoEnterTextEditWhenKeydownv0.6.13+ | Boolean | true | 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式 | |
| richTextEditFakeInPlacev0.6.13+ | Boolean | false | 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果 | |
| customHandleClipboardTextv0.6.14+ | Function | null | 自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据如果你想处理其他思维导图的数据比如processon、zhixi等那么可以传递一个函数接受当前剪贴板中的文本为参数返回处理后的数据可以返回两种类型1.返回一个纯文本那么会直接以该文本创建一个子节点2.返回一个节点对象,格式如下:{ simpleMindMap: true, data: { data: { text: '' }, children: [] } }代表是simple-mind-map格式的数据节点数据同simple-mind-map节点数据格式如果你的处理逻辑存在异步逻辑也可以返回一个promise | |
| errorHandlerv0.6.15+ | Function | | 自定义错误处理函数,目前只会抛出一些异步逻辑出错的情况。可以传递一个函数,会接收两个参数,第一个为错误的类型,第二个为错误对象 | |
| disableMouseWheelZoomv0.6.15+ | Boolean | false | 禁止鼠标滚轮缩放你仍旧可以使用api进行缩放 | |
| resetCssv0.6.16+ | String | * { margin: 0; padding: 0; box-sizing: border-box; } | 设置导出图片和svg时针对富文本节点内容也就是嵌入到svg中的html节点的默认样式覆盖如果不覆盖节点内容会发生偏移 | |
| enableDblclickResetv0.6.17+ | Boolean | truev0.7.0+改为false | 开启鼠标双击复位思维导图位置及缩放 | |
| minExportImgCanvasScalev0.7.0+ | Number | 2 | 导出图片和pdf时canvas的缩放倍数该配置会和window.devicePixelRatio值取最大值用于提升图片清晰度 | |
| hoverRectColorv0.7.0+ | String | rgb(94, 200, 248) | 节点鼠标hover和激活时显示的矩形边框颜色hover时会添加0.6的透明度 | |
| hoverRectPaddingv0.7.0+ | Number | 2 | 节点鼠标hover和激活时显示的矩形边框距节点内容的距离 | |
| selectTextOnEnterEditTextv0.7.0+ | Boolean | true | 双击节点进入节点文本编辑时是否默认选中文本,默认只在创建新节点时会选中 | |
| deleteNodeActivev0.7.1+ | Boolean | true | 是否开启删除节点后自动激活节点相邻节点或父节点的功能 | |
| autoMoveWhenMouseInEdgeOnDragv0.7.1+ | Boolean | true | 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动 | |
| fitv0.7.1-fix.2+ | Boolean | false | 首次渲染时是否缩放至适应画布大小 | |
| 字段名称 | 类型 | 默认值 | 描述 |
| -------------------------------- | ------- | ---------------- | ------------------------------------------------------------ |
| el | Element | | 容器元素,必传,必须为DOM元素 |
| data | Object | {} | 思维导图数据,可参考下方【数据结构】介绍 |
| layout | String | logicalStructure | 布局类型可选列表logicalStructure逻辑结构图、mindMap思维导图、catalogOrganization目录组织图、organizationStructure组织结构图、timelinev0.5.4+时间轴、timeline2v0.5.4+上下交替型时间轴、fishbonev0.5.4+,鱼骨图) |
| fishboneDegv0.5.4+ | Number | 45 | 设置鱼骨结构图的斜线角度 |
| theme | String | default | 主题可选列表default默认、classic脑图经典、minions小黄人、pinkGrape粉红葡萄、mint薄荷、gold金色vip、vitalityOrange活力橙、greenLeaf绿叶、dark2暗色2、skyGreen天清绿、classic2脑图经典2、classic3脑图经典3、classic4脑图经典4v0.2.0+、classicGreen经典绿、classicBlue经典蓝、blueSky天空蓝、brainImpairedPink脑残粉、dark暗色、earthYellow泥土黄、freshGreen清新绿、freshRed清新红、romanticPurple浪漫紫、simpleBlackv0.5.4+简约黑、courseGreenv0.5.4+课程绿、coffeev0.5.4+咖啡、redSpiritv0.5.4+红色精神、blackHumourv0.5.4+黑色幽默、lateNightOfficev0.5.4+深夜办公室、blackGoldv0.5.4+黑金、avocadov.5.10-fix.2+牛油果、autumnv.5.10-fix.2+秋天、orangeJuicev.5.10-fix.2+橙汁) |
| themeConfig | Object | {} | 主题配置,会和所选择的主题进行合并,可用字段可参考:[default.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js) |
| scaleRatio | Number | 0.1 | 放大缩小的增量比例 |
| maxTag | Number | 5 | 节点里最多显示的标签数量,多余的会被丢弃 |
| exportPadding | Number | 20 | 导出图片时的内边距 |
| imgTextMargin | Number | 5 | 节点里图片和文字的间距 |
| textContentMargin | Number | 2 | 节点里各种文字信息的间距,如图标和文字的间距 |
| selectTranslateStep | Number | 3 | 多选节点时鼠标移动到边缘时的画布移动偏移量 |
| selectTranslateLimit | Number | 20 | 多选节点时鼠标移动距边缘多少距离时开始偏移 |
| customNoteContentShowv0.1.6+ | Object | null | 自定义节点备注内容显示Object类型结构为{show: (noteContent, left, top) => {// 你的显示节点备注逻辑 }, hide: () => {// 你的隐藏节点备注逻辑 }} |
| readonlyv0.1.7+ | Boolean | false | 是否是只读模式 |
| enableFreeDragv0.2.4+ | Boolean | false | 是否开启节点自由拖拽 |
| watermarkConfigv0.2.4+ | Object | | 水印配置,详细配置请参考下方表格【水印配置】 |
| textAutoWrapWidthv0.3.4+ | Number | 500 | 节点内每行文本达到该宽度后自动换行 |
| customHandleMousewheelv0.4.3+ | Function | null | 自定义鼠标滚轮事件处理,可以传一个函数,回调参数为事件对象 |
| mousewheelActionv0.4.3+ | String | zoom | 鼠标滚轮的行为,`zoom`(放大缩小)、`move`(上下移动)。如果`customHandleMousewheel`传了自定义函数,这个属性不生效 |
| mousewheelMoveStepv0.4.3+ | Number | 100 | 当`mousewheelAction`设为`move`时,可以通过该属性控制鼠标滚动一下视图移动的步长,单位`px` |
| mousewheelZoomActionReversev0.6.5+ | Boolean | false | 当mousewheelAction设为zoom时默认向前滚动是缩小向后滚动是放大如果该属性设为true那么会反过来 |
| defaultInsertSecondLevelNodeTextv0.4.7+ | String | 二级节点 | 默认插入的二级节点的文字 |
| defaultInsertBelowSecondLevelNodeTextv0.4.7+ | String | 分支主题 | 默认插入的二级以下节点的文字 |
| expandBtnStylev0.5.0+ | Object | { color: '#808080', fill: '#fff', fontSize: 13, strokeColor: '#333333' } | 展开收起按钮的颜色fontSize及strokeColor字段为0.7.0+版本新增的,用于设置收起时显示节点数量的文字样式) |
| expandBtnIconv0.5.0+ | Object | { open: '', close: '' } | 自定义展开收起按钮的图标可以传图标的svg字符串 |
| expandBtnNumHandlerv0.7.0+ | Function | | 用于自定义收起时显示节点数量的内容接收一个参数代表收起的节点实例需要返回一个数字或字符串代表最终显示的内容比如你可以当数量大于99时显示99+ |
| isShowExpandNumv0.7.0+ | Boolean | true | 节点收起时是否显示收起的数量 |
| enableShortcutOnlyWhenMouseInSvgv0.5.1+ | Boolean | true | 是否只有当鼠标在画布内才响应快捷键事件 |
| enableNodeTransitionMovev0.5.1+v0.6.7+已去除该特性) | Boolean | true | 是否开启节点动画过渡 |
| nodeTransitionMoveDurationv0.5.1+v0.6.7+已去除该特性) | Number | 300 | 如果开启节点动画过渡可以通过该属性设置过渡的时间单位ms |
| initRootNodePositionv0.5.3+ | Array | null | 初始根节点的位置,可传一个数组,默认为`['center', 'center']`,代表根节点处于画布中心位置,除了`center`,关键词还可以设置`left``top``right``bottom`,除了可以传关键词,数组的每项还可以传递一个数字,代表具体的像素,可以传递一个百分比字符串,比如`['40%', '60%']`,代表水平位置在画布宽度的`40%`的位置,垂直位置在画布高度的`60%`的位置 |
| exportPaddingXv0.5.5+ | Number | 10 | 导出png、svg、pdf时的图形水平内边距 |
| exportPaddingYv0.5.5+ | Number | 10 | 导出png、svg、pdf时的图形垂直内边距 |
| nodeTextEditZIndexv0.5.5+ | Number | 3000 | 节点文本编辑框元素的z-index |
| nodeNoteTooltipZIndexv0.5.5+ | Number | 3000 | 节点备注浮层元素的z-index |
| isEndNodeTextEditOnClickOuterv0.5.5+ | Boolean | true | 是否在点击了画布外的区域时结束节点文本的编辑状态 |
| maxHistoryCountv0.5.6+ | Number | 1000 | 最大历史记录数 |
| alwaysShowExpandBtnv0.5.8+ | Boolean | false | 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示 |
| iconListv0.5.8+ | Array | [] | 扩展节点可插入的图标,数组的每一项为一个对象,对象详细结构请参考下方【图标配置】表格 |
| maxNodeCacheCountv0.5.10+ | Number | 1000 | 节点最大缓存数量。为了优化性能,内部会维护一个节点缓存池,用来复用节点,通过该属性可以指定池的最大缓存数量 |
| defaultAssociativeLineTextv0.5.11+ | String | 关联 | 关联线默认文字 |
| fitPaddingv0.6.0+ | Number | 50 | 思维导图适应画布大小时的内边距单位px |
| enableCtrlKeyNodeSelectionv0.6.0+ | Boolean | true | 是否开启按住ctrl键多选节点的功能 |
| useLeftKeySelectionRightKeyDragv0.6.0+ | Boolean | false | 设置为左键多选节点,右键拖动画布 |
| beforeTextEditv0.6.0+ | Function/null | null | 节点即将进入编辑前的回调方法如果该方法返回true以外的值那么将取消编辑函数可以返回一个值或一个Promise回调参数为节点实例 |
| isUseCustomNodeContentv0.6.3+ | Boolean | false | 是否自定义节点内容 |
| customCreateNodeContentv0.6.3+ | Function/null | null | 如果`isUseCustomNodeContent`设为`true`,那么需要使用该选项传入一个方法,接收节点实例`node`为参数(如果要获取该节点的数据,可以通过`node.nodeData.data`需要返回自定义节点内容元素也就是DOM节点如果某个节点不需要自定义那么返回`null`即可 |
| mouseScaleCenterUseMousePositionv0.6.4-fix.1+ | Boolean | true | 鼠标缩放是否以鼠标当前位置为中心点,否则以画布中心点 |
| customInnerElsAppendTov0.6.12+ | null/HTMLElement | null | 指定内部一些元素节点文本编辑元素、节点备注显示元素、关联线文本编辑元素、节点图片调整按钮元素添加到的位置默认添加到document.body下 |
| nodeDragPlaceholderMaxSizev0.6.12+ | Number | 20 | 拖拽元素时,指示元素新位置的块的最大高度 |
| enableCreateHiddenInputv0.6.13+v0.6.14+版本已去除该特性) | Boolean | true | 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态 |
| enableAutoEnterTextEditWhenKeydownv0.6.13+ | Boolean | true | 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式 |
| richTextEditFakeInPlacev0.6.13+ | Boolean | false | 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果,需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果 |
| customHandleClipboardTextv0.6.14+ | Function | null | 自定义对剪贴板文本的处理。当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据如果你想处理其他思维导图的数据比如processon、zhixi等那么可以传递一个函数接受当前剪贴板中的文本为参数返回处理后的数据可以返回两种类型1.返回一个纯文本那么会直接以该文本创建一个子节点2.返回一个节点对象,格式如下:{ simpleMindMap: true, data: { data: { text: '' }, children: [] } }代表是simple-mind-map格式的数据节点数据同simple-mind-map节点数据格式如果你的处理逻辑存在异步逻辑也可以返回一个promise |
| errorHandlerv0.6.15+ | Function | | 自定义错误处理函数,目前只会抛出一些异步逻辑出错的情况。可以传递一个函数,会接收两个参数,第一个为错误的类型,第二个为错误对象 |
| disableMouseWheelZoomv0.6.15+ | Boolean | false | 禁止鼠标滚轮缩放你仍旧可以使用api进行缩放 |
| resetCssv0.6.16+ | String | * { margin: 0; padding: 0; box-sizing: border-box; } | 设置导出图片和svg时针对富文本节点内容也就是嵌入到svg中的html节点的默认样式覆盖如果不覆盖节点内容会发生偏移 |
| enableDblclickResetv0.6.17+ | Boolean | truev0.7.0+改为false | 开启鼠标双击复位思维导图位置及缩放 |
| minExportImgCanvasScalev0.7.0+ | Number | 2 | 导出图片和pdf时canvas的缩放倍数该配置会和window.devicePixelRatio值取最大值用于提升图片清晰度 |
| hoverRectColorv0.7.0+ | String | rgb(94, 200, 248) | 节点鼠标hover和激活时显示的矩形边框颜色hover时会添加0.6的透明度 |
| hoverRectPaddingv0.7.0+ | Number | 2 | 节点鼠标hover和激活时显示的矩形边框距节点内容的距离 |
| selectTextOnEnterEditTextv0.7.0+ | Boolean | true | 双击节点进入节点文本编辑时是否默认选中文本,默认只在创建新节点时会选中 |
| deleteNodeActivev0.7.1+ | Boolean | true | 是否开启删除节点后自动激活节点相邻节点或父节点的功能 |
| autoMoveWhenMouseInEdgeOnDragv0.7.1+ | Boolean | true | 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动 |
| fitv0.7.1-fix.2+ | Boolean | false | 首次渲染时是否缩放至适应画布大小 |
| dragMultiNodeRectConfigv0.7.2+ | Object | { width: 40, height: 20, fill: '' } | 拖拽多个节点时随鼠标移动的示意矩形的样式配置,传递一个对象,字段含义分别为矩形的宽、高、填充色 |
| dragPlaceholderRectFillv0.7.2+ | String | | 节点拖拽时新位置的示意矩形的填充颜色,如果不传默认使用连线的颜色 |
| dragOpacityConfigv0.7.2+ | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | 节点拖拽时的透明度配置,传递一个对象,字段含义分别为:跟随鼠标移动的克隆节点或矩形的透明度、被拖拽节点的透明度 |
| tagsColorMapv0.7.2+ | Object | {} | 自定义节点标签的颜色可传一个对象key为要指定颜色的标签内容value为该标签内容的颜色如果不传内部会根据标签内容生成对应的颜色 |
### 数据结构
@@ -373,7 +377,7 @@ mindMap.updateConfig({
| SELECT_ALL | 全选 | |
| BACK | 回退指定的步数 | step要回退的步数默认为1 |
| FORWARD | 前进指定的步数 | step要前进的步数默认为1 |
| INSERT_NODE | 插入同级节点,操作节点为当前激活的节点或指定节点,如果有多个激活节点,只会对第一个有效 | openEditv0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodesv0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData可选指定新创建节点的数据比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js))、 appointChildrenv0.6.14+,可选,指定新创建节点的子节点,数组类型) |
| INSERT_NODE | 插入同级节点,操作节点为当前激活的节点或指定节点,如果有多个激活节点,只会对第一个有效v0.7.2+支持对多个激活节点同时插入兄弟节点) | openEditv0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodesv0.4.7+,可选,指定要插入兄弟节点的节点,指定多个节点可以传一个数组)、 appointData可选指定新创建节点的数据比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js))、 appointChildrenv0.6.14+,可选,指定新创建节点的子节点,数组类型) |
| INSERT_CHILD_NODE | 插入子节点,操作节点为当前激活的节点或指定节点 | openEditv0.4.6+,是否激活新插入的节点并进入编辑模式,默认为`true`)、 appointNodesv0.4.7+,可选,指定节点,指定多个节点可以传一个数组)、 appointData可选指定新创建节点的数据比如{text: 'xxx', ...},详细结构可以参考[exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js))、 appointChildrenv0.6.14+,可选,指定新创建节点的子节点,数组类型) |
| UP_NODE | 上移节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的第一个节点使用无效 | |
| DOWN_NODE | 操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的最后一个节点使用无效 | |
@@ -395,15 +399,18 @@ mindMap.updateConfig({
| SET_NODE_HYPERLINK | 设置节点超链接 | node要设置的节点、link超链接地址、title超链接名称可选 |
| SET_NODE_NOTE | 设置节点备注 | node要设置的节点、note备注文字 |
| SET_NODE_TAG | 设置节点标签 | node要设置的节点、tag字符串数组内置颜色信息可在[constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js)里获取到) |
| INSERT_AFTERv0.1.5+ | 将节点移动到另一个节点的后面 | node要移动的节点、 exist目标节点 |
| INSERT_BEFOREv0.1.5+ | 将节点移动到另一个节点的前面 | node要移动的节点、 exist目标节点 |
| MOVE_NODE_TOv0.1.5+ | 移动一个节点作为另一个节点的子节点 | node要移动的节点、 toNode目标节点 |
| INSERT_AFTERv0.1.5+ | 将节点移动到另一个节点的后面 | node要移动的节点v0.7.2+支持传递节点数组实现同时移动多个节点))、 exist目标节点 |
| INSERT_BEFOREv0.1.5+ | 将节点移动到另一个节点的前面v0.7.2+支持传递节点数组实现同时移动多个节点) | node要移动的节点、 exist目标节点 |
| MOVE_NODE_TOv0.1.5+ | 移动节点作为另一个节点的子节点v0.7.2+支持传递节点数组实现同时移动多个节点) | node要移动的节点、 toNode目标节点 |
| ADD_GENERALIZATIONv0.2.0+ | 添加节点概要 | data概要的数据对象格式节点的数字段都支持默认为{text: '概要'} |
| REMOVE_GENERALIZATIONv0.2.0+ | 删除节点概要 | |
| SET_NODE_CUSTOM_POSITIONv0.2.0+ | 设置节点自定义位置 | node要设置的节点、 left自定义的x坐标默认为undefined、 top自定义的y坐标默认为undefined |
| RESET_LAYOUTv0.2.0+ | 一键整理布局 | |
| SET_NODE_SHAPEv0.2.4+ | 设置节点形状 | node要设置的节点、shape形状全部形状[Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js) |
| GO_TARGET_NODEv0.6.7+ | 定位到某个节点,如果该节点被收起,那么会自动展开到该节点 | node要定位到的节点实例或节点uid、callbackv0.6.9+,定位完成后的回调函数) |
| INSERT_MULTI_NODEv0.7.2+ | 给指定的节点同时插入多个同级节点,操作节点为当前激活的节点或指定节点 | appointNodes可选指定节点指定多个节点可以传一个数组, nodeList新插入节点的数据列表数组类型 |
| INSERT_MULTI_CHILD_NODEv0.7.2+ | 给指定的节点同时插入多个子节点,操作节点为当前激活的节点或指定节点 | appointNodes可选指定节点指定多个节点可以传一个数组, childList新插入节点的数据列表数组类型 |
| INSERT_FORMULAv0.7.2+ | 给节点插入数学公式,操作节点为当前激活的节点或指定节点 | formula要插入的数学公式LaText语法, appointNodes可选指定要插入公式的节点多个节点可以传数组否则默认为当前激活的节点 |
### setData(data)

View File

@@ -24,7 +24,6 @@
<th>类型</th>
<th>默认值</th>
<th>描述</th>
<th>是否必填</th>
</tr>
</thead>
<tbody>
@@ -32,463 +31,421 @@
<td>el</td>
<td>Element</td>
<td></td>
<td>容器元素必须为DOM元素</td>
<td></td>
<td>容器元素须为DOM元素</td>
</tr>
<tr>
<td>data</td>
<td>Object</td>
<td>{}</td>
<td>思维导图数据可参考下方数据结构介绍</td>
<td></td>
</tr>
<tr>
<td>layout</td>
<td>String</td>
<td>logicalStructure</td>
<td>布局类型可选列表logicalStructure逻辑结构图mindMap思维导图catalogOrganization目录组织图organizationStructure组织结构图timelinev0.5.4+时间轴timeline2v0.5.4+上下交替型时间轴fishbonev0.5.4+鱼骨图</td>
<td></td>
</tr>
<tr>
<td>fishboneDegv0.5.4+</td>
<td>Number</td>
<td>45</td>
<td>设置鱼骨结构图的斜线角度</td>
<td></td>
</tr>
<tr>
<td>theme</td>
<td>String</td>
<td>default</td>
<td>主题可选列表default默认classic脑图经典minions小黄人pinkGrape粉红葡萄mint薄荷gold金色vipvitalityOrange活力橙greenLeaf绿叶dark2暗色2skyGreen天清绿classic2脑图经典2classic3脑图经典3classic4脑图经典4v0.2.0+classicGreen经典绿classicBlue经典蓝blueSky天空蓝brainImpairedPink脑残粉dark暗色earthYellow泥土黄freshGreen清新绿freshRed清新红romanticPurple浪漫紫simpleBlackv0.5.4+简约黑courseGreenv0.5.4+课程绿coffeev0.5.4+咖啡redSpiritv0.5.4+红色精神blackHumourv0.5.4+黑色幽默lateNightOfficev0.5.4+深夜办公室blackGoldv0.5.4+黑金avocadov.5.10-fix.2+牛油果autumnv.5.10-fix.2+秋天orangeJuicev.5.10-fix.2+橙汁</td>
<td></td>
</tr>
<tr>
<td>themeConfig</td>
<td>Object</td>
<td>{}</td>
<td>主题配置会和所选择的主题进行合并可用字段可参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js">default.js</a></td>
<td></td>
</tr>
<tr>
<td>scaleRatio</td>
<td>Number</td>
<td>0.1</td>
<td>放大缩小的增量比例</td>
<td></td>
</tr>
<tr>
<td>maxTag</td>
<td>Number</td>
<td>5</td>
<td>节点里最多显示的标签数量多余的会被丢弃</td>
<td></td>
</tr>
<tr>
<td>exportPadding</td>
<td>Number</td>
<td>20</td>
<td>导出图片时的内边距</td>
<td></td>
</tr>
<tr>
<td>imgTextMargin</td>
<td>Number</td>
<td>5</td>
<td>节点里图片和文字的间距</td>
<td></td>
</tr>
<tr>
<td>textContentMargin</td>
<td>Number</td>
<td>2</td>
<td>节点里各种文字信息的间距如图标和文字的间距</td>
<td></td>
</tr>
<tr>
<td>selectTranslateStep</td>
<td>Number</td>
<td>3</td>
<td>多选节点时鼠标移动到边缘时的画布移动偏移量</td>
<td></td>
</tr>
<tr>
<td>selectTranslateLimit</td>
<td>Number</td>
<td>20</td>
<td>多选节点时鼠标移动距边缘多少距离时开始偏移</td>
<td></td>
</tr>
<tr>
<td>customNoteContentShowv0.1.6+</td>
<td>Object</td>
<td>null</td>
<td>自定义节点备注内容显示Object类型结构为{show: (noteContent, left, top) =&gt; {// 你的显示节点备注逻辑 }, hide: () =&gt; {// 你的隐藏节点备注逻辑 }}</td>
<td></td>
</tr>
<tr>
<td>readonlyv0.1.7+</td>
<td>Boolean</td>
<td>false</td>
<td>是否是只读模式</td>
<td></td>
</tr>
<tr>
<td>enableFreeDragv0.2.4+</td>
<td>Boolean</td>
<td>false</td>
<td>是否开启节点自由拖拽</td>
<td></td>
</tr>
<tr>
<td>watermarkConfigv0.2.4+</td>
<td>Object</td>
<td></td>
<td>水印配置详细配置请参考下方表格水印配置</td>
<td></td>
</tr>
<tr>
<td>textAutoWrapWidthv0.3.4+</td>
<td>Number</td>
<td>500</td>
<td>节点内每行文本达到该宽度后自动换行</td>
<td></td>
</tr>
<tr>
<td>customHandleMousewheelv0.4.3+</td>
<td>Function</td>
<td>null</td>
<td>自定义鼠标滚轮事件处理可以传一个函数回调参数为事件对象</td>
<td></td>
</tr>
<tr>
<td>mousewheelActionv0.4.3+</td>
<td>String</td>
<td>zoom</td>
<td>鼠标滚轮的行为<code>zoom</code>放大缩小<code>move</code>上下移动如果<code>customHandleMousewheel</code>传了自定义函数这个属性不生效</td>
<td></td>
</tr>
<tr>
<td>mousewheelMoveStepv0.4.3+</td>
<td>Number</td>
<td>100</td>
<td><code>mousewheelAction</code>设为<code>move</code>可以通过该属性控制鼠标滚动一下视图移动的步长单位<code>px</code></td>
<td></td>
</tr>
<tr>
<td>mousewheelZoomActionReversev0.6.5+</td>
<td>Boolean</td>
<td>false</td>
<td>当mousewheelAction设为zoom时默认向前滚动是缩小向后滚动是放大如果该属性设为true那么会反过来</td>
<td></td>
</tr>
<tr>
<td>defaultInsertSecondLevelNodeTextv0.4.7+</td>
<td>String</td>
<td>二级节点</td>
<td>默认插入的二级节点的文字</td>
<td></td>
</tr>
<tr>
<td>defaultInsertBelowSecondLevelNodeTextv0.4.7+</td>
<td>String</td>
<td>分支主题</td>
<td>默认插入的二级以下节点的文字</td>
<td></td>
</tr>
<tr>
<td>expandBtnStylev0.5.0+</td>
<td>Object</td>
<td>{ color: '#808080', fill: '#fff', fontSize: 13, strokeColor: '#333333' }</td>
<td>展开收起按钮的颜色fontSize及strokeColor字段为0.7.0+版本新增的用于设置收起时显示节点数量的文字样式</td>
<td></td>
</tr>
<tr>
<td>expandBtnIconv0.5.0+</td>
<td>Object</td>
<td>{ open: '', close: '' }</td>
<td>自定义展开收起按钮的图标可以传图标的svg字符串</td>
<td></td>
</tr>
<tr>
<td>expandBtnNumHandlerv0.7.0+</td>
<td>Function</td>
<td></td>
<td>用于自定义收起时显示节点数量的内容接收一个参数代表收起的节点实例需要返回一个数字或字符串代表最终显示的内容比如你可以当数量大于99时显示99+</td>
<td></td>
</tr>
<tr>
<td>isShowExpandNumv0.7.0+</td>
<td>Boolean</td>
<td>true</td>
<td>节点收起时是否显示收起的数量</td>
<td></td>
</tr>
<tr>
<td>enableShortcutOnlyWhenMouseInSvgv0.5.1+</td>
<td>Boolean</td>
<td>true</td>
<td>是否只有当鼠标在画布内才响应快捷键事件</td>
<td></td>
</tr>
<tr>
<td>enableNodeTransitionMovev0.5.1+v0.6.7+已去除该特性</td>
<td>Boolean</td>
<td>true</td>
<td>是否开启节点动画过渡</td>
<td></td>
</tr>
<tr>
<td>nodeTransitionMoveDurationv0.5.1+v0.6.7+已去除该特性</td>
<td>Number</td>
<td>300</td>
<td>如果开启节点动画过渡可以通过该属性设置过渡的时间单位ms</td>
<td></td>
</tr>
<tr>
<td>initRootNodePositionv0.5.3+</td>
<td>Array</td>
<td>null</td>
<td>初始根节点的位置可传一个数组默认为<code>['center', 'center']</code>代表根节点处于画布中心位置除了<code>center</code>关键词还可以设置<code>left</code><code>top</code><code>right</code><code>bottom</code>除了可以传关键词数组的每项还可以传递一个数字代表具体的像素可以传递一个百分比字符串比如<code>['40%', '60%']</code>代表水平位置在画布宽度的<code>40%</code>的位置垂直位置在画布高度的<code>60%</code>的位置</td>
<td></td>
</tr>
<tr>
<td>exportPaddingXv0.5.5+</td>
<td>Number</td>
<td>10</td>
<td>导出pngsvgpdf时的图形水平内边距</td>
<td></td>
</tr>
<tr>
<td>exportPaddingYv0.5.5+</td>
<td>Number</td>
<td>10</td>
<td>导出pngsvgpdf时的图形垂直内边距</td>
<td></td>
</tr>
<tr>
<td>nodeTextEditZIndexv0.5.5+</td>
<td>Number</td>
<td>3000</td>
<td>节点文本编辑框元素的z-index</td>
<td></td>
</tr>
<tr>
<td>nodeNoteTooltipZIndexv0.5.5+</td>
<td>Number</td>
<td>3000</td>
<td>节点备注浮层元素的z-index</td>
<td></td>
</tr>
<tr>
<td>isEndNodeTextEditOnClickOuterv0.5.5+</td>
<td>Boolean</td>
<td>true</td>
<td>是否在点击了画布外的区域时结束节点文本的编辑状态</td>
<td></td>
</tr>
<tr>
<td>maxHistoryCountv0.5.6+</td>
<td>Number</td>
<td>1000</td>
<td>最大历史记录数</td>
<td></td>
</tr>
<tr>
<td>alwaysShowExpandBtnv0.5.8+</td>
<td>Boolean</td>
<td>false</td>
<td>是否一直显示节点的展开收起按钮默认为鼠标移上去和激活时才显示</td>
<td></td>
</tr>
<tr>
<td>iconListv0.5.8+</td>
<td>Array</td>
<td>[]</td>
<td>扩展节点可插入的图标数组的每一项为一个对象对象详细结构请参考下方图标配置表格</td>
<td></td>
</tr>
<tr>
<td>maxNodeCacheCountv0.5.10+</td>
<td>Number</td>
<td>1000</td>
<td>节点最大缓存数量为了优化性能内部会维护一个节点缓存池用来复用节点通过该属性可以指定池的最大缓存数量</td>
<td></td>
</tr>
<tr>
<td>defaultAssociativeLineTextv0.5.11+</td>
<td>String</td>
<td>关联</td>
<td>关联线默认文字</td>
<td></td>
</tr>
<tr>
<td>fitPaddingv0.6.0+</td>
<td>Number</td>
<td>50</td>
<td>思维导图适应画布大小时的内边距单位px</td>
<td></td>
</tr>
<tr>
<td>enableCtrlKeyNodeSelectionv0.6.0+</td>
<td>Boolean</td>
<td>true</td>
<td>是否开启按住ctrl键多选节点的功能</td>
<td></td>
</tr>
<tr>
<td>useLeftKeySelectionRightKeyDragv0.6.0+</td>
<td>Boolean</td>
<td>false</td>
<td>设置为左键多选节点右键拖动画布</td>
<td></td>
</tr>
<tr>
<td>beforeTextEditv0.6.0+</td>
<td>Function/null</td>
<td>null</td>
<td>节点即将进入编辑前的回调方法如果该方法返回true以外的值那么将取消编辑函数可以返回一个值或一个Promise回调参数为节点实例</td>
<td></td>
</tr>
<tr>
<td>isUseCustomNodeContentv0.6.3+</td>
<td>Boolean</td>
<td>false</td>
<td>是否自定义节点内容</td>
<td></td>
</tr>
<tr>
<td>customCreateNodeContentv0.6.3+</td>
<td>Function/null</td>
<td>null</td>
<td>如果<code>isUseCustomNodeContent</code>设为<code>true</code>那么需要使用该选项传入一个方法接收节点实例<code>node</code>为参数如果要获取该节点的数据可以通过<code>node.nodeData.data</code>需要返回自定义节点内容元素也就是DOM节点如果某个节点不需要自定义那么返回<code>null</code>即可</td>
<td></td>
</tr>
<tr>
<td>mouseScaleCenterUseMousePositionv0.6.4-fix.1+</td>
<td>Boolean</td>
<td>true</td>
<td>鼠标缩放是否以鼠标当前位置为中心点否则以画布中心点</td>
<td></td>
</tr>
<tr>
<td>customInnerElsAppendTov0.6.12+</td>
<td>null/HTMLElement</td>
<td>null</td>
<td>指定内部一些元素节点文本编辑元素节点备注显示元素关联线文本编辑元素节点图片调整按钮元素添加到的位置默认添加到document.body下</td>
<td></td>
</tr>
<tr>
<td>nodeDragPlaceholderMaxSizev0.6.12+</td>
<td>Number</td>
<td>20</td>
<td>拖拽元素时指示元素新位置的块的最大高度</td>
<td></td>
</tr>
<tr>
<td>enableCreateHiddenInputv0.6.13+v0.6.14+版本已去除该特性</td>
<td>Boolean</td>
<td>true</td>
<td>是否允许创建一个隐藏的输入框该输入框会在节点激活时聚焦用于粘贴数据和自动进入文本编辑状态</td>
<td></td>
</tr>
<tr>
<td>enableAutoEnterTextEditWhenKeydownv0.6.13+</td>
<td>Boolean</td>
<td>true</td>
<td>是否在存在一个激活节点时当按下中文英文数字按键时自动进入文本编辑模式</td>
<td></td>
</tr>
<tr>
<td>richTextEditFakeInPlacev0.6.13+</td>
<td>Boolean</td>
<td>false</td>
<td>设置富文本节点编辑框和节点大小一致形成伪原地编辑的效果需要注意的是只有当节点内只有文本且形状是矩形才会有比较好的效果</td>
<td></td>
</tr>
<tr>
<td>customHandleClipboardTextv0.6.14+</td>
<td>Function</td>
<td>null</td>
<td>自定义对剪贴板文本的处理当按ctrl+v粘贴时会读取用户剪贴板中的文本和图片默认只会判断文本是否是普通文本和simple-mind-map格式的节点数据如果你想处理其他思维导图的数据比如processonzhixi等那么可以传递一个函数接受当前剪贴板中的文本为参数返回处理后的数据可以返回两种类型1.返回一个纯文本那么会直接以该文本创建一个子节点2.返回一个节点对象格式如下{ simpleMindMap: true, data: { data: { text: '' }, children: [] } }代表是simple-mind-map格式的数据节点数据同simple-mind-map节点数据格式如果你的处理逻辑存在异步逻辑也可以返回一个promise</td>
<td></td>
</tr>
<tr>
<td>errorHandlerv0.6.15+</td>
<td>Function</td>
<td></td>
<td>自定义错误处理函数目前只会抛出一些异步逻辑出错的情况可以传递一个函数会接收两个参数第一个为错误的类型第二个为错误对象</td>
<td></td>
</tr>
<tr>
<td>disableMouseWheelZoomv0.6.15+</td>
<td>Boolean</td>
<td>false</td>
<td>禁止鼠标滚轮缩放你仍旧可以使用api进行缩放</td>
<td></td>
</tr>
<tr>
<td>resetCssv0.6.16+</td>
<td>String</td>
<td>* { margin: 0; padding: 0; box-sizing: border-box; }</td>
<td>设置导出图片和svg时针对富文本节点内容也就是嵌入到svg中的html节点的默认样式覆盖如果不覆盖节点内容会发生偏移</td>
<td></td>
</tr>
<tr>
<td>enableDblclickResetv0.6.17+</td>
<td>Boolean</td>
<td>truev0.7.0+改为false</td>
<td>开启鼠标双击复位思维导图位置及缩放</td>
<td></td>
</tr>
<tr>
<td>minExportImgCanvasScalev0.7.0+</td>
<td>Number</td>
<td>2</td>
<td>导出图片和pdf时canvas的缩放倍数该配置会和window.devicePixelRatio值取最大值用于提升图片清晰度</td>
<td></td>
</tr>
<tr>
<td>hoverRectColorv0.7.0+</td>
<td>String</td>
<td>rgb(94, 200, 248)</td>
<td>节点鼠标hover和激活时显示的矩形边框颜色hover时会添加0.6的透明度</td>
<td></td>
</tr>
<tr>
<td>hoverRectPaddingv0.7.0+</td>
<td>Number</td>
<td>2</td>
<td>节点鼠标hover和激活时显示的矩形边框距节点内容的距离</td>
<td></td>
</tr>
<tr>
<td>selectTextOnEnterEditTextv0.7.0+</td>
<td>Boolean</td>
<td>true</td>
<td>双击节点进入节点文本编辑时是否默认选中文本默认只在创建新节点时会选中</td>
<td></td>
</tr>
<tr>
<td>deleteNodeActivev0.7.1+</td>
<td>Boolean</td>
<td>true</td>
<td>是否开启删除节点后自动激活节点相邻节点或父节点的功能</td>
<td></td>
</tr>
<tr>
<td>autoMoveWhenMouseInEdgeOnDragv0.7.1+</td>
<td>Boolean</td>
<td>true</td>
<td>拖拽节点时鼠标移动到画布边缘是否开启画布自动移动</td>
<td></td>
</tr>
<tr>
<td>fitv0.7.1-fix.2+</td>
<td>Boolean</td>
<td>false</td>
<td>首次渲染时是否缩放至适应画布大小</td>
</tr>
<tr>
<td>dragMultiNodeRectConfigv0.7.2+</td>
<td>Object</td>
<td>{ width: 40, height: 20, fill: '' }</td>
<td>拖拽多个节点时随鼠标移动的示意矩形的样式配置传递一个对象字段含义分别为矩形的宽填充色</td>
</tr>
<tr>
<td>dragPlaceholderRectFillv0.7.2+</td>
<td>String</td>
<td></td>
<td>节点拖拽时新位置的示意矩形的填充颜色如果不传默认使用连线的颜色</td>
</tr>
<tr>
<td>dragOpacityConfigv0.7.2+</td>
<td>Object</td>
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
<td>节点拖拽时的透明度配置传递一个对象字段含义分别为跟随鼠标移动的克隆节点或矩形的透明度被拖拽节点的透明度</td>
</tr>
<tr>
<td>tagsColorMapv0.7.2+</td>
<td>Object</td>
<td>{}</td>
<td>自定义节点标签的颜色可传一个对象key为要指定颜色的标签内容value为该标签内容的颜色如果不传内部会根据标签内容生成对应的颜色</td>
</tr>
</tbody>
</table>
@@ -951,8 +908,8 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
</tr>
<tr>
<td>INSERT_NODE</td>
<td>插入同级节点操作节点为当前激活的节点或指定节点如果有多个激活节点只会对第一个有效</td>
<td>openEditv0.4.6+是否激活新插入的节点并进入编辑模式默认为<code>true</code> appointNodesv0.4.7+可选指定节点指定多个节点可以传一个数组 appointData可选指定新创建节点的数据比如{text: 'xxx', ...}详细结构可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> appointChildrenv0.6.14+可选指定新创建节点的子节点数组类型</td>
<td>插入同级节点操作节点为当前激活的节点或指定节点如果有多个激活节点只会对第一个有效v0.7.2+支持对多个激活节点同时插入兄弟节点</td>
<td>openEditv0.4.6+是否激活新插入的节点并进入编辑模式默认为<code>true</code> appointNodesv0.4.7+可选指定要插入兄弟节点的节点指定多个节点可以传一个数组 appointData可选指定新创建节点的数据比如{text: 'xxx', ...}详细结构可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> appointChildrenv0.6.14+可选指定新创建节点的子节点数组类型</td>
</tr>
<tr>
<td>INSERT_CHILD_NODE</td>
@@ -1062,16 +1019,16 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<tr>
<td>INSERT_AFTERv0.1.5+</td>
<td>将节点移动到另一个节点的后面</td>
<td>node要移动的节点 exist目标节点</td>
<td>node要移动的节点v0.7.2+支持传递节点数组实现同时移动多个节点 exist目标节点</td>
</tr>
<tr>
<td>INSERT_BEFOREv0.1.5+</td>
<td>将节点移动到另一个节点的前面</td>
<td>将节点移动到另一个节点的前面v0.7.2+支持传递节点数组实现同时移动多个节点</td>
<td>node要移动的节点 exist目标节点</td>
</tr>
<tr>
<td>MOVE_NODE_TOv0.1.5+</td>
<td>移动一个节点作为另一个节点的子节点</td>
<td>移动节点作为另一个节点的子节点v0.7.2+支持传递节点数组实现同时移动多个节点</td>
<td>node要移动的节点 toNode目标节点</td>
</tr>
<tr>
@@ -1104,6 +1061,21 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<td>定位到某个节点如果该节点被收起那么会自动展开到该节点</td>
<td>node要定位到的节点实例或节点uidcallbackv0.6.9+定位完成后的回调函数</td>
</tr>
<tr>
<td>INSERT_MULTI_NODEv0.7.2+</td>
<td>给指定的节点同时插入多个同级节点操作节点为当前激活的节点或指定节点</td>
<td>appointNodes可选指定节点指定多个节点可以传一个数组, nodeList新插入节点的数据列表数组类型</td>
</tr>
<tr>
<td>INSERT_MULTI_CHILD_NODEv0.7.2+</td>
<td>给指定的节点同时插入多个子节点操作节点为当前激活的节点或指定节点</td>
<td>appointNodes可选指定节点指定多个节点可以传一个数组, childList新插入节点的数据列表数组类型</td>
</tr>
<tr>
<td>INSERT_FORMULAv0.7.2+</td>
<td>给节点插入数学公式操作节点为当前激活的节点或指定节点</td>
<td>formula要插入的数学公式LaText语法, appointNodes可选指定要插入公式的节点多个节点可以传数组否则默认为当前激活的节点</td>
</tr>
</tbody>
</table>
<h3>setData(data)</h3>

View File

@@ -0,0 +1,36 @@
# Formula 插件
> v0.7.2+
> 该插件仅在富文本模式下支持所以需要在注册了RichText插件的前提下使用
该插件用于支持给节点插入公式。
## 注册
```js
import MindMap from 'simple-mind-map'
import Formula from 'simple-mind-map/src/plugins/Formula.js'
MindMap.usePlugin(Formula)
```
注册完且实例化`MindMap`后可通过`mindMap.formula`获取到该实例。
## 使用
注册了该插件后,可以使用命令`INSERT_FORMULA`来给节点插入指定公式:
```js
mindMap.execCommand('INSERT_FORMULA', 'a^2')
```
上述命令会给当前激活的节点插入`a^2`公式。
如果要指定给某个或某些节点插入公式,可以传递第二个参数:
```js
mindMap.execCommand('INSERT_FORMULA', 'a^2', [Node])
```
通过第二个参数传入指定的节点实例即可。

View File

@@ -0,0 +1,39 @@
<template>
<div>
<h1>Formula 插件</h1>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<blockquote>
<p>该插件仅在富文本模式下支持所以需要在注册了RichText插件的前提下使用</p>
</blockquote>
<p>该插件用于支持给节点插入公式</p>
<h2>注册</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> Formula <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/plugins/Formula.js&#x27;</span>
MindMap.usePlugin(Formula)
</code></pre>
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.formula</code>获取到该实例</p>
<h2>使用</h2>
<p>注册了该插件后可以使用命令<code>INSERT_FORMULA</code>来给节点插入指定公式</p>
<pre class="hljs"><code>mindMap.execCommand(<span class="hljs-string">&#x27;INSERT_FORMULA&#x27;</span>, <span class="hljs-string">&#x27;a^2&#x27;</span>)
</code></pre>
<p>上述命令会给当前激活的节点插入<code>a^2</code>公式</p>
<p>如果要指定给某个或某些节点插入公式可以传递第二个参数</p>
<pre class="hljs"><code>mindMap.execCommand(<span class="hljs-string">&#x27;INSERT_FORMULA&#x27;</span>, <span class="hljs-string">&#x27;a^2&#x27;</span>, [Node])
</code></pre>
<p>通过第二个参数传入指定的节点实例即可</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@@ -11,12 +11,12 @@
- [x] 插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积
- [x] 支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构
- [x] 内置多种主题,允许高度自定义样式,支持注册新主题
- [x] 节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要
- [x] 节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式
- [x] 节点支持拖拽(拖拽移动、自由调整)、多种节点形状,支持使用 DDM 完全自定义节点内容
- [x] 支持画布拖动、缩放
- [x] 支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式
- [x] 支持导出为`json``png``svg``pdf``markdown``xmind`,支持从`json``xmind``markdown`导入
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条
- [x] 提供丰富的配置,满足各种场景各种使用习惯
## 仓库目录介绍
@@ -53,6 +53,8 @@
[我的第一个Electron应用](https://juejin.cn/post/7233012756314701884)
[探索如何将html和svg导出为图片](https://juejin.cn/post/7276712861514170409)
## 特别说明
本项目可用于学习和参考,用于实际项目时请先深度体验一下是否能满足您的需求。
@@ -61,7 +63,7 @@
如果有建议或发现了bug可以在此提交[issues](https://github.com/wanglin2/mind-map/issues)。
项目内置的主题和图标来自于:
项目内置的主题和图标部分来自于:
[百度脑图](https://naotu.baidu.com/)
@@ -81,7 +83,7 @@
`kityminder-core`是百度开发的开源的脑图工具功能很强大性能也很好但是它已经不维护了所以代码比较陈旧界面美观度也比较一般另外bug只能自己修功能只能自己开发对前端开发能力要求比较高。
3.[jsmind](https://github.com/hizzgdev/jsmind)、[Mind-elixir](https://github.com/ssshooter/mind-elixir-core)、[my-mind](https://github.com/ondras/my-mind)、[blink-mind](https://github.com/awehook/blink-mind)、[remind](https://github.com/luvsic3/remind)、[vue3-mindmap](https://github.com/hellowuxin/vue3-mindmap)、[ZMindMap](https://github.com/zyascend/ZMindMap)...
3.[jsmind](https://github.com/hizzgdev/jsmind)、[Mind-elixir](https://github.com/ssshooter/mind-elixir-core)、[my-mind](https://github.com/ondras/my-mind)、[blink-mind](https://github.com/awehook/blink-mind)、[remind](https://github.com/luvsic3/remind)、[vue3-mindmap](https://github.com/hellowuxin/vue3-mindmap)、[ZMindMap](https://github.com/zyascend/ZMindMap)、[mindmaptree](https://github.com/RockyRen/mindmaptree)...
这些开源的思维导图也都不错,各有各的特点,但是它们也都有一定缺点,比如停止更新、界面美观度一般、功能比较少、依赖某个框架等等。
@@ -197,4 +199,8 @@
<img src="../../../../assets/avatar/敏.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>敏</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>沐风牧草</p>
</div>
</div>

View File

@@ -8,16 +8,16 @@
</blockquote>
<h2>特性</h2>
<ul>
<li><input type="checkbox" id="checkbox15" checked="true" /><label for="checkbox15">插件化架构除核心功能外其他功能作为插件提供按需使用减小打包体积</label></li>
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">支持逻辑结构图思维导图组织结构图目录组织图时间轴横向竖向鱼骨图等结构</label></li>
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">内置多种主题允许高度自定义样式支持注册新主题</label></li>
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">节点内容支持文本普通文本富文本图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">节点支持拖拽拖拽移动自由调整多种节点形状支持使用 DDM 完全自定义节点内容</label></li>
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">支持画布拖动缩放</label></li>
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式</label></li>
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">支持导出为</label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code>支持从<code>json</code><code>xmind</code><code>markdown</code>导入</li>
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">支持快捷键前进后退关联线搜索替换小地图水印</label></li>
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">提供丰富的配置满足各种场景各种使用习惯</label></li>
<li><input type="checkbox" id="checkbox0" checked="true" /><label for="checkbox0">插件化架构除核心功能外其他功能作为插件提供按需使用减小打包体积</label></li>
<li><input type="checkbox" id="checkbox1" checked="true" /><label for="checkbox1">支持逻辑结构图思维导图组织结构图目录组织图时间轴横向竖向鱼骨图等结构</label></li>
<li><input type="checkbox" id="checkbox2" checked="true" /><label for="checkbox2">内置多种主题允许高度自定义样式支持注册新主题</label></li>
<li><input type="checkbox" id="checkbox3" checked="true" /><label for="checkbox3">节点内容支持文本普通文本富文本图片图标超链接备注标签概要数学公式</label></li>
<li><input type="checkbox" id="checkbox4" checked="true" /><label for="checkbox4">节点支持拖拽拖拽移动自由调整多种节点形状支持使用 DDM 完全自定义节点内容</label></li>
<li><input type="checkbox" id="checkbox5" checked="true" /><label for="checkbox5">支持画布拖动缩放</label></li>
<li><input type="checkbox" id="checkbox6" checked="true" /><label for="checkbox6">支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式</label></li>
<li><input type="checkbox" id="checkbox7" checked="true" /><label for="checkbox7">支持导出为</label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code>支持从<code>json</code><code>xmind</code><code>markdown</code>导入</li>
<li><input type="checkbox" id="checkbox8" checked="true" /><label for="checkbox8">支持快捷键前进后退关联线搜索替换小地图水印滚动条</label></li>
<li><input type="checkbox" id="checkbox9" checked="true" /><label for="checkbox9">提供丰富的配置满足各种场景各种使用习惯</label></li>
</ul>
<h2>仓库目录介绍</h2>
<p>1.<code>simple-mind-map</code></p>
@@ -25,11 +25,11 @@
<p>2.<code>web</code></p>
<p>使用<code>simple-mind-map</code>基于<code>vue2.x</code><code>ElementUI</code>搭建的在线思维导图特性</p>
<ul>
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">工具栏支持插入节点删除节点编辑节点图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">侧边栏基础样式设置面板节点样式设置面板大纲面板主题选择面板结构选择面板</label></li>
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">导入导出功能数据默认保存在浏览器本地存储也支持直接创建打开编辑电脑本地文件</label></li>
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">右键菜单支持展开收起整理布局等操作</label></li>
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">底部栏支持节点数量字数统计支持切换编辑和只读模式支持放大缩小支持全屏切换支持小地图</label></li>
<li><input type="checkbox" id="checkbox10" checked="true" /><label for="checkbox10">工具栏支持插入节点删除节点编辑节点图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox11" checked="true" /><label for="checkbox11">侧边栏基础样式设置面板节点样式设置面板大纲面板主题选择面板结构选择面板</label></li>
<li><input type="checkbox" id="checkbox12" checked="true" /><label for="checkbox12">导入导出功能数据默认保存在浏览器本地存储也支持直接创建打开编辑电脑本地文件</label></li>
<li><input type="checkbox" id="checkbox13" checked="true" /><label for="checkbox13">右键菜单支持展开收起整理布局等操作</label></li>
<li><input type="checkbox" id="checkbox14" checked="true" /><label for="checkbox14">底部栏支持节点数量字数统计支持切换编辑和只读模式支持放大缩小支持全屏切换支持小地图</label></li>
</ul>
<p>提供文档页面服务</p>
<p>3.<code>dist</code></p>
@@ -40,11 +40,12 @@
<p><a href="https://juejin.cn/post/7199666255883927612">当你按下方向键电视是如何寻找下一个焦点的</a></p>
<p><a href="https://juejin.cn/post/7204854015463538744">如何在canvas中模拟css的背景图片样式</a></p>
<p><a href="https://juejin.cn/post/7233012756314701884">我的第一个Electron应用</a></p>
<p><a href="https://juejin.cn/post/7276712861514170409">探索如何将html和svg导出为图片</a></p>
<h2>特别说明</h2>
<p>本项目可用于学习和参考用于实际项目时请先深度体验一下是否能满足您的需求</p>
<p>本项目可能没有完整测试到每一个功能点所以可能存在bug另外当节点数量非常多的时候性能也存在一些问题因为每个人能接受的卡顿程度不一样所以你可以自行测试节点数量上限</p>
<p>如果有建议或发现了bug可以在此提交<a href="https://github.com/wanglin2/mind-map/issues">issues</a></p>
<p>项目内置的主题和图标来自于</p>
<p>项目内置的主题和图标部分来自于</p>
<p><a href="https://naotu.baidu.com/">百度脑图</a></p>
<p><a href="https://www.zhixi.com/">知犀思维导图</a></p>
<p>尊重版权主题和图标请勿直接用于商业项目</p>
@@ -54,7 +55,7 @@
<p>类似知犀的其他在线思维导图产品还有很多比如<a href="https://gitmind.cn/">GitMind</a><a href="http://www.mindline.cn/">MindLine</a><a href="https://www.mindmeister.com/zh">MinMeister</a><a href="https://mubu.com/">幕布</a>等等搜索引擎上搜索一下非常多但是这些产品或者是要收费或者是小公司开发的稳定性和持续性无法保证当然最关键的就是它们都不开源</p>
<p>2.<a href="https://github.com/fex-team/kityminder-core">kityminder-core</a></p>
<p><code>kityminder-core</code>是百度开发的开源的脑图工具功能很强大性能也很好但是它已经不维护了所以代码比较陈旧界面美观度也比较一般另外bug只能自己修功能只能自己开发对前端开发能力要求比较高</p>
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a><a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a><a href="https://github.com/ondras/my-mind">my-mind</a><a href="https://github.com/awehook/blink-mind">blink-mind</a><a href="https://github.com/luvsic3/remind">remind</a><a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a><a href="https://github.com/zyascend/ZMindMap">ZMindMap</a>...</p>
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a><a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a><a href="https://github.com/ondras/my-mind">my-mind</a><a href="https://github.com/awehook/blink-mind">blink-mind</a><a href="https://github.com/luvsic3/remind">remind</a><a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a><a href="https://github.com/zyascend/ZMindMap">ZMindMap</a><a href="https://github.com/RockyRen/mindmaptree">mindmaptree</a>...</p>
<p>这些开源的思维导图也都不错各有各的特点但是它们也都有一定缺点比如停止更新界面美观度一般功能比较少依赖某个框架等等</p>
<p>综上在开源的思维导图中你很难找到一个比<code>simple-mind-map</code>更好的选择当然<code>simple-mind-map</code>也远远谈不上最好它也有很多不足如你在前面的特别说明所看到的那样不过<code>simple-mind-map</code>一直处于快速迭代中欢迎你加入进来一起完善它</p>
<h2>浏览器兼容性</h2>
@@ -157,6 +158,10 @@
<img src="../../../../assets/avatar/敏.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p></p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>沐风牧草</p>
</div>
</div>
</div>
</template>

View File

@@ -56,6 +56,26 @@
## 方法
### setOpacity(val)
> v0.7.2+
- `val`透明度0-1
设置节点透明度,包括连接线和下级节点。
### hideChildren()
> v0.7.2+
隐藏下级节点。
### showChildren()
> v0.7.2+
显示下级节点。
### hasCustomStyle()
> v0.6.2+

View File

@@ -31,6 +31,24 @@
</blockquote>
<p>节点是否正在拖拽中</p>
<h2>方法</h2>
<h3>setOpacity(val)</h3>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<ul>
<li><code>val</code>透明度0-1</li>
</ul>
<p>设置节点透明度包括连接线和下级节点</p>
<h3>hideChildren()</h3>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<p>隐藏下级节点</p>
<h3>showChildren()</h3>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
<p>显示下级节点</p>
<h3>hasCustomStyle()</h3>
<blockquote>
<p>v0.6.2+</p>

View File

@@ -1,4 +1,12 @@
# 参与翻译
# 贡献
## 参与开发
如果你想贡献代码的话可以`fork`本项目,然后切换到`feature`分支下进行开发,开发并测试完后可以提交`pr`到本项目的`feature`分支,提交时请尽量提交功能相关的文件,非必要的文件请勿提交。
在开发前最好通过新建一个`issue`来描述你想要新增的功能,我们可以先进行充分的沟通,在提交`pr`时请详细描述你开发的功能。
## 参与翻译
> 感谢[Emircan ERKUL](https://github.com/emircanerkul)提供的第一版英文翻译。
>

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