diff --git a/simple-mind-map/src/core/render/Render.js b/simple-mind-map/src/core/render/Render.js index 3f0b0a4b..0a23119e 100644 --- a/simple-mind-map/src/core/render/Render.js +++ b/simple-mind-map/src/core/render/Render.js @@ -7,7 +7,7 @@ import Timeline from '../../layouts/Timeline' import VerticalTimeline from '../../layouts/VerticalTimeline' import Fishbone from '../../layouts/Fishbone' import TextEdit from './TextEdit' -import { copyNodeTree, simpleDeepClone, walk } from '../../utils' +import { copyNodeTree, simpleDeepClone, walk, bfsWalk } from '../../utils' import { shapeList } from './node/Shape' import { lineStyleProps } from '../../themes/default' import { CONSTANTS } from '../../constants/constant' @@ -195,6 +195,9 @@ class Render { // 设置节点形状 this.setNodeShape = this.setNodeShape.bind(this) this.mindMap.command.add('SET_NODE_SHAPE', this.setNodeShape) + // 定位节点 + this.goTargetNode = this.goTargetNode.bind(this) + this.mindMap.command.add('GO_TARGET_NODE', this.goTargetNode) } // 注册快捷键 @@ -985,6 +988,19 @@ class Render { }) } + // 定位到指定节点 + goTargetNode(node) { + let uid = typeof node === 'string' ? node : node.nodeData.data.uid + if (!uid) return + this.expandToNodeUid(uid, () => { + let targetNode = this.findNodeByUid(uid) + if (targetNode) { + targetNode.active() + this.moveNodeToCenter(targetNode) + } + }) + } + // 更新节点数据 setNodeData(node, data) { Object.keys(data).forEach(key => { @@ -1021,6 +1037,44 @@ class Render { this.mindMap.view.translateY(offsetY) this.mindMap.view.setScale(1) } + + // 展开到指定uid的节点 + expandToNodeUid(uid, callback = () => {}) { + let parentsList = [] + const cache = {} + bfsWalk(this.renderTree, (node, parent) => { + if (node.data.uid === uid) { + parentsList = parent ? [...cache[parent.data.uid], parent] : [] + return 'stop' + } else { + cache[node.data.uid] = parent ? [...cache[parent.data.uid], parent]: [] + } + }) + let needRender = false + parentsList.forEach((node) => { + if (!node.data.expand) { + needRender = true + node.data.expand = true + } + }) + if (needRender) { + this.mindMap.render(callback) + } else { + callback() + } + } + + // 根据uid找到对应的节点实例 + findNodeByUid(uid) { + let res = null + walk(this.root, null, (node) => { + if (node.nodeData.data.uid === uid) { + res = node + return true + } + }) + return res + } } export default Render diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js index b5188cba..f3876262 100644 --- a/simple-mind-map/src/layouts/Base.js +++ b/simple-mind-map/src/layouts/Base.js @@ -102,7 +102,7 @@ class Base { } } else { // 创建新节点 - let uid = createUid() + let uid = data.data.uid || createUid() newNode = new Node({ data, uid, diff --git a/simple-mind-map/src/plugins/KeyboardNavigation.js b/simple-mind-map/src/plugins/KeyboardNavigation.js index cdbf95f2..0a3f6098 100644 --- a/simple-mind-map/src/plugins/KeyboardNavigation.js +++ b/simple-mind-map/src/plugins/KeyboardNavigation.js @@ -28,8 +28,7 @@ class KeyboardNavigation { this.focus(dir) } else { let root = this.mindMap.renderer.root - this.mindMap.renderer.moveNodeToCenter(root) - root.active() + this.mindMap.execCommand('GO_TARGET_NODE', root) } } @@ -81,8 +80,7 @@ class KeyboardNavigation { // 找到了则让目标节点聚焦 if (targetNode) { - this.mindMap.renderer.moveNodeToCenter(targetNode) - targetNode.active() + this.mindMap.execCommand('GO_TARGET_NODE', targetNode) } } diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index 8dbe6f8d..462b1913 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -33,9 +33,11 @@ export const walk = ( // 广度优先遍历树 export const bfsWalk = (root, callback) => { - callback(root) let stack = [root] let isStop = false + if (callback(root, null) === 'stop') { + isStop = true + } while (stack.length) { if (isStop) { break @@ -43,8 +45,9 @@ export const bfsWalk = (root, callback) => { let cur = stack.shift() if (cur.children && cur.children.length) { cur.children.forEach(item => { + if (isStop) return stack.push(item) - if (callback(item) === 'stop') { + if (callback(item, cur) === 'stop') { isStop = true } }) diff --git a/web/src/pages/Edit/components/Outline.vue b/web/src/pages/Edit/components/Outline.vue index cf23a93b..e5cd2e84 100644 --- a/web/src/pages/Edit/components/Outline.vue +++ b/web/src/pages/Edit/components/Outline.vue @@ -112,12 +112,11 @@ export default { }, // 激活当前节点且移动当前节点到画布中间 - onClick(e, data) { + onClick(e, node) { this.notHandleDataChange = true - let node = data.data._node - if (node.nodeData.data.isActive) return - node.mindMap.renderer.moveNodeToCenter(node) - node.active() + let targetNode = node.data._node + if (targetNode && targetNode.nodeData.data.isActive) return + this.mindMap.execCommand('GO_TARGET_NODE', node.data.data.uid) }, } }