Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
193b293cfe | ||
|
|
615ff3ea25 | ||
|
|
8b9cfd2972 | ||
|
|
03f8cb9290 | ||
|
|
1ea0c7e316 | ||
|
|
a39c8c30e6 | ||
|
|
26ce08c27d | ||
|
|
4bfc98a96f | ||
|
|
7560411922 | ||
|
|
4288e44f3a | ||
|
|
b82c5247fa | ||
|
|
c7d2082944 | ||
|
|
29458ade9c | ||
|
|
49d366628e | ||
|
|
b093153262 | ||
|
|
02f276bc2a | ||
|
|
69cb961cc1 | ||
|
|
7096391f3b | ||
|
|
280ffcf01d | ||
|
|
db3c2b71f5 | ||
|
|
f11f364d00 | ||
|
|
0e8c50d430 | ||
|
|
dd8d250857 | ||
|
|
693ead6b49 | ||
|
|
dc3c91270c | ||
|
|
71ac739964 | ||
|
|
eae5dc5854 | ||
|
|
c45ceac7dc | ||
|
|
3d8702be8a | ||
|
|
084dd9fd84 | ||
|
|
0c6c68820f | ||
|
|
f5ff479f47 | ||
|
|
e9722efe93 | ||
|
|
db1f9c04c1 |
209
README.md
@@ -8,37 +8,37 @@
|
||||
|
||||
- [x] 支持快捷键
|
||||
|
||||
- [x] 节点内容支持图片、图标、超链接、备注、标签
|
||||
- [x] 节点内容支持图片、图标、超链接、备注、标签、概要
|
||||
|
||||
- [x] 支持前进后退
|
||||
|
||||
- [x] 支持拖动、缩放
|
||||
|
||||
- [x] 支持右键多选
|
||||
- [x] 支持右键按住多选
|
||||
|
||||
- [x] 支持节点拖拽
|
||||
- [x] 支持节点自由拖拽、拖拽调整
|
||||
|
||||
## 目录介绍
|
||||
|
||||
1.simple-mind-map
|
||||
1.`simple-mind-map`
|
||||
|
||||
思维导图工具库。
|
||||
|
||||
2.web
|
||||
2.`web`
|
||||
|
||||
使用`simple-mind-map`工具库,基于vue2.x、ElementUI搭建的在线思维导图。
|
||||
使用`simple-mind-map`工具库,基于`vue2.x`、`ElementUI`搭建的在线思维导图。
|
||||
|
||||
3.dist
|
||||
3.`dist`
|
||||
|
||||
打包后的资源文件夹。
|
||||
|
||||
4.docs
|
||||
4.`docs`
|
||||
|
||||
文档等。
|
||||
|
||||
## 开发
|
||||
|
||||
本地开发
|
||||
### 本地开发
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wanglin2/mind-map.git
|
||||
@@ -52,7 +52,27 @@ npm link simple-mind-map
|
||||
npm run serve
|
||||
```
|
||||
|
||||
打包
|
||||
### 打包库
|
||||
|
||||
自`0.2.0`版本开始增加了对核心库`simple-mind-map`的打包,复用了示例项目`web`的打包工具。
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm run buildLibrary
|
||||
```
|
||||
|
||||
`simple-mind-map`库的`package.json`文件提供了两个导出字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"module": "index.js",
|
||||
"main": "./dist/simpleMindMap.umd.min.js",
|
||||
}
|
||||
```
|
||||
|
||||
支持`module`字段的环境会以`index.js`为入口,否则会以打包后的`simpleMindMap.umd.min.js`为入口。
|
||||
|
||||
### 打包demo
|
||||
|
||||
```bash
|
||||
cd web
|
||||
@@ -66,10 +86,24 @@ npm run build
|
||||
|
||||
# 安装
|
||||
|
||||
> 当然仓库版本:0.2.3,当前npm版本:0.2.3
|
||||
|
||||
```bash
|
||||
npm i simple-mind-map
|
||||
```
|
||||
|
||||
`0.2.0`版本之前的注意事项:
|
||||
|
||||
>注意:本项目为源码直接发布,并未进行打包,如果出现编译失败的情况,Vue CLI创建的项目可以在vue.config.js文件中增加如下配置来让babel-loader编译本依赖:
|
||||
>
|
||||
>```js
|
||||
>module.exports = {
|
||||
> transpileDependencies: ['simple-mind-map']
|
||||
>}
|
||||
>```
|
||||
>
|
||||
>其他项目请自行修改打包配置。
|
||||
|
||||
# API
|
||||
|
||||
## 实例化
|
||||
@@ -96,7 +130,7 @@ const mindMap = new MindMap({
|
||||
| el | Element | | 容器元素,必须为DOM元素 | 是 |
|
||||
| data | Object | {} | 思维导图数据,可参考:[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) | |
|
||||
| layout | String | logicalStructure | 布局类型,可选列表:logicalStructure(逻辑结构图)、mindMap(思维导图)、catalogOrganization(目录组织图)、organizationStructure(组织结构图) | |
|
||||
| theme | String | default | 主题,可选列表:default(默认)、classic(脑图经典)、minions(小黄人)、pinkGrape(粉红葡萄)、mint(薄荷)、gold(金色vip)、vitalityOrange(活力橙)、greenLeaf(绿叶)、dark2(暗色2)、skyGreen(天清绿)、classic2(脑图经典2)、classic3(脑图经典3)、classicGreen(经典绿)、classicBlue(经典蓝)、blueSky(天空蓝)、brainImpairedPink(脑残粉)、dark(暗色)、earthYellow(泥土黄)、freshGreen(清新绿)、freshRed(清新红)、romanticPurple(浪漫紫) | |
|
||||
| theme | String | default | 主题,可选列表:default(默认)、classic(脑图经典)、minions(小黄人)、pinkGrape(粉红葡萄)、mint(薄荷)、gold(金色vip)、vitalityOrange(活力橙)、greenLeaf(绿叶)、dark2(暗色2)、skyGreen(天清绿)、classic2(脑图经典2)、classic3(脑图经典3)、classic4(脑图经典4,v0.2.0+)、classicGreen(经典绿)、classicBlue(经典蓝)、blueSky(天空蓝)、brainImpairedPink(脑残粉)、dark(暗色)、earthYellow(泥土黄)、freshGreen(清新绿)、freshRed(清新红)、romanticPurple(浪漫紫) | |
|
||||
| themeConfig | Object | {} | 主题配置,会和所选择的主题进行合并,可用字段可参考:[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js) | |
|
||||
| scaleRatio | Number | 0.1 | 放大缩小的增量比例 | |
|
||||
| maxTag | Number | 5 | 节点里最多显示的标签数量,多余的会被丢弃 | |
|
||||
@@ -106,6 +140,7 @@ const mindMap = new MindMap({
|
||||
| selectTranslateStep | Number | 3 | 多选节点时鼠标移动到边缘时的画布移动偏移量 | |
|
||||
| selectTranslateLimit | Number | 20 | 多选节点时鼠标移动距边缘多少距离时开始偏移 | |
|
||||
| customNoteContentShow(v0.1.6+) | Object | null | 自定义节点备注内容显示,Object类型,结构为:{show: (noteContent, left, top) => {// 你的显示节点备注逻辑 }, hide: () => {// 你的隐藏节点备注逻辑 }} | |
|
||||
| readonly(v0.1.7+) | Boolean | false | 是否是只读模式 | |
|
||||
|
||||
|
||||
### 实例方法:
|
||||
@@ -126,7 +161,11 @@ const mindMap = new MindMap({
|
||||
|
||||
容器尺寸变化后,需要调用该方法进行适应
|
||||
|
||||
#### setMode(mode)
|
||||
|
||||
v0.1.7+。切换模式为只读或编辑。
|
||||
|
||||
`mode`:readonly、edit
|
||||
|
||||
#### on(event, fn)
|
||||
|
||||
@@ -213,34 +252,38 @@ const mindMap = new MindMap({
|
||||
|
||||
执行命令,每执行一个命令就会在历史堆栈里添加一条记录用于回退或前进。所有命令如下:
|
||||
|
||||
| 命令名称 | 描述 | 参数 |
|
||||
| ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| SELECT_ALL | 全选 | |
|
||||
| BACK | 回退指定的步数 | step(要回退的步数,默认为1) |
|
||||
| FORWARD | 前进指定的步数 | step(要前进的步数,默认为1) |
|
||||
| INSERT_NODE | 插入同级节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效 | |
|
||||
| INSERT_CHILD_NODE | 插入子节点,操作节点为当前激活的节点 | |
|
||||
| UP_NODE | 上移节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的第一个节点使用无效 | |
|
||||
| DOWN_NODE | 操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的最后一个节点使用无效 | |
|
||||
| REMOVE_NODE | 删除节点,操作节点为当前激活的节点 | |
|
||||
| PASTE_NODE | 粘贴节点到节点,操作节点为当前激活的节点 | data(要粘贴的节点数据,一般通过`renderer.copyNode()`方法和`renderer.cutNode()`方法获取) |
|
||||
| CUT_NODE | 剪切节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点使用无效 | callback(回调函数,剪切的节点数据会通过调用该函数并通过参数返回) |
|
||||
| SET_NODE_STYLE | 修改节点样式 | node(要设置样式的节点)、prop(样式属性)、value(样式属性值)、isActive(布尔值,是否设置的是激活状态的样式) |
|
||||
| SET_NODE_ACTIVE | 设置节点是否激活 | node(要设置的节点)、active(布尔值,是否激活) |
|
||||
| CLEAR_ACTIVE_NODE | 清除当前已激活节点的激活状态,操作节点为当前激活的节点 | |
|
||||
| SET_NODE_EXPAND | 设置节点是否展开 | node(要设置的节点)、expand(布尔值,是否展开) |
|
||||
| EXPAND_ALL | 展开所有节点 | |
|
||||
| UNEXPAND_ALL | 收起所有节点 | |
|
||||
| SET_NODE_DATA | 更新节点数据,即更新节点数据对象里`data`对象的数据 | node(要设置的节点)、data(对象,要更新的数据,如`{expand: true}`) |
|
||||
| SET_NODE_TEXT | 设置节点文本 | node(要设置的节点)、text(要设置的文本字符串,换行可以使用`\n`) |
|
||||
| SET_NODE_IMAGE | 设置节点图片 | node(要设置的节点)、imgData(对象,图片信息,结构为:`{url, title, width, height}`,图片的宽高必须要传) |
|
||||
| SET_NODE_ICON | 设置节点图标 | node(要设置的节点)、icons(数组,预定义的图片名称组成的数组,可用图标可在[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件里的`nodeIconList`列表里获取到,图标名称为`type_name`,如`['priority_1']`) |
|
||||
| SET_NODE_HYPERLINK | 设置节点超链接 | node(要设置的节点)、link(超链接地址)、title(超链接名称,可选) |
|
||||
| SET_NODE_NOTE | 设置节点备注 | node(要设置的节点)、note(备注文字) |
|
||||
| SET_NODE_TAG | 设置节点标签 | node(要设置的节点)、tag(字符串数组,内置颜色信息可在[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/utils/constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/utils/constant.js)里获取到) |
|
||||
| INSERT_AFTER(v0.1.5+) | 将节点移动到另一个节点的后面 | node(要移动的节点)、 exist(目标节点) |
|
||||
| INSERT_BEFORE(v0.1.5+) | 将节点移动到另一个节点的前面 | node(要移动的节点)、 exist(目标节点) |
|
||||
| MOVE_NODE_TO(v0.1.5+) | 移动一个节点作为另一个节点的子节点 | node(要移动的节点)、 toNode(目标节点) |
|
||||
| 命令名称 | 描述 | 参数 |
|
||||
| ----------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| SELECT_ALL | 全选 | |
|
||||
| BACK | 回退指定的步数 | step(要回退的步数,默认为1) |
|
||||
| FORWARD | 前进指定的步数 | step(要前进的步数,默认为1) |
|
||||
| INSERT_NODE | 插入同级节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效 | |
|
||||
| INSERT_CHILD_NODE | 插入子节点,操作节点为当前激活的节点 | |
|
||||
| UP_NODE | 上移节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的第一个节点使用无效 | |
|
||||
| DOWN_NODE | 操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点或在列表里的最后一个节点使用无效 | |
|
||||
| REMOVE_NODE | 删除节点,操作节点为当前激活的节点 | |
|
||||
| PASTE_NODE | 粘贴节点到节点,操作节点为当前激活的节点 | data(要粘贴的节点数据,一般通过`renderer.copyNode()`方法和`renderer.cutNode()`方法获取) |
|
||||
| CUT_NODE | 剪切节点,操作节点为当前激活的节点,如果有多个激活节点,只会对第一个有效,对根节点使用无效 | callback(回调函数,剪切的节点数据会通过调用该函数并通过参数返回) |
|
||||
| SET_NODE_STYLE | 修改节点样式 | node(要设置样式的节点)、prop(样式属性)、value(样式属性值)、isActive(布尔值,是否设置的是激活状态的样式) |
|
||||
| SET_NODE_ACTIVE | 设置节点是否激活 | node(要设置的节点)、active(布尔值,是否激活) |
|
||||
| CLEAR_ACTIVE_NODE | 清除当前已激活节点的激活状态,操作节点为当前激活的节点 | |
|
||||
| SET_NODE_EXPAND | 设置节点是否展开 | node(要设置的节点)、expand(布尔值,是否展开) |
|
||||
| EXPAND_ALL | 展开所有节点 | |
|
||||
| UNEXPAND_ALL | 收起所有节点 | |
|
||||
| SET_NODE_DATA | 更新节点数据,即更新节点数据对象里`data`对象的数据 | node(要设置的节点)、data(对象,要更新的数据,如`{expand: true}`) |
|
||||
| SET_NODE_TEXT | 设置节点文本 | node(要设置的节点)、text(要设置的文本字符串,换行可以使用`\n`) |
|
||||
| SET_NODE_IMAGE | 设置节点图片 | node(要设置的节点)、imgData(对象,图片信息,结构为:`{url, title, width, height}`,图片的宽高必须要传) |
|
||||
| SET_NODE_ICON | 设置节点图标 | node(要设置的节点)、icons(数组,预定义的图片名称组成的数组,可用图标可在[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件里的`nodeIconList`列表里获取到,图标名称为`type_name`,如`['priority_1']`) |
|
||||
| SET_NODE_HYPERLINK | 设置节点超链接 | node(要设置的节点)、link(超链接地址)、title(超链接名称,可选) |
|
||||
| SET_NODE_NOTE | 设置节点备注 | node(要设置的节点)、note(备注文字) |
|
||||
| SET_NODE_TAG | 设置节点标签 | node(要设置的节点)、tag(字符串数组,内置颜色信息可在[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/utils/constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/utils/constant.js)里获取到) |
|
||||
| INSERT_AFTER(v0.1.5+) | 将节点移动到另一个节点的后面 | node(要移动的节点)、 exist(目标节点) |
|
||||
| INSERT_BEFORE(v0.1.5+) | 将节点移动到另一个节点的前面 | node(要移动的节点)、 exist(目标节点) |
|
||||
| MOVE_NODE_TO(v0.1.5+) | 移动一个节点作为另一个节点的子节点 | node(要移动的节点)、 toNode(目标节点) |
|
||||
| ADD_GENERALIZATION(v0.2.0+) | 添加节点概要 | data(概要的数据,对象格式,节点的数字段都支持,默认为{text: '概要'}) |
|
||||
| REMOVE_GENERALIZATION(v0.2.0+) | 删除节点概要 | |
|
||||
| SET_NODE_CUSTOM_POSITION(v0.2.0+) | 设置节点自定义位置 | node(要设置的节点)、 left(自定义的x坐标,默认为undefined)、 top(自定义的y坐标,默认为undefined) |
|
||||
| RESET_LAYOUT(v0.2.0+) | 一键整理布局 | |
|
||||
|
||||
|
||||
#### setData(data)
|
||||
@@ -254,7 +297,7 @@ const mindMap = new MindMap({
|
||||
|
||||
导出
|
||||
|
||||
`type`:要导出的类型,可选值:png、svg
|
||||
`type`:要导出的类型,可选值:png、svg、json、pdf(v0.2.1+)、smm(本质也是json)
|
||||
|
||||
`isDownload`:是否需要直接触发下载,布尔值,默认为`false`
|
||||
|
||||
@@ -288,6 +331,14 @@ v0.1.5+
|
||||
|
||||
### 方法
|
||||
|
||||
#### clearActive()
|
||||
|
||||
清除当前激活的节点
|
||||
|
||||
#### clearAllActive()
|
||||
|
||||
清除当前所有激活节点,并会触发`node_active`事件
|
||||
|
||||
#### startTextEdit()
|
||||
|
||||
(v0.1.6+)若有文字编辑需求可调用该方法,会禁用回车键和删除键相关快捷键防止冲突
|
||||
@@ -370,7 +421,7 @@ v0.1.5+
|
||||
|
||||
### 方法
|
||||
|
||||
#### keyCommand(key, fn)
|
||||
#### addShortcut(key, fn)
|
||||
|
||||
添加快捷键
|
||||
|
||||
@@ -378,7 +429,7 @@ v0.1.5+
|
||||
|
||||
```js
|
||||
// 单个按键
|
||||
mindMap.keyCommand..addShortcut('Enter', () => {})
|
||||
mindMap.keyCommand.addShortcut('Enter', () => {})
|
||||
// 或
|
||||
mindMap.keyCommand.addShortcut('Del|Backspace', () => {})
|
||||
// 组合键
|
||||
@@ -387,6 +438,29 @@ mindMap.keyCommand.addShortcut('Control+Enter', () => {})
|
||||
|
||||
`fn`:要执行的方法
|
||||
|
||||
#### removeShortcut(key, fn)
|
||||
|
||||
移除快捷键命令,`fn`不指定则移除该快捷键的所有回调方法
|
||||
|
||||
#### getShortcutFn(key)
|
||||
|
||||
v0.2.2+。获取指定快捷键的处理函数
|
||||
|
||||
#### pause()
|
||||
|
||||
v0.2.2+。暂停所有快捷键响应
|
||||
|
||||
#### recovery()
|
||||
|
||||
v0.2.2+。恢复快捷键响应
|
||||
|
||||
#### save()
|
||||
|
||||
v0.2.3+。保存当前注册的快捷键数据,然后清空快捷键数据
|
||||
|
||||
#### restore()
|
||||
|
||||
v0.2.3+。恢复保存的快捷键数据,然后清空缓存数据
|
||||
|
||||
|
||||
## command实例
|
||||
@@ -781,6 +855,54 @@ v0.1.5+
|
||||
|
||||
|
||||
|
||||
#### checkHasGeneralization()
|
||||
|
||||
v0.2.0+
|
||||
|
||||
检查是否存在概要
|
||||
|
||||
|
||||
|
||||
#### hideGeneralization()
|
||||
|
||||
v0.2.0+
|
||||
|
||||
隐藏概要节点
|
||||
|
||||
|
||||
|
||||
#### showGeneralization()
|
||||
|
||||
v0.2.0+
|
||||
|
||||
显示概要节点
|
||||
|
||||
|
||||
|
||||
#### updateGeneralization()
|
||||
|
||||
v0.2.0+
|
||||
|
||||
更新概要节点
|
||||
|
||||
|
||||
|
||||
#### hasCustomPosition()
|
||||
|
||||
v0.2.0+
|
||||
|
||||
检查节点是否存在自定义数据
|
||||
|
||||
|
||||
|
||||
#### ancestorHasCustomPosition()
|
||||
|
||||
v0.2.0+
|
||||
|
||||
检查节点是否存在自定义位置的祖先节点
|
||||
|
||||
|
||||
|
||||
## 内置工具方法
|
||||
|
||||
引用:
|
||||
@@ -907,3 +1029,6 @@ copyNodeTree({}, node)
|
||||
|
||||
[知犀思维导图](https://www.zhixi.com/)
|
||||
|
||||
# License
|
||||
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!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,initial-scale=1"><title>一个简单的web思维导图实现</title><link href="dist/css/app.9f8f33bc.css" rel="preload" as="style"><link href="dist/css/chunk-vendors.6fd71983.css" rel="preload" as="style"><link href="dist/js/app.ae3c62cc.js" rel="preload" as="script"><link href="dist/js/chunk-vendors.384d822e.js" rel="preload" as="script"><link href="dist/css/chunk-vendors.6fd71983.css" rel="stylesheet"><link href="dist/css/app.9f8f33bc.css" 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 src="dist/js/chunk-vendors.384d822e.js"></script><script src="dist/js/app.ae3c62cc.js"></script></body></html>
|
||||
<!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,initial-scale=1"><title>一个简单的web思维导图实现</title><link href="dist/js/chunk-2d20ec02.81d632f4.js" rel="prefetch"><link href="dist/js/chunk-2d216b67.228f2009.js" rel="prefetch"><link href="dist/js/chunk-e86f1494.f8dd20e2.js" rel="prefetch"><link href="dist/css/app.d29688d8.css" rel="preload" as="style"><link href="dist/css/chunk-vendors.6fd71983.css" rel="preload" as="style"><link href="dist/js/app.88b2cb65.js" rel="preload" as="script"><link href="dist/js/chunk-vendors.094115db.js" rel="preload" as="script"><link href="dist/css/chunk-vendors.6fd71983.css" rel="stylesheet"><link href="dist/css/app.d29688d8.css" 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 src="dist/js/chunk-vendors.094115db.js"></script><script src="dist/js/app.88b2cb65.js"></script></body></html>
|
||||
BIN
simple-mind-map/dist/img/blueSky.3c7f8ccb.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
simple-mind-map/dist/img/brainImpairedPink.511fee22.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
simple-mind-map/dist/img/catalogOrganization.380bb277.jpg
vendored
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
simple-mind-map/dist/img/classic.733f273c.jpg
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
simple-mind-map/dist/img/classic2.cdfe2a8d.jpg
vendored
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
simple-mind-map/dist/img/classic3.19d6c347.jpg
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
simple-mind-map/dist/img/classic4.087902fc.jpg
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
simple-mind-map/dist/img/classicBlue.4b8243c6.jpg
vendored
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
simple-mind-map/dist/img/classicGreen.c2ae7bde.jpg
vendored
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
simple-mind-map/dist/img/dark.894c1d36.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
simple-mind-map/dist/img/dark2.c49dc11c.jpg
vendored
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
simple-mind-map/dist/img/default.1312a3ba.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
simple-mind-map/dist/img/earthYellow.c35e546d.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
simple-mind-map/dist/img/freshGreen.0e344e3e.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
simple-mind-map/dist/img/freshRed.1c5bde77.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
simple-mind-map/dist/img/gold.3093b3c8.jpg
vendored
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
simple-mind-map/dist/img/greenLeaf.6789e8fc.jpg
vendored
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
simple-mind-map/dist/img/logicalStructure.624920ce.jpg
vendored
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
simple-mind-map/dist/img/mindMap.223b38aa.jpg
vendored
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
simple-mind-map/dist/img/minions.c2a93f9e.jpg
vendored
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
simple-mind-map/dist/img/mint.7933f60a.jpg
vendored
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
simple-mind-map/dist/img/organizationStructure.8064f4da.jpg
vendored
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
simple-mind-map/dist/img/pinkGrape.32c2587b.jpg
vendored
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
simple-mind-map/dist/img/romanticPurple.7607e58a.jpg
vendored
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
simple-mind-map/dist/img/skyGreen.4cfa829a.jpg
vendored
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
simple-mind-map/dist/img/vitalityOrange.5dd9014f.jpg
vendored
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
@@ -10,7 +10,10 @@ const createFullData = () => {
|
||||
"tag": ["标签1", "标签2"],
|
||||
"hyperlink": "http://lxqnsys.com/",
|
||||
"hyperlinkTitle": "理想青年实验室",
|
||||
"note": "理想青年实验室\n一个有意思的角落"
|
||||
"note": "理想青年实验室\n一个有意思的角落",
|
||||
// 自定义位置
|
||||
// "customLeft": 1318,
|
||||
// "customTop": 374.5
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,110 +35,110 @@ const data1 = {
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
...createFullData()
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
...createFullData()
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}]
|
||||
@@ -147,36 +150,36 @@ const data1 = {
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
},
|
||||
@@ -187,40 +190,40 @@ const data1 = {
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}]
|
||||
@@ -232,225 +235,225 @@ const data1 = {
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
"children": [{
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}, {
|
||||
"data": {
|
||||
"text": "子节点",
|
||||
"text": "分支主题",
|
||||
},
|
||||
}]
|
||||
}]
|
||||
@@ -767,13 +770,13 @@ const data3 = {
|
||||
"children": [
|
||||
{
|
||||
"data": {
|
||||
"text": "子节点"
|
||||
"text": "分支主题"
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "子节点"
|
||||
"text": "分支主题"
|
||||
},
|
||||
"children": []
|
||||
}
|
||||
@@ -864,6 +867,39 @@ const data4 = {
|
||||
}
|
||||
}
|
||||
|
||||
// 带概要
|
||||
const data5 = {
|
||||
"root": {
|
||||
"data": {
|
||||
"text": "根节点"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"data": {
|
||||
"text": "二级节点",
|
||||
"generalization": {
|
||||
"text": "概要",
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"data": {
|
||||
"text": "分支主题"
|
||||
},
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text": "分支主题"
|
||||
},
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const rootData = {
|
||||
"root": {
|
||||
"data": {
|
||||
@@ -876,11 +912,12 @@ const rootData = {
|
||||
export default {
|
||||
// ...data1,
|
||||
// ...data2,
|
||||
...data3,
|
||||
// ...data3,
|
||||
// ...data4,
|
||||
...data5,
|
||||
// ...rootData,
|
||||
"theme": {
|
||||
"template": "minions",
|
||||
"template": "classic4",
|
||||
"config": {
|
||||
// 自定义配置...
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import {
|
||||
|
||||
// 默认选项配置
|
||||
const defaultOpt = {
|
||||
// 是否只读
|
||||
readonly: false,
|
||||
// 布局
|
||||
layout: 'logicalStructure',
|
||||
// 主题
|
||||
@@ -347,6 +349,24 @@ class MindMap {
|
||||
y: y - this.elRect.top
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-06-08 14:12:38
|
||||
* @Desc: 设置只读模式、编辑模式
|
||||
*/
|
||||
setMode(mode) {
|
||||
if (!['readonly', 'edit'].includes(mode)) {
|
||||
return
|
||||
}
|
||||
this.opt.readonly = mode === 'readonly'
|
||||
if (this.opt.readonly) {
|
||||
// 取消当前激活的元素
|
||||
this.renderer.clearAllActive()
|
||||
}
|
||||
this.emit('mode_change', mode)
|
||||
}
|
||||
}
|
||||
|
||||
export default MindMap
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.1.6",
|
||||
"version": "0.2.3",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
@@ -18,13 +18,14 @@
|
||||
"url": "https://github.com/wanglin2/mind-map"
|
||||
},
|
||||
"scripts": {},
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"module": "index.js",
|
||||
"main": "./dist/simpleMindMap.umd.min.js",
|
||||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.0.16",
|
||||
"canvg": "^3.0.7",
|
||||
"deepmerge": "^1.5.2",
|
||||
"eventemitter3": "^4.0.7"
|
||||
"eventemitter3": "^4.0.7",
|
||||
"jspdf": "^2.5.1"
|
||||
},
|
||||
"keywords": [
|
||||
"javascript",
|
||||
|
||||
@@ -71,6 +71,9 @@ 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
|
||||
}
|
||||
@@ -96,6 +99,9 @@ class Drag extends Base {
|
||||
this.mouseDownY = y
|
||||
})
|
||||
this.mindMap.on('mousemove', (e) => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
@@ -123,11 +129,12 @@ class Drag extends Base {
|
||||
* @Date: 2021-11-23 19:38:02
|
||||
* @Desc: 鼠标松开事件
|
||||
*/
|
||||
onMouseup() {
|
||||
onMouseup(e) {
|
||||
if (!this.isMousedown) {
|
||||
return;
|
||||
}
|
||||
this.isMousedown = false
|
||||
let _nodeIsDrag = this.node.isDrag
|
||||
this.node.isDrag = false
|
||||
this.node.show()
|
||||
this.removeCloneNode()
|
||||
@@ -141,6 +148,26 @@ class Drag extends Base {
|
||||
} else if (this.nextNode) { // 存在下一个相邻节点,作为其前一个兄弟节点
|
||||
this.mindMap.renderer.setNodeActive(this.nextNode, false)
|
||||
this.mindMap.execCommand('INSERT_BEFORE', this.node, this.nextNode)
|
||||
} else if (_nodeIsDrag) {
|
||||
// 自定义位置
|
||||
let {
|
||||
x,
|
||||
y
|
||||
} = this.mindMap.toPos(e.clientX - this.offsetX, e.clientY - this.offsetY)
|
||||
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.mindMap.render()
|
||||
}
|
||||
this.reset()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { imgToDataUrl, downloadFile } from './utils'
|
||||
import JsPDF from 'jspdf'
|
||||
const URL = window.URL || window.webkitURL || window
|
||||
|
||||
/**
|
||||
@@ -24,8 +25,8 @@ class Export {
|
||||
*/
|
||||
async export(type, isDownload = true, name = '思维导图') {
|
||||
if (this[type]) {
|
||||
let result = await this[type]()
|
||||
if (isDownload) {
|
||||
let result = await this[type](name)
|
||||
if (isDownload && type !== 'pdf') {
|
||||
downloadFile(result, name + '.' + type)
|
||||
}
|
||||
return result
|
||||
@@ -52,7 +53,7 @@ class Export {
|
||||
// 获取变换后的位置尺寸信息,其实是getBoundingClientRect方法的包装方法
|
||||
const rect = draw.rbox()
|
||||
// 将svg设置为实际内容的宽高
|
||||
svg.size(rect.wdith, rect.height)
|
||||
svg.size(rect.width, rect.height)
|
||||
// 把实际内容变换
|
||||
draw.translate(-rect.x + elRect.left, -rect.y + elRect.top)
|
||||
// 克隆一份数据
|
||||
@@ -163,6 +164,43 @@ class Export {
|
||||
return imgDataUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-08 19:23:08
|
||||
* @Desc: 导出为pdf
|
||||
*/
|
||||
async pdf(name) {
|
||||
let img = await this.png()
|
||||
let pdf = new JsPDF('', 'pt', 'a4')
|
||||
let a4Width = 595
|
||||
let a4Height = 841
|
||||
let a4Ratio = a4Width / a4Height
|
||||
let image = new Image()
|
||||
image.onload = () => {
|
||||
let imageWidth = image.width
|
||||
let imageHeight = image.height
|
||||
let imageRatio = imageWidth / imageHeight
|
||||
let w, h
|
||||
if (imageWidth <= a4Width && imageHeight <= a4Height) {
|
||||
// 使用图片原始宽高
|
||||
w = imageWidth
|
||||
h = imageHeight
|
||||
} else if (a4Ratio > imageRatio) {
|
||||
// 以a4Height为高度,缩放图片宽度
|
||||
w = imageRatio * a4Height
|
||||
h = a4Height
|
||||
} else {
|
||||
// 以a4Width为宽度,缩放图片高度
|
||||
w = a4Width
|
||||
h = a4Width / imageRatio
|
||||
}
|
||||
pdf.addImage(img, 'PNG', (a4Width - w) / 2, (a4Height - h) / 2, w, h)
|
||||
pdf.save(name)
|
||||
}
|
||||
image.src = img
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-04 15:32:07
|
||||
@@ -223,4 +261,4 @@ class Export {
|
||||
}
|
||||
}
|
||||
|
||||
export default Export
|
||||
export default Export
|
||||
|
||||
@@ -16,9 +16,51 @@ export default class KeyCommand {
|
||||
this.shortcutMap = {
|
||||
//Enter: [fn]
|
||||
}
|
||||
this.shortcutMapCache = {}
|
||||
this.isPause = false
|
||||
this.bindEvent()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-08-14 08:57:55
|
||||
* @Desc: 暂停快捷键响应
|
||||
*/
|
||||
pause() {
|
||||
this.isPause = true
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-08-14 08:58:43
|
||||
* @Desc: 恢复快捷键响应
|
||||
*/
|
||||
recovery() {
|
||||
this.isPause = false
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-16 16:29:01
|
||||
* @Desc: 保存当前注册的快捷键数据,然后清空快捷键数据
|
||||
*/
|
||||
save() {
|
||||
this.shortcutMapCache = this.shortcutMap
|
||||
this.shortcutMap = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-16 16:29:38
|
||||
* @Desc: 恢复保存的快捷键数据,然后清空缓存数据
|
||||
*/
|
||||
restore() {
|
||||
this.shortcutMap = this.shortcutMapCache
|
||||
this.shortcutMapCache = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-24 15:23:22
|
||||
@@ -26,6 +68,9 @@ export default class KeyCommand {
|
||||
*/
|
||||
bindEvent() {
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (this.isPause) {
|
||||
return
|
||||
}
|
||||
Object.keys(this.shortcutMap).forEach((key) => {
|
||||
if (this.checkKey(e, key)) {
|
||||
e.stopPropagation()
|
||||
@@ -139,4 +184,17 @@ export default class KeyCommand {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-08-14 08:49:58
|
||||
* @Desc: 获取指定快捷键的处理函数
|
||||
*/
|
||||
getShortcutFn(key) {
|
||||
let res = []
|
||||
key.split(/\s*\|\s*/).forEach((item) => {
|
||||
res = this.shortcutMap[item] || []
|
||||
})
|
||||
return res
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,9 @@ class Node {
|
||||
this.style = new Style(this, this.themeConfig)
|
||||
// 是否是根节点
|
||||
this.isRoot = opt.isRoot === undefined ? false : opt.isRoot
|
||||
// 是否是概要节点
|
||||
this.isGeneralization = opt.isGeneralization === undefined ? false : opt.isGeneralization
|
||||
this.generalizationBelongNode = null
|
||||
// 节点层级
|
||||
this.layerIndex = opt.layerIndex === undefined ? 0 : opt.layerIndex
|
||||
// 节点宽
|
||||
@@ -52,9 +55,12 @@ class Node {
|
||||
// 节点高
|
||||
this.height = opt.height || 0
|
||||
// left
|
||||
this.left = opt.left || 0
|
||||
this._left = opt.left || 0
|
||||
// top
|
||||
this.top = opt.top || 0
|
||||
this._top = opt.top || 0
|
||||
// 自定义位置
|
||||
this.customLeft = opt.data.data.customLeft || undefined
|
||||
this.customTop = opt.data.data.customTop || undefined
|
||||
// 是否正在拖拽中
|
||||
this.isDrag = false
|
||||
// 父节点
|
||||
@@ -73,13 +79,18 @@ class Node {
|
||||
this.noteEl = null
|
||||
this._expandBtn = null
|
||||
this._lines = []
|
||||
this._generalizationLine = null
|
||||
this._generalizationNode = null
|
||||
// 尺寸信息
|
||||
this._rectInfo = {
|
||||
imgContentWidth: 0,
|
||||
imgContentHeight: 0,
|
||||
textContentHeight: 0,
|
||||
textContentWidth: 0,
|
||||
textContentHeight: 0
|
||||
}
|
||||
// 概要节点的宽高
|
||||
this._generalizationNodeWidth = 0
|
||||
this._generalizationNodeHeight = 0
|
||||
// 各种文字信息的间距
|
||||
this.textContentItemMargin = this.mindMap.opt.textContentMargin
|
||||
// 图片和文字节点的间距
|
||||
@@ -89,10 +100,27 @@ class Node {
|
||||
// 初始渲染
|
||||
this.initRender = true
|
||||
// 初始化
|
||||
this.createNodeData()
|
||||
// this.createNodeData()
|
||||
this.getSize()
|
||||
}
|
||||
|
||||
// 支持自定义位置
|
||||
get left() {
|
||||
return this.customLeft || this._left
|
||||
}
|
||||
|
||||
set left(val) {
|
||||
this._left = val
|
||||
}
|
||||
|
||||
get top() {
|
||||
return this.customTop || this._top
|
||||
}
|
||||
|
||||
set top(val) {
|
||||
this._top = val
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-12 07:40:47
|
||||
@@ -131,6 +159,33 @@ class Node {
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-02 19:53:40
|
||||
* @Desc: 检查节点是否存在自定义数据
|
||||
*/
|
||||
hasCustomPosition() {
|
||||
return this.customLeft !== undefined && this.customTop !== undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-04 09:06:56
|
||||
* @Desc: 检查节点是否存在自定义位置的祖先节点
|
||||
*/
|
||||
ancestorHasCustomPosition() {
|
||||
let node = this
|
||||
while(node) {
|
||||
if (node.hasCustomPosition()) {
|
||||
return true
|
||||
}
|
||||
node = node.parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
@@ -153,6 +208,7 @@ class Node {
|
||||
this._hyperlinkData = this.createHyperlinkNode()
|
||||
this._tagData = this.createTagNode()
|
||||
this._noteData = this.createNoteNode()
|
||||
this.createGeneralizationNode()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +255,8 @@ class Node {
|
||||
this.group.remove()
|
||||
this.group = null
|
||||
}
|
||||
// 概要
|
||||
this.removeGeneralization()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,6 +557,10 @@ class Node {
|
||||
let { paddingY } = this.getPaddingVale()
|
||||
// 创建组
|
||||
this.group = new G()
|
||||
// 概要节点添加一个带所属节点id的类名
|
||||
if (this.isGeneralization && this.generalizationBelongNode) {
|
||||
this.group.addClass('generalization_' + this.generalizationBelongNode.uid)
|
||||
}
|
||||
this.draw.add(this.group)
|
||||
this.update(true)
|
||||
// 节点矩形
|
||||
@@ -576,11 +638,17 @@ class Node {
|
||||
})
|
||||
// 双击事件
|
||||
this.group.on('dblclick', (e) => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
e.stopPropagation()
|
||||
this.mindMap.emit('node_dblclick', this, e)
|
||||
})
|
||||
// 右键菜单事件
|
||||
this.group.on('contextmenu', (e) => {
|
||||
if (this.mindMap.opt.readonly || this.isGeneralization) {
|
||||
return
|
||||
}
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
if (this.nodeData.data.isActive) {
|
||||
@@ -597,6 +665,9 @@ class Node {
|
||||
* @Desc: 激活节点
|
||||
*/
|
||||
active(e) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
e.stopPropagation()
|
||||
if (this.nodeData.data.isActive) {
|
||||
return
|
||||
@@ -637,6 +708,7 @@ class Node {
|
||||
} else {
|
||||
this.updateExpandBtnPos()
|
||||
}
|
||||
this.renderGeneralization()
|
||||
let t = this.group.transform()
|
||||
if (!layout) {
|
||||
this.group.animate(300).translate(this.left - t.translateX, this.top - t.translateY)
|
||||
@@ -699,6 +771,7 @@ class Node {
|
||||
*/
|
||||
hide() {
|
||||
this.group.hide()
|
||||
this.hideGeneralization()
|
||||
if (this.parent) {
|
||||
let index = this.parent.children.indexOf(this)
|
||||
this.parent._lines[index].hide()
|
||||
@@ -719,8 +792,12 @@ class Node {
|
||||
* @Date: 2021-11-23 18:39:14
|
||||
* @Desc: 显示节点
|
||||
*/
|
||||
show() {
|
||||
show() {
|
||||
if (!this.group) {
|
||||
return;
|
||||
}
|
||||
this.group.show()
|
||||
this.showGeneralization()
|
||||
if (this.parent) {
|
||||
let index = this.parent.children.indexOf(this)
|
||||
this.parent._lines[index].show()
|
||||
@@ -777,6 +854,136 @@ class Node {
|
||||
this._lines = []
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-01 09:27:30
|
||||
* @Desc: 检查是否存在概要
|
||||
*/
|
||||
checkHasGeneralization() {
|
||||
return !!this.nodeData.data.generalization
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-31 09:41:28
|
||||
* @Desc: 创建概要节点
|
||||
*/
|
||||
createGeneralizationNode() {
|
||||
if (this.isGeneralization || !this.checkHasGeneralization()) {
|
||||
return
|
||||
}
|
||||
if (!this._generalizationLine) {
|
||||
this._generalizationLine = this.draw.path()
|
||||
}
|
||||
if (!this._generalizationNode) {
|
||||
this._generalizationNode = new Node({
|
||||
data: {
|
||||
data: this.nodeData.data.generalization
|
||||
},
|
||||
uid: this.mindMap.uid++,
|
||||
renderer: this.renderer,
|
||||
mindMap: this.mindMap,
|
||||
draw: this.draw,
|
||||
isGeneralization: true
|
||||
})
|
||||
this._generalizationNodeWidth = this._generalizationNode.width
|
||||
this._generalizationNodeHeight = this._generalizationNode.height
|
||||
this._generalizationNode.generalizationBelongNode = this
|
||||
if (this.nodeData.data.generalization.isActive) {
|
||||
this.renderer.addActiveNode(this._generalizationNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-01 15:38:52
|
||||
* @Desc: 更新概要节点
|
||||
*/
|
||||
updateGeneralization() {
|
||||
this.removeGeneralization()
|
||||
this.createGeneralizationNode()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 08:35:51
|
||||
* @Desc: 渲染概要节点
|
||||
*/
|
||||
renderGeneralization() {
|
||||
if (this.isGeneralization) {
|
||||
return
|
||||
}
|
||||
if (!this.checkHasGeneralization()) {
|
||||
this.removeGeneralization()
|
||||
this._generalizationNodeWidth = 0
|
||||
this._generalizationNodeHeight = 0
|
||||
return
|
||||
}
|
||||
if (this.nodeData.data.expand === false) {
|
||||
this.removeGeneralization()
|
||||
return
|
||||
}
|
||||
this.createGeneralizationNode()
|
||||
this.renderer.layout.renderGeneralization(this, this._generalizationLine, this._generalizationNode)
|
||||
this.style.generalizationLine(this._generalizationLine)
|
||||
this._generalizationNode.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 13:11:27
|
||||
* @Desc: 删除概要节点
|
||||
*/
|
||||
removeGeneralization() {
|
||||
if (this._generalizationLine) {
|
||||
this._generalizationLine.remove()
|
||||
this._generalizationLine = null
|
||||
}
|
||||
if (this._generalizationNode) {
|
||||
// 删除概要节点时要同步从激活节点里删除
|
||||
this.renderer.removeActiveNode(this._generalizationNode)
|
||||
this._generalizationNode.remove()
|
||||
this._generalizationNode = null
|
||||
}
|
||||
// hack修复当激活一个节点时创建概要,然后立即激活创建的概要节点后会重复创建概要节点并且无法删除的问题
|
||||
if (this.generalizationBelongNode) {
|
||||
this.draw.find('.generalization_' + this.generalizationBelongNode.uid).remove()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-01 09:56:46
|
||||
* @Desc: 隐藏概要节点
|
||||
*/
|
||||
hideGeneralization() {
|
||||
if (this._generalizationLine) {
|
||||
this._generalizationLine.hide()
|
||||
}
|
||||
if (this._generalizationNode) {
|
||||
this._generalizationNode.hide()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-01 09:57:42
|
||||
* @Desc: 显示概要节点
|
||||
*/
|
||||
showGeneralization() {
|
||||
if (this._generalizationLine) {
|
||||
this._generalizationLine.show()
|
||||
}
|
||||
if (this._generalizationNode) {
|
||||
this._generalizationNode.show()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-10 17:59:14
|
||||
@@ -1000,4 +1207,4 @@ class Node {
|
||||
}
|
||||
}
|
||||
|
||||
export default Node
|
||||
export default Node
|
||||
|
||||
@@ -163,6 +163,18 @@ class Render {
|
||||
// 设置节点标签
|
||||
this.setNodeTag = this.setNodeTag.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
|
||||
// 添加节点概要
|
||||
this.addGeneralization = this.addGeneralization.bind(this)
|
||||
this.mindMap.command.add('ADD_GENERALIZATION', this.addGeneralization)
|
||||
// 删除节点概要
|
||||
this.removeGeneralization = this.removeGeneralization.bind(this)
|
||||
this.mindMap.command.add('REMOVE_GENERALIZATION', this.removeGeneralization)
|
||||
// 设置节点自定义位置
|
||||
this.setNodeCustomPosition = this.setNodeCustomPosition.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_CUSTOM_POSITION', this.setNodeCustomPosition)
|
||||
// 一键整理布局
|
||||
this.resetLayout = this.resetLayout.bind(this)
|
||||
this.mindMap.command.add('RESET_LAYOUT', this.resetLayout)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,15 +195,11 @@ class Render {
|
||||
this.mindMap.execCommand('INSERT_NODE')
|
||||
}
|
||||
this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap)
|
||||
// 插入概要
|
||||
this.mindMap.keyCommand.addShortcut('Control+s', this.addGeneralization)
|
||||
// 展开/收起节点
|
||||
this.mindMap.keyCommand.addShortcut('/', () => {
|
||||
this.activeNodeList.forEach((node) => {
|
||||
if (node.nodeData.children.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.toggleNodeExpand(node)
|
||||
})
|
||||
})
|
||||
this.toggleActiveExpand = this.toggleActiveExpand.bind(this)
|
||||
this.mindMap.keyCommand.addShortcut('/', this.toggleActiveExpand)
|
||||
// 删除节点
|
||||
this.removeNodeWrap = () => {
|
||||
this.mindMap.execCommand('REMOVE_NODE')
|
||||
@@ -208,6 +216,13 @@ class Render {
|
||||
this.mindMap.keyCommand.addShortcut('Control+a', () => {
|
||||
this.mindMap.execCommand('SELECT_ALL')
|
||||
})
|
||||
// 一键整理布局
|
||||
this.mindMap.keyCommand.addShortcut('Control+l', this.resetLayout)
|
||||
// 上移节点
|
||||
this.mindMap.keyCommand.addShortcut('Control+Up', this.upNode)
|
||||
// 下移节点
|
||||
this.mindMap.keyCommand.addShortcut('Control+Down', this.downNode)
|
||||
// 复制节点、剪切节点、粘贴节点的快捷键需开发者自行注册实现,可参考demo
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,8 +232,10 @@ class Render {
|
||||
* @Desc: 开启文字编辑,会禁用回车键和删除键相关快捷键防止冲突
|
||||
*/
|
||||
startTextEdit() {
|
||||
this.mindMap.keyCommand.removeShortcut('Del|Backspace')
|
||||
this.mindMap.keyCommand.removeShortcut('Enter', this.insertNodeWrap)
|
||||
this.mindMap.keyCommand.save()
|
||||
// this.mindMap.keyCommand.removeShortcut('Del|Backspace')
|
||||
// this.mindMap.keyCommand.removeShortcut('/')
|
||||
// this.mindMap.keyCommand.removeShortcut('Enter', this.insertNodeWrap)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,8 +245,10 @@ class Render {
|
||||
* @Desc: 结束文字编辑,会恢复回车键和删除键相关快捷键
|
||||
*/
|
||||
endTextEdit() {
|
||||
this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap)
|
||||
this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap)
|
||||
this.mindMap.keyCommand.restore()
|
||||
// this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeNodeWrap)
|
||||
// this.mindMap.keyCommand.addShortcut('/', this.toggleActiveExpand)
|
||||
// this.mindMap.keyCommand.addShortcut('Enter', this.insertNodeWrap)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,6 +265,7 @@ class Render {
|
||||
this.root = root
|
||||
this.root.render()
|
||||
})
|
||||
this.mindMap.emit('node_active', null, this.activeNodeList)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,13 +399,14 @@ class Render {
|
||||
if (first.isRoot) {
|
||||
this.insertChildNode()
|
||||
} else {
|
||||
let text = first.layerIndex === 1 ? '二级节点' : '分支主题'
|
||||
if (first.layerIndex === 1) {
|
||||
first.parent.initRender = true
|
||||
}
|
||||
let index = this.getNodeIndex(first)
|
||||
first.parent.nodeData.children.splice(index + 1, 0, {
|
||||
"data": {
|
||||
"text": "分支主题",
|
||||
"text": text,
|
||||
"expand": true
|
||||
},
|
||||
"children": []
|
||||
@@ -407,9 +428,10 @@ class Render {
|
||||
if (!node.nodeData.children) {
|
||||
node.nodeData.children = []
|
||||
}
|
||||
let text = node.isRoot ? '二级节点' : '分支主题'
|
||||
node.nodeData.children.push({
|
||||
"data": {
|
||||
"text": "分支主题",
|
||||
"text": text,
|
||||
"expand": true
|
||||
},
|
||||
"children": []
|
||||
@@ -579,7 +601,15 @@ class Render {
|
||||
}
|
||||
for (let i = 0; i < this.activeNodeList.length; i++) {
|
||||
let node = this.activeNodeList[i]
|
||||
if (node.isRoot) {
|
||||
if (node.isGeneralization) {
|
||||
// 删除概要节点
|
||||
this.setNodeData(node.generalizationBelongNode, {
|
||||
generalization: null
|
||||
})
|
||||
node.generalizationBelongNode.update()
|
||||
this.removeActiveNode(node)
|
||||
i--
|
||||
} else if (node.isRoot) {
|
||||
node.children.forEach((child) => {
|
||||
child.remove()
|
||||
})
|
||||
@@ -769,6 +799,20 @@ class Render {
|
||||
}, null, true, 0, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-08-14 09:18:40
|
||||
* @Desc: 切换激活节点的展开状态
|
||||
*/
|
||||
toggleActiveExpand() {
|
||||
this.activeNodeList.forEach((node) => {
|
||||
if (node.nodeData.children.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.toggleNodeExpand(node)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-11 17:15:33
|
||||
@@ -855,6 +899,84 @@ class Render {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 20:52:42
|
||||
* @Desc: 添加节点概要
|
||||
*/
|
||||
addGeneralization(data) {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.activeNodeList.forEach((node) => {
|
||||
if (node.nodeData.data.generalization || node.isRoot) {
|
||||
return
|
||||
}
|
||||
this.setNodeData(node, {
|
||||
generalization: data || {
|
||||
text: '概要'
|
||||
}
|
||||
})
|
||||
node.update()
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 21:16:33
|
||||
* @Desc: 删除节点概要
|
||||
*/
|
||||
removeGeneralization() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.activeNodeList.forEach((node) => {
|
||||
if (!node.nodeData.data.generalization) {
|
||||
return
|
||||
}
|
||||
this.setNodeData(node, {
|
||||
generalization: null
|
||||
})
|
||||
node.update()
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-02 19:04:24
|
||||
* @Desc: 设置节点自定义位置
|
||||
*/
|
||||
setNodeCustomPosition(node, left = undefined, top = undefined) {
|
||||
let nodeList = [node] || this.activeNodeList
|
||||
nodeList.forEach((item) => {
|
||||
this.setNodeData(item, {
|
||||
customLeft: left,
|
||||
customTop: top
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-02 20:02:50
|
||||
* @Desc: 一键整理布局,即去除自定义位置
|
||||
*/
|
||||
resetLayout() {
|
||||
walk(this.root, null, (node) => {
|
||||
node.customLeft = undefined
|
||||
node.customTop = undefined
|
||||
this.setNodeData(node, {
|
||||
customLeft: undefined,
|
||||
customTop: undefined
|
||||
})
|
||||
this.mindMap.render()
|
||||
}, null, true, 0, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:19:48
|
||||
@@ -876,6 +998,10 @@ class Render {
|
||||
let changed = node.getSize()
|
||||
node.renderNode()
|
||||
if (changed) {
|
||||
if (node.isGeneralization) {
|
||||
// 概要节点
|
||||
node.generalizationBelongNode.updateGeneralization()
|
||||
}
|
||||
this.mindMap.render()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@ class Select {
|
||||
bindEvent() {
|
||||
this.checkInNodes = throttle(this.checkInNodes, 500, this)
|
||||
this.mindMap.on('mousedown', (e) => {
|
||||
if (e.which !== 3) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!e.ctrlKey && e.which !== 3) {
|
||||
return
|
||||
}
|
||||
this.isMousedown = true
|
||||
@@ -41,6 +44,9 @@ class Select {
|
||||
this.createRect(x, y)
|
||||
})
|
||||
this.mindMap.on('mousemove', (e) => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
@@ -54,6 +60,9 @@ class Select {
|
||||
this.onMove(x, y)
|
||||
})
|
||||
this.mindMap.on('mouseup', (e) => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ class Style {
|
||||
let defaultConfig = this.themeConfig.node
|
||||
if (root || rootProp.includes(prop)) {// 直接使用最外层样式
|
||||
defaultConfig = this.themeConfig
|
||||
} else if (this.ctx.isGeneralization) {// 概要节点
|
||||
defaultConfig = this.themeConfig.generalization
|
||||
} else if (this.ctx.layerIndex === 0) {// 根节点
|
||||
defaultConfig = this.themeConfig.root
|
||||
} else if (this.ctx.layerIndex === 1) {// 二级节点
|
||||
@@ -154,6 +156,15 @@ class Style {
|
||||
node.stroke({ width: this.merge('lineWidth', true), color: this.merge('lineColor', true) }).fill({ color: 'none' })
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 16:19:03
|
||||
* @Desc: 概要连线
|
||||
*/
|
||||
generalizationLine(node) {
|
||||
node.stroke({ width: this.merge('generalizationLineWidth', true), color: this.merge('generalizationLineColor', true) }).fill({ color: 'none' })
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 20:03:59
|
||||
|
||||
@@ -47,10 +47,6 @@ export default class TextEdit {
|
||||
this.mindMap.on('before_node_active', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
// 注册回车快捷键
|
||||
this.mindMap.keyCommand.addShortcut('Enter', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
// 注册编辑快捷键
|
||||
this.mindMap.keyCommand.addShortcut('F2', () => {
|
||||
if (this.renderer.activeNodeList.length <= 0) {
|
||||
@@ -60,6 +56,19 @@ export default class TextEdit {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-16 16:27:02
|
||||
* @Desc: 注册临时快捷键
|
||||
*/
|
||||
registerTmpShortcut() {
|
||||
// 注册回车快捷键
|
||||
this.mindMap.keyCommand.addShortcut('Enter', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-13 22:15:56
|
||||
@@ -76,6 +85,7 @@ export default class TextEdit {
|
||||
*/
|
||||
showEditTextBox(node, rect) {
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
this.registerTmpShortcut()
|
||||
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;`
|
||||
@@ -119,6 +129,10 @@ export default class TextEdit {
|
||||
this.renderer.activeNodeList.forEach((node) => {
|
||||
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
|
||||
this.mindMap.execCommand('SET_NODE_TEXT', node, str)
|
||||
if (node.isGeneralization) {
|
||||
// 概要节点
|
||||
node.generalizationBelongNode.updateGeneralization()
|
||||
}
|
||||
this.mindMap.render()
|
||||
})
|
||||
this.mindMap.emit('hide_text_edit', this.textEditNode, this.renderer.activeNodeList)
|
||||
|
||||
@@ -50,6 +50,10 @@ class View {
|
||||
this.sy = this.y
|
||||
})
|
||||
this.mindMap.event.on('drag', (e, event) => {
|
||||
if (e.ctrlKey) {
|
||||
// 按住ctrl键拖动为多选
|
||||
return
|
||||
}
|
||||
if (this.firstDrag) {
|
||||
this.firstDrag = false
|
||||
// 清除激活节点
|
||||
|
||||
BIN
simple-mind-map/src/assets/classic4.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -1,4 +1,7 @@
|
||||
import Node from '../Node'
|
||||
import {
|
||||
walk,
|
||||
} from '../utils'
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
@@ -49,6 +52,13 @@ class Base {
|
||||
throw new Error('【renderExpandBtn】方法为必要方法,需要子类进行重写!')
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 22:49:28
|
||||
* @Desc: 概要节点
|
||||
*/
|
||||
renderGeneralization() {}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-10 21:30:54
|
||||
@@ -109,7 +119,7 @@ class Base {
|
||||
updateChildren(children, prop, offset) {
|
||||
children.forEach((item) => {
|
||||
item[prop] += offset
|
||||
if (item.children && item.children.length) {
|
||||
if (item.children && item.children.length && !item.hasCustomPosition()) {// 适配自定义位置
|
||||
this.updateChildren(item.children, prop, offset)
|
||||
}
|
||||
})
|
||||
@@ -156,6 +166,83 @@ class Base {
|
||||
getMarginY(layerIndex) {
|
||||
return layerIndex === 1 ? this.mindMap.themeConfig.second.marginY : this.mindMap.themeConfig.node.marginY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-31 20:53:12
|
||||
* @Desc: 获取节点包括概要在内的宽度
|
||||
*/
|
||||
getNodeWidthWithGeneralization(node) {
|
||||
return Math.max(node.width, node.checkHasGeneralization() ? node._generalizationNodeWidth : 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-31 20:53:12
|
||||
* @Desc: 获取节点包括概要在内的高度
|
||||
*/
|
||||
getNodeHeightWithGeneralization(node) {
|
||||
return Math.max(node.height, node.checkHasGeneralization() ? node._generalizationNodeHeight : 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-31 09:14:03
|
||||
* @Desc: 获取节点的边界值
|
||||
* dir:生长方向,h(水平)、v(垂直)
|
||||
* isLeft:是否向左生长
|
||||
*/
|
||||
getNodeBoundaries(node, dir, isLeft) {
|
||||
let { generalizationLineMargin, generalizationNodeMargin } = this.mindMap.themeConfig
|
||||
let walk = (root) => {
|
||||
let _left = Infinity
|
||||
let _right = -Infinity
|
||||
let _top = Infinity
|
||||
let _bottom = -Infinity
|
||||
if (root.children && root.children.length > 0) {
|
||||
root.children.forEach((child) => {
|
||||
let {left, right, top, bottom} = walk(child)
|
||||
// 概要内容的宽度
|
||||
let generalizationWidth = child.checkHasGeneralization() && child.nodeData.data.expand ? child._generalizationNodeWidth + generalizationNodeMargin : 0
|
||||
// 概要内容的高度
|
||||
let generalizationHeight = child.checkHasGeneralization() && child.nodeData.data.expand ? child._generalizationNodeHeight + generalizationNodeMargin : 0
|
||||
if (left - (dir === 'h' ? generalizationWidth : 0) < _left) {
|
||||
_left = left - (dir === 'h' ? generalizationWidth : 0)
|
||||
}
|
||||
if (right + (dir === 'h' ? generalizationWidth : 0) > _right) {
|
||||
_right = right + (dir === 'h' ? generalizationWidth : 0)
|
||||
}
|
||||
if (top < _top) {
|
||||
_top = top
|
||||
}
|
||||
if (bottom + (dir === 'v' ? generalizationHeight : 0) > _bottom) {
|
||||
_bottom = bottom + (dir === 'v' ? generalizationHeight : 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
let cur = {
|
||||
left: root.left,
|
||||
right: root.left + root.width,
|
||||
top: root.top,
|
||||
bottom: root.top + root.height
|
||||
}
|
||||
return {
|
||||
left: cur.left < _left ? cur.left : _left,
|
||||
right: cur.right > _right ? cur.right : _right,
|
||||
top: cur.top < _top ? cur.top : _top,
|
||||
bottom: cur.bottom > _bottom ? cur.bottom : _bottom
|
||||
}
|
||||
}
|
||||
let {left, right, top, bottom} = walk(node)
|
||||
return {
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
bottom,
|
||||
generalizationLineMargin,
|
||||
generalizationNodeMargin
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default Base
|
||||
@@ -165,15 +165,18 @@ class CatalogOrganization extends Base {
|
||||
let index = childrenList.findIndex((item) => {
|
||||
return item === node
|
||||
})
|
||||
// 第一个或最后一个节点自身也需要移动,否则两边不对称
|
||||
if (index === 0 || index === childrenList.length - 1) {
|
||||
// 存在大于一个节点时,第一个或最后一个节点自身也需要移动,否则两边不对称
|
||||
if ((index === 0 || index === childrenList.length - 1) && childrenList.length > 1) {
|
||||
let _offset = index === 0 ? -addWidth : addWidth
|
||||
node.left += _offset
|
||||
if (node.children && node.children.length) {
|
||||
if (node.children && node.children.length && !node.hasCustomPosition()) {
|
||||
this.updateChildren(node.children, 'left', _offset)
|
||||
}
|
||||
}
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item.hasCustomPosition()) {// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
if (_index < index) { // 左边的节点往左移
|
||||
_offset = -addWidth
|
||||
@@ -204,6 +207,9 @@ class CatalogOrganization extends Base {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item.hasCustomPosition()) {// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
// 下面的节点往下移
|
||||
if (_index > index) {
|
||||
@@ -239,44 +245,80 @@ class CatalogOrganization extends Base {
|
||||
let len = node.children.length
|
||||
let marginX = this.getMarginX(node.layerIndex + 1)
|
||||
if (node.isRoot) {
|
||||
// 根节点
|
||||
let x1 = left + width / 2
|
||||
let y1 = top + height
|
||||
let s1 = marginX * 0.7
|
||||
let minx = 0
|
||||
let maxx = 0
|
||||
let minx = Infinity
|
||||
let maxx = -Infinity
|
||||
node.children.forEach((item, index) => {
|
||||
let x2 = item.left +item.width / 2
|
||||
let y2 = item.top
|
||||
if (index === 0) {
|
||||
if (x2 < minx) {
|
||||
minx = x2
|
||||
} else if (index >= len - 1) {
|
||||
}
|
||||
if (x2 > maxx) {
|
||||
maxx = x2
|
||||
}
|
||||
let path = `M ${x2},${y1 + s1} L ${x2},${y2}`
|
||||
let path = `M ${x2},${y1 + s1} L ${x2},${y1 + s1 > y2 ? y2 + item.height : y2}`
|
||||
// 竖线
|
||||
lines[index].plot(path)
|
||||
})
|
||||
minx = Math.min(minx, x1)
|
||||
maxx = Math.max(maxx, x1)
|
||||
// 父节点的竖线
|
||||
let line1 = this.draw.path()
|
||||
node.style.line(line1)
|
||||
line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`)
|
||||
node._lines.push(line1)
|
||||
// 水平线
|
||||
if (len > 1) {
|
||||
if (len > 0) {
|
||||
let lin2 = this.draw.path()
|
||||
node.style.line(lin2)
|
||||
lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`)
|
||||
node._lines.push(lin2)
|
||||
}
|
||||
} else {
|
||||
// 非根节点
|
||||
let y1 = top + height
|
||||
let maxy = 0
|
||||
let maxy = -Infinity
|
||||
let x2 = node.left + node.width * 0.3
|
||||
node.children.forEach((item, index) => {
|
||||
// 为了适配自定义位置,下面做了各种位置的兼容
|
||||
let y2 = item.top + item.height / 2
|
||||
if (index >= len - 1) {
|
||||
if (y2 > maxy) {
|
||||
maxy = y2
|
||||
}
|
||||
let path = `M ${x2},${y2} L ${x2 + node.width * 0.2},${y2}`
|
||||
// 水平线
|
||||
let path = ''
|
||||
let _left = item.left
|
||||
let _isLeft = item.left + item.width < x2
|
||||
let _isXCenter = false
|
||||
if (_isLeft) {
|
||||
// 水平位置在父节点左边
|
||||
_left = item.left + item.width
|
||||
} else if (item.left < x2 && item.left + item.width > x2) {
|
||||
// 水平位置在父节点之间
|
||||
_isXCenter = true
|
||||
y2 = item.top
|
||||
maxy = y2
|
||||
}
|
||||
if (y2 > top && y2 < y1) {
|
||||
// 自定义位置的情况:垂直位置节点在父节点之间
|
||||
path = `M ${_isLeft ? node.left : node.left + node.width},${y2} L ${_left},${y2}`
|
||||
} else if (y2 < y1) {
|
||||
// 自定义位置的情况:垂直位置节点在父节点上面
|
||||
if (_isXCenter) {
|
||||
y2 = item.top + item.height
|
||||
_left = x2
|
||||
}
|
||||
path = `M ${x2},${top} L ${x2},${y2} L ${_left},${y2}`
|
||||
} else {
|
||||
if (_isXCenter) {
|
||||
_left = x2
|
||||
}
|
||||
path = `M ${x2},${y2} L ${_left},${y2}`
|
||||
}
|
||||
lines[index].plot(path)
|
||||
})
|
||||
// 竖线
|
||||
@@ -284,7 +326,12 @@ class CatalogOrganization extends Base {
|
||||
let lin2 = this.draw.path()
|
||||
expandBtnSize = len > 0 ? expandBtnSize : 0
|
||||
node.style.line(lin2)
|
||||
lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`)
|
||||
if (maxy < y1 + expandBtnSize) {
|
||||
lin2.hide()
|
||||
} else {
|
||||
lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`)
|
||||
lin2.show()
|
||||
}
|
||||
node._lines.push(lin2)
|
||||
}
|
||||
}
|
||||
@@ -310,6 +357,25 @@ class CatalogOrganization extends Base {
|
||||
btn.translate(width * 0.3 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 08:30:35
|
||||
* @Desc: 创建概要节点
|
||||
*/
|
||||
renderGeneralization(node, gLine, gNode) {
|
||||
let { top, bottom, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'h')
|
||||
let x1 = right + generalizationLineMargin
|
||||
let y1 = top
|
||||
let x2 = right + generalizationLineMargin
|
||||
let y2 = bottom
|
||||
let cx = x1 + 20
|
||||
let cy = y1 + (y2 - y1) / 2
|
||||
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
gLine.plot(path)
|
||||
gNode.left = right + generalizationNodeMargin
|
||||
gNode.top = top + (bottom - top - gNode.height) / 2
|
||||
}
|
||||
}
|
||||
|
||||
export default CatalogOrganization
|
||||
@@ -120,7 +120,7 @@ class LogicalStructure extends Base {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item === node) {
|
||||
if (item === node || item.hasCustomPosition()) {// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
@@ -188,6 +188,25 @@ class LogicalStructure extends Base {
|
||||
} = btn.transform()
|
||||
btn.translate(width - translateX, height / 2 - translateY)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 08:30:35
|
||||
* @Desc: 创建概要节点
|
||||
*/
|
||||
renderGeneralization(node, gLine, gNode) {
|
||||
let { top, bottom, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'h')
|
||||
let x1 = right + generalizationLineMargin
|
||||
let y1 = top
|
||||
let x2 = right + generalizationLineMargin
|
||||
let y2 = bottom
|
||||
let cx = x1 + 20
|
||||
let cy = y1 + (y2 - y1) / 2
|
||||
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
gLine.plot(path)
|
||||
gNode.left = right + generalizationNodeMargin
|
||||
gNode.top = top + (bottom - top - gNode.height) / 2
|
||||
}
|
||||
}
|
||||
|
||||
export default LogicalStructure
|
||||
@@ -155,6 +155,9 @@ class MindMap extends Base {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item.hasCustomPosition()) {// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
let addHeight = item.dir === 'left' ? leftAddHeight : rightAddHeight
|
||||
// 上面的节点往上移
|
||||
@@ -224,6 +227,27 @@ class MindMap extends Base {
|
||||
let y = height / 2 - translateY
|
||||
btn.translate(x, y)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 08:30:35
|
||||
* @Desc: 创建概要节点
|
||||
*/
|
||||
renderGeneralization(node, gLine, gNode) {
|
||||
let isLeft = node.dir === 'left'
|
||||
let { top, bottom, left, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'h', isLeft)
|
||||
let x = isLeft ? left - generalizationLineMargin : right + generalizationLineMargin
|
||||
let x1 = x
|
||||
let y1 = top
|
||||
let x2 = x
|
||||
let y2 = bottom
|
||||
let cx = x1 + (isLeft ? -20 : 20)
|
||||
let cy = y1 + (y2 - y1) / 2
|
||||
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
gLine.plot(path)
|
||||
gNode.left = x + (isLeft ? -generalizationNodeMargin : generalizationNodeMargin) - (isLeft ? gNode.width : 0)
|
||||
gNode.top = top + (bottom - top - gNode.height) / 2
|
||||
}
|
||||
}
|
||||
|
||||
export default MindMap
|
||||
@@ -121,6 +121,9 @@ class OrganizationStructure extends Base {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item.hasCustomPosition()) {// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
// 上面的节点往上移
|
||||
if (_index < index) {
|
||||
@@ -160,20 +163,23 @@ class OrganizationStructure extends Base {
|
||||
let y1 = top + height
|
||||
let marginX = this.getMarginX(node.layerIndex + 1)
|
||||
let s1 = marginX * 0.7
|
||||
let minx = 0
|
||||
let maxx = 0
|
||||
let minx = Infinity
|
||||
let maxx = -Infinity
|
||||
let len = node.children.length
|
||||
node.children.forEach((item, index) => {
|
||||
let x2 = item.left + item.width / 2
|
||||
let y2 = item.top
|
||||
if (index === 0) {
|
||||
let y2 = y1 + s1 > item.top ? item.top + item.height : item.top
|
||||
if (x2 < minx) {
|
||||
minx = x2
|
||||
} else if (index >= len - 1) {
|
||||
}
|
||||
if (x2 > maxx) {
|
||||
maxx = x2
|
||||
}
|
||||
let path = `M ${x2},${y1 + s1} L ${x2},${y2}`
|
||||
lines[index].plot(path)
|
||||
})
|
||||
minx = Math.min(x1, minx)
|
||||
maxx = Math.max(x1, maxx)
|
||||
// 父节点的竖线
|
||||
let line1 = this.draw.path()
|
||||
node.style.line(line1)
|
||||
@@ -181,7 +187,7 @@ class OrganizationStructure extends Base {
|
||||
line1.plot(`M ${x1},${y1 + expandBtnSize} L ${x1},${y1 + s1}`)
|
||||
node._lines.push(line1)
|
||||
// 水平线
|
||||
if (len > 1) {
|
||||
if (len > 0) {
|
||||
let lin2 = this.draw.path()
|
||||
node.style.line(lin2)
|
||||
lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`)
|
||||
@@ -206,6 +212,25 @@ class OrganizationStructure extends Base {
|
||||
} = btn.transform()
|
||||
btn.translate(width / 2 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2022-07-30 08:30:35
|
||||
* @Desc: 创建概要节点
|
||||
*/
|
||||
renderGeneralization(node, gLine, gNode) {
|
||||
let { bottom, left, right, generalizationLineMargin, generalizationNodeMargin } = this.getNodeBoundaries(node, 'v')
|
||||
let x1 = left
|
||||
let y1 = bottom + generalizationLineMargin
|
||||
let x2 = right
|
||||
let y2 = bottom + generalizationLineMargin
|
||||
let cx = x1 + (x2 - x1) / 2
|
||||
let cy = y1 + 20
|
||||
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
gLine.plot(path)
|
||||
gNode.top = bottom + generalizationNodeMargin
|
||||
gNode.left = left + (right - left - gNode.width) / 2
|
||||
}
|
||||
}
|
||||
|
||||
export default OrganizationStructure
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(115, 161, 191)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#333',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(115, 161, 191)',
|
||||
@@ -37,4 +41,13 @@ export default merge(defaultTheme, {
|
||||
borderColor: 'rgb(57, 80, 96)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#333',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(191, 115, 148)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#333',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(191, 115, 148)',
|
||||
@@ -36,5 +40,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 74)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#333',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 74)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: '#fff',
|
||||
// 连线的粗细
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#fff',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(58, 65, 68)',
|
||||
// 背景图片
|
||||
@@ -49,5 +53,15 @@ export default merge(defaultTheme, {
|
||||
fillColor: 'rgb(254, 219, 0)',
|
||||
borderColor: 'transparent'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'transparent',
|
||||
color: '#333',
|
||||
active: {
|
||||
fillColor: 'rgb(254, 219, 0)',
|
||||
borderColor: 'transparent'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(51, 51, 51)',
|
||||
// 背景颜色
|
||||
backgroundColor: '#fff',
|
||||
// 根节点样式
|
||||
@@ -41,5 +45,15 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(51, 51, 51)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'rgb(51, 51, 51)',
|
||||
borderWidth: 2,
|
||||
color: '#1a1a1a',
|
||||
active: {
|
||||
borderColor: 'rgb(18, 187, 55)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(94, 202, 110)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#1a1a1a',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(241, 241, 241)',
|
||||
// 根节点样式
|
||||
@@ -44,5 +48,15 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(94, 202, 110)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#1a1a1a',
|
||||
color: '#1a1a1a',
|
||||
borderWidth: 2,
|
||||
active: {
|
||||
borderColor: 'rgb(94, 202, 110)'
|
||||
}
|
||||
}
|
||||
})
|
||||
65
simple-mind-map/src/themes/classic4.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import defaultTheme from './default';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-04-11 15:22:18
|
||||
* @Desc: 经典4
|
||||
*/
|
||||
export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(30, 53, 86)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 2,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(56, 123, 233)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(241, 241, 241)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(30, 53, 86)',
|
||||
color: '#fff',
|
||||
fontSize: 24,
|
||||
borderRadius: 10,
|
||||
borderColor: 'rgb(189, 197, 201)',
|
||||
borderWidth: 2,
|
||||
active: {
|
||||
borderColor: 'rgb(169, 218, 218)'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
second: {
|
||||
fillColor: 'rgb(169, 218, 218)',
|
||||
borderColor: 'rgb(30, 53, 86)',
|
||||
borderWidth: 2,
|
||||
color: '#fff',
|
||||
fontSize: 18,
|
||||
borderRadius: 10,
|
||||
active: {
|
||||
borderColor: 'rgb(56, 123, 233)'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
fontSize: 14,
|
||||
color: 'rgb(30, 53, 86)',
|
||||
borderColor: 'rgb(30, 53, 86)',
|
||||
borderWidth: 1,
|
||||
marginY: 20,
|
||||
active: {
|
||||
borderColor: 'rgb(169, 218, 218)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: 'rgb(56, 123, 233)',
|
||||
borderColor: 'rgb(56, 123, 233)',
|
||||
color: '#fff',
|
||||
borderWidth: 0,
|
||||
active: {
|
||||
borderColor: 'rgb(169, 218, 218)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 2,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(51, 51, 51)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(239, 248, 250)',
|
||||
// 根节点样式
|
||||
@@ -39,5 +43,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(94, 199, 248)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'rgb(51, 51, 51)',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(94, 199, 248)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(123, 199, 120)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(236, 245, 231)',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 2,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(123, 199, 120)',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(253, 244, 217)',
|
||||
@@ -37,5 +41,15 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(94, 199, 248)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: 'rgb(123, 199, 120)',
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 2,
|
||||
color: '#fff',
|
||||
active: {
|
||||
borderColor: 'rgb(94, 199, 248)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(17, 68, 23)',
|
||||
// 连线的粗细
|
||||
lineWidth: 2,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 2,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#fff',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(15, 16, 17)',
|
||||
// 根节点样式
|
||||
@@ -41,5 +45,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(17, 68, 23)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'transparent',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(17, 68, 23)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(75, 81, 78)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(255, 119, 34)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(27, 31, 34)',
|
||||
// 根节点样式
|
||||
@@ -42,5 +46,15 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(254, 199, 13)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: 'transparent',
|
||||
borderColor: 'rgb(255, 119, 34)',
|
||||
borderWidth: 2,
|
||||
color: 'rgb(204, 204, 204)',
|
||||
active: {
|
||||
borderColor: 'rgb(254, 199, 13)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -17,6 +17,14 @@ export default {
|
||||
lineWidth: 1,
|
||||
// 连线的颜色
|
||||
lineColor: '#549688',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#549688',
|
||||
// 概要曲线距节点的距离
|
||||
generalizationLineMargin: 0,
|
||||
// 概要节点距节点的距离
|
||||
generalizationNodeMargin: 20,
|
||||
// 背景颜色
|
||||
backgroundColor: '#fafafa',
|
||||
// 背景图片
|
||||
@@ -86,5 +94,27 @@ export default {
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none',
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
marginX: 100,
|
||||
marginY: 40,
|
||||
fillColor: '#fff',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#565656',
|
||||
fontSize: 16,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: '#549688',
|
||||
borderWidth: 1,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none',
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(191, 147, 115)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#333',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(191, 147, 115)',
|
||||
@@ -36,5 +40,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(96, 73, 57)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#333',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 73, 57)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: '#333',
|
||||
// 背景颜色
|
||||
backgroundColor: '#d1f6ec',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#333',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: '#1fb27d'
|
||||
@@ -22,4 +26,15 @@ export default merge(defaultTheme, {
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#333',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none',
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(191, 115, 115)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#333',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(191, 115, 115)',
|
||||
@@ -36,5 +40,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 57)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#333',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(96, 57, 57)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 56, 62)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(127, 93, 64)',
|
||||
// 背景颜色
|
||||
backgroundColor: '#fff',
|
||||
// 根节点样式
|
||||
@@ -42,5 +46,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(0, 192, 184)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: 'rgb(127, 93, 64)',
|
||||
borderColor: 'transparent',
|
||||
color: 'rgb(255, 214, 175)',
|
||||
active: {
|
||||
borderColor: 'rgb(51, 56, 62)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(40, 193, 84)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(251, 158, 0)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(238, 255, 243)',
|
||||
// 根节点样式
|
||||
@@ -42,5 +46,15 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(25, 193, 73)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'rgb(251, 158, 0)',
|
||||
borderWidth: 2,
|
||||
color: 'rgb(51, 51, 51)',
|
||||
active: {
|
||||
borderColor: 'rgb(25, 193, 73)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -8,6 +8,7 @@ import earthYellow from './earthYellow'
|
||||
import classic from './classic'
|
||||
import classic2 from './classic2'
|
||||
import classic3 from './classic3'
|
||||
import classic4 from './classic4';
|
||||
import dark from './dark';
|
||||
import classicGreen from './classicGreen'
|
||||
import classicBlue from './classicBlue'
|
||||
@@ -31,6 +32,7 @@ export default {
|
||||
classic,
|
||||
classic2,
|
||||
classic3,
|
||||
classic4,
|
||||
dark,
|
||||
classicGreen,
|
||||
classicBlue,
|
||||
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#222',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(248, 215, 49)',
|
||||
// 根节点样式
|
||||
@@ -39,5 +43,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(55, 165, 255)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
borderColor: '#222',
|
||||
borderWidth: 3,
|
||||
color: '#222',
|
||||
active: {
|
||||
borderColor: 'rgb(55, 165, 255)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(104, 204, 202)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(90, 206, 241)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(239, 255, 255)',
|
||||
// 根节点样式
|
||||
@@ -40,5 +44,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(0, 192, 184)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: 'rgb(90, 206, 241)',
|
||||
borderColor: 'transparent',
|
||||
color: '#fff',
|
||||
active: {
|
||||
borderColor: 'rgb(0, 192, 184)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(166, 101, 106)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#fff',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(255, 208, 211)',
|
||||
// 根节点样式
|
||||
@@ -41,5 +45,15 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(139, 109, 225)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'transparent',
|
||||
color: '#222',
|
||||
active: {
|
||||
borderColor: 'rgb(139, 109, 225)',
|
||||
borderWidth: 2,
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -11,6 +11,10 @@ export default merge(defaultTheme, {
|
||||
lineColor: 'rgb(123, 115, 191)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(251, 251, 251)',
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#333',
|
||||
// 根节点样式
|
||||
root: {
|
||||
fillColor: 'rgb(123, 115, 191)',
|
||||
@@ -36,5 +40,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(61, 57, 96)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: '#333',
|
||||
color: '#333',
|
||||
active: {
|
||||
borderColor: 'rgb(61, 57, 96)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: '#fff',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#fff',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(80, 156, 170)',
|
||||
// 根节点样式
|
||||
@@ -42,5 +46,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(251, 227, 188)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: '#fff',
|
||||
borderColor: 'transparent',
|
||||
color: 'rgb(65, 89, 158)',
|
||||
active: {
|
||||
borderColor: 'rgb(251, 227, 188)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -10,6 +10,10 @@ export default merge(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(254, 146, 0)',
|
||||
lineWidth: 3,
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 3,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: 'rgb(255, 222, 69)',
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(255, 246, 243)',
|
||||
// 根节点样式
|
||||
@@ -42,5 +46,14 @@ export default merge(defaultTheme, {
|
||||
active: {
|
||||
borderColor: 'rgb(255, 112, 52)'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
fillColor: 'rgb(255, 222, 69)',
|
||||
borderColor: 'transparent',
|
||||
color: 'rgb(51, 51, 51)',
|
||||
active: {
|
||||
borderColor: 'rgb(255, 112, 52)'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -122,6 +122,11 @@ export const themeList = [
|
||||
value: 'classic3',
|
||||
img: require('../assets/classic3.jpg')
|
||||
},
|
||||
{
|
||||
name: '脑图经典4',
|
||||
value: 'classic4',
|
||||
img: require('../assets/classic4.jpg')
|
||||
},
|
||||
{
|
||||
name: '经典绿',
|
||||
value: 'classicGreen',
|
||||
|
||||
@@ -178,7 +178,7 @@ export const imgToDataUrl = (src) => {
|
||||
// 图片绘制到canvas里
|
||||
ctx.drawImage(img, 0, 0, img.width, img.height)
|
||||
resolve(canvas.toDataURL())
|
||||
} catch (error) {
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
}
|
||||
@@ -229,7 +229,7 @@ export const asyncRun = (taskList, callback = () => {}) => {
|
||||
let index = 0
|
||||
let len = taskList.length
|
||||
if (len <= 0) {
|
||||
return
|
||||
return callback()
|
||||
}
|
||||
let loop = () => {
|
||||
if (index >= len) {
|
||||
@@ -243,4 +243,4 @@ export const asyncRun = (taskList, callback = () => {}) => {
|
||||
}, 0)
|
||||
}
|
||||
loop()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build && node ../copy.js",
|
||||
"lint": "vue-cli-service lint"
|
||||
"lint": "vue-cli-service lint",
|
||||
"buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/index.js --dest ../simple-mind-map/dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@toast-ui/editor": "^3.1.5",
|
||||
|
||||
BIN
web/src/.DS_Store
vendored
BIN
web/src/assets/.DS_Store
vendored
@@ -54,6 +54,48 @@
|
||||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">剪切</div>
|
||||
<div class="code-name">&#xe601;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">整理</div>
|
||||
<div class="code-name">&#xe83b;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">复制</div>
|
||||
<div class="code-name">&#xe604;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">粘贴</div>
|
||||
<div class="code-name">&#xe63f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">上移</div>
|
||||
<div class="code-name">&#xe6be;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">下移</div>
|
||||
<div class="code-name">&#xe6bf;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">概括总览</div>
|
||||
<div class="code-name">&#xe609;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">全选</div>
|
||||
@@ -258,9 +300,9 @@
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.woff2?t=1628093007325') format('woff2'),
|
||||
url('iconfont.woff?t=1628093007325') format('woff'),
|
||||
url('iconfont.ttf?t=1628093007325') format('truetype');
|
||||
src: url('iconfont.woff2?t=1659615576455') format('woff2'),
|
||||
url('iconfont.woff?t=1659615576455') format('woff'),
|
||||
url('iconfont.ttf?t=1659615576455') format('truetype');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
@@ -286,6 +328,69 @@
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconjianqie"></span>
|
||||
<div class="name">
|
||||
剪切
|
||||
</div>
|
||||
<div class="code-name">.iconjianqie
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconzhengli"></span>
|
||||
<div class="name">
|
||||
整理
|
||||
</div>
|
||||
<div class="code-name">.iconzhengli
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconfuzhi"></span>
|
||||
<div class="name">
|
||||
复制
|
||||
</div>
|
||||
<div class="code-name">.iconfuzhi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconniantie"></span>
|
||||
<div class="name">
|
||||
粘贴
|
||||
</div>
|
||||
<div class="code-name">.iconniantie
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconshangyi"></span>
|
||||
<div class="name">
|
||||
上移
|
||||
</div>
|
||||
<div class="code-name">.iconshangyi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconxiayi"></span>
|
||||
<div class="name">
|
||||
下移
|
||||
</div>
|
||||
<div class="code-name">.iconxiayi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icongaikuozonglan"></span>
|
||||
<div class="name">
|
||||
概括总览
|
||||
</div>
|
||||
<div class="code-name">.icongaikuozonglan
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont iconquanxuan"></span>
|
||||
<div class="name">
|
||||
@@ -592,6 +697,62 @@
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconjianqie"></use>
|
||||
</svg>
|
||||
<div class="name">剪切</div>
|
||||
<div class="code-name">#iconjianqie</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconzhengli"></use>
|
||||
</svg>
|
||||
<div class="name">整理</div>
|
||||
<div class="code-name">#iconzhengli</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconfuzhi"></use>
|
||||
</svg>
|
||||
<div class="name">复制</div>
|
||||
<div class="code-name">#iconfuzhi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconniantie"></use>
|
||||
</svg>
|
||||
<div class="name">粘贴</div>
|
||||
<div class="code-name">#iconniantie</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconshangyi"></use>
|
||||
</svg>
|
||||
<div class="name">上移</div>
|
||||
<div class="code-name">#iconshangyi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconxiayi"></use>
|
||||
</svg>
|
||||
<div class="name">下移</div>
|
||||
<div class="code-name">#iconxiayi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icongaikuozonglan"></use>
|
||||
</svg>
|
||||
<div class="name">概括总览</div>
|
||||
<div class="code-name">#icongaikuozonglan</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#iconquanxuan"></use>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2479351 */
|
||||
src: url('iconfont.woff2?t=1628093007325') format('woff2'),
|
||||
url('iconfont.woff?t=1628093007325') format('woff'),
|
||||
url('iconfont.ttf?t=1628093007325') format('truetype');
|
||||
src: url('iconfont.woff2?t=1659615576455') format('woff2'),
|
||||
url('iconfont.woff?t=1659615576455') format('woff'),
|
||||
url('iconfont.ttf?t=1659615576455') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -13,6 +13,34 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconjianqie:before {
|
||||
content: "\e601";
|
||||
}
|
||||
|
||||
.iconzhengli:before {
|
||||
content: "\e83b";
|
||||
}
|
||||
|
||||
.iconfuzhi:before {
|
||||
content: "\e604";
|
||||
}
|
||||
|
||||
.iconniantie:before {
|
||||
content: "\e63f";
|
||||
}
|
||||
|
||||
.iconshangyi:before {
|
||||
content: "\e6be";
|
||||
}
|
||||
|
||||
.iconxiayi:before {
|
||||
content: "\e6bf";
|
||||
}
|
||||
|
||||
.icongaikuozonglan:before {
|
||||
content: "\e609";
|
||||
}
|
||||
|
||||
.iconquanxuan:before {
|
||||
content: "\f199";
|
||||
}
|
||||
|
||||
@@ -5,6 +5,55 @@
|
||||
"css_prefix_text": "icon",
|
||||
"description": "思维导图",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "1117",
|
||||
"name": "剪切",
|
||||
"font_class": "jianqie",
|
||||
"unicode": "e601",
|
||||
"unicode_decimal": 58881
|
||||
},
|
||||
{
|
||||
"icon_id": "1415523",
|
||||
"name": "整理",
|
||||
"font_class": "zhengli",
|
||||
"unicode": "e83b",
|
||||
"unicode_decimal": 59451
|
||||
},
|
||||
{
|
||||
"icon_id": "2815710",
|
||||
"name": "复制",
|
||||
"font_class": "fuzhi",
|
||||
"unicode": "e604",
|
||||
"unicode_decimal": 58884
|
||||
},
|
||||
{
|
||||
"icon_id": "11121506",
|
||||
"name": "粘贴",
|
||||
"font_class": "niantie",
|
||||
"unicode": "e63f",
|
||||
"unicode_decimal": 58943
|
||||
},
|
||||
{
|
||||
"icon_id": "11383392",
|
||||
"name": "上移",
|
||||
"font_class": "shangyi",
|
||||
"unicode": "e6be",
|
||||
"unicode_decimal": 59070
|
||||
},
|
||||
{
|
||||
"icon_id": "11383396",
|
||||
"name": "下移",
|
||||
"font_class": "xiayi",
|
||||
"unicode": "e6bf",
|
||||
"unicode_decimal": 59071
|
||||
},
|
||||
{
|
||||
"icon_id": "14843439",
|
||||
"name": "概括总览",
|
||||
"font_class": "gaikuozonglan",
|
||||
"unicode": "e609",
|
||||
"unicode_decimal": 58889
|
||||
},
|
||||
{
|
||||
"icon_id": "19738998",
|
||||
"name": "全选",
|
||||
|
||||
@@ -214,6 +214,21 @@ export const shortcutKeyList = [
|
||||
name: '插入同级节点',
|
||||
value: 'Enter'
|
||||
},
|
||||
{
|
||||
icon: 'iconshangyi',
|
||||
name: '上移节点',
|
||||
value: 'Ctrl + ↑'
|
||||
},
|
||||
{
|
||||
icon: 'iconxiayi',
|
||||
name: '下移节点',
|
||||
value: 'Ctrl + ↓'
|
||||
},
|
||||
{
|
||||
icon: 'icongaikuozonglan',
|
||||
name: '插入概要',
|
||||
value: 'Ctrl + S'
|
||||
},
|
||||
{
|
||||
icon: 'iconzhankai',
|
||||
name: '展开/收起节点',
|
||||
@@ -224,6 +239,21 @@ export const shortcutKeyList = [
|
||||
name: '删除节点',
|
||||
value: 'Delete | Backspace'
|
||||
},
|
||||
{
|
||||
icon: 'iconfuzhi',
|
||||
name: '复制节点',
|
||||
value: 'Ctrl + C'
|
||||
},
|
||||
{
|
||||
icon: 'iconjianqie',
|
||||
name: '剪切节点',
|
||||
value: 'Ctrl + X'
|
||||
},
|
||||
{
|
||||
icon: 'iconniantie',
|
||||
name: '粘贴节点',
|
||||
value: 'Ctrl + V'
|
||||
},
|
||||
{
|
||||
icon: 'iconbianji',
|
||||
name: '编辑节点',
|
||||
@@ -248,7 +278,17 @@ export const shortcutKeyList = [
|
||||
icon: 'iconquanxuan',
|
||||
name: '全选',
|
||||
value: 'Ctrl + A'
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: 'iconquanxuan',
|
||||
name: '多选',
|
||||
value: '右键 / Ctrl + 左键'
|
||||
},
|
||||
{
|
||||
icon: 'iconzhengli',
|
||||
name: '一键整理布局',
|
||||
value: 'Ctrl + L'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -94,6 +94,50 @@
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 概要连线 -->
|
||||
<div class="title noTop">概要的连线</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">颜色</span>
|
||||
<span
|
||||
class="block"
|
||||
v-popover:popover
|
||||
:style="{ backgroundColor: style.generalizationLineColor }"
|
||||
></span>
|
||||
<el-popover ref="popover" placement="bottom" trigger="click">
|
||||
<Color
|
||||
:color="style.generalizationLineColor"
|
||||
@change="
|
||||
(color) => {
|
||||
update('generalizationLineColor', color);
|
||||
}
|
||||
"
|
||||
></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">粗细</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.generalizationLineWidth"
|
||||
placeholder=""
|
||||
@change="
|
||||
(value) => {
|
||||
update('generalizationLineWidth', value);
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in lineWidthList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 内边距 -->
|
||||
<div class="title noTop">节点内边距</div>
|
||||
<div class="row">
|
||||
@@ -259,6 +303,8 @@ export default {
|
||||
backgroundColor: "",
|
||||
lineColor: "",
|
||||
lineWidth: "",
|
||||
generalizationLineWidth: "",
|
||||
generalizationLineColor: "",
|
||||
paddingX: 0,
|
||||
paddingY: 0,
|
||||
imgMaxWidth: 0,
|
||||
@@ -291,6 +337,8 @@ export default {
|
||||
"backgroundColor",
|
||||
"lineWidth",
|
||||
"lineColor",
|
||||
"generalizationLineWidth",
|
||||
"generalizationLineColor",
|
||||
"paddingX",
|
||||
"paddingY",
|
||||
"imgMaxWidth",
|
||||
|
||||
@@ -11,14 +11,23 @@
|
||||
:class="{ disabled: insertNodeBtnDisabled }"
|
||||
>
|
||||
插入同级节点
|
||||
<span class="desc">Enter</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('INSERT_CHILD_NODE')">
|
||||
插入子级节点
|
||||
<span class="desc">Tab</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('ADD_GENERALIZATION')" :class="{ disabled: insertNodeBtnDisabled }">
|
||||
插入概要
|
||||
<span class="desc">Ctrl + S</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('INSERT_CHILD_NODE')">插入子级节点</div>
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('UP_NODE')"
|
||||
:class="{ disabled: upNodeBtnDisabled }"
|
||||
>
|
||||
上移节点
|
||||
<span class="desc">Ctrl + ↑</span>
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
@@ -26,22 +35,37 @@
|
||||
:class="{ disabled: downNodeBtnDisabled }"
|
||||
>
|
||||
下移节点
|
||||
<span class="desc">Ctrl + ↓</span>
|
||||
</div>
|
||||
<div class="item danger" @click="exec('REMOVE_NODE')">
|
||||
删除节点
|
||||
<span class="desc">Delete</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('COPY_NODE')">
|
||||
复制节点
|
||||
<span class="desc">Ctrl + C</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('CUT_NODE')">
|
||||
剪切节点
|
||||
<span class="desc">Ctrl + X</span>
|
||||
</div>
|
||||
<div class="item danger" @click="exec('REMOVE_NODE')">删除节点</div>
|
||||
<div class="item" @click="exec('COPY_NODE')">复制节点</div>
|
||||
<div class="item" @click="exec('CUT_NODE')">剪切节点</div>
|
||||
<div
|
||||
class="item"
|
||||
:class="{ disabled: copyData === null }"
|
||||
@click="exec('PASTE_NODE')"
|
||||
>
|
||||
粘贴节点
|
||||
<span class="desc">Ctrl + V</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="type === 'svg'">
|
||||
<div class="item" @click="exec('RETURN_CENTER')">回到中心</div>
|
||||
<div class="item" @click="exec('EXPAND_ALL')">展开所有</div>
|
||||
<div class="item" @click="exec('UNEXPAND_ALL')">收起所有</div>
|
||||
<div class="item" @click="exec('RESET_LAYOUT')">
|
||||
一键整理布局
|
||||
<span class="desc">Ctrl + L</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -106,6 +130,10 @@ export default {
|
||||
this.$bus.$on("expand_btn_click", this.hide);
|
||||
this.$bus.$on("svg_mousedown", this.onMousedown);
|
||||
this.$bus.$on("mouseup", this.onMouseup);
|
||||
// 注册快捷键
|
||||
this.mindMap.keyCommand.addShortcut('Control+c', this.copy);
|
||||
this.mindMap.keyCommand.addShortcut('Control+v', this.paste);
|
||||
this.mindMap.keyCommand.addShortcut('Control+x', this.cut);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off("node_contextmenu", this.show);
|
||||
@@ -114,6 +142,10 @@ export default {
|
||||
this.$bus.$off("expand_btn_click", this.hide);
|
||||
this.$bus.$on("svg_mousedown", this.onMousedown);
|
||||
this.$bus.$on("mouseup", this.onMouseup);
|
||||
// 移除快捷键
|
||||
this.mindMap.keyCommand.removeShortcut('Control+c', this.copy);
|
||||
this.mindMap.keyCommand.removeShortcut('Control+v', this.paste);
|
||||
this.mindMap.keyCommand.removeShortcut('Control+x', this.cut);
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@@ -214,6 +246,33 @@ export default {
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-04 14:25:45
|
||||
* @Desc: 复制
|
||||
*/
|
||||
copy() {
|
||||
this.exec("COPY_NODE");
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-04 14:26:43
|
||||
* @Desc: 粘贴
|
||||
*/
|
||||
paste() {
|
||||
this.exec("PASTE_NODE");
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-08-04 14:27:32
|
||||
* @Desc: 剪切
|
||||
*/
|
||||
cut() {
|
||||
this.exec("CUT_NODE");
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -221,7 +280,7 @@ export default {
|
||||
<style lang="less" scoped>
|
||||
.contextmenuContainer {
|
||||
position: fixed;
|
||||
width: 161px;
|
||||
width: 200px;
|
||||
background: #fff;
|
||||
box-shadow: 0 4px 12px 0 hsla(0, 0%, 69%, 0.5);
|
||||
border-radius: 4px;
|
||||
@@ -235,8 +294,10 @@ export default {
|
||||
.item {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
padding-left: 16px;
|
||||
padding: 0 16px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&.danger {
|
||||
color: #f56c6c;
|
||||
@@ -249,11 +310,16 @@ export default {
|
||||
&.disabled {
|
||||
color: grey;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Theme :mindMap="mindMap"></Theme>
|
||||
<Structure :mindMap="mindMap"></Structure>
|
||||
<ShortcutKey></ShortcutKey>
|
||||
<Contextmenu :mindMap="mindMap"></Contextmenu>
|
||||
<Contextmenu v-if="mindMap" :mindMap="mindMap"></Contextmenu>
|
||||
<NodeNoteContentShow></NodeNoteContentShow>
|
||||
</div>
|
||||
</template>
|
||||
@@ -200,6 +200,7 @@ export default {
|
||||
'expand_btn_click',
|
||||
'svg_mousedown',
|
||||
'mouseup',
|
||||
'mode_change'
|
||||
].forEach((event) => {
|
||||
this.mindMap.on(event, (...args) => {
|
||||
this.$bus.$emit(event, ...args)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<el-radio label="json">json文件(.json)</el-radio>
|
||||
<el-radio label="png">图片文件(.png)</el-radio>
|
||||
<el-radio label="svg">svg文件(.svg)</el-radio>
|
||||
<el-radio label="pdf">pdf文件(.pdf)</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="tip">tips:.smm文件可用于导入</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
<template>
|
||||
<div class="navigatorContainer">
|
||||
<div class="item">
|
||||
<el-switch
|
||||
v-model="isReadonly"
|
||||
active-text="只读模式"
|
||||
inactive-text="编辑模式"
|
||||
@change="readonlyChange"
|
||||
>
|
||||
</el-switch>
|
||||
</div>
|
||||
<div class="item">
|
||||
<Scale :mindMap="mindMap"></Scale>
|
||||
</div>
|
||||
@@ -28,6 +37,16 @@ export default {
|
||||
mindMap: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isReadonly: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
readonlyChange(value) {
|
||||
this.mindMap.setMode(value ? 'readonly' : 'edit')
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -53,6 +53,7 @@ export default {
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeLink", () => {
|
||||
this.activeNodes[0].mindMap.keyCommand.pause();
|
||||
this.$bus.$emit('startTextEdit');
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
@@ -65,6 +66,7 @@ export default {
|
||||
*/
|
||||
cancel() {
|
||||
this.dialogVisible = false;
|
||||
this.activeNodes[0].mindMap.keyCommand.recovery();
|
||||
this.$bus.$emit('endTextEdit');
|
||||
},
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
v-for="icon in item.list"
|
||||
:key="icon.name"
|
||||
v-html="icon.icon"
|
||||
:class="{
|
||||
selected: iconList.includes(item.type + '_' + icon.name)
|
||||
}"
|
||||
@click="setIcon(item.type, icon.name)"
|
||||
></div>
|
||||
</div>
|
||||
@@ -34,7 +37,7 @@ export default {
|
||||
return {
|
||||
nodeIconList,
|
||||
dialogVisible: false,
|
||||
icon: [],
|
||||
iconList: [],
|
||||
activeNodes: [],
|
||||
};
|
||||
},
|
||||
@@ -43,9 +46,9 @@ export default {
|
||||
this.activeNodes = args[1];
|
||||
if (this.activeNodes.length > 0) {
|
||||
let firstNode = this.activeNodes[0];
|
||||
this.icon = firstNode.getData("icon") || [];
|
||||
this.iconList = firstNode.getData("icon") || [];
|
||||
} else {
|
||||
this.icon = [];
|
||||
this.iconList = [];
|
||||
}
|
||||
});
|
||||
this.$bus.$on("showNodeIcon", () => {
|
||||
@@ -59,16 +62,27 @@ export default {
|
||||
* @Desc: 设置icon
|
||||
*/
|
||||
setIcon(type, name) {
|
||||
let index = this.icon.findIndex((item) => {
|
||||
return item.split("_")[0] === type;
|
||||
let key = type + "_" + name;
|
||||
let index = this.iconList.findIndex((item) => {
|
||||
return item === key;
|
||||
});
|
||||
// 删除icon
|
||||
if (index !== -1) {
|
||||
this.icon.splice(index, 1, type + "_" + name);
|
||||
this.iconList.splice(index, 1);
|
||||
} else {
|
||||
this.icon.push(type + "_" + name);
|
||||
let typeIndex = this.iconList.findIndex((item) => {
|
||||
return item.split("_")[0] === type;
|
||||
});
|
||||
// 替换icon
|
||||
if (typeIndex !== -1) {
|
||||
this.iconList.splice(typeIndex, 1, key);
|
||||
} else {
|
||||
// 增加icon
|
||||
this.iconList.push(key);
|
||||
}
|
||||
}
|
||||
this.activeNodes.forEach((node) => {
|
||||
node.setIcon([...this.icon]);
|
||||
node.setIcon([...this.iconList]);
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -81,6 +95,10 @@ export default {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.deleteBtn {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-bottom: 20px;
|
||||
font-weight: bold;
|
||||
@@ -99,6 +117,20 @@ export default {
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&.selected {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: -4px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #409EFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export default {
|
||||
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
padding: 20px;
|
||||
padding: 0 20px;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: backEnd,
|
||||
disabled: readonly || backEnd,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'BACK')"
|
||||
>
|
||||
@@ -16,7 +16,7 @@
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: forwardEnd,
|
||||
disabled: readonly || forwardEnd,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'FORWARD')"
|
||||
>
|
||||
@@ -26,7 +26,7 @@
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot,
|
||||
disabled: activeNodes.length <= 0 || hasRoot || hasGeneralization,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_NODE')"
|
||||
>
|
||||
@@ -36,7 +36,7 @@
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0,
|
||||
disabled: activeNodes.length <= 0 || hasGeneralization,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'INSERT_CHILD_NODE')"
|
||||
>
|
||||
@@ -103,6 +103,16 @@
|
||||
<span class="icon iconfont iconbiaoqian"></span>
|
||||
<span class="text">标签</span>
|
||||
</div>
|
||||
<div
|
||||
class="toolbarBtn"
|
||||
:class="{
|
||||
disabled: activeNodes.length <= 0 || hasRoot,
|
||||
}"
|
||||
@click="$bus.$emit('execCommand', 'ADD_GENERALIZATION')"
|
||||
>
|
||||
<span class="icon iconfont icongaikuozonglan"></span>
|
||||
<span class="text">概要</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 通用操作 -->
|
||||
<div class="toolbarBlock">
|
||||
@@ -178,7 +188,8 @@ export default {
|
||||
return {
|
||||
activeNodes: [],
|
||||
backEnd: false,
|
||||
forwardEnd: true
|
||||
forwardEnd: true,
|
||||
readonly: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -187,8 +198,16 @@ export default {
|
||||
return node.isRoot;
|
||||
});
|
||||
},
|
||||
hasGeneralization() {
|
||||
return this.activeNodes.find((node) => {
|
||||
return node.isGeneralization;
|
||||
});
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("mode_change", (mode) => {
|
||||
this.readonly = mode === 'readonly'
|
||||
});
|
||||
this.$bus.$on("node_active", (...args) => {
|
||||
this.activeNodes = args[1];
|
||||
});
|
||||
@@ -251,6 +270,7 @@ export default {
|
||||
&.disabled {
|
||||
color: #bcbcbc;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
||||