日常提交

This commit is contained in:
wanglin 2021-06-28 07:46:12 +08:00
parent 54ae4b3e26
commit adcf77f60d
28 changed files with 776 additions and 652 deletions

View File

@ -1,3 +1,19 @@
const createFullData = () => {
return {
// "image": "http://aliyuncdn.lxqnsys.com/whbm/enJFNMHnedQTYTESGfDkctCp2",
// "imageTitle": "图片名称",
// "imageSize": {
// "width": 1000,
// "height": 563
// },
// "icon": ['priority_1'],
// "tag": ["标签1", "标签2"],
// "hyperlink": "http://lxqnsys.com/",
// "hyperlinkTitle": "理想青年实验室",
// "note": "理想青年实验室\n一个有意思的角落"
};
}
/**
* @Author: 王林
* @Date: 2021-04-15 22:23:24
@ -8,33 +24,162 @@ export default {
"data": {
"text": "根节点",
},
"children": [{
"data": {
"text": "二级节点",
"expand": true,
},
"children": [{
"children": [
{
"data": {
"text": "子节点",
// "image": "http://aliyuncdn.lxqnsys.com/whbm/enJFNMHnedQTYTESGfDkctCp2",
// "imageTitle": "图片名称",
// "imageSize": {
// "width": 1000,
// "height": 563
// },
// "icon": ['priority_1'],
// "tag": ["标签1", "标签2"],
// "hyperlink": "http://lxqnsys.com/",
// "hyperlinkTitle": "理想青年实验室",
// "note": "理想青年实验室\n一个有意思的角落"
"text": "二级节点1",
"expand": true,
},
"children": []
}, {
"children": [{
"data": {
"text": "子节点1-1",
...createFullData()
},
}, {
"data": {
"text": "子节点1-2",
...createFullData()
}
},]
},
{
"data": {
"text": "子节点",
}
}]
}]
"text": "二级节点2"
},
"children": [
{
"data": {
"text": "子节点2-1",
...createFullData()
},
"children": [
{
"data": {
"text": "子节点2-1-1",
...createFullData()
}
},
{
"data": {
"text": "子节点2-1-2",
...createFullData()
},
"children": [
{
"data": {
"text": "子节点2-1-2-1",
...createFullData()
}
},
{
"data": {
"text": "子节点2-1-2-2",
...createFullData()
},
"children": [
{
"data": {
"text": "子节点2-1-2-2-1",
...createFullData()
}
},
{
"data": {
"text": "子节点2-1-2-2-2",
...createFullData()
}
},
{
"data": {
"text": "子节点2-1-2-2-3",
...createFullData()
}
}
]
},
{
"data": {
"text": "子节点4-1-2-3",
...createFullData()
}
}
]
},
{
"data": {
"text": "子节点2-1-3",
...createFullData()
}
}
]
},
{
"data": {
"text": "子节点2-2",
...createFullData()
}
}
]
},
{
"data": {
"text": "二级节点3",
},
"children": [
{
"data": {
"text": "子节点3-1",
...createFullData()
}
},
{
"data": {
"text": "子节点3-2",
...createFullData()
}
}
]
},
{
"data": {
"text": "二级节点4",
},
"children": [
{
"data": {
"text": "子节点4-1",
...createFullData()
},
"children": [
{
"data": {
"text": "子节点4-1-1",
...createFullData()
}
},
{
"data": {
"text": "子节点4-1-2",
...createFullData()
}
},
{
"data": {
"text": "子节点4-1-3",
...createFullData()
}
}
]
},
{
"data": {
"text": "子节点4-2",
...createFullData()
}
}
]
}
]
},
"theme": {
"template": "default",
@ -42,5 +187,7 @@ export default {
// 自定义配置...
}
},
// "layout": "mindMap",
"layout": "logicalStructure"
// "layout": "catalogOrganization"
}

View File

@ -5,7 +5,8 @@ import merge from 'deepmerge'
import theme from './src/themes'
import Style from './src/Style'
import KeyCommand from './src/KeyCommand'
import Command from './src/Command';
import Command from './src/Command'
import BatchExecution from './src/BatchExecution'
import {
SVG
} from '@svgdotjs/svg.js'
@ -52,7 +53,7 @@ class MindMap {
// 画笔
this.draw = SVG().addTo(this.el).size(width, height)
// 节点id
this.uid = 0
@ -85,6 +86,9 @@ class MindMap {
draw: this.draw
})
// 批量执行类
this.batchExecution = new BatchExecution()
// 初始渲染
this.renderer.render()
setTimeout(() => {
@ -99,9 +103,11 @@ class MindMap {
* @Desc: 渲染
*/
render() {
this.draw.clear()
this.initTheme()
this.renderer.render()
this.batchExecution.push('render', () => {
this.draw.clear()
this.initTheme()
this.renderer.render()
})
}
/**

View File

@ -0,0 +1,85 @@
/**
* @Author: 王林
* @Date: 2021-06-27 13:16:23
* @Desc: 在下一个事件循环里执行任务
*/
const nextTick = function (fn, ctx) {
let pending = false
let timerFunc = null
let handle = () => {
pending = false
ctx ? fn.call(ctx) : fn()
}
// 支持MutationObserver接口的话使用MutationObserver
if (typeof MutationObserver !== 'undefined') {
let counter = 1
let observer = new MutationObserver(handle)
let textNode = document.createTextNode(counter)
observer.observe(textNode, {
characterData: true// 设为 true 表示监视指定目标节点或子节点树中节点所包含的字符数据的变化
})
timerFunc = function () {
counter = (counter + 1) % 2// counter会在0和1两者循环变化
textNode.data = counter// 节点变化会触发回调handle
}
} else {// 否则使用定时器
timerFunc = setTimeout
}
return function (cb, ctx) {
if (pending) return
pending = true
timerFunc(handle, 0)
}
}
/**
* @Author: 王林
* @Date: 2021-06-26 22:40:52
* @Desc: 批量执行
*/
class BatchExecution {
/**
* @Author: 王林
* @Date: 2021-06-26 22:41:41
* @Desc: 构造函数
*/
constructor() {
this.has = {}
this.queue = []
this.nextTick = nextTick(this.flush, this)
}
/**
* @Author: 王林
* @Date: 2021-06-27 12:54:04
* @Desc: 添加任务
*/
push(name, fn) {
if (this.has[name]) {
return;
}
this.has[name] = true
this.queue.push({
name,
fn
})
this.nextTick()
}
/**
* @Author: 王林
* @Date: 2021-06-27 13:09:24
* @Desc: 执行队列
*/
flush() {
let fns = this.queue.slice(0)
this.queue = []
fns.forEach(({ name, fn }) => {
this.has[name] = false
fn()
})
}
}
export default BatchExecution

View File

@ -1,6 +1,7 @@
import Style from './Style'
import {
resizeImgSize
resizeImgSize,
copyRenderTree
} from './utils'
import {
Image,
@ -62,6 +63,8 @@ class Node {
this._textContentItemMargin = 2
// 图片和文字节点的间距
this._blockContentMargin = 5
// 展开收缩按钮尺寸
this._expandBtnSize = 20
// 计算节点尺寸
this.refreshSize()
}
@ -491,7 +494,7 @@ class Node {
* @Desc: 展开收缩按钮
*/
renderExpandBtn() {
if (this.children.length <= 0 || this.isRoot) {
if ((!this.nodeData.data.cacheChildren || this.nodeData.data.cacheChildren.length <= 0) && this.children.length <= 0 || this.isRoot) {
return;
}
let g = this.draw.group()
@ -501,8 +504,8 @@ class Node {
} else {
iconSvg = btnsSvg.close
}
let node = SVG(iconSvg).size(20, 20)
let fillNode = new Circle().size(20)
let node = SVG(iconSvg).size(this._expandBtnSize, this._expandBtnSize)
let fillNode = new Circle().size(this._expandBtnSize)
this.renderer.layout.renderExpandBtn(this, [node, fillNode])
node.dx(0).dy(-10)
fillNode.dx(0).dy(-10)
@ -518,10 +521,21 @@ class Node {
})
})
g.click(() => {
// 需要反映到实际数据上
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
expand: !this.nodeData.data.expand
})
// 展开收缩
let data = {}
let children = []
if (this.nodeData.data.expand) {
data.expand = false
data.cacheChildren = this.nodeData.children.map((item) => {
return copyRenderTree({}, item);
})
children = []
} else {
data.expand = true
children = this.nodeData.data.cacheChildren
data.cacheChildren = []
}
this.mindMap.execCommand('UPDATE_NODE_DATA', this, data, children)
this.mindMap.emit('expand_btn_click', this)
})
g.add(fillNode)

View File

@ -1,11 +1,17 @@
import merge from 'deepmerge'
import LogicalStructure from './layouts/LogicalStructure'
import MindMap from './layouts/MindMap'
import CatalogOrganization from './layouts/CatalogOrganization';
import TextEdit from './TextEdit'
// 布局列表
const layouts = {
// 逻辑结构图
logicalStructure: LogicalStructure,
// 思维导图
logicalStructure: LogicalStructure
mindMap: MindMap,
// 目录组织图
catalogOrganization: CatalogOrganization
}
/**
@ -146,6 +152,9 @@ class Render {
return;
}
let first = this.activeNodeList[0]
if (!first.nodeData.children) {
first.nodeData.children = []
}
first.nodeData.children.push({
"data": {
"text": "分支主题",
@ -184,10 +193,13 @@ class Render {
* @Date: 2021-05-04 14:19:48
* @Desc: 更新节点数据
*/
updateNodeData(node, data) {
updateNodeData(node, data, children) {
Object.keys(data).forEach((key) => {
node.nodeData.data[key] = data[key]
})
if (children) {
node.nodeData.children = children
}
this.mindMap.render()
}
}

View File

@ -99,6 +99,7 @@ export default class TextEdit {
this.renderer.activeNodeList.forEach((node) => {
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
node.nodeData.data.text = str
console.log(8)
this.mindMap.render()
})
this.mindMap.emit('hide_text_edit', this.textEditNode, this.renderer.activeNodeList)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -30,6 +30,7 @@ class Base {
* @Desc: 计算节点位置
*/
doLayout() {
console.log('布局')
throw new Error('【computed】方法为必要方法需要子类进行重写')
}
@ -65,6 +66,48 @@ class Base {
}
})
}
/**
* @Author: 王林
* @Date: 2021-04-11 15:05:01
* @Desc: 二次贝塞尔曲线
*/
quadraticCurvePath(x1, y1, x2, y2) {
let cx = x1 + (x2 - x1) * 0.2
let cy = y1 + (y2 - y1) * 0.8
return `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
}
/**
* @Author: 王林
* @Date: 2021-04-11 15:05:18
* @Desc: 三次贝塞尔曲线
*/
cubicBezierPath(x1, y1, x2, y2) {
let cx1 = x1 + (x2 - x1) / 2
let cy1 = y1
let cx2 = x2 - (x2 - x1) / 2
let cy2 = y2
return `M ${x1},${y1} C ${cx1},${cy1} ${cx2},${cy2} ${x2},${y2}`
}
/**
* @Author: 王林
* @Date: 2021-06-27 19:00:07
* @Desc: 获取节点的marginX
*/
getMarginX(layerIndex) {
return layerIndex === 1 ? this.themeConfig.second.marginX : this.themeConfig.node.marginX;
}
/**
* @Author: 王林
* @Date: 2021-04-11 15:34:20
* @Desc: 获取节点的marginY
*/
getMarginY(layerIndex) {
return layerIndex === 1 ? this.themeConfig.second.marginY : this.themeConfig.node.marginY;
}
}
export default Base

View File

@ -1,186 +0,0 @@
import {
walk
} from '../Utils'
import Node from '../Node'
import merge from 'deepmerge'
/**
* 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.draw = this.mindMap.draw
// 渲染树
this.renderTree = merge({}, this.mindMap.opt.data || {})
// 根节点
this.root = null
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:27:55
* @Desc: 渲染
*/
render() {
this.computed()
this.root.render()
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-06 14:04:20
* @Desc: 计算位置数据
*/
computed() {
// 计算节点的width、height
this.computedBaseValue()
// 计算节点的left、top
this.computedLeftTopValue()
// 调整节点top
// this.adjustTopValue()
// 调整节点left
// this.adjustLeftValue()
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:49:32
* @Desc: 计算节点的widthheight
*/
computedBaseValue() {
walk(this.renderTree, null, (node, parent, isRoot, index, layerIndex) => {
// 设置width、height
let {
children,
...props
} = node
let newNode = new Node({
...props,
mindMap: this.mindMap,
draw: this.draw,
layerIndex
})
// 计算节点的宽高
newNode.refreshSize()
// 计算节点的top
if (isRoot) {
newNode.isRoot = true
newNode.left = this.mindMap.width / 2
newNode.top = this.mindMap.height / 2
this.root = newNode
} else {
newNode.parent = parent._node
parent._node.addChildren(newNode)
}
node._node = newNode
}, (node) => {
// 遍历完子节点返回时
}, true)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:59:25
* @Desc: 计算节点的lefttop
*/
computedLeftTopValue() {
let margin = Math.max(this.mindMap.opt.marginX, this.mindMap.opt.marginY)
walk(this.root, null, (node) => {
if (node.children && node.children.length) {
let rad = (360 / node.children.length) * (Math.PI / 180)
let totalRad = 0
node.children.forEach((item) => {
let r = node.width / 2 + margin + item.width / 2
item.left = node.left + r * Math.cos(totalRad)
item.top = node.top + r * Math.sin(totalRad)
totalRad += rad
})
}
}, null, true)
// return
walk(this.root, null, null, (node) => {
if (node.children && node.children.length) {
let minLeft = Infinity,
minTop = Infinity,
maxRight = -Infinity,
maxBottom = -Infinity
node.children.concat([node]).forEach((item) => {
if ((item.left - item.width / 2) < minLeft) {
minLeft = item.left - item.width / 2
}
if ((item.top - item.width / 2) < minTop) {
minTop = item.top - item.width / 2
}
if ((item.left + item.width / 2) > maxRight) {
maxRight = item.left + item.width / 2
}
if ((item.top + item.width / 2) < maxBottom) {
maxBottom = item.top + item.width / 2
}
})
let width = Math.max(maxRight - minLeft, maxBottom - minTop)
let difference = width - node.width
this.update(node, difference)
}
}, true)
}
update(node, difference) {
if (node.parent) {
// console.log(node.text, difference)
let rad = (360 / node.parent.children.length) * (Math.PI / 180)
let totalRad = 0
node.parent.children.forEach((item) => {
if (item === node) {
item.left += difference * Math.cos(totalRad)
item.top += difference * Math.sin(totalRad)
if (node.children && node.children.length) {
// this.updateChildren(node)
}
}
totalRad += rad
})
this.update(node.parent, difference)
}
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-07 11:25:52
* @Desc: 更新子节点
*/
updateChildren(node, difference) {
let margin = Math.max(this.mindMap.opt.marginX, this.mindMap.opt.marginY)
walk(node, null, (node) => {
if (node.children && node.children.length) {
let rad = (360 / node.children.length) * (Math.PI / 180)
let totalRad = 0
node.children.forEach((item) => {
let r = node.width / 2 + margin + item.width / 2
item.left = node.left + r * Math.cos(totalRad)
item.top = node.top + r * Math.sin(totalRad)
totalRad += rad
})
}
}, null, true)
}
}
export default Render

View File

@ -1,105 +1,87 @@
import Base from './Base';
import {
walk
} from '../Utils'
} from '../utils'
import Node from '../Node'
import merge from 'deepmerge'
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:07
* @Desc: 目录组织图
* @Author: 王林
* @Date: 2021-04-12 22:25:58
* @Desc: 目录组织图
* 思路第一轮只计算节点的宽高以及某个节点的所有子节点所占的高度之和以及该节点里所有子节点中宽度最宽是多少第二轮计算节点的left和top需要区分二级节点和其他节点二级节点top相同一行依次从做向右排开其他节点的left相同一列从上往下依次排开
*/
class Render {
class CatalogOrganization extends Base {
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:32
* @Author: 王林
* @Date: 2021-04-12 22:26:31
* @Desc: 构造函数
*/
constructor(opt = {}) {
this.opt = opt
this.mindMap = opt.mindMap
this.draw = this.mindMap.draw
// 渲染树
this.renderTree = merge({}, this.mindMap.opt.data || {})
// 根节点
this.root = null
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:27:55
* @Desc: 渲染
*/
render() {
this.computed()
this.root.render()
super(opt)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-06 14:04:20
* @Desc: 计算位置数据
* @Desc: 布局
*/
computed() {
// 计算节点的width、height
doLayout() {
// 遍历数据计算节点的width、height
this.computedBaseValue()
// 计算节点的left、top
this.computedLeftTopValue()
// 调整节点top
this.adjustTopValue()
// 调整节点left
this.adjustLeftValue()
// this.adjustLeftValue()
return this.root;
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:49:32
* @Desc: 计算节点的widthheight
* @Desc: 遍历数据计算节点的widthheight
*/
computedBaseValue() {
walk(this.renderTree, null, (node, parent, isRoot, index) => {
// 设置width、height
let {
children,
...props
} = node
walk(this.renderTree, null, (cur, parent, isRoot, layerIndex) => {
// 创建节点
let newNode = new Node({
...props,
data: cur,
uid: this.mindMap.uid++,
renderer: this.renderer,
mindMap: this.mindMap,
draw: this.draw
draw: this.draw,
layerIndex
})
// 计算节点的宽高
newNode.refreshSize()
// 计算节点的top
// 数据关联实际节点
cur._node = newNode
// 根节点定位在画布中心位置
if (isRoot) {
newNode.isRoot = true
newNode.left = (this.mindMap.width - newNode.width) / 2
newNode.top = (this.mindMap.height - newNode.height) / 2
this.root = newNode
} else {
// 互相收集
newNode.parent = parent._node
parent._node.addChildren(newNode)
}
node._node = newNode
}, (node) => {
// 遍历完子节点返回时
// 计算节点的areaHeight也就是子节点所占的高度之和包括外边距
let len = node._node.children.length
if (node._node.isRoot) {
node._node.childrenAreaWidth = len ? node._node.children.reduce((h, cur) => {
return h + cur.width
}, 0) + (len + 1) * this.mindMap.opt.marginX : 0
}, (cur, parent, isRoot, layerIndex) => {
// 返回时计算节点的areaHeight也就是子节点所占的高度之和包括外边距
let len = cur._node.children.length
if (isRoot) {// 计算二级节点所占的宽度之和
cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => {
return h + item.width
}, 0) + (len + 1) * this.getMarginX(layerIndex) : 0
}
node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => {
return h + cur.height
}, 0) + (len + 1) * this.mindMap.opt.marginY : 0
}, true)
// 计算子节点所占的高度之和
cur._node.childrenAreaHeight = len ? cur._node.children.reduce((h, item) => {
return h + item.height
}, 0) + (len + 1) * this.getMarginY(layerIndex) : 0
}, true, 0)
}
/**
@ -109,30 +91,79 @@ class Render {
* @Desc: 计算节点的lefttop
*/
computedLeftTopValue() {
walk(this.root, null, (node) => {
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
let marginX = this.getMarginX(layerIndex)
let marginY = this.getMarginY(layerIndex)
if (node.children && node.children.length) {
if (node.isRoot) {
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
let totalLeft = left + this.mindMap.opt.marginX
let totalLeft = left + marginX
node.children.forEach((cur) => {
// left
cur.left = totalLeft
totalLeft += cur.width + this.mindMap.opt.marginX
totalLeft += cur.width + marginX
// top
cur.top = node.top + node.height + this.mindMap.opt.marginY
cur.top = node.top + node.height + marginY
})
} else {
let totalTop = node.top + node.height + this.mindMap.opt.marginY
let totalTop = node.top + node.height + marginY
node.children.forEach((cur) => {
cur.left = node.left + node.width / 5 + this.mindMap.opt.marginX
cur.left = node.left + node.width / 5
cur.top = totalTop
totalTop += cur.height + this.mindMap.opt.marginY
totalTop += cur.height + marginY
})
}
}
}, null, true)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 10:04:05
* @Desc: 调整节点top该节点之后的节点都往下进行偏移
*/
adjustTopValue() {
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
let marginY = this.getMarginY(layerIndex)
if (!node.isRoot && !node.parent.isRoot) {
// 判断子节点的areaHeight是否大于该节点自身大于则需要调整位置
if (node.children && node.children.length > 0) {
let difference = node.childrenAreaHeight - marginY
this.updateBrothersTopValue(node, difference)
}
}
}, null, true)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-07 14:26:03
* @Desc: 更新兄弟节点的top
*/
updateBrothersTopValue(node, addHeight) {
if (node.parent && !node.parent.isRoot) {
let childrenList = node.parent.children
let index = childrenList.findIndex((item) => {
return item === node
})
childrenList.forEach((item, _index) => {
let _offset = 0
if (_index > index) {
_offset = addHeight
}
item.top += _offset
// 同步更新子节点的位置
if (item.children && item.children.length && _offset > 0) {
this.updateChildren(item.children, 'top', _offset)
}
})
// 更新父节点的位置
this.updateBrothersTopValue(node.parent, addHeight)
}
}
/**
* javascript comment
* @Author: 王林25
@ -140,10 +171,11 @@ class Render {
* @Desc: 调整节点left
*/
adjustLeftValue() {
walk(this.root, null, (node) => {
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
let marginX = this.getMarginY(layerIndex)
if (node.parent && node.parent.isRoot) {
let childrenAreaWidth = this.getNodeWidth(node)
let difference = childrenAreaWidth - node.width
let difference = childrenAreaWidth - node.width - marginX
if (difference > 0) {
this.updateBrothersLeftValue(node, difference / 2)
}
@ -161,7 +193,7 @@ class Render {
let widthArr = []
let loop = (node, width) => {
if (node.children.length) {
width += node.width / 5 + this.mindMap.opt.marginX
width += node.width / 5
node.children.forEach((item) => {
loop(item, width)
})
@ -205,66 +237,60 @@ class Render {
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 10:04:05
* @Desc: 调整节点top该节点之后的节点都往下进行偏移
* @Author: 王林
* @Date: 2021-04-11 14:42:48
* @Desc: 绘制连线连接该节点到其子节点
*/
adjustTopValue() {
let marginY = this.mindMap.opt.marginY
walk(this.root, null, (node) => {
if (!node.isRoot && !node.parent.isRoot) {
// 判断子节点的areaHeight是否大于该节点自身大于则需要调整位置
if (node.children && node.children.length > 0) {
let difference = node.childrenAreaHeight - marginY
this.updateBrothersTopValue(node, difference)
}
}
}, null, true)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-07 14:26:03
* @Desc: 更新兄弟节点的top
*/
updateBrothersTopValue(node, addHeight) {
if (node.parent && !node.parent.isRoot) {
let childrenList = node.parent.children
let index = childrenList.findIndex((item) => {
return item === node
})
childrenList.forEach((item, _index) => {
let _offset = 0
if (_index > index) {
_offset = addHeight
}
item.top += _offset
// 同步更新子节点的位置
if (item.children && item.children.length) {
this.updateChildren(item.children, 'top', _offset)
}
})
// 更新父节点的位置
this.updateBrothersTopValue(node.parent, addHeight)
renderLine(node) {
return [];
if (node.children.length <= 0) {
return [];
}
let {
left,
top,
width,
height
} = node
let lines = []
if (!node.isRoot) {
let line = this.draw.line(left + width, top + height / 2, left + width + 20, top + height / 2)
lines.push(line)
}
node.children.forEach((item) => {
let x1 = node.layerIndex === 0 ? left + width / 2 : left + width + 20
let y1 = node.layerIndex === 0 ? top + height / 2 : top + height / 2
let x2 = item.left
let y2 = item.top + item.height / 2
let path = ''
if (node.isRoot) {
path = this.quadraticCurvePath(x1, y1, x2, y2)
} else {
path = this.cubicBezierPath(x1, y1, x2, y2)
}
let line = this.draw.path(path)
lines.push(line)
})
return lines;
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-07 11:25:52
* @Desc: 更新子节点属性
* @Author: 王林
* @Date: 2021-04-11 19:54:26
* @Desc: 渲染按钮
*/
updateChildren(children, prop, offset) {
children.forEach((item) => {
item[prop] += offset
if (item.children && item.children.length) {
this.updateChildren(item.children, prop, offset)
}
renderExpandBtn(node, icons) {
return;
let {
left,
top,
width,
height
} = node
icons.forEach((icon) => {
icon.x(left + width).y(top + height / 2)
})
}
}
export default Render
export default CatalogOrganization

View File

@ -147,39 +147,6 @@ class LogicalStructure extends Base {
}
}
/**
* @Author: 王林
* @Date: 2021-04-11 15:34:20
* @Desc: 获取节点的marginY
*/
getMarginY(layerIndex) {
return layerIndex === 1 ? this.themeConfig.second.marginY : this.themeConfig.node.marginY;
}
/**
* @Author: 王林
* @Date: 2021-04-11 15:05:01
* @Desc: 二次贝塞尔曲线
*/
quadraticCurvePath(x1, y1, x2, y2) {
let cx = x1 + (x2 - x1) * 0.2
let cy = y1 + (y2 - y1) * 0.8
return `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
}
/**
* @Author: 王林
* @Date: 2021-04-11 15:05:18
* @Desc: 三次贝塞尔曲线
*/
cubicBezierPath(x1, y1, x2, y2) {
let cx1 = x1 + (x2 - x1) / 2
let cy1 = y1
let cx2 = x2 - (x2 - x1) / 2
let cy2 = y2
return `M ${x1},${y1} C ${cx1},${cy1} ${cx2},${cy2} ${x2},${y2}`
}
/**
* @Author: 王林
* @Date: 2021-04-11 14:42:48

View File

@ -1,125 +1,131 @@
import Base from './Base';
import {
walk
} from '../Utils'
} from '../utils'
import Node from '../Node'
import merge from 'deepmerge'
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:07
* @Desc: 思维导图
* @Author: 王林
* @Date: 2021-04-12 22:25:58
* @Desc: 思维导图
* 思路在逻辑结构图的基础上增加一个变量来记录生长方向向左还是向右同时在计算left的时候根据方向来计算调整top时只考虑同方向的节点即可
*/
class Render {
class MindMap extends Base {
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:32
* @Author: 王林
* @Date: 2021-04-12 22:26:31
* @Desc: 构造函数
*/
constructor(opt = {}) {
this.opt = opt
this.mindMap = opt.mindMap
this.draw = this.mindMap.draw
// 渲染树
this.renderTree = merge({}, this.mindMap.opt.data || {})
// 根节点
this.root = null
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:27:55
* @Desc: 渲染
*/
render() {
this.computed()
this.root.render()
super(opt)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-06 14:04:20
* @Desc: 计算位置数据
* @Desc: 布局
*/
computed() {
// 计算节点的left、width、height
doLayout() {
// 遍历数据计算节点的left、width、height
this.computedBaseValue()
// 计算节点的top
this.computedTopValue()
// 调整节点top
this.adjustTopValue()
return this.root;
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:49:32
* @Desc: 计算节点的leftwidthheight
* @Desc: 遍历数据计算节点的leftwidthheight
*/
computedBaseValue() {
walk(this.renderTree, null, (node, parent, isRoot, index) => {
// 生长方向
walk(this.renderTree, null, (cur, parent, isRoot, layerIndex, index) => {
// 节点生长方向
let dir = ''
if (isRoot) {
dir = ''
} else if (parent._node.isRoot) {
} else if (parent._node.isRoot) {// 二级节点根据索引来判断显示在左侧还是右侧
dir = index % 2 === 0 ? 'right' : 'left'
} else {
} else {// 三级及以下节点以上级为准
dir = parent._node.dir
}
// 设置left、width、height
let {
children,
...props
} = node
// 创建节点
let newNode = new Node({
...props,
data: cur,
uid: this.mindMap.uid++,
renderer: this.renderer,
mindMap: this.mindMap,
draw: this.draw,
dir
layerIndex
})
// 计算节点的宽高
newNode.refreshSize()
// 计算节点的left
newNode.dir = dir
// 数据关联实际节点
cur._node = newNode
// 根节点定位在画布中心位置
if (isRoot) {
newNode.isRoot = true
newNode.left = (this.mindMap.width - newNode.width) / 2
newNode.top = (this.mindMap.height - newNode.height) / 2
this.root = newNode
} else {
newNode.left = dir === 'right' ? parent._node.left + parent._node.width + this.mindMap.opt.marginX : parent._node.left - this.mindMap.opt.marginX - newNode.width
// 非根节点
let marginX = layerIndex === 1 ? this.themeConfig.second.marginX : this.themeConfig.node.marginX
// 根据生长方向定位到父节点的左侧还是右侧
newNode.left = dir === 'right' ? parent._node.left + parent._node.width + marginX : parent._node.left - newNode.width - marginX
// 互相收集
newNode.parent = parent._node
parent._node.addChildren(newNode)
}
node._node = newNode
}, (node) => {
}, (cur, parent, isRoot, layerIndex) => {
// 返回时计算节点的areaHeight也就是子节点所占的高度之和包括外边距
let len = node._node.children.length
node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => {
return h + cur.height
}, 0) + (len + 1) * this.mindMap.opt.marginY : 0
}, true)
if (cur.data.expand === false) {
cur._node.leftChildrenAreaHeight = 0
cur._node.rightChildrenAreaHeight = 0
return ;
}
let leftLen = 0
let rightLen = 0
let leftAreaHeight = 0
let rightAreaHeight = 0
cur._node.children.forEach((item) => {
if (item.dir === 'left') {
leftLen++
leftAreaHeight += item.height
} else {
rightLen++
rightAreaHeight += item.height
}
})
cur._node.leftChildrenAreaHeight = leftAreaHeight + (leftLen + 1) * this.getMarginY(layerIndex)
cur._node.rightChildrenAreaHeight = rightAreaHeight + (rightLen + 1) * this.getMarginY(layerIndex)
}, true, 0)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:59:25
* @Desc: 计算节点的top
* @Desc: 遍历节点树计算节点的top
*/
computedTopValue() {
walk(this.root, null, (node) => {
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
if (node.children && node.children.length) {
// 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半
let top = node.top + node.height / 2 - node.childrenAreaHeight / 2
let totalTop = top + this.mindMap.opt.marginY
let marginY = this.getMarginY(layerIndex)
let top = node.top + node.height / 2
let leftTotalTop = top - node.leftChildrenAreaHeight / 2 + marginY
let rightTotalTop = top - node.rightChildrenAreaHeight / 2 + marginY
node.children.forEach((cur) => {
cur.top = totalTop
totalTop += cur.height + this.mindMap.opt.marginY
if (cur.dir === 'left') {
cur.top = leftTotalTop
leftTotalTop += cur.height + marginY
} else {
cur.top = rightTotalTop
rightTotalTop += cur.height + marginY
}
})
}
}, null, true)
@ -132,12 +138,13 @@ class Render {
* @Desc: 调整节点top
*/
adjustTopValue() {
let margin = this.mindMap.opt.marginY * 2
walk(this.root, null, (node) => {
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
// 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置
let difference = node.childrenAreaHeight - margin - node.height
if (difference > 0) {
this.updateBrothers(node, difference / 2)
let h = this.getMarginY(layerIndex) + node.height
let leftDifference = node.leftChildrenAreaHeight - h
let rightDifference = node.rightChildrenAreaHeight - h
if (leftDifference > 0 || rightDifference > 0) {
this.updateBrothers(node, leftDifference / 2, rightDifference / 2)
}
}, null, true)
}
@ -148,7 +155,7 @@ class Render {
* @Date: 2021-04-07 14:26:03
* @Desc: 更新兄弟节点的top
*/
updateBrothers(node, addHeight) {
updateBrothers(node, leftAddHeight, rightAddHeight) {
if (node.parent) {
let childrenList = node.parent.children.filter((item) => {
return item.dir === node.dir
@ -158,9 +165,11 @@ class Render {
})
childrenList.forEach((item, _index) => {
let _offset = 0
let addHeight = item.dir === 'left' ? leftAddHeight : rightAddHeight
// 上面的节点往上移
if (_index < index) {
_offset = -addHeight
} else if (_index > index) {
} else if (_index > index) {// 下面的节点往下移
_offset = addHeight
}
item.top += _offset
@ -170,26 +179,65 @@ class Render {
}
})
// 更新父节点的位置
this.updateBrothers(node.parent, addHeight)
this.updateBrothers(node.parent, leftAddHeight, rightAddHeight)
}
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-07 11:25:52
* @Desc: 更新子节点属性
* @Author: 王林
* @Date: 2021-04-11 14:42:48
* @Desc: 绘制连线连接该节点到其子节点
*/
updateChildren(children, prop, offset) {
children.forEach((item) => {
item[prop] += offset
if (item.children && item.children.length) {
this.updateChildren(item.children, prop, offset)
renderLine(node) {
if (node.children.length <= 0) {
return [];
}
let {
left,
top,
width,
height,
_expandBtnSize
} = node
let lines = []
// if (!node.isRoot) {
// let line = this.draw.line(left + width, top + height / 2, left + width + 20, top + height / 2)
// lines.push(line)
// }
node.children.forEach((item) => {
let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'right' ? left + width + _expandBtnSize : left - _expandBtnSize
let y1 = node.layerIndex === 0 ? top + height / 2 : top + height / 2
let x2 = item.dir === 'right' ? item.left : item.left + item.width
let y2 = item.top + item.height / 2
let path = ''
if (node.isRoot) {
path = this.quadraticCurvePath(x1, y1, x2, y2)
} else {
path = this.cubicBezierPath(x1, y1, x2, y2)
}
let line = this.draw.path(path)
lines.push(line)
})
return lines;
}
/**
* @Author: 王林
* @Date: 2021-04-11 19:54:26
* @Desc: 渲染按钮
*/
renderExpandBtn(node, icons) {
let {
left,
top,
width,
height,
_expandBtnSize
} = node
icons.forEach((icon) => {
node.dir === 'right' ? icon.x(left + width).y(top + height / 2) : icon.x(left - _expandBtnSize).y(top + height / 2)
})
}
}
export default Render
export default MindMap

View File

@ -1,11 +0,0 @@
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-12 17:21:04
* @Desc: 基类
*/
class Structure {
}
export default Structure

View File

@ -8,7 +8,8 @@ import merge from 'deepmerge'
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 16:25:07
* @Desc: 鱼骨图
* @Desc: 目录组织图
* 思路第一轮只计算节点的宽高以及某个节点的所有子节点所占的高度之和以及该节点里所有子节点中宽度最宽是多少第二轮计算节点的left和top需要区分二级节点和其他节点二级节点top相同一行依次从做向右排开其他节点的left相同一列从上往下依次排开
*/
class Render {
/**
@ -50,9 +51,9 @@ class Render {
// 计算节点的left、top
this.computedLeftTopValue()
// 调整节点top
// this.adjustTopValue()
this.adjustTopValue()
// 调整节点left
// this.adjustLeftValue()
this.adjustLeftValue()
}
/**
@ -62,16 +63,7 @@ class Render {
* @Desc: 计算节点的widthheight
*/
computedBaseValue() {
walk(this.renderTree, null, (node, parent, isRoot, index, layerIndex) => {
// 生长方向
let dir = ''
if (isRoot) {
dir = ''
} else if (parent._node.isRoot) {
dir = index % 2 === 0 ? 'up' : 'down'
} else {
dir = parent._node.dir
}
walk(this.renderTree, null, (node, parent, isRoot) => {
// 设置width、height
let {
children,
@ -80,9 +72,7 @@ class Render {
let newNode = new Node({
...props,
mindMap: this.mindMap,
draw: this.draw,
dir,
layerIndex
draw: this.draw
})
// 计算节点的宽高
newNode.refreshSize()
@ -99,7 +89,13 @@ class Render {
node._node = newNode
}, (node) => {
// 遍历完子节点返回时
// 计算节点的areaHeight也就是子节点所占的高度之和包括外边距
let len = node._node.children.length
if (node._node.isRoot) {
node._node.childrenAreaWidth = len ? node._node.children.reduce((h, cur) => {
return h + cur.width
}, 0) + (len + 1) * this.mindMap.opt.marginX : 0
}
node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => {
return h + cur.height
}, 0) + (len + 1) * this.mindMap.opt.marginY : 0
@ -114,126 +110,24 @@ class Render {
*/
computedLeftTopValue() {
walk(this.root, null, (node) => {
// 二级节点
if (node.isRoot && node.children && node.children.length) {
let totalLeft = node.left + node.width + this.mindMap.opt.marginX
node.children.forEach((item) => {
item.left = totalLeft
item.top = node.top + node.height / 2 - this.mindMap.opt.marginY - item.height
totalLeft += item.width + this.mindMap.opt.marginX
this.computedThirdLevelLeftTopValue(item)
})
}
}, null, true)
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-13 09:33:04
* @Desc: 计算三级节点
*/
computedThirdLevelLeftTopValue(node) {
if (node.children && node.children.length > 0) {
let totalLeft = node.left
let totalTop = node.top - this.mindMap.opt.marginY
node.children.forEach((item) => {
let h = node.height + this.mindMap.opt.marginY
let w = h / Math.tan(70)
item.left = totalLeft + w
totalLeft += w
item.top = totalTop - item.height
totalTop -= this.mindMap.opt.marginY + item.height
this.computedThirdAfterLevelLeftTopValue(item)
})
}
}
/**
* javascript comment
* @Author: 王林25
* @Date: 2021-04-13 09:55:54
* @Desc: 计算三级以后的节点
*/
computedThirdAfterLevelLeftTopValue(root) {
let marginY = this.mindMap.opt.marginY
let marginX = this.mindMap.opt.marginX
// 计算left、top
walk(root, null, (node) => {
if (node.children && node.children.length) {
let totalTop = node.top + node.height + marginY
node.children.forEach((cur) => {
cur.left = node.left + node.width / 5 + marginX
cur.top = totalTop
totalTop += cur.height + marginY
})
}
}, null, true)
// 调整top
const updateBrothersTopValue = (node, addHeight) => {
if (node.parent) {
let childrenList = node.parent.children
let index = childrenList.findIndex((item) => {
return item === node
})
childrenList.forEach((item, _index) => {
let _offset = 0
if (_index > index) {
_offset = addHeight
}
item.top += _offset
// 同步更新子节点的位置
if (item.children && item.children.length) {
this.updateChildren(item.children, 'top', _offset)
}
})
// 更新父节点的位置
updateBrothersTopValue(node.parent, addHeight)
}
}
walk(root, null, (node) => {
// 判断子节点的areaHeight是否大于该节点自身大于则需要调整位置
if (node.children && node.children.length > 0) {
let difference = node.childrenAreaHeight - marginY
updateBrothersTopValue(node, difference)
}
}, null, true)
// 调整left
const updateBrothersLeftValue = (node, w, h) => {
if (node.parent && node.parent.layerIndex > 0) {
let childrenList = node.parent.children
let index = childrenList.findIndex((item) => {
return item === node
})
childrenList.forEach((item, _index) => {
let _w = 0
let _h = 0
if (_index >= index) {
_w = w
_h = -h
}
console.log(item.text, _w, _h)
item.left += _w
item.top += _h
// 同步更新子节点的位置
if (item.children && item.children.length) {
this.updateChildren(item.children, 'left', _w)
this.updateChildren(item.children, 'left', _h)
}
})
// 更新父节点的位置
updateBrothersLeftValue(node.parent, w, h)
}
}
walk(root, null, (node) => {
if (node.layerIndex > 1) {
let h = node.childrenAreaHeight - marginY
if (h > 0) {
let w = h / Math.tan(70)
console.log(node.text, w, h)
// let childrenAreaWidth = getNodeWidth(node)
// let differenceX = childrenAreaWidth - node.width
// updateBrothersLeftValue(node, w, h)
if (node.isRoot) {
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
let totalLeft = left + this.mindMap.opt.marginX
node.children.forEach((cur) => {
// left
cur.left = totalLeft
totalLeft += cur.width + this.mindMap.opt.marginX
// top
cur.top = node.top + node.height + this.mindMap.opt.marginY
})
} else {
let totalTop = node.top + node.height + this.mindMap.opt.marginY
node.children.forEach((cur) => {
cur.left = node.left + node.width / 5 + this.mindMap.opt.marginX
cur.top = totalTop
totalTop += cur.height + this.mindMap.opt.marginY
})
}
}
}, null, true)

View File

@ -4,15 +4,15 @@
* @Date: 2021-04-06 14:13:17
* @Desc: 深度优先遍历树
*/
export const walk = (root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0) => {
beforeCallback && beforeCallback(root, parent, isRoot, layerIndex)
export const walk = (root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0) => {
beforeCallback && beforeCallback(root, parent, isRoot, layerIndex, index)
if (root.children && root.children.length > 0) {
let _layerIndex = layerIndex + 1
root.children.forEach((node) => {
walk(node, root, beforeCallback, afterCallback, false, _layerIndex)
root.children.forEach((node, nodeIndex) => {
walk(node, root, beforeCallback, afterCallback, false, _layerIndex, nodeIndex)
})
}
afterCallback && afterCallback(root, parent, isRoot, layerIndex)
afterCallback && afterCallback(root, parent, isRoot, layerIndex, index)
}
/**
@ -118,10 +118,10 @@ export const simpleDeepClone = (data) => {
}
/**
* @Author: 王林
* @Date: 2021-05-04 14:40:11
* @Desc: 复制渲染树数据
*/
* @Author: 王林
* @Date: 2021-05-04 14:40:11
* @Desc: 复制渲染树数据
*/
export const copyRenderTree = (tree, root) => {
tree.data = simpleDeepClone(root.data)
tree.children = []

View File

@ -205,4 +205,9 @@ export const backgroundPositionList = [
name: '中下',
value: 'center bottom'
}
]
]
// 数据存储
export const store = {
sidebarZIndex: 1//侧边栏zIndex
}

View File

@ -227,13 +227,18 @@
<script>
import Sidebar from "./Sidebar";
import Color from "./Color";
import { lineWidthList, backgroundRepeatList, backgroundSizeList, backgroundPositionList } from "@/config";
import {
lineWidthList,
backgroundRepeatList,
backgroundSizeList,
backgroundPositionList,
} from "@/config";
import ImgUpload from "@/components/ImgUpload";
/**
* @Author: 王林
* @Date: 2021-06-24 22:52:56
* @Desc: 基础样式
/**
* @Author: 王林
* @Date: 2021-06-24 22:52:56
* @Desc: 基础样式
*/
export default {
name: "BaseStyle",
@ -269,15 +274,18 @@ export default {
iconSize: 0,
backgroundImage: "",
backgroundRepeat: "no-repeat",
backgroundSize: 'auto',
backgroundPosition: '0% 0%'
backgroundSize: "auto",
backgroundPosition: "0% 0%",
},
};
},
created() {
this.$bus.$on("showBaseStyle", () => {
this.$refs.sidebar.show = true;
this.initStyle();
this.$refs.sidebar.show = false;
this.$nextTick(() => {
this.$refs.sidebar.show = true;
this.initStyle();
});
});
},
methods: {
@ -299,7 +307,7 @@ export default {
"backgroundImage",
"backgroundRepeat",
"backgroundSize",
"backgroundPosition"
"backgroundPosition",
].forEach((key) => {
this.style[key] = this.mindMap.getThemeConfig(key);
});

View File

@ -9,6 +9,7 @@
@change="changeThemeConfig"
></BaseStyle>
<Theme :mindMap="mindMap"></Theme>
<Structure :mindMap="mindMap"></Structure>
</div>
</template>
@ -19,6 +20,7 @@ import Style from "./Style";
import BaseStyle from "./BaseStyle";
import exampleData from "simple-mind-map/example/exampleData";
import Theme from "./Theme";
import Structure from './Structure';
/**
* @Author: 王林
@ -32,6 +34,7 @@ export default {
Style,
BaseStyle,
Theme,
Structure
},
data() {
return {
@ -82,6 +85,7 @@ export default {
* @Desc: 重新渲染
*/
reRender() {
console.log(12)
this.mindMap.render();
},

View File

@ -7,10 +7,10 @@
<script>
import Sidebar from "./Sidebar";
/**
* @Author: 王林
* @Date: 2021-06-24 22:54:14
* @Desc: 大纲内容
/**
* @Author: 王林
* @Date: 2021-06-24 22:54:14
* @Desc: 大纲内容
*/
export default {
name: "Outline",
@ -31,9 +31,12 @@ export default {
this.$bus.$on("data_change", (data) => {
this.data = [data];
});
this.$bus.$on('showOutline', () => {
this.$refs.sidebar.show = true
})
this.$bus.$on("showOutline", () => {
this.$refs.sidebar.show = false;
this.$nextTick(() => {
this.$refs.sidebar.show = true;
});
});
},
};
</script>

View File

@ -1,5 +1,10 @@
<template>
<div class="sidebarContainer" :class="{show: show}">
<div
class="sidebarContainer"
@click.stop
:class="{ show: show }"
:style="{ zIndex: zIndex }"
>
<span class="closeBtn el-icon-close" @click="show = false"></span>
<div class="sidebarHeader" v-if="title">
{{ title }}
@ -11,10 +16,12 @@
</template>
<script>
/**
* @Author: 王林
* @Date: 2021-06-24 22:54:25
* @Desc: 侧边栏容器
import { store } from "@/config";
/**
* @Author: 王林
* @Date: 2021-06-24 22:54:25
* @Desc: 侧边栏容器
*/
export default {
name: "Sidebar",
@ -24,11 +31,19 @@ export default {
default: "",
},
},
data() {
return {
show: false
}
}
data() {
return {
show: false,
zIndex: 0,
};
},
watch: {
show(val, oldVal) {
if (val && !oldVal) {
this.zIndex = store.sidebarZIndex++;
}
},
},
};
</script>
@ -43,11 +58,11 @@ export default {
border-left: 1px solid #e8e8e8;
display: flex;
flex-direction: column;
transition: all 0.3s;
transition: all 0.3s;
&.show {
right: 0;
}
&.show {
right: 0;
}
.closeBtn {
position: absolute;

View File

@ -0,0 +1,33 @@
<template>
<Sidebar ref="sidebar" title="结构"> </Sidebar>
</template>
<script>
import Sidebar from "./Sidebar";
/**
* @Author: 王林
* @Date: 2021-06-24 22:54:14
* @Desc: 结构
*/
export default {
name: "Structure",
components: {
Sidebar,
},
data() {
return {};
},
created() {
this.$bus.$on("showStructure", () => {
this.$refs.sidebar.show = false;
this.$nextTick(() => {
this.$refs.sidebar.show = true;
});
});
},
};
</script>
<style lang="less" scoped>
</style>

View File

@ -261,11 +261,14 @@ export default {
},
created() {
this.$bus.$on("node_active", (...args) => {
this.activeTab = "normal";
let activeNodes = args[1];
this.activeNode = activeNodes[0];
this.$refs.sidebar.show = activeNodes.length > 0;
this.initNodeStyle();
this.$refs.sidebar.show = false;
this.$nextTick(() => {
this.activeTab = "normal";
let activeNodes = args[1];
this.activeNode = activeNodes[0];
this.$refs.sidebar.show = activeNodes.length > 0;
this.initNodeStyle();
});
});
},
methods: {

View File

@ -44,8 +44,11 @@ export default {
},
created() {
this.$bus.$on("showTheme", () => {
this.theme = this.mindMap.getTheme();
this.$refs.sidebar.show = true;
this.$refs.sidebar.show = false;
this.$nextTick(() => {
this.theme = this.mindMap.getTheme();
this.$refs.sidebar.show = true;
});
});
},
methods: {

View File

@ -98,6 +98,10 @@
<span class="icon iconfont iconjingzi"></span>
<span class="text">主题</span>
</div>
<div class="toolbarBtn" @click="$bus.$emit('showStructure')">
<span class="icon iconfont iconjiegou"></span>
<span class="text">结构</span>
</div>
</div>
</div>
<NodeImage></NodeImage>