mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 18:37:43 +08:00
基本完成
This commit is contained in:
parent
7982a1373f
commit
a798a40fab
@ -30,7 +30,7 @@ class Command {
|
||||
fn(...args)
|
||||
})
|
||||
if (name === 'BACK' || name === 'FORWARD') {
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
this.addHistory()
|
||||
}
|
||||
@ -49,6 +49,28 @@ class Command {
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 23:02:41
|
||||
* @Desc: 移除命令
|
||||
*/
|
||||
remove(name, fn) {
|
||||
if (!this.commands[name]) {
|
||||
return
|
||||
}
|
||||
if (!fn) {
|
||||
this.commands[name] = []
|
||||
delete this.commands[name]
|
||||
} else {
|
||||
let index = this.commands[name].find((item) => {
|
||||
return item === fn;
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.commands[name].splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:35:43
|
||||
|
||||
@ -47,6 +47,7 @@ class Event extends EventEmitter {
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
this.onMousewheel = this.onMousewheel.bind(this)
|
||||
this.onContextmenu = this.onContextmenu.bind(this)
|
||||
this.onSvgMousedown = this.onSvgMousedown.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,6 +59,7 @@ class Event extends EventEmitter {
|
||||
bind() {
|
||||
this.mindMap.svg.on('click', this.onDrawClick)
|
||||
this.mindMap.el.addEventListener('mousedown', this.onMousedown)
|
||||
this.mindMap.svg.on('mousedown', this.onSvgMousedown)
|
||||
window.addEventListener('mousemove', this.onMousemove)
|
||||
window.addEventListener('mouseup', this.onMouseup)
|
||||
// 兼容火狐浏览器
|
||||
@ -93,6 +95,15 @@ class Event extends EventEmitter {
|
||||
this.emit('draw_click', e)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-16 13:37:30
|
||||
* @Desc: svg画布的鼠标按下事件
|
||||
*/
|
||||
onSvgMousedown(e) {
|
||||
this.emit('svg_mousedown', e)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
|
||||
@ -165,7 +165,7 @@ class Node {
|
||||
this._expandBtn.off(['mouseover', 'mouseout', 'click'])
|
||||
}
|
||||
if (this.group) {
|
||||
this.group.off(['click', 'dblclick', 'contextmenu'])
|
||||
this.group.off(['click', 'dblclick', 'contextmenu', 'mousedown', 'mouseup'])
|
||||
}
|
||||
}
|
||||
|
||||
@ -551,6 +551,14 @@ class Node {
|
||||
this.mindMap.emit('node_click', this)
|
||||
this.active(e)
|
||||
})
|
||||
this.group.on('mousedown', (e) => {
|
||||
e.stopPropagation()
|
||||
this.mindMap.emit('node_mousedown', this)
|
||||
})
|
||||
this.group.on('mouseup', (e) => {
|
||||
e.stopPropagation()
|
||||
this.mindMap.emit('node_mouseup', this)
|
||||
})
|
||||
// 双击事件
|
||||
this.group.on('dblclick', (e) => {
|
||||
e.stopPropagation()
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import merge from 'deepmerge'
|
||||
import LogicalStructure from './layouts/LogicalStructure'
|
||||
import MindMap from './layouts/MindMap'
|
||||
import CatalogOrganization from './layouts/CatalogOrganization';
|
||||
import CatalogOrganization from './layouts/CatalogOrganization'
|
||||
import OrganizationStructure from './layouts/OrganizationStructure'
|
||||
import TextEdit from './TextEdit'
|
||||
import { copyNodeTree, simpleDeepClone, walk } from './utils'
|
||||
|
||||
// 布局列表
|
||||
const layouts = {
|
||||
@ -62,7 +63,7 @@ class Render {
|
||||
* @Desc: 设置布局结构
|
||||
*/
|
||||
setLayout() {
|
||||
this.layout = new(layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this)
|
||||
this.layout = new (layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,9 +109,12 @@ class Render {
|
||||
// 删除节点
|
||||
this.removeNode = this.removeNode.bind(this)
|
||||
this.mindMap.command.add('REMOVE_NODE', this.removeNode)
|
||||
// 复制节点
|
||||
this.copyNode = this.copyNode.bind(this)
|
||||
this.mindMap.command.add('COPY_NODE', this.copyNode)
|
||||
// 粘贴节点
|
||||
this.pasteNode = this.pasteNode.bind(this)
|
||||
this.mindMap.command.add('PASTE_NODE', this.pasteNode)
|
||||
// 剪切节点
|
||||
this.cutNode = this.cutNode.bind(this)
|
||||
this.mindMap.command.add('CUT_NODE', this.cutNode)
|
||||
// 修改节点样式
|
||||
this.setNodeStyle = this.setNodeStyle.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_STYLE', this.setNodeStyle)
|
||||
@ -123,6 +127,12 @@ class Render {
|
||||
// 切换节点是否展开
|
||||
this.setNodeExpand = this.setNodeExpand.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_EXPAND', this.setNodeExpand)
|
||||
// 展开所有节点
|
||||
this.expandAllNode = this.expandAllNode.bind(this)
|
||||
this.mindMap.command.add('EXPAND_ALL', this.expandAllNode)
|
||||
// 收起所有节点
|
||||
this.unexpandAllNode = this.unexpandAllNode.bind(this)
|
||||
this.mindMap.command.add('UNEXPAND_ALL', this.unexpandAllNode)
|
||||
// 设置节点数据
|
||||
this.setNodeData = this.setNodeData.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_DATA', this.setNodeData)
|
||||
@ -222,6 +232,9 @@ class Render {
|
||||
*/
|
||||
removeActiveNode(node) {
|
||||
let index = this.findActiveNodeIndex(node)
|
||||
if (index === -1) {
|
||||
return
|
||||
}
|
||||
this.activeNodeList.splice(index, 1)
|
||||
}
|
||||
|
||||
@ -232,7 +245,7 @@ class Render {
|
||||
*/
|
||||
findActiveNodeIndex(node) {
|
||||
return this.activeNodeList.findIndex((item) => {
|
||||
return item === node;
|
||||
return item === node
|
||||
})
|
||||
}
|
||||
|
||||
@ -281,7 +294,7 @@ class Render {
|
||||
*/
|
||||
insertNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
let first = this.activeNodeList[0]
|
||||
if (first.isRoot) {
|
||||
@ -306,7 +319,7 @@ class Render {
|
||||
*/
|
||||
insertChildNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
this.activeNodeList.forEach((node, index) => {
|
||||
if (!node.nodeData.children) {
|
||||
@ -344,7 +357,7 @@ class Render {
|
||||
let parent = node.parent
|
||||
let childList = parent.children
|
||||
let index = childList.findIndex((item) => {
|
||||
return item === node;
|
||||
return item === node
|
||||
})
|
||||
if (index === -1 || index === 0) {
|
||||
return
|
||||
@ -375,7 +388,7 @@ class Render {
|
||||
let parent = node.parent
|
||||
let childList = parent.children
|
||||
let index = childList.findIndex((item) => {
|
||||
return item === node;
|
||||
return item === node
|
||||
})
|
||||
if (index === -1 || index === childList.length - 1) {
|
||||
return
|
||||
@ -397,7 +410,7 @@ class Render {
|
||||
*/
|
||||
removeNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < this.activeNodeList.length; i++) {
|
||||
let node = this.activeNodeList[i]
|
||||
@ -410,10 +423,7 @@ class Render {
|
||||
break
|
||||
} else {
|
||||
this.removeActiveNode(node)
|
||||
let index = this.getNodeIndex(node)
|
||||
node.remove()
|
||||
node.parent.children.splice(index, 1)
|
||||
node.parent.nodeData.children.splice(index, 1)
|
||||
this.removeOneNode(node)
|
||||
i--
|
||||
}
|
||||
}
|
||||
@ -421,18 +431,67 @@ class Render {
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 22:46:27
|
||||
* @Desc: 移除某个指定节点
|
||||
*/
|
||||
removeOneNode(node) {
|
||||
let index = this.getNodeIndex(node)
|
||||
node.remove()
|
||||
node.parent.children.splice(index, 1)
|
||||
node.parent.nodeData.children.splice(index, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-15 09:53:23
|
||||
* @Desc: 复制节点
|
||||
* @Desc: 复制节点,多个节点只会操作第一个节点
|
||||
*/
|
||||
copyNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
let copyData = []
|
||||
|
||||
return copyNodeTree({}, this.activeNodeList[0])
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 22:36:45
|
||||
* @Desc: 剪切节点,多个节点只会操作第一个节点
|
||||
*/
|
||||
cutNode(callback) {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
let node = this.activeNodeList[0]
|
||||
if (node.isRoot) {
|
||||
return null
|
||||
}
|
||||
let copyData = copyNodeTree({}, node)
|
||||
this.removeActiveNode(node)
|
||||
this.removeOneNode(node)
|
||||
this.mindMap.emit('node_active', null, this.activeNodeList)
|
||||
this.mindMap.render()
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback(copyData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 20:09:39
|
||||
* @Desc: 粘贴节点到节点
|
||||
*/
|
||||
pasteNode(data) {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.activeNodeList.forEach((item) => {
|
||||
item.nodeData.children.push(simpleDeepClone(data))
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -494,6 +553,39 @@ class Render {
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 23:23:37
|
||||
* @Desc: 展开所有
|
||||
*/
|
||||
expandAllNode() {
|
||||
walk(this.renderTree, null, (node) => {
|
||||
if (!node.data.expand) {
|
||||
node.data.expand = true
|
||||
}
|
||||
}, null, true, 0, 0)
|
||||
this.mindMap.render()
|
||||
this.root.children.forEach((item) => {
|
||||
item.updateExpandBtnNode()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 23:27:14
|
||||
* @Desc: 收起所有
|
||||
*/
|
||||
unexpandAllNode() {
|
||||
this.root.children.forEach((item) => {
|
||||
this.setNodeExpand(item, false)
|
||||
})
|
||||
walk(this.renderTree, null, (node, parent, isRoot) => {
|
||||
if (!isRoot) {
|
||||
node.data.expand = false
|
||||
}
|
||||
}, null, true, 0, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-11 17:15:33
|
||||
|
||||
@ -136,6 +136,23 @@ export const copyRenderTree = (tree, root) => {
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 14:40:11
|
||||
* @Desc: 复制节点树数据
|
||||
*/
|
||||
export const copyNodeTree = (tree, root) => {
|
||||
tree.data = simpleDeepClone(root.nodeData.data)
|
||||
tree.data.isActive = false
|
||||
tree.children = []
|
||||
if (root.children && root.children.length > 0) {
|
||||
root.children.forEach((item, index) => {
|
||||
tree.children[index] = copyNodeTree({}, item)
|
||||
})
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-04 09:08:43
|
||||
|
||||
@ -4,32 +4,45 @@
|
||||
v-if="isShow"
|
||||
:style="{ left: left + 'px', top: top + 'px' }"
|
||||
>
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('INSERT_NODE', insertNodeBtnDisabled)"
|
||||
:class="{ disabled: insertNodeBtnDisabled }"
|
||||
>
|
||||
插入同级节点
|
||||
</div>
|
||||
<div class="item" @click="exec('INSERT_CHILD_NODE')">插入子级节点</div>
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('UP_NODE')"
|
||||
:class="{ disabled: upNodeBtnDisabled }"
|
||||
>
|
||||
上移节点
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('DOWN_NODE')"
|
||||
:class="{ disabled: downNodeBtnDisabled }"
|
||||
>
|
||||
下移节点
|
||||
</div>
|
||||
<div class="item danger" @click="exec('REMOVE_NODE')">删除节点</div>
|
||||
<div class="item">复制节点</div>
|
||||
<div class="item">剪切节点</div>
|
||||
<div class="item">粘贴节点</div>
|
||||
<template v-if="type === 'node'">
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('INSERT_NODE', insertNodeBtnDisabled)"
|
||||
:class="{ disabled: insertNodeBtnDisabled }"
|
||||
>
|
||||
插入同级节点
|
||||
</div>
|
||||
<div class="item" @click="exec('INSERT_CHILD_NODE')">插入子级节点</div>
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('UP_NODE')"
|
||||
:class="{ disabled: upNodeBtnDisabled }"
|
||||
>
|
||||
上移节点
|
||||
</div>
|
||||
<div
|
||||
class="item"
|
||||
@click="exec('DOWN_NODE')"
|
||||
:class="{ disabled: downNodeBtnDisabled }"
|
||||
>
|
||||
下移节点
|
||||
</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')"
|
||||
>
|
||||
粘贴节点
|
||||
</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>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -52,6 +65,11 @@ export default {
|
||||
left: 0,
|
||||
top: 0,
|
||||
node: null,
|
||||
copyData: null,
|
||||
type: "",
|
||||
isMousedown: false,
|
||||
mosuedownX: 0,
|
||||
mosuedownY: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -76,7 +94,8 @@ export default {
|
||||
let isLast =
|
||||
children.findIndex((item) => {
|
||||
return item === this.node;
|
||||
}) === children.length - 1;
|
||||
}) ===
|
||||
children.length - 1;
|
||||
return isLast;
|
||||
},
|
||||
},
|
||||
@ -85,26 +104,74 @@ export default {
|
||||
this.$bus.$on("node_click", this.hide);
|
||||
this.$bus.$on("draw_click", this.hide);
|
||||
this.$bus.$on("expand_btn_click", this.hide);
|
||||
this.$bus.$on("svg_mousedown", this.onMousedown);
|
||||
this.$bus.$on("mouseup", this.onMouseup);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.$off("node_contextmenu", this.show);
|
||||
this.$bus.$off("node_click", this.hide);
|
||||
this.$bus.$off("draw_click", this.hide);
|
||||
this.$bus.$off("expand_btn_click", this.hide);
|
||||
this.$bus.$on("svg_mousedown", this.onMousedown);
|
||||
this.$bus.$on("mouseup", this.onMouseup);
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-14 21:38:50
|
||||
* @Desc: 显示
|
||||
* @Desc: 节点右键显示
|
||||
*/
|
||||
show(e, node) {
|
||||
this.type = "node";
|
||||
this.left = e.clientX + 10;
|
||||
this.top = e.clientY + 10;
|
||||
this.isShow = true;
|
||||
this.node = node;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-16 13:27:48
|
||||
* @Desc: 鼠标按下事件
|
||||
*/
|
||||
onMousedown(e) {
|
||||
if (e.which !== 3) {
|
||||
return;
|
||||
}
|
||||
this.mosuedownX = e.clientX
|
||||
this.mosuedownY = e.clientY
|
||||
this.isMousedown = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-16 13:27:53
|
||||
* @Desc: 鼠标松开事件
|
||||
*/
|
||||
onMouseup(e) {
|
||||
if (!this.isMousedown) {
|
||||
return;
|
||||
}
|
||||
this.isMousedown = false
|
||||
if (Math.abs(this.mosuedownX - e.clientX) > 3 || Math.abs(this.mosuedownY - e.clientY) > 3) {
|
||||
this.hide()
|
||||
return;
|
||||
}
|
||||
this.show2(e)
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-15 22:54:08
|
||||
* @Desc: 画布右键显示
|
||||
*/
|
||||
show2(e) {
|
||||
this.type = "svg";
|
||||
this.left = e.clientX + 10;
|
||||
this.top = e.clientY + 10;
|
||||
this.isShow = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-07-14 21:37:55
|
||||
@ -114,6 +181,7 @@ export default {
|
||||
this.isShow = false;
|
||||
this.left = 0;
|
||||
this.top = 0;
|
||||
this.type = "";
|
||||
},
|
||||
|
||||
/**
|
||||
@ -125,7 +193,25 @@ export default {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
this.$bus.$emit("execCommand", key);
|
||||
switch (key) {
|
||||
case "COPY_NODE":
|
||||
this.copyData = this.mindMap.renderer.copyNode();
|
||||
break;
|
||||
case "CUT_NODE":
|
||||
this.$bus.$emit("execCommand", key, (copyData) => {
|
||||
this.copyData = copyData;
|
||||
});
|
||||
break;
|
||||
case "PASTE_NODE":
|
||||
this.$bus.$emit("execCommand", key, this.copyData);
|
||||
break;
|
||||
case "RETURN_CENTER":
|
||||
this.mindMap.view.reset();
|
||||
break;
|
||||
default:
|
||||
this.$bus.$emit("execCommand", key);
|
||||
break;
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
},
|
||||
@ -153,7 +239,7 @@ export default {
|
||||
cursor: pointer;
|
||||
|
||||
&.danger {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
@ -89,7 +89,9 @@ export default {
|
||||
"node_contextmenu",
|
||||
"node_click",
|
||||
"draw_click",
|
||||
"expand_btn_click"
|
||||
"expand_btn_click",
|
||||
"svg_mousedown",
|
||||
"mouseup"
|
||||
].forEach((event) => {
|
||||
this.mindMap.on(event, (...args) => {
|
||||
this.$bus.$emit(event, ...args);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user