diff --git a/simple-mind-map/example/exampleData.js b/simple-mind-map/example/exampleData.js
index de6c1ee6..e44a0c68 100644
--- a/simple-mind-map/example/exampleData.js
+++ b/simple-mind-map/example/exampleData.js
@@ -6,29 +6,27 @@
export default {
"root": {
"data": {
- "text": "鱼骨头图",
+ "text": "根节点",
},
"children": [{
"data": {
- "text": "分支主题",
- "expand": true
+ "text": "二级节点",
+ "expand": true,
},
"children": [{
"data": {
- "text": "分支主题",
- "hyperlink": "https://naotu.baidu.com/",
- "hyperlinkTitle": "百度脑图",
- "image": "https://kityminder-img.gz.bcebos.com/865551aedebd1e02ac6e76d24c093231df9aafda",
+ "text": "子节点",
+ "image": "http://aliyuncdn.lxqnsys.com/whbm/enJFNMHnedQTYTESGfDkctCp2",
"imageTitle": "图片名称",
"imageSize": {
- "width": 200,
- "height": 112
+ "width": 1000,
+ "height": 563
},
- "note": "我是备注",
- "resource": ["标签1", "标签2"],
- "priority": 5,
- "progress": 7,
- // ... 其他类型的图标
+ "icon": ['a'],
+ "tag": ["标签1", "标签2"],
+ "hyperlink": "http://lxqnsys.com/",
+ "hyperlinkTitle": "理想青年实验室",
+ "note": "理想青年实验室\n一个有意思的角落"
},
"children": []
}]
diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js
index 15c8d263..d919ee2f 100644
--- a/simple-mind-map/src/Node.js
+++ b/simple-mind-map/src/Node.js
@@ -4,12 +4,11 @@ import {
} from './utils'
import {
Image,
- Text,
SVG,
- Circle,
- Element
+ Circle
} from '@svgdotjs/svg.js'
import btnsSvg from './svg/btns'
+import iconsSvg from './svg/icons';
/**
* javascript comment
@@ -26,7 +25,7 @@ class Node {
*/
constructor(opt = {}) {
// 节点数据
- this.data = opt.data || {}
+ this.nodeData = this.handleData(opt.data || {})
// id
this.uid = opt.uid
// 控制实例
@@ -41,16 +40,14 @@ class Node {
this.style = new Style(this, this.themeConfig)
// 是否是根节点
this.isRoot = opt.isRoot === undefined ? false : opt.isRoot
- // 是否激活
- this.isActive = opt.isActive === undefined ? false : opt.isActive
- // 是否展开
- this.expand = opt.expand === undefined ? true : opt.expand
// 节点层级
this.layerIndex = opt.layerIndex === undefined ? 0 : opt.layerIndex
// 节点宽
this.width = opt.width || 0
// 节点高
this.height = opt.height || 0
+ // 节点文字内容部分高
+ this._textContentHeight = 0
// left
this.left = opt.left || 0
// top
@@ -61,6 +58,23 @@ class Node {
this.children = opt.children || []
// 文本节点
this.textNode = null
+ // icon间距
+ this._textContentItemMargin = 2
+ // 图片和文字节点的间距
+ this._blockContentMargin = 5
+ // 计算节点尺寸
+ this.refreshSize()
+ }
+
+ /**
+ * @Author: 王林
+ * @Date: 2021-06-20 10:12:31
+ * @Desc: 处理数据
+ */
+ handleData(data) {
+ data.data.expand = data.data.expand === false ? false : true
+ data.data.isActive = data.data.isActive === true ? true : false
+ return data;
}
/**
@@ -95,39 +109,62 @@ class Node {
* @Desc: 计算节点尺寸信息
*/
getNodeRect() {
- let width = this.themeConfig.paddingX * 2
- let height = this.themeConfig.paddingY * 2
- let maxWidth = 0
- if (this.img) {
- let img = this.createImgNode()
- if (img.width > maxWidth) {
- maxWidth = img.width
- }
- height += img.height
+ // 宽高
+ let imgContentWidth = 0
+ let imgContentHeight = 0
+ let textContentWidth = 0
+ let textContentHeight = 0
+ // 存在图片
+ let imgObj = this.createImgNode()
+ if (imgObj) {
+ imgContentWidth = imgObj.width
+ imgContentHeight = imgObj.height
}
- if (this.icon && this.text) {
- let icon = this.createIconNode()
- let text = this.createTextNode()
- if (icon.width + text.width > maxWidth) {
- maxWidth = icon.width + text.width
- }
- height += Math.max(text.height, icon.height)
- } else if (this.text) {
- let text = this.createTextNode()
- if (text.width > maxWidth) {
- maxWidth = text.width
- }
- height += text.height
- } else if (this.icon) {
- let icon = this.createIconNode()
- if (icon.width > maxWidth) {
- maxWidth = icon.width
- }
- height += icon.height
+ // 图标
+ let iconObjs = this.createIconNode()
+ if (iconObjs.length > 0) {
+ textContentWidth += iconObjs.reduce((sum, cur) => {
+ textContentHeight = Math.max(textContentHeight, cur.height)
+ return sum += cur.width + this._textContentItemMargin
+ }, 0)
}
+ // 文字
+ let textObj = this.createTextNode()
+ if (textObj) {
+ textContentWidth += textObj.width
+ textContentHeight = Math.max(textContentHeight, textObj.height)
+ }
+ // 超链接
+ let hyperlinkObj = this.createHyperlinkNode()
+ if (hyperlinkObj) {
+ textContentWidth += hyperlinkObj.width
+ textContentHeight = Math.max(textContentHeight, hyperlinkObj.height)
+ hyperlinkObj.node.remove()
+ }
+ // 标签
+ let tagObjs = this.createTagNode()
+ if (tagObjs.length > 0) {
+ textContentWidth += tagObjs.reduce((sum, cur) => {
+ textContentHeight = Math.max(textContentHeight, cur.height)
+ cur.node.remove()
+ return sum += cur.width + this._textContentItemMargin
+ }, 0)
+ }
+ // 备注
+ let noteObj = this.createNoteNode()
+ if (noteObj) {
+ textContentWidth += noteObj.width
+ textContentHeight = Math.max(textContentHeight, noteObj.height)
+ noteObj.node.remove()
+ }
+ // 文字内容部分的高度
+ this._textContentHeight = textContentHeight
+ // 间距
+ let margin = imgContentHeight > 0 && textContentHeight > 0 ? this._blockContentMargin : 0
+ let { paddingX, paddingY } = this.getPaddingVale()
return {
- width: width + maxWidth,
- height
+ width: Math.max(imgContentWidth, textContentWidth) + paddingX * 2,
+ height: imgContentHeight + textContentHeight + paddingY * 2 + margin
}
}
@@ -138,17 +175,55 @@ class Node {
* @Desc: 创建图片节点
*/
createImgNode() {
- if (!this.img) {
+ let img = this.nodeData.data.image
+ if (!img) {
return
}
let imgSize = this.getImgShowSize()
+ let node = new Image().load(img).size(...imgSize)
+ if (this.nodeData.data.imageTitle) {
+ node.attr('title', this.nodeData.data.imageTitle)
+ }
return {
- node: new Image().load(this.img).size(...imgSize),
+ node,
width: imgSize[0],
height: imgSize[1]
}
}
+ /**
+ * javascript comment
+ * @Author: 王林25
+ * @Date: 2021-04-09 10:12:51
+ * @Desc: 获取图片显示宽高
+ */
+ getImgShowSize() {
+ return resizeImgSize(this.nodeData.data.imageSize.width, this.nodeData.data.imageSize.height, this.themeConfig.imgMaxWidth, this.themeConfig.imgMaxHeight)
+ }
+
+ /**
+ * javascript comment
+ * @Author: 王林25
+ * @Date: 2021-04-09 14:10:48
+ * @Desc: 创建icon节点
+ */
+ createIconNode() {
+ let _data = this.nodeData.data
+ if (!_data.icon || _data.icon.length <= 0) {
+ return [];
+ }
+ let node = SVG('').size(this.themeConfig.iconSize, this.themeConfig.iconSize)
+ return [{
+ node,
+ width: this.themeConfig.iconSize,
+ height: this.themeConfig.iconSize
+ }, {
+ node: node.clone(),
+ width: this.themeConfig.iconSize,
+ height: this.themeConfig.iconSize
+ }]
+ }
+
/**
* javascript comment
* @Author: 王林25
@@ -156,10 +231,10 @@ class Node {
* @Desc: 创建文本节点
*/
createTextNode() {
- if (!this.text) {
+ if (!this.nodeData.data.text) {
return
}
- let node = this.draw.text(this.text)
+ let node = this.draw.text(this.nodeData.data.text)
this.style.text(node)
let {
width,
@@ -175,21 +250,101 @@ class Node {
}
/**
- * javascript comment
- * @Author: 王林25
- * @Date: 2021-04-09 14:10:48
- * @Desc: 创建icon节点
+ * @Author: 王林
+ * @Date: 2021-06-20 15:28:54
+ * @Desc: 创建超链接节点
*/
- createIconNode() {
- if (!this.icon) {
+ createHyperlinkNode() {
+ if (!this.nodeData.data.hyperlink) {
return
}
- let node = SVG('').size(this.themeConfig.iconSize, this.themeConfig.iconSize)
+ let iconSize = this.themeConfig.iconSize
+ let node = this.draw.element('a')
+ node.node.addEventListener('click', (e) => {
+ e.stopPropagation()
+ })
+ node.attr('href', this.nodeData.data.hyperlink).attr('target', '_blank')
+ if (this.nodeData.data.hyperlinkTitle) {
+ node.attr('title', this.nodeData.data.hyperlinkTitle)
+ }
+ node.add(this.draw.rect(iconSize, iconSize).fill({ color: 'transparent' }))
+ node.add(SVG(iconsSvg.hyperlink).size(iconSize, iconSize))
+ return {
+ node: this.draw.nested().add(node),
+ width: iconSize,
+ height: iconSize
+ }
+ }
+
+ /**
+ * @Author: 王林
+ * @Date: 2021-06-20 19:49:15
+ * @Desc: 创建标签节点
+ */
+ createTagNode() {
+ if (!this.nodeData.data.tag || this.nodeData.data.tag.length <= 0) {
+ return [];
+ }
+ let nodes = []
+ this.nodeData.data.tag.slice(0, 5).forEach((item, index) => {
+ let tag = this.draw.nested()
+ let text = this.draw.text(item).x(8).cy(10)
+ this.style.tagText(text, index)
+ let {
+ width,
+ height
+ } = text.bbox()
+ let cloneText = text.clone()
+ text.remove()
+ let rect = this.draw.rect(width + 16, 20)
+ this.style.tagRect(rect, index)
+ tag.add(rect).add(cloneText)
+ nodes.push({
+ node: tag,
+ width: width + 16,
+ height: 20
+ })
+ })
+ return nodes;
+ }
+
+ /**
+ * @Author: 王林
+ * @Date: 2021-06-20 21:19:36
+ * @Desc: 创建备注节点
+ */
+ createNoteNode() {
+ if (!this.nodeData.data.note) {
+ return null;
+ }
+ let node = this.draw.nested().attr('cursor', 'pointer')
+ let iconSize = this.themeConfig.iconSize
+ node.add(this.draw.rect(iconSize, iconSize).fill({ color: 'transparent' }))
+ node.add(SVG(iconsSvg.note).size(iconSize, iconSize))
+ let el = document.createElement('div')
+ el.style.cssText = `
+ position: absolute;
+ padding: 10px;
+ border-radius: 5px;
+ box-shadow: 0 2px 5px rgb(0 0 0 / 10%);
+ display: none;
+ `
+ el.innerText = this.nodeData.data.note
+ document.body.appendChild(el)
+ node.on('mouseover', () => {
+ let { left, top } = node.node.getBoundingClientRect()
+ el.style.left = left + 'px'
+ el.style.top = top + iconSize + 'px'
+ el.style.display = 'block'
+ })
+ node.on('mouseout', () => {
+ el.style.display = 'none'
+ })
return {
node,
- width: this.themeConfig.iconSize,
- height: this.themeConfig.iconSize
- }
+ width: iconSize,
+ height: iconSize
+ };
}
/**
@@ -203,46 +358,87 @@ class Node {
left,
top,
width,
- height
+ height,
+ _textContentHeight,
+ _textContentItemMargin
} = this
- let paddingY = this.themeConfig.paddingY
+ let { paddingY } = this.getPaddingVale()
// 创建组
let group = this.draw.group()
// 节点矩形
- let _rectNode = group.rect(width, height).x(left).y(top)
- this.style.rect(_rectNode)
- // 内容节点
- let imgNode = this.createImgNode()
- let iconNode = this.createIconNode()
- let textNode = this.createTextNode()
- let imgHeight = imgNode ? imgNode.height : 0
- // 图片
- if (imgNode) {
- group.add(imgNode.node)
- imgNode.node.cx(left + width / 2).y(top + paddingY)
+ this.style.rect(group.rect(width, height).x(left).y(top))
+ // 图片节点
+ let imgObj = this.createImgNode()
+ let imgHeight = 0
+ if (imgObj) {
+ imgHeight = imgObj.height
+ group.add(imgObj.node)
+ imgObj.node.cx(left + width / 2).y(top + paddingY)
}
+ // 内容节点
+ let textContentNested = this.draw.nested()
+ let textContentOffsetX = 0
// icon
- if (iconNode) {
- group.add(iconNode.node)
- iconNode.node.x(left + width / 2).y(top + paddingY + imgHeight + (textNode && textNode.height > iconNode.height ? (textNode.height - iconNode.height) / 2 : 0)).dx(textNode ? -textNode.width / 2 - iconNode.width / 2 : 0)
+ let iconObjs = this.createIconNode()
+ let iconNested = this.draw.nested()
+ if (iconObjs && iconObjs.length > 0) {
+ let iconLeft = 0
+ iconObjs.forEach((item) => {
+ item.node.x(textContentOffsetX + iconLeft).y((_textContentHeight - item.height) / 2)
+ iconNested.add(item.node)
+ iconLeft += item.width + _textContentItemMargin
+ })
+ textContentNested.add(iconNested)
+ textContentOffsetX += iconLeft
}
// 文字
- if (textNode) {
- this.textNode = textNode
- group.add(textNode.node)
- textNode.node.cx(left + width / 2).y(top + paddingY + imgHeight).dx(iconNode ? iconNode.width / 2 : 0)
+ let textObj = this.createTextNode()
+ if (textObj) {
+ textObj.node.x(textContentOffsetX).y(0)
+ this.textNode = textObj
+ textContentNested.add(textObj.node)
+ textContentOffsetX += textObj.width + _textContentItemMargin
}
+ // 超链接
+ let hyperlinkObj = this.createHyperlinkNode()
+ if (hyperlinkObj) {
+ hyperlinkObj.node.x(textContentOffsetX).y((_textContentHeight - hyperlinkObj.height) / 2)
+ textContentNested.add(hyperlinkObj.node)
+ textContentOffsetX += hyperlinkObj.width + _textContentItemMargin
+ }
+ // 标签
+ let tagObjs = this.createTagNode()
+ let tagNested = this.draw.nested()
+ if (tagObjs && tagObjs.length > 0) {
+ let tagLeft = 0
+ tagObjs.forEach((item) => {
+ item.node.x(textContentOffsetX + tagLeft).y((_textContentHeight - item.height) / 2)
+ tagNested.add(item.node)
+ tagLeft += item.width + _textContentItemMargin
+ })
+ textContentNested.add(tagNested)
+ textContentOffsetX += tagLeft
+ }
+ // 备注
+ let noteObj = this.createNoteNode()
+ if (noteObj) {
+ noteObj.node.x(textContentOffsetX).y((_textContentHeight - noteObj.height) / 2)
+ textContentNested.add(noteObj.node)
+ textContentOffsetX += noteObj.width
+ }
+ // 文字内容整体
+ textContentNested.x(left + width / 2).dx(-textContentNested.bbox().width / 2).y(top + imgHeight + paddingY + (imgHeight > 0 && _textContentHeight > 0 ? this._blockContentMargin : 0))
+ group.add(textContentNested)
// 单击事件
group.click((e) => {
e.stopPropagation()
- if (this.isActive) {
+ if (this.nodeData.data.isActive) {
return;
}
this.mindMap.emit('before_node_active', this, this.renderer.activeNodeList)
this.renderer.clearActive()
- this.isActive = true
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
- isActive: this.isActive
+ isActive: !this.nodeData.data.isActive
})
this.renderer.activeNodeList.push(this)
this.mindMap.render()
@@ -263,13 +459,13 @@ class Node {
*/
render() {
// 连线
- this.drawLine()
+ this.renderLine()
// 按钮
- this.drawBtn()
+ this.renderExpandBtn()
// 节点
this.draw.add(this.createNode())
// 子节点
- if (this.children && this.children.length && this.expand) {
+ if (this.children && this.children.length && this.nodeData.data.expand !== false) {
this.children.forEach((child) => {
child.render()
})
@@ -281,11 +477,11 @@ class Node {
* @Date: 2021-04-10 22:01:53
* @Desc: 连线
*/
- drawLine() {
- if (!this.expand) {
+ renderLine() {
+ if (this.nodeData.data.expand === false) {
return;
}
- let lines = this.renderer.layout.drawLine(this)
+ let lines = this.renderer.layout.renderLine(this)
lines.forEach((line) => {
this.style.line(line)
})
@@ -296,20 +492,20 @@ class Node {
* @Date: 2021-04-11 19:47:01
* @Desc: 展开收缩按钮
*/
- drawBtn() {
+ renderExpandBtn() {
if (this.children.length <= 0 || this.isRoot) {
return;
}
let g = this.draw.group()
let iconSvg
- if (this.expand) {
- iconSvg = btnsSvg.close
- } else {
+ if (this.nodeData.data.expand === false) {
iconSvg = btnsSvg.open
+ } else {
+ iconSvg = btnsSvg.close
}
let node = SVG(iconSvg).size(20, 20)
let fillNode = new Circle().size(20)
- this.renderer.layout.drawIcon(this, [node, fillNode])
+ this.renderer.layout.renderExpandBtn(this, [node, fillNode])
node.dx(0).dy(-10)
fillNode.dx(0).dy(-10)
this.style.iconBtn(node, fillNode)
@@ -324,10 +520,9 @@ class Node {
})
})
g.click(() => {
- this.expand = !this.expand
// 需要反映到实际数据上
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
- expand: this.expand
+ expand: !this.nodeData.data.expand
})
this.mindMap.render()
this.mindMap.emit('expand_btn_click', this)
@@ -337,13 +532,15 @@ class Node {
}
/**
- * javascript comment
- * @Author: 王林25
- * @Date: 2021-04-09 10:12:51
- * @Desc: 获取图片显示宽高
+ * @Author: 王林
+ * @Date: 2021-06-20 22:51:57
+ * @Desc: 获取padding值
*/
- getImgShowSize() {
- return resizeImgSize(this.imgWidth, this.imgHeight, this.themeConfig.imgMaxWidth, this.themeConfig.imgMaxHeight)
+ getPaddingVale() {
+ return {
+ paddingX: this.getStyle('paddingX', true, this.nodeData.data.isActive),
+ paddingY: this.getStyle('paddingY', true, this.nodeData.data.isActive)
+ };
}
/**
@@ -365,7 +562,7 @@ class Node {
if (isActive) {
this.mindMap.execCommand('UPDATE_NODE_DATA', this, {
activeStyle: {
- ...(this.data.activeStyle || {}),
+ ...(this.nodeData.data.activeStyle || {}),
[prop]: value
}
})
diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js
index c27eeb2b..d93663bf 100644
--- a/simple-mind-map/src/Render.js
+++ b/simple-mind-map/src/Render.js
@@ -35,11 +35,30 @@ class Render {
// 文本编辑框
this.textEdit = new TextEdit(this)
// 布局
- 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)
+ // 绑定事件
+ this.bindEvent()
// 注册命令
this.registerCommands()
}
+ /**
+ * @Author: 王林
+ * @Date: 2021-06-20 10:34:06
+ * @Desc: 绑定事件
+ */
+ bindEvent() {
+ // 点击事件
+ this.mindMap.on('draw_click', () => {
+ // 清除激活状态
+ if (this.activeNodeList.length > 0) {
+ this.clearActive()
+ this.mindMap.render()
+ this.mindMap.emit('node_active', null, [])
+ }
+ })
+ }
+
/**
* @Author: 王林
* @Date: 2021-05-04 13:19:06
@@ -167,7 +186,7 @@ class Render {
*/
updateNodeData(node, data) {
Object.keys(data).forEach((key) => {
- node.data[key] = data[key]
+ node.nodeData.data[key] = data[key]
})
}
}
diff --git a/simple-mind-map/src/Style.js b/simple-mind-map/src/Style.js
index 006b6893..76c19754 100644
--- a/simple-mind-map/src/Style.js
+++ b/simple-mind-map/src/Style.js
@@ -1,3 +1,26 @@
+const tagColorList = [
+ {
+ color: 'rgb(77, 65, 0)',
+ background: 'rgb(255, 244, 179)'
+ },
+ {
+ color: 'rgb(0, 50, 77)',
+ background: 'rgb(179, 229, 255)'
+ },
+ {
+ color: 'rgb(77, 0, 73)',
+ background: 'rgb(255, 179, 251)'
+ },
+ {
+ color: 'rgb(57, 77, 0)',
+ background: 'rgb(236, 255, 179)'
+ },
+ {
+ color: 'rgb(0, 77, 47)',
+ background: 'rgb(179, 255, 226)'
+ }
+]
+const rootProp = ['paddingX', 'paddingY']
/**
* @Author: 王林
@@ -37,23 +60,23 @@ class Style {
merge(prop, root, isActive) {
// 三级及以下节点
let defaultConfig = this.themeConfig.node
- if (root) {// 直接使用最外层样式
+ if (root || rootProp.includes(prop)) {// 直接使用最外层样式
defaultConfig = this.themeConfig
} else if (this.ctx.layerIndex === 0) {// 根节点
defaultConfig = this.themeConfig.root
} else if (this.ctx.layerIndex === 1) {// 二级节点
- defaultConfig = this.themeConfig.secondLevel
+ defaultConfig = this.themeConfig.second
}
// 激活状态
- if (isActive !== undefined ? isActive : this.ctx.isActive) {
- if (this.ctx.activeStyle && this.ctx.activeStyle[prop] !== undefined) {
- return this.ctx.activeStyle[prop];
+ if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) {
+ if (this.ctx.nodeData.data.activeStyle && this.ctx.nodeData.data.activeStyle[prop] !== undefined) {
+ return this.ctx.nodeData.data.activeStyle[prop];
} else if (defaultConfig.active && defaultConfig.active[prop]) {
return defaultConfig.active[prop]
}
}
// 优先使用节点本身的样式
- return this.ctx[prop] !== undefined ? this.ctx[prop] : defaultConfig[prop]
+ return this.ctx.nodeData.data[prop] !== undefined ? this.ctx.nodeData.data[prop] : defaultConfig[prop]
}
/**
@@ -99,6 +122,30 @@ class Style {
node.style.fontWeight = this.merge('fontWeight') || 'normal'
}
+ /**
+ * @Author: 王林
+ * @Date: 2021-06-20 20:02:18
+ * @Desc: 标签文字
+ */
+ tagText(node, index) {
+ node.fill({
+ color: tagColorList[index].color
+ }).css({
+ 'font-size': '12px'
+ })
+ }
+
+ /**
+ * @Author: 王林
+ * @Date: 2021-06-20 21:04:11
+ * @Desc: 标签矩形
+ */
+ tagRect(node, index) {
+ node.fill({
+ color: tagColorList[index].background
+ })
+ }
+
/**
* @Author: 王林
* @Date: 2021-04-11 14:50:49
diff --git a/simple-mind-map/src/TextEdit.js b/simple-mind-map/src/TextEdit.js
index 3472eff0..33a65428 100644
--- a/simple-mind-map/src/TextEdit.js
+++ b/simple-mind-map/src/TextEdit.js
@@ -16,6 +16,7 @@ export default class TextEdit {
* @Desc: 构造函数
*/
constructor(renderer) {
+ this.renderer = renderer
this.mindMap = renderer.mindMap
// 文本编辑框
this.textEditNode = null
@@ -37,12 +38,6 @@ export default class TextEdit {
this.mindMap.on('draw_click', () => {
// 隐藏文本编辑框
this.hideEditTextBox()
- // 清除激活状态
- if (this.activeNodeList.length > 0) {
- this.clearActive()
- this.mindMap.render()
- this.mindMap.emit('node_active', null, [])
- }
})
// 展开收缩按钮点击事件
this.mindMap.on('expand_btn_click', () => {
@@ -64,10 +59,10 @@ export default class TextEdit {
* @Desc: 显示文本编辑框
*/
show(node) {
- if (!node.text) {
+ if (!node.nodeData.data.text) {
return;
}
- this.showEditTextBox(this, this.textNode.node.node.getBoundingClientRect())
+ this.showEditTextBox(node, node.textNode.node.node.getBoundingClientRect())
}
/**
@@ -83,7 +78,7 @@ export default class TextEdit {
document.body.appendChild(this.textEditNode)
}
node.style.domText(this.textEditNode)
- this.textEditNode.innerHTML = node.data.text.split(/\n/img).join('
')
+ this.textEditNode.innerHTML = node.nodeData.data.text.split(/\n/img).join('
')
this.textEditNode.style.minWidth = rect.width + 10 + 'px'
this.textEditNode.style.minHeight = rect.height + 6 + 'px'
this.textEditNode.style.left = rect.left + 'px'
@@ -101,12 +96,12 @@ export default class TextEdit {
if (!this.showTextEdit) {
return
}
- this.activeNodeList.forEach((node) => {
+ this.renderer.activeNodeList.forEach((node) => {
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
- node.data.text = str
+ node.nodeData.data.text = str
this.mindMap.render()
})
- this.mindMap.emit('hide_text_edit', this.textEditNode, this.activeNodeList)
+ this.mindMap.emit('hide_text_edit', this.textEditNode, this.renderer.activeNodeList)
this.textEditNode.style.display = 'none'
this.textEditNode.innerHTML = ''
this.textEditNode.style.fontFamily = 'inherit'
diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js
index 17965b64..d5efe671 100644
--- a/simple-mind-map/src/layouts/Base.js
+++ b/simple-mind-map/src/layouts/Base.js
@@ -38,17 +38,17 @@ class Base {
* @Date: 2021-04-12 22:41:04
* @Desc: 连线
*/
- drawLine() {
- throw new Error('【drawLine】方法为必要方法,需要子类进行重写!')
+ renderLine() {
+ throw new Error('【renderLine】方法为必要方法,需要子类进行重写!')
}
/**
* @Author: 王林
* @Date: 2021-04-12 22:42:08
- * @Desc: 定位显示展开收缩按钮
+ * @Desc: 定位展开收缩按钮
*/
- drawIcon() {
- throw new Error('【drawIcon】方法为必要方法,需要子类进行重写!')
+ renderExpandBtn() {
+ throw new Error('【renderExpandBtn】方法为必要方法,需要子类进行重写!')
}
/**
diff --git a/simple-mind-map/src/layouts/LogicalStructure.js b/simple-mind-map/src/layouts/LogicalStructure.js
index 40905e61..73c32000 100644
--- a/simple-mind-map/src/layouts/LogicalStructure.js
+++ b/simple-mind-map/src/layouts/LogicalStructure.js
@@ -26,7 +26,7 @@ class LogicalStructure extends Base {
* @Desc: 布局
*/
doLayout() {
- // 计算节点的left、width、height
+ // 遍历数据计算节点的left、width、height
this.computedBaseValue()
// 计算节点的top
this.computedTopValue()
@@ -40,39 +40,41 @@ class LogicalStructure extends Base {
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:49:32
- * @Desc: 计算节点的left、width、height
+ * @Desc: 遍历数据计算节点的left、width、height
*/
computedBaseValue() {
- walk(this.renderTree, null, (node, parent, isRoot, layerIndex) => {
- // 遍历子节点前设置left、width、height
+ walk(this.renderTree, null, (cur, parent, isRoot, layerIndex) => {
// 创建节点
let newNode = new Node({
+ data: cur,
uid: this.mindMap.uid++,
- data: node,
renderer: this.renderer,
mindMap: this.mindMap,
draw: this.draw,
layerIndex
})
- // 计算节点的宽高
- newNode.refreshSize()
+ // 数据关联实际节点
+ 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 {
- let marginX = layerIndex === 1 ? this.themeConfig.secondLevel.marginX : this.themeConfig.node.marginX
- newNode.left = parent._node.left + parent._node.width + marginX,
- newNode.parent = parent._node
+ // 非根节点
+ let marginX = layerIndex === 1 ? this.themeConfig.second.marginX : this.themeConfig.node.marginX
+ // 定位到父节点右侧
+ newNode.left = parent._node.left + parent._node.width + marginX
+ // 互相收集
+ newNode.parent = parent._node
parent._node.addChildren(newNode)
}
- node._node = newNode
- }, (node, parent, isRoot, layerIndex) => {
+ }, (cur, parent, isRoot, layerIndex) => {
// 返回时计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距
- let len = node.expand === false ? 0 : node._node.children.length
- node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => {
- return h + cur.height
+ let len = cur.data.expand === false ? 0 : cur._node.children.length
+ cur._node.childrenAreaHeight = len ? cur._node.children.reduce((h, item) => {
+ return h + item.height
}, 0) + (len + 1) * this.getMarginY(layerIndex) : 0
}, true, 0)
}
@@ -81,7 +83,7 @@ class LogicalStructure extends Base {
* javascript comment
* @Author: 王林25
* @Date: 2021-04-08 09:59:25
- * @Desc: 计算节点的top
+ * @Desc: 遍历节点树计算节点的top
*/
computedTopValue() {
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
@@ -151,7 +153,7 @@ class LogicalStructure extends Base {
* @Desc: 获取节点的marginY
*/
getMarginY(layerIndex) {
- return layerIndex === 1 ? this.themeConfig.secondLevel.marginY : this.themeConfig.node.marginY;
+ return layerIndex === 1 ? this.themeConfig.second.marginY : this.themeConfig.node.marginY;
}
/**
@@ -183,7 +185,7 @@ class LogicalStructure extends Base {
* @Date: 2021-04-11 14:42:48
* @Desc: 绘制连线,连接该节点到其子节点
*/
- drawLine(node) {
+ renderLine(node) {
if (node.children.length <= 0) {
return [];
}
@@ -220,7 +222,7 @@ class LogicalStructure extends Base {
* @Date: 2021-04-11 19:54:26
* @Desc: 渲染按钮
*/
- drawIcon(node, icons) {
+ renderExpandBtn(node, icons) {
let {
left,
top,
diff --git a/simple-mind-map/src/svg/icons.js b/simple-mind-map/src/svg/icons.js
new file mode 100644
index 00000000..2454f489
--- /dev/null
+++ b/simple-mind-map/src/svg/icons.js
@@ -0,0 +1,10 @@
+// 超链接图标
+const hyperlink = ''
+
+// 备注图标
+const note = ''
+
+export default {
+ hyperlink,
+ note
+}
\ No newline at end of file
diff --git a/simple-mind-map/src/themes/blueSky.js b/simple-mind-map/src/themes/blueSky.js
index 551ed1db..6b2add3e 100644
--- a/simple-mind-map/src/themes/blueSky.js
+++ b/simple-mind-map/src/themes/blueSky.js
@@ -19,7 +19,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(238, 243, 246)',
color: '#333',
borderColor: 'rgb(115, 161, 191)',
diff --git a/simple-mind-map/src/themes/brainImpairedPink.js b/simple-mind-map/src/themes/brainImpairedPink.js
index 1e91793c..9b43e42f 100644
--- a/simple-mind-map/src/themes/brainImpairedPink.js
+++ b/simple-mind-map/src/themes/brainImpairedPink.js
@@ -19,7 +19,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(246, 238, 242)',
color: '#333',
borderColor: 'rgb(191, 115, 148)',
diff --git a/simple-mind-map/src/themes/classic.js b/simple-mind-map/src/themes/classic.js
index 0661183c..48bed19e 100644
--- a/simple-mind-map/src/themes/classic.js
+++ b/simple-mind-map/src/themes/classic.js
@@ -29,7 +29,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(164, 197, 192)',
borderColor: 'transparent',
color: '#333',
diff --git a/simple-mind-map/src/themes/classic2.js b/simple-mind-map/src/themes/classic2.js
index a2841006..269c863e 100644
--- a/simple-mind-map/src/themes/classic2.js
+++ b/simple-mind-map/src/themes/classic2.js
@@ -24,7 +24,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(241, 242, 241)',
borderColor: 'transparent',
color: '#1a1a1a',
diff --git a/simple-mind-map/src/themes/classic3.js b/simple-mind-map/src/themes/classic3.js
index a14184a3..f37e7917 100644
--- a/simple-mind-map/src/themes/classic3.js
+++ b/simple-mind-map/src/themes/classic3.js
@@ -26,7 +26,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(255, 245, 214)',
borderColor: 'rgb(249, 199, 84)',
borderWidth: 1,
diff --git a/simple-mind-map/src/themes/dark.js b/simple-mind-map/src/themes/dark.js
index 8c4faf86..1bc2adb1 100644
--- a/simple-mind-map/src/themes/dark.js
+++ b/simple-mind-map/src/themes/dark.js
@@ -24,7 +24,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(55, 56, 58)',
color: 'rgb(147,148,149)',
fontSize: 18,
diff --git a/simple-mind-map/src/themes/default.js b/simple-mind-map/src/themes/default.js
index 7a3da117..117422cf 100644
--- a/simple-mind-map/src/themes/default.js
+++ b/simple-mind-map/src/themes/default.js
@@ -8,9 +8,9 @@ export default {
paddingX: 20,
paddingY: 10,
// 图片显示的最大宽度
- imgMaxWidth: 200,
+ imgMaxWidth: 100,
// 图片显示的最大高度
- imgMaxHeight: 200,
+ imgMaxHeight: 100,
// icon的大小
iconSize: 20,
// 连线的粗细
@@ -43,7 +43,7 @@ export default {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
marginX: 100,
marginY: 40,
fillColor: '#fff',
diff --git a/simple-mind-map/src/themes/earthYellow.js b/simple-mind-map/src/themes/earthYellow.js
index c7e906f7..ec9323d7 100644
--- a/simple-mind-map/src/themes/earthYellow.js
+++ b/simple-mind-map/src/themes/earthYellow.js
@@ -19,7 +19,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(246, 242, 238)',
color: '#333',
borderColor: 'rgb(191, 147, 115)',
diff --git a/simple-mind-map/src/themes/freshGreen.js b/simple-mind-map/src/themes/freshGreen.js
index 5db06ac1..e903c788 100644
--- a/simple-mind-map/src/themes/freshGreen.js
+++ b/simple-mind-map/src/themes/freshGreen.js
@@ -16,7 +16,7 @@ export default merge(defaultTheme, {
fillColor: '#1fb27d'
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: '#fff',
color: '#565656',
borderColor: 'transparent',
diff --git a/simple-mind-map/src/themes/freshRed.js b/simple-mind-map/src/themes/freshRed.js
index ec3a754b..3028d920 100644
--- a/simple-mind-map/src/themes/freshRed.js
+++ b/simple-mind-map/src/themes/freshRed.js
@@ -19,7 +19,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(246, 238, 238)',
color: '#333',
borderColor: 'rgb(191, 115, 115)',
diff --git a/simple-mind-map/src/themes/romanticPurple.js b/simple-mind-map/src/themes/romanticPurple.js
index ce8b045b..4cde9383 100644
--- a/simple-mind-map/src/themes/romanticPurple.js
+++ b/simple-mind-map/src/themes/romanticPurple.js
@@ -19,7 +19,7 @@ export default merge(defaultTheme, {
}
},
// 二级节点样式
- secondLevel: {
+ second: {
fillColor: 'rgb(239, 238, 246)',
color: '#333',
borderColor: 'rgb(123, 115, 191)',
diff --git a/web/src/pages/Edit/components/NodeImage.vue b/web/src/pages/Edit/components/NodeImage.vue
index a8f6e698..dd6389d9 100644
--- a/web/src/pages/Edit/components/NodeImage.vue
+++ b/web/src/pages/Edit/components/NodeImage.vue
@@ -25,7 +25,6 @@ export default {
this.$bus.$on("node_active", (...args) => {
let activeNodes = args[1];
this.activeNode = activeNodes[0];
- console.log(args);
});
this.$bus.$on("showNodeImage", () => {
this.dialogVisible = true;
diff --git a/web/src/pages/Edit/components/Style.vue b/web/src/pages/Edit/components/Style.vue
index 5bd6284e..352f1ea5 100644
--- a/web/src/pages/Edit/components/Style.vue
+++ b/web/src/pages/Edit/components/Style.vue
@@ -6,6 +6,7 @@