diff --git a/simple-mind-map/example/exampleData.js b/simple-mind-map/example/exampleData.js index 2851f417..e0e4c742 100644 --- a/simple-mind-map/example/exampleData.js +++ b/simple-mind-map/example/exampleData.js @@ -793,8 +793,8 @@ export default { // 自定义配置... } }, + "layout": "logicalStructure", // "layout": "mindMap", - // "layout": "logicalStructure" // "layout": "catalogOrganization" - "layout": "organizationStructure" + // "layout": "organizationStructure" } \ No newline at end of file diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index 5e9d2a55..1f9b9825 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -9,6 +9,9 @@ import Command from './src/Command' import BatchExecution from './src/BatchExecution' import Export from './src/Export' import Select from './src/Select' +import { + layoutValueList +} from './src/utils/constant' import { SVG } from '@svgdotjs/svg.js' @@ -32,7 +35,11 @@ const defaultOpt = { // 节点里图片和文字的间距 imgTextMargin: 5, // 节点里各种文字信息的间距,如图标和文字的间距 - textContentMargin: 2 + textContentMargin: 2, + // 多选节点时鼠标移动到边缘时的画布移动偏移量 + selectTranslateStep: 3, + // 多选节点时鼠标移动距边缘多少距离时开始偏移 + selectTranslateLimit: 20 } /** @@ -123,7 +130,7 @@ class MindMap { */ handleOpt(opt) { // 检查布局配置 - if (!['logicalStructure', 'mindMap', 'catalogOrganization', 'organizationStructure'].includes(opt.layout)) { + if (!layoutValueList.includes(opt.layout)) { opt.layout = 'logicalStructure' } // 检查主题配置 @@ -248,6 +255,32 @@ class MindMap { return prop === undefined ? this.themeConfig : this.themeConfig[prop] } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 16:17:06 + * @Desc: 获取当前布局结构 + */ + getLayout() { + return this.opt.layout + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 16:17:33 + * @Desc: 设置布局结构 + */ + setLayout(layout) { + // 检查布局配置 + if (!layoutValueList.includes(layout)) { + layout = 'logicalStructure' + } + this.opt.layout = layout + this.renderer.setLayout() + this.render() + } + /** * @Author: 王林 * @Date: 2021-05-04 13:01:00 @@ -262,7 +295,7 @@ class MindMap { * @Date: 2021-07-01 22:06:38 * @Desc: 导出 */ - async export(...args) { + async export (...args) { let result = await this.doExport.export(...args) return result } diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index ecc3b685..6ca5f0ee 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -78,15 +78,13 @@ class Node { textContentHeight: 0 } // 各种文字信息的间距 - this._textContentItemMargin = this.mindMap.opt.textContentMargin + this.textContentItemMargin = this.mindMap.opt.textContentMargin // 图片和文字节点的间距 - this._blockContentMargin = this.mindMap.opt.imgTextMargin + this.blockContentMargin = this.mindMap.opt.imgTextMargin // 展开收缩按钮尺寸 - this._expandBtnSize = this.mindMap.opt.expandBtnSize + this.expandBtnSize = this.mindMap.opt.expandBtnSize // 初始渲染 - this._initRender = true - // 更新的时候的钩子 - this.updateHooks = [] + this.initRender = true // 初始化 this.createNodeData() this.getSize() @@ -241,7 +239,7 @@ class Node { if (this._iconData.length > 0) { textContentWidth += this._iconData.reduce((sum, cur) => { textContentHeight = Math.max(textContentHeight, cur.height) - return sum += cur.width + this._textContentItemMargin + return sum += cur.width + this.textContentItemMargin }, 0) } // 文字 @@ -258,7 +256,7 @@ class Node { if (this._tagData.length > 0) { textContentWidth += this._tagData.reduce((sum, cur) => { textContentHeight = Math.max(textContentHeight, cur.height) - return sum += cur.width + this._textContentItemMargin + return sum += cur.width + this.textContentItemMargin }, 0) } // 备注 @@ -270,7 +268,7 @@ class Node { this._rectInfo.textContentWidth = textContentWidth this._rectInfo.textContentHeight = textContentHeight // 间距 - let margin = imgContentHeight > 0 && textContentHeight > 0 ? this._blockContentMargin : 0 + let margin = imgContentHeight > 0 && textContentHeight > 0 ? this.blockContentMargin : 0 let { paddingX, paddingY } = this.getPaddingVale() return { width: Math.max(imgContentWidth, textContentWidth) + paddingX * 2, @@ -481,7 +479,7 @@ class Node { let { width, height, - _textContentItemMargin + textContentItemMargin } = this let { paddingY } = this.getPaddingVale() // 创建组 @@ -507,7 +505,7 @@ class Node { this._iconData.forEach((item) => { item.node.x(textContentOffsetX + iconLeft).y((this._rectInfo.textContentHeight - item.height) / 2) iconNested.add(item.node) - iconLeft += item.width + _textContentItemMargin + iconLeft += item.width + textContentItemMargin }) textContentNested.add(iconNested) textContentOffsetX += iconLeft @@ -516,13 +514,13 @@ class Node { if (this._textData) { this._textData.node.x(textContentOffsetX).y(0) textContentNested.add(this._textData.node) - textContentOffsetX += this._textData.width + _textContentItemMargin + textContentOffsetX += this._textData.width + textContentItemMargin } // 超链接 if (this._hyperlinkData) { this._hyperlinkData.node.x(textContentOffsetX).y((this._rectInfo.textContentHeight - this._hyperlinkData.height) / 2) textContentNested.add(this._hyperlinkData.node) - textContentOffsetX += this._hyperlinkData.width + _textContentItemMargin + textContentOffsetX += this._hyperlinkData.width + textContentItemMargin } // 标签 let tagNested = new G() @@ -531,7 +529,7 @@ class Node { this._tagData.forEach((item) => { item.node.x(textContentOffsetX + tagLeft).y((this._rectInfo.textContentHeight - item.height) / 2) tagNested.add(item.node) - tagLeft += item.width + _textContentItemMargin + tagLeft += item.width + textContentItemMargin }) textContentNested.add(tagNested) textContentOffsetX += tagLeft @@ -545,7 +543,7 @@ class Node { // 文字内容整体 textContentNested.translate( width / 2 - textContentNested.bbox().width / 2, - imgHeight + paddingY + (imgHeight > 0 && this._rectInfo.textContentHeight > 0 ? this._blockContentMargin : 0) + imgHeight + paddingY + (imgHeight > 0 && this._rectInfo.textContentHeight > 0 ? this.blockContentMargin : 0) ) this.group.add(textContentNested) // 单击事件,选中节点 @@ -606,11 +604,8 @@ class Node { this.removeExpandBtn() } else if (!this._expandBtn && this.nodeData.children.length > 0) {// 需要添加展开收缩按钮 this.renderExpandBtn() - } - if (!layout) { - this.updateHooks.forEach((hook) => { - hook(this) - }) + } else { + this.updateExpandBtnPos() } let t = this.group.transform() if (!layout) { @@ -630,8 +625,8 @@ class Node { // 连线 this.renderLine() // 节点 - if (this._initRender) { - this._initRender = false + if (this.initRender) { + this.initRender = false this.renderNode() } else { this.update() @@ -652,7 +647,7 @@ class Node { * @Desc: 递归删除 */ remove() { - this._initRender = true + this.initRender = true this.removeAllEvent() this.removeAllNode() this.removeLine() @@ -723,10 +718,10 @@ class Node { } else { iconSvg = btnsSvg.close } - let node = SVG(iconSvg).size(this._expandBtnSize, this._expandBtnSize) - let fillNode = new Circle().size(this._expandBtnSize) - node.x(0).y(-this._expandBtnSize / 2) - fillNode.x(0).y(-this._expandBtnSize / 2) + let node = SVG(iconSvg).size(this.expandBtnSize, this.expandBtnSize) + let fillNode = new Circle().size(this.expandBtnSize) + node.x(0).y(-this.expandBtnSize / 2) + fillNode.x(0).y(-this.expandBtnSize / 2) this.style.iconBtn(node, fillNode) this._expandBtn.add(fillNode).add(node) } @@ -741,7 +736,6 @@ class Node { if (!this._expandBtn) { return } - console.log('更新') this.renderer.layout.renderExpandBtn(this, this._expandBtn) } @@ -775,7 +769,7 @@ class Node { this.mindMap.emit('expand_btn_click', this) }) this.group.add(this._expandBtn) - this.renderer.layout.renderExpandBtn(this, this._expandBtn) + this.updateExpandBtnPos() } /** diff --git a/simple-mind-map/src/Render.js b/simple-mind-map/src/Render.js index 1aca04ec..0302d855 100644 --- a/simple-mind-map/src/Render.js +++ b/simple-mind-map/src/Render.js @@ -44,7 +44,7 @@ class Render { // 根节点 this.root = null // 布局 - this.layout = new (layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this) + this.setLayout() // 绑定事件 this.bindEvent() // 注册命令 @@ -55,6 +55,16 @@ class Render { 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 @@ -371,9 +381,7 @@ class Render { this.setNodeData(node, { isActive: active }) - let s = Date.now() node.renderNode() - console.log(Date.now() - s) } /** diff --git a/simple-mind-map/src/Select.js b/simple-mind-map/src/Select.js index e7776013..b330dbaf 100644 --- a/simple-mind-map/src/Select.js +++ b/simple-mind-map/src/Select.js @@ -73,12 +73,27 @@ class Select { * @Desc: 鼠标移动到边缘后移动画布 */ move (x, y) { - if (x >= this.mindMap.elRect.right - 20) { - console.log('小于') + let step = this.mindMap.opt.selectTranslateStep + let limit = this.mindMap.opt.selectTranslateLimit + // 左边缘 + if (x <= this.mindMap.elRect.left + limit) { + this.mouseDownX += step + this.mindMap.view.translateX(step) } - if (y >= this.mindMap.elRect.bottom - 20) { - console.log('小于') - this.mindMap.view.translateY(-3) + // 右边缘 + if (x >= this.mindMap.elRect.right - limit) { + this.mouseDownX -= step + this.mindMap.view.translateX(-step) + } + // 上边缘 + if (y <= this.mindMap.elRect.top + limit) { + this.mouseDownY += step + this.mindMap.view.translateY(step) + } + // 下边缘 + if (y >= this.mindMap.elRect.bottom - limit) { + this.mouseDownY -= step + this.mindMap.view.translateY(-step) } } diff --git a/simple-mind-map/src/View.js b/simple-mind-map/src/View.js index f20e55bb..4ea4764a 100644 --- a/simple-mind-map/src/View.js +++ b/simple-mind-map/src/View.js @@ -60,10 +60,23 @@ class View { }) } - translateX() { - + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 15:49:06 + * @Desc: 平移x方向 + */ + translateX(step) { + this.x += step + this.transform() } + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 15:48:52 + * @Desc: 平移y方向 + */ translateY(step) { this.y += step this.transform() diff --git a/simple-mind-map/src/assets/catalogOrganization.jpg b/simple-mind-map/src/assets/catalogOrganization.jpg new file mode 100644 index 00000000..7978d11f Binary files /dev/null and b/simple-mind-map/src/assets/catalogOrganization.jpg differ diff --git a/simple-mind-map/src/assets/dark2.jpg b/simple-mind-map/src/assets/dark2.jpg new file mode 100644 index 00000000..aabfec16 Binary files /dev/null and b/simple-mind-map/src/assets/dark2.jpg differ diff --git a/simple-mind-map/src/assets/gold.jpg b/simple-mind-map/src/assets/gold.jpg new file mode 100644 index 00000000..4192a94e Binary files /dev/null and b/simple-mind-map/src/assets/gold.jpg differ diff --git a/simple-mind-map/src/assets/greenLeaf.jpg b/simple-mind-map/src/assets/greenLeaf.jpg new file mode 100644 index 00000000..440b89de Binary files /dev/null and b/simple-mind-map/src/assets/greenLeaf.jpg differ diff --git a/simple-mind-map/src/assets/icon_newcreat_classify.png b/simple-mind-map/src/assets/icon_newcreat_classify.png deleted file mode 100644 index 6fa0bcf8..00000000 Binary files a/simple-mind-map/src/assets/icon_newcreat_classify.png and /dev/null differ diff --git a/simple-mind-map/src/assets/icon_newcreat_mindmap.png b/simple-mind-map/src/assets/icon_newcreat_mindmap.png deleted file mode 100644 index 389b5051..00000000 Binary files a/simple-mind-map/src/assets/icon_newcreat_mindmap.png and /dev/null differ diff --git a/simple-mind-map/src/assets/icon_newcreat_structure.png b/simple-mind-map/src/assets/icon_newcreat_structure.png deleted file mode 100644 index 24f3b15c..00000000 Binary files a/simple-mind-map/src/assets/icon_newcreat_structure.png and /dev/null differ diff --git a/simple-mind-map/src/assets/icon_newcreat_theright.png b/simple-mind-map/src/assets/icon_newcreat_theright.png deleted file mode 100644 index 3889465b..00000000 Binary files a/simple-mind-map/src/assets/icon_newcreat_theright.png and /dev/null differ diff --git a/simple-mind-map/src/assets/logicalStructure.jpg b/simple-mind-map/src/assets/logicalStructure.jpg new file mode 100644 index 00000000..998922a4 Binary files /dev/null and b/simple-mind-map/src/assets/logicalStructure.jpg differ diff --git a/simple-mind-map/src/assets/mindMap.jpg b/simple-mind-map/src/assets/mindMap.jpg new file mode 100644 index 00000000..9a35f185 Binary files /dev/null and b/simple-mind-map/src/assets/mindMap.jpg differ diff --git a/simple-mind-map/src/assets/mint.jpg b/simple-mind-map/src/assets/mint.jpg new file mode 100644 index 00000000..4f6f72b4 Binary files /dev/null and b/simple-mind-map/src/assets/mint.jpg differ diff --git a/simple-mind-map/src/assets/organizationStructure.jpg b/simple-mind-map/src/assets/organizationStructure.jpg new file mode 100644 index 00000000..0159e807 Binary files /dev/null and b/simple-mind-map/src/assets/organizationStructure.jpg differ diff --git a/simple-mind-map/src/assets/skyGreen.jpg b/simple-mind-map/src/assets/skyGreen.jpg new file mode 100644 index 00000000..76a0c1d0 Binary files /dev/null and b/simple-mind-map/src/assets/skyGreen.jpg differ diff --git a/simple-mind-map/src/assets/vitalityOrange.jpg b/simple-mind-map/src/assets/vitalityOrange.jpg new file mode 100644 index 00000000..8fc9c922 Binary files /dev/null and b/simple-mind-map/src/assets/vitalityOrange.jpg differ diff --git a/simple-mind-map/src/layouts/CatalogOrganization.js b/simple-mind-map/src/layouts/CatalogOrganization.js index fc5511f1..5fbdb1eb 100644 --- a/simple-mind-map/src/layouts/CatalogOrganization.js +++ b/simple-mind-map/src/layouts/CatalogOrganization.js @@ -29,9 +29,9 @@ class CatalogOrganization extends Base { let task = [() => { this.computedBaseValue() }, () => { - this.computedLeftValue() + this.computedLeftTopValue() }, () => { - // this.adjustTopValue() + this.adjustLeftTopValue() }, () => { callback(this.root) }] @@ -53,18 +53,20 @@ class CatalogOrganization extends Base { newNode.top = (this.mindMap.height - newNode.height) / 2 } else { // 非根节点 - // 定位到父节点下方 - newNode.top = parent._node.top + parent._node.height + this.getMarginX(layerIndex) + if (parent._node.isRoot) { + newNode.top = parent._node.top + parent._node.height + this.getMarginX(layerIndex) + } } if (!cur.data.expand) { return true; } }, (cur, parent, isRoot, layerIndex) => { - // 返回时计算节点的areaWidth和areaHeight,也就是子节点所占的高度之和,包括外边距 - let len = cur.data.expand === false ? 0 : cur._node.children.length - cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => { - return h + item.width - }, 0) + (len + 1) * this.getMarginY(layerIndex + 1) : 0 + if (isRoot) { + let len = cur.data.expand === false ? 0 : cur._node.children.length + cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => { + return h + item.width + }, 0) + (len + 1) * this.getMarginX(layerIndex + 1) : 0 + } }, true, 0) } @@ -72,19 +74,28 @@ class CatalogOrganization extends Base { * javascript comment * @Author: 王林25 * @Date: 2021-04-08 09:59:25 - * @Desc: 遍历节点树计算节点的left + * @Desc: 遍历节点树计算节点的left、top */ - computedLeftValue() { + computedLeftTopValue() { walk(this.root, null, (node, parent, isRoot, layerIndex) => { if (node.nodeData.data.expand && node.children && node.children.length) { - let marginX = this.getMarginY(layerIndex + 1) - // 第一个子节点的left值 = 该节点中心的left值 - 子节点的宽度之和的一半 - let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 - let totalLeft = left + marginX - node.children.forEach((cur) => { - cur.left = totalLeft - totalLeft += cur.width + marginX - }) + let marginX = this.getMarginX(layerIndex + 1) + let marginY = this.getMarginY(layerIndex + 1) + if (isRoot) { + let left = node.left + node.width / 2 - node.childrenAreaWidth / 2 + let totalLeft = left + marginX + node.children.forEach((cur) => { + cur.left = totalLeft + totalLeft += cur.width + marginX + }) + } else { + let totalTop = node.top + node.height + marginY + node.expandBtnSize + node.children.forEach((cur) => { + cur.left = node.left + node.width * 0.5 + cur.top = totalTop + totalTop += cur.height + marginY + node.expandBtnSize + }) + } } }, null, true) } @@ -93,17 +104,29 @@ class CatalogOrganization extends Base { * javascript comment * @Author: 王林25 * @Date: 2021-04-08 10:04:05 - * @Desc: 调整节点top + * @Desc: 调整节点left、top */ - adjustTopValue() { + adjustLeftTopValue() { walk(this.root, null, (node, parent, isRoot, layerIndex) => { if (!node.nodeData.data.expand) { return; } - // 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置 - let difference = node.childrenAreaHeight - this.getMarginY(layerIndex + 1) * 2 - node.height - if (difference > 0) { - this.updateBrothers(node, difference / 2) + // 调整left + if (parent && parent.isRoot) { + let areaWidth = this.getNodeAreaWidth(node) + let difference = areaWidth - node.width + if (difference > 0) { + this.updateBrothersLeft(node, difference / 2) + } + } + // 调整top + let len = node.children.length + if (parent && !parent.isRoot && len > 0) { + let marginY = this.getMarginY(layerIndex + 1) + let totalHeight = node.children.reduce((h, item) => { + return h + item.height + }, 0) + (len + 1) * marginY + len * node.expandBtnSize + this.updateBrothersTop(node, totalHeight) } }, null, true) } @@ -111,21 +134,80 @@ class CatalogOrganization extends Base { /** * javascript comment * @Author: 王林25 - * @Date: 2021-04-07 14:26:03 - * @Desc: 更新兄弟节点的top + * @Date: 2021-04-12 18:55:03 + * @Desc: 递归计算节点的宽度 */ - updateBrothers(node, addHeight) { + getNodeAreaWidth(node) { + let widthArr = [] + let loop = (node, width) => { + if (node.children.length) { + width += node.width / 2 + node.children.forEach((item) => { + loop(item, width) + }) + } else { + width += node.width + widthArr.push(width) + } + } + loop(node, 0) + return Math.max(...widthArr) + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 11:12:51 + * @Desc: 调整兄弟节点的left + */ + updateBrothersLeft(node, addWidth) { if (node.parent) { + let childrenList = node.parent.children + let index = childrenList.findIndex((item) => { + return item === node + }) + // 第一个或最后一个节点自身也需要移动,否则两边不对称 + if (index === 0 || index === childrenList.length - 1) { + let _offset = index === 0 ? -addWidth : addWidth + node.left += _offset + if (node.children && node.children.length) { + this.updateChildren(node.children, 'left', _offset) + } + } + childrenList.forEach((item, _index) => { + let _offset = 0 + if (_index < index) { // 左边的节点往左移 + _offset = -addWidth + } else if (_index > index) { // 右边的节点往右移 + _offset = addWidth + } + item.left += _offset + // 同步更新子节点的位置 + if (item.children && item.children.length) { + this.updateChildren(item.children, 'left', _offset) + } + }) + // 更新父节点的位置 + this.updateBrothersLeft(node.parent, addWidth) + } + } + + /** + * javascript comment + * @Author: 王林25 + * @Date: 2021-04-07 14:26:03 + * @Desc: 调整兄弟节点的top + */ + updateBrothersTop(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 - } else if (_index > index) { // 下面的节点往下移 + // 下面的节点往下移 + if (_index > index) { _offset = addHeight } item.top += _offset @@ -135,7 +217,7 @@ class CatalogOrganization extends Base { } }) // 更新父节点的位置 - this.updateBrothers(node.parent, addHeight) + this.updateBrothersTop(node.parent, addHeight) } } @@ -145,7 +227,6 @@ class CatalogOrganization extends Base { * @Desc: 绘制连线,连接该节点到其子节点 */ renderLine(node, lines) { - return if (node.children.length <= 0) { return []; } @@ -153,21 +234,61 @@ class CatalogOrganization extends Base { left, top, width, - height + height, + expandBtnSize } = node - node.children.forEach((item, index) => { - 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 len = node.children.length + let marginX = this.getMarginX(node.layerIndex + 1) + if (node.isRoot) { + let x1 = left + width / 2 + let y1 = top + height + let s1 = marginX * 0.7 + let minx = 0 + let maxx = 0 + node.children.forEach((item, index) => { + let x2 = item.left +item.width / 2 + let y2 = item.top + if (index === 0) { + minx = x2 + } else if (index >= len - 1) { + maxx = x2 + } + let path = `M ${x2},${y1 + s1} L ${x2},${y2}` + lines[index].plot(path) + }) + // 父节点的竖线 + let line1 = this.draw.path() + node.style.line(line1) + line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`) + node._lines.push(line1) + // 水平线 + if (len > 1) { + let lin2 = this.draw.path() + node.style.line(lin2) + lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`) + node._lines.push(lin2) } - lines[index].plot(path) - }) + } else { + let y1 = top + height + let maxy = 0 + let x2 = node.left + node.width * 0.3 + node.children.forEach((item, index) => { + let y2 = item.top + item.height / 2 + if (index >= len - 1) { + maxy = y2 + } + let path = `M ${x2},${y2} L ${x2 + node.width * 0.2},${y2}` + lines[index].plot(path) + }) + // 竖线 + if (len > 0) { + let lin2 = this.draw.path() + expandBtnSize = len > 0 ? expandBtnSize : 0 + node.style.line(lin2) + lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`) + node._lines.push(lin2) + } + } } /** @@ -176,12 +297,19 @@ class CatalogOrganization extends Base { * @Desc: 渲染按钮 */ renderExpandBtn(node, btn) { - return let { width, - height + height, + expandBtnSize, + isRoot } = node - btn.translate(width, height / 2) + if (!isRoot) { + let { + translateX, + translateY + } = btn.transform() + btn.translate(width * 0.3 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY) + } } } diff --git a/simple-mind-map/src/layouts/LogicalStructure.js b/simple-mind-map/src/layouts/LogicalStructure.js index 45932e20..a469019f 100644 --- a/simple-mind-map/src/layouts/LogicalStructure.js +++ b/simple-mind-map/src/layouts/LogicalStructure.js @@ -179,7 +179,11 @@ class LogicalStructure extends Base { width, height } = node - btn.translate(width, height / 2) + let { + translateX, + translateY + } = btn.transform() + btn.translate(width - translateX, height / 2 - translateY) } } diff --git a/simple-mind-map/src/layouts/MindMap.js b/simple-mind-map/src/layouts/MindMap.js index 068be7d6..5dfcf4f7 100644 --- a/simple-mind-map/src/layouts/MindMap.js +++ b/simple-mind-map/src/layouts/MindMap.js @@ -48,12 +48,6 @@ class MindMap extends Base { computedBaseValue() { walk(this.renderer.renderTree, null, (cur, parent, isRoot, layerIndex, index) => { let newNode = this.createNode(cur, parent, isRoot, layerIndex) - // 更新时展开收缩按钮位置可能会变化,需要更新 - if (newNode.updateHooks.length <= 0) { - newNode.updateHooks.push((node) => { - node.updateExpandBtnPos() - }) - } // 根节点定位在画布中心位置 if (isRoot) { newNode.left = (this.mindMap.width - newNode.width) / 2 @@ -195,10 +189,10 @@ class MindMap extends Base { top, width, height, - _expandBtnSize + expandBtnSize } = node node.children.forEach((item, index) => { - let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'left' ? left - _expandBtnSize : left + width + 20 + let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'left' ? left - expandBtnSize : left + width + 20 let y1 = node.layerIndex === 0 ? top + height / 2 : top + height / 2 let x2 = item.dir === 'left' ? item.left + item.width : item.left let y2 = item.top + item.height / 2 @@ -221,13 +215,13 @@ class MindMap extends Base { let { width, height, - _expandBtnSize + expandBtnSize } = node let { translateX, translateY } = btn.transform() - let x = (node.dir === 'left' ? 0 - _expandBtnSize : width) - translateX + let x = (node.dir === 'left' ? 0 - expandBtnSize : width) - translateX let y = height / 2 - translateY btn.translate(x, y) } diff --git a/simple-mind-map/src/layouts/OrganizationStructure.js b/simple-mind-map/src/layouts/OrganizationStructure.js index 8f32c8be..e776344d 100644 --- a/simple-mind-map/src/layouts/OrganizationStructure.js +++ b/simple-mind-map/src/layouts/OrganizationStructure.js @@ -154,7 +154,7 @@ class OrganizationStructure extends Base { top, width, height, - _expandBtnSize, + expandBtnSize, isRoot } = node let x1 = left + width / 2 @@ -178,8 +178,8 @@ class OrganizationStructure extends Base { // 父节点的竖线 let line1 = this.draw.path() node.style.line(line1) - _expandBtnSize = len > 0 && !isRoot ? _expandBtnSize : 0 - line1.plot(`M ${x1},${y1 + _expandBtnSize} L ${x1},${y1 + s1}`) + expandBtnSize = len > 0 && !isRoot ? expandBtnSize : 0 + line1.plot(`M ${x1},${y1 + expandBtnSize} L ${x1},${y1 + s1}`) node._lines.push(line1) // 水平线 if (len > 1) { @@ -199,9 +199,13 @@ class OrganizationStructure extends Base { let { width, height, - _expandBtnSize + expandBtnSize } = node - btn.translate(width / 2 - _expandBtnSize / 2, height + _expandBtnSize / 2) + let { + translateX, + translateY + } = btn.transform() + btn.translate(width / 2 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY) } } diff --git a/simple-mind-map/src/layouts/_CatalogOrganization.js b/simple-mind-map/src/layouts/_CatalogOrganization.js deleted file mode 100644 index 0b8eea9a..00000000 --- a/simple-mind-map/src/layouts/_CatalogOrganization.js +++ /dev/null @@ -1,270 +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: 目录组织图 - * 思路:第一轮只计算节点的宽高,以及某个节点的所有子节点所占的高度之和,以及该节点里所有子节点中宽度最宽是多少、第二轮计算节点的left和top,需要区分二级节点和其他节点,二级节点top相同,一行依次从做向右排开,其他节点的left相同,一列从上往下依次排开 - */ -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: 计算节点的width、height - */ - computedBaseValue() { - walk(this.renderTree, null, (node, parent, isRoot) => { - // 设置width、height - let { - children, - ...props - } = node - let newNode = new Node({ - ...props, - mindMap: this.mindMap, - draw: this.draw - }) - // 计算节点的宽高 - newNode.getSize() - // 计算节点的top - 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 - } - node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => { - return h + cur.height - }, 0) + (len + 1) * this.mindMap.opt.marginY : 0 - }, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 09:59:25 - * @Desc: 计算节点的left、top - */ - computedLeftTopValue() { - walk(this.root, null, (node) => { - 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 - 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) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-12 17:07:29 - * @Desc: 调整节点left - */ - adjustLeftValue() { - walk(this.root, null, (node) => { - if (node.parent && node.parent.isRoot) { - let childrenAreaWidth = this.getNodeWidth(node) - let difference = childrenAreaWidth - node.width - if (difference > 0) { - this.updateBrothersLeftValue(node, difference / 2) - } - } - }, null, true) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-12 18:55:03 - * @Desc: 计算节点的宽度,包括子节点 - */ - getNodeWidth(node) { - let widthArr = [] - let loop = (node, width) => { - if (node.children.length) { - width += node.width / 5 + this.mindMap.opt.marginX - node.children.forEach((item) => { - loop(item, width) - }) - } else { - width += node.width - widthArr.push(width) - } - } - loop(node, 0) - return Math.max(...widthArr) - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-12 18:21:46 - * @Desc: 调整兄弟节点的left - */ - updateBrothersLeftValue(node, addWidth) { - 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 = addWidth - } else { - _offset = -addWidth - } - item.left += _offset - // 同步更新子节点的位置 - if (item.children && item.children.length) { - this.updateChildren(item.children, 'left', _offset) - } - }) - // 更新父节点的位置 - this.updateBrothersLeftValue(node.parent, addWidth) - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-08 10:04:05 - * @Desc: 调整节点top,该节点之后的节点都往下进行偏移 - */ - 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) - } - } - - /** - * javascript comment - * @Author: 王林25 - * @Date: 2021-04-07 11:25:52 - * @Desc: 更新子节点属性 - */ - updateChildren(children, prop, offset) { - children.forEach((item) => { - item[prop] += offset - if (item.children && item.children.length) { - this.updateChildren(item.children, prop, offset) - } - }) - } -} - -export default Render \ No newline at end of file diff --git a/simple-mind-map/src/utils/constant.js b/simple-mind-map/src/utils/constant.js index d9de6727..45fa535b 100644 --- a/simple-mind-map/src/utils/constant.js +++ b/simple-mind-map/src/utils/constant.js @@ -26,6 +26,36 @@ export const tagColorList = [ } ] +/** + * javascript comment + * @Author: 王林25 + * @Date: 2021-07-13 15:56:28 + * @Desc: 布局结构列表 + */ +export const layoutList = [ + { + name: '逻辑结构图', + value: 'logicalStructure', + img: require('../assets/logicalStructure.jpg') + }, + { + name: '思维导图', + value: 'mindMap', + img: require('../assets/mindMap.jpg') + }, + { + name: '组织结构图', + value: 'organizationStructure', + img: require('../assets/organizationStructure.jpg') + }, + { + name: '目录组织图', + value: 'catalogOrganization', + img: require('../assets/catalogOrganization.jpg') + } +] +export const layoutValueList = ['logicalStructure', 'mindMap', 'catalogOrganization', 'organizationStructure'] + /** * @Author: 王林 * @Date: 2021-06-24 22:58:42 @@ -52,6 +82,36 @@ export const themeList = [ value: 'pinkGrape', img: require('../assets/pinkGrape.jpg') }, + { + name: '薄荷', + value: 'mint', + img: require('../assets/mint.jpg') + }, + { + name: '金色vip', + value: 'gold', + img: require('../assets/gold.jpg') + }, + { + name: '活力橙', + value: 'vitalityOrange', + img: require('../assets/vitalityOrange.jpg') + }, + { + name: '绿叶', + value: 'greenLeaf', + img: require('../assets/greenLeaf.jpg') + }, + { + name: '暗色2', + value: 'dark2', + img: require('../assets/dark2.jpg') + }, + { + name: '天清绿', + value: 'skyGreen', + img: require('../assets/skyGreen.jpg') + }, { name: '脑图经典2', value: 'classic2', diff --git a/web/src/pages/Edit/components/Structure.vue b/web/src/pages/Edit/components/Structure.vue index 6aaf7001..3e2b180e 100644 --- a/web/src/pages/Edit/components/Structure.vue +++ b/web/src/pages/Edit/components/Structure.vue @@ -1,9 +1,25 @@