基本完成

This commit is contained in:
wanglin 2021-07-16 13:42:37 +08:00
parent 7982a1373f
commit a798a40fab
7 changed files with 290 additions and 52 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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);