mind-map/simple-mind-map/src/Render.js
2021-07-15 17:46:36 +08:00

609 lines
16 KiB
JavaScript

import merge from 'deepmerge'
import LogicalStructure from './layouts/LogicalStructure'
import MindMap from './layouts/MindMap'
import CatalogOrganization from './layouts/CatalogOrganization';
import OrganizationStructure from './layouts/OrganizationStructure'
import TextEdit from './TextEdit'
// 布局列表
const layouts = {
// 逻辑结构图
logicalStructure: LogicalStructure,
// 思维导图
mindMap: MindMap,
// 目录组织图
catalogOrganization: CatalogOrganization,
// 组织结构图
organizationStructure: OrganizationStructure
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:07
* @Desc: 渲染
*/
class Render {
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:32
* @Desc: 构造函数
*/
constructor(opt = {}) {
this.opt = opt
this.mindMap = opt.mindMap
this.themeConfig = this.mindMap.themeConfig
this.draw = this.mindMap.draw
// 渲染树,操作过程中修改的都是这里的数据
this.renderTree = merge({}, this.mindMap.opt.data || {})
// 是否重新渲染
this.reRender = false
// 当前激活的节点列表
this.activeNodeList = []
// 根节点
this.root = null
// 布局
this.setLayout()
// 绑定事件
this.bindEvent()
// 注册命令
this.registerCommands()
// 注册快捷键
this.registerShortcutKeys()
// 文本编辑框
this.textEdit = new TextEdit(this)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-07-13 16:20:07
* @Desc: 设置布局结构
*/
setLayout() {
this.layout = new(layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this)
}
/**
* @Author: 王林
* @Date: 2021-06-20 10:34:06
* @Desc: 绑定事件
*/
bindEvent() {
// 点击事件
this.mindMap.on('draw_click', () => {
// 清除激活状态
if (this.activeNodeList.length > 0) {
this.clearActive()
this.mindMap.emit('node_active', null, [])
}
})
}
/**
* @Author: 王林
* @Date: 2021-05-04 13:19:06
* @Desc: 注册命令
*/
registerCommands() {
// 回退
this.back = this.back.bind(this)
this.mindMap.command.add('BACK', this.back)
// 前进
this.forward = this.forward.bind(this)
this.mindMap.command.add('FORWARD', this.forward)
// 插入同级节点
this.insertNode = this.insertNode.bind(this)
this.mindMap.command.add('INSERT_NODE', this.insertNode)
// 插入子节点
this.insertChildNode = this.insertChildNode.bind(this)
this.mindMap.command.add('INSERT_CHILD_NODE', this.insertChildNode)
// 上移节点
this.upNode = this.upNode.bind(this)
this.mindMap.command.add('UP_NODE', this.upNode)
// 下移节点
this.downNode = this.downNode.bind(this)
this.mindMap.command.add('DOWN_NODE', this.downNode)
// 删除节点
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.setNodeStyle = this.setNodeStyle.bind(this)
this.mindMap.command.add('SET_NODE_STYLE', this.setNodeStyle)
// 切换节点是否激活
this.setNodeActive = this.setNodeActive.bind(this)
this.mindMap.command.add('SET_NODE_ACTIVE', this.setNodeActive)
// 清除所有激活节点
this.clearActive = this.clearActive.bind(this)
this.mindMap.command.add('CLEAR_ACTIVE_NODE', this.clearActive)
// 切换节点是否展开
this.setNodeExpand = this.setNodeExpand.bind(this)
this.mindMap.command.add('SET_NODE_EXPAND', this.setNodeExpand)
// 设置节点数据
this.setNodeData = this.setNodeData.bind(this)
this.mindMap.command.add('SET_NODE_DATA', this.setNodeData)
// 设置节点文本
this.setNodeText = this.setNodeText.bind(this)
this.mindMap.command.add('SET_NODE_TEXT', this.setNodeText)
// 设置节点图片
this.setNodeImage = this.setNodeImage.bind(this)
this.mindMap.command.add('SET_NODE_IMAGE', this.setNodeImage)
// 设置节点图标
this.setNodeIcon = this.setNodeIcon.bind(this)
this.mindMap.command.add('SET_NODE_ICON', this.setNodeIcon)
// 设置节点超链接
this.setNodeHyperlink = this.setNodeHyperlink.bind(this)
this.mindMap.command.add('SET_NODE_HYPERLINK', this.setNodeHyperlink)
// 设置节点备注
this.setNodeNote = this.setNodeNote.bind(this)
this.mindMap.command.add('SET_NODE_NOTE', this.setNodeNote)
// 设置节点标签
this.setNodeTag = this.setNodeTag.bind(this)
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
}
/**
* @Author: 王林
* @Date: 2021-07-11 16:55:44
* @Desc: 注册快捷键
*/
registerShortcutKeys() {
// 插入下级节点
this.mindMap.keyCommand.addShortcut('Tab', () => {
this.insertChildNode()
})
// 插入同级节点
this.mindMap.keyCommand.addShortcut('Enter', () => {
if (this.textEdit.showTextEdit) {
return
}
this.insertNode()
})
// 展开/收起节点
this.mindMap.keyCommand.addShortcut('/', () => {
this.activeNodeList.forEach((node) => {
if (node.nodeData.children.length <= 0) {
return
}
this.toggleNodeExpand(node)
})
})
// 删除节点
this.mindMap.keyCommand.addShortcut('Del|Backspace', () => {
this.removeNode()
})
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:27:55
* @Desc: 渲染
*/
render() {
this.layout.doLayout((root) => {
this.root = root
this.root.render()
})
}
/**
* @Author: 王林
* @Date: 2021-04-12 22:45:01
* @Desc: 清除当前激活的节点
*/
clearActive() {
this.activeNodeList.forEach((item) => {
this.mindMap.execCommand('SET_NODE_ACTIVE', item, false)
})
this.activeNodeList = []
}
/**
* @Author: 王林
* @Date: 2021-07-11 10:54:00
* @Desc: 添加节点到激活列表里
*/
addActiveNode(node) {
let index = this.findActiveNodeIndex(node)
if (index === -1) {
this.activeNodeList.push(node)
}
}
/**
* @Author: 王林
* @Date: 2021-07-10 10:04:04
* @Desc: 在激活列表里移除某个节点
*/
removeActiveNode(node) {
let index = this.findActiveNodeIndex(node)
this.activeNodeList.splice(index, 1)
}
/**
* @Author: 王林
* @Date: 2021-07-11 10:55:23
* @Desc: 检索某个节点在激活列表里的索引
*/
findActiveNodeIndex(node) {
return this.activeNodeList.findIndex((item) => {
return item === node;
})
}
/**
* @Author: 王林
* @Date: 2021-05-04 13:46:08
* @Desc: 获取节点在同级里的索引位置
*/
getNodeIndex(node) {
return node.parent ? node.parent.children.findIndex((item) => {
return item === node
}) : 0
}
/**
* @Author: 王林
* @Date: 2021-07-11 22:34:12
* @Desc: 回退
*/
back(step) {
let data = this.mindMap.command.back(step)
if (data) {
this.renderTree = data
this.mindMap.reRender()
}
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-07-12 10:44:51
* @Desc: 前进
*/
forward(step) {
let data = this.mindMap.command.forward(step)
if (data) {
this.renderTree = data
this.mindMap.reRender()
}
}
/**
* @Author: 王林
* @Date: 2021-05-04 13:19:54
* @Desc: 插入同级节点,多个节点只会操作第一个节点
*/
insertNode() {
if (this.activeNodeList.length <= 0) {
return;
}
let first = this.activeNodeList[0]
if (first.isRoot) {
this.insertChildNode()
} else {
let index = this.getNodeIndex(first)
first.parent.nodeData.children.splice(index + 1, 0, {
"data": {
"text": "分支主题",
"expand": true
},
"children": []
})
this.mindMap.render()
}
}
/**
* @Author: 王林
* @Date: 2021-05-04 13:31:02
* @Desc: 插入子节点
*/
insertChildNode() {
if (this.activeNodeList.length <= 0) {
return;
}
this.activeNodeList.forEach((node, index) => {
if (!node.nodeData.children) {
node.nodeData.children = []
}
node.nodeData.children.push({
"data": {
"text": "分支主题",
"expand": true
},
"children": []
})
if (node.isRoot) {
this.mindMap.batchExecution.push('renderNode' + index, () => {
node.renderNode()
})
}
})
this.mindMap.render()
}
/**
* @Author: 王林
* @Date: 2021-07-14 23:34:14
* @Desc: 上移节点,多个节点只会操作第一个节点
*/
upNode() {
if (this.activeNodeList.length <= 0) {
return
}
let node = this.activeNodeList[0]
if (node.isRoot) {
return
}
let parent = node.parent
let childList = parent.children
let index = childList.findIndex((item) => {
return item === node;
})
if (index === -1 || index === 0) {
return
}
let insertIndex = index - 1
// 节点实例
childList.splice(index, 1)
childList.splice(insertIndex, 0, node)
// 节点数据
parent.nodeData.children.splice(index, 1)
parent.nodeData.children.splice(insertIndex, 0, node.nodeData)
this.mindMap.render()
}
/**
* @Author: 王林
* @Date: 2021-07-14 23:34:18
* @Desc: 下移节点,多个节点只会操作第一个节点
*/
downNode() {
if (this.activeNodeList.length <= 0) {
return
}
let node = this.activeNodeList[0]
if (node.isRoot) {
return
}
let parent = node.parent
let childList = parent.children
let index = childList.findIndex((item) => {
return item === node;
})
if (index === -1 || index === childList.length - 1) {
return
}
let insertIndex = index + 1
// 节点实例
childList.splice(index, 1)
childList.splice(insertIndex, 0, node)
// 节点数据
parent.nodeData.children.splice(index, 1)
parent.nodeData.children.splice(insertIndex, 0, node.nodeData)
this.mindMap.render()
}
/**
* @Author: 王林
* @Date: 2021-05-04 13:40:39
* @Desc: 移除节点
*/
removeNode() {
if (this.activeNodeList.length <= 0) {
return;
}
for (let i = 0; i < this.activeNodeList.length; i++) {
let node = this.activeNodeList[i]
if (node.isRoot) {
node.children.forEach((child) => {
child.remove()
})
node.children = []
node.nodeData.children = []
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)
i--
}
}
this.mindMap.emit('node_active', null, [])
this.mindMap.render()
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-07-15 09:53:23
* @Desc: 复制节点
*/
copyNode() {
if (this.activeNodeList.length <= 0) {
return;
}
let copyData = []
}
/**
* @Author: 王林
* @Date: 2021-07-08 21:54:30
* @Desc: 设置节点样式
*/
setNodeStyle(node, prop, value, isActive) {
let data = {}
if (isActive) {
data = {
activeStyle: {
...(node.nodeData.data.activeStyle || {}),
[prop]: value
}
}
} else {
data = {
[prop]: value
}
}
this.setNodeDataRender(node, data)
}
/**
* @Author: 王林
* @Date: 2021-07-08 22:13:03
* @Desc: 设置节点是否激活
*/
setNodeActive(node, active) {
this.setNodeData(node, {
isActive: active
})
node.renderNode()
}
/**
* @Author: 王林
* @Date: 2021-07-10 16:52:41
* @Desc: 设置节点是否展开
*/
setNodeExpand(node, expand) {
this.setNodeData(node, {
expand
})
if (expand) { // 展开
node.children.forEach((item) => {
item.render()
})
node.renderLine()
node.updateExpandBtnNode()
} else { // 收缩
node.children.forEach((item) => {
item.remove()
})
node.removeLine()
node.updateExpandBtnNode()
}
this.mindMap.render()
}
/**
* @Author: 王林
* @Date: 2021-07-11 17:15:33
* @Desc: 切换节点展开状态
*/
toggleNodeExpand(node) {
this.mindMap.execCommand('SET_NODE_EXPAND', node, !node.nodeData.data.expand)
}
/**
* @Author: 王林
* @Date: 2021-07-09 22:04:19
* @Desc: 设置节点文本
*/
setNodeText(node, text) {
this.setNodeDataRender(node, {
text
})
}
/**
* @Author: 王林
* @Date: 2021-07-10 08:37:40
* @Desc: 设置节点图片
*/
setNodeImage(node, {
url,
title,
width,
height
}) {
this.setNodeDataRender(node, {
image: url,
imageTitle: title || '',
imageSize: {
width,
height,
},
})
}
/**
* @Author: 王林
* @Date: 2021-07-10 08:44:06
* @Desc: 设置节点图标
*/
setNodeIcon(node, icons) {
this.setNodeDataRender(node, {
icon: icons
})
}
/**
* @Author: 王林
* @Date: 2021-07-10 08:49:33
* @Desc: 设置节点超链接
*/
setNodeHyperlink(node, link, title = '') {
this.setNodeDataRender(node, {
hyperlink: link,
hyperlinkTitle: title,
})
}
/**
* @Author: 王林
* @Date: 2021-07-10 08:52:59
* @Desc: 设置节点备注
*/
setNodeNote(node, note) {
this.setNodeDataRender(node, {
note
})
}
/**
* @Author: 王林
* @Date: 2021-07-10 08:54:53
* @Desc: 设置节点标签
*/
setNodeTag(node, tag) {
this.setNodeDataRender(node, {
tag
})
}
/**
* @Author: 王林
* @Date: 2021-05-04 14:19:48
* @Desc: 更新节点数据
*/
setNodeData(node, data) {
Object.keys(data).forEach((key) => {
node.nodeData.data[key] = data[key]
})
}
/**
* @Author: 王林
* @Date: 2021-07-10 08:45:48
* @Desc: 设置节点数据,并判断是否渲染
*/
setNodeDataRender(node, data) {
this.setNodeData(node, data)
let changed = node.getSize()
node.renderNode()
if (changed) {
this.mindMap.render()
}
}
}
export default Render