diff --git a/index.html b/index.html index 4b55ffd1..45054831 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -思绪思维导图
\ No newline at end of file +思绪思维导图
\ No newline at end of file diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index 8cc6b91c..731edd37 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -32,9 +32,6 @@ class MindMap { this.svg = SVG().addTo(this.el).size(this.width, this.height) this.draw = this.svg.group() - // 节点id - this.uid = 1 - // 初始化主题 this.initTheme() @@ -238,7 +235,7 @@ class MindMap { // 获取思维导图数据,节点树、主题、布局等 getData(withConfig) { - let nodeData = this.command.removeDataUid(this.command.getCopyData()) + let nodeData = this.command.getCopyData() let data = {} if (withConfig) { data = { diff --git a/simple-mind-map/package-lock.json b/simple-mind-map/package-lock.json index 811a8646..29f719ea 100644 --- a/simple-mind-map/package-lock.json +++ b/simple-mind-map/package-lock.json @@ -1,11 +1,11 @@ { "name": "simple-mind-map", - "version": "0.6.0", + "version": "0.6.7", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.6.0", + "version": "0.6.7", "license": "MIT", "dependencies": { "@svgdotjs/svg.js": "^3.0.16", diff --git a/simple-mind-map/package.json b/simple-mind-map/package.json index 8939adc3..18640db9 100644 --- a/simple-mind-map/package.json +++ b/simple-mind-map/package.json @@ -1,6 +1,6 @@ { "name": "simple-mind-map", - "version": "0.6.6", + "version": "0.6.7", "description": "一个简单的web在线思维导图", "authors": [ { diff --git a/simple-mind-map/src/constants/defaultOptions.js b/simple-mind-map/src/constants/defaultOptions.js index 26abae16..a89f448d 100644 --- a/simple-mind-map/src/constants/defaultOptions.js +++ b/simple-mind-map/src/constants/defaultOptions.js @@ -79,10 +79,6 @@ export const defaultOpt = { }, // 是否只有当鼠标在画布内才响应快捷键事件 enableShortcutOnlyWhenMouseInSvg: true, - // 是否开启节点动画过渡 - enableNodeTransitionMove: true, - // 如果开启节点动画过渡,可以通过该属性设置过渡的时间,单位ms - nodeTransitionMoveDuration: 300, // 初始根节点的位置 initRootNodePosition: null, // 导出png、svg、pdf时的图形内边距 diff --git a/simple-mind-map/src/core/command/Command.js b/simple-mind-map/src/core/command/Command.js index 2a5f3115..d8edde54 100644 --- a/simple-mind-map/src/core/command/Command.js +++ b/simple-mind-map/src/core/command/Command.js @@ -89,7 +89,7 @@ class Command { this.history.shift() } this.activeHistoryIndex = this.history.length - 1 - this.mindMap.emit('data_change', this.removeDataUid(data)) + this.mindMap.emit('data_change', data) this.mindMap.emit( 'back_forward', this.activeHistoryIndex, @@ -110,7 +110,7 @@ class Command { this.history.length ) let data = simpleDeepClone(this.history[this.activeHistoryIndex]) - this.mindMap.emit('data_change', this.removeDataUid(data)) + this.mindMap.emit('data_change', data) return data } } @@ -125,7 +125,7 @@ class Command { this.activeHistoryIndex += step this.mindMap.emit('back_forward', this.activeHistoryIndex, this.history.length) let data = simpleDeepClone(this.history[this.activeHistoryIndex]) - this.mindMap.emit('data_change', this.removeDataUid(data)) + this.mindMap.emit('data_change', data) return data } } diff --git a/simple-mind-map/src/core/render/Render.js b/simple-mind-map/src/core/render/Render.js index 708b689f..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) } // 注册快捷键 @@ -259,7 +262,6 @@ class Render { // 渲染 render(callback = () => {}, source) { - let t = Date.now() // 如果当前还没有渲染完毕,不再触发渲染 if (this.isRendering) { // 等待当前渲染完毕后再进行一次渲染 @@ -290,7 +292,7 @@ class Render { // 更新根节点 this.root = root // 渲染节点 - const onEnd = () => { + this.root.render(() => { this.isRendering = false this.mindMap.emit('node_tree_render_end') callback && callback() @@ -303,18 +305,6 @@ class Render { this.mindMap.command.addHistory() } } - } - let { enableNodeTransitionMove, nodeTransitionMoveDuration } = - this.mindMap.opt - this.root.render(() => { - let dur = Date.now() - t - if (enableNodeTransitionMove && dur <= nodeTransitionMoveDuration) { - setTimeout(() => { - onEnd() - }, nodeTransitionMoveDuration - dur); - } else { - onEnd() - } }) }) this.mindMap.emit('node_active', null, this.activeNodeList) @@ -439,11 +429,14 @@ class Render { first.parent.destroy() } let index = this.getNodeIndex(first) + let isRichText = !!this.mindMap.richText first.parent.nodeData.children.splice(index + 1, 0, { inserting: openEdit, data: { text: text, expand: true, + richText: isRichText, + resetRichText: isRichText, ...(appointData || {}) }, children: [] @@ -468,11 +461,14 @@ class Render { node.nodeData.children = [] } let text = node.isRoot ? defaultInsertSecondLevelNodeText : defaultInsertBelowSecondLevelNodeText + let isRichText = !!this.mindMap.richText node.nodeData.children.push({ inserting: openEdit, data: { text: text, expand: true, + richText: isRichText, + resetRichText: isRichText, ...(appointData || {}) }, children: [] @@ -992,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 => { @@ -1028,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/core/render/node/Node.js b/simple-mind-map/src/core/render/node/Node.js index e0f36761..4dd66d84 100644 --- a/simple-mind-map/src/core/render/node/Node.js +++ b/simple-mind-map/src/core/render/node/Node.js @@ -365,8 +365,8 @@ class Node { this._unVisibleRectRegionNode.fill({ color: 'transparent' }) - this.group.add(this._unVisibleRectRegionNode) } + this.group.add(this._unVisibleRectRegionNode) this.renderer.layout.renderExpandBtnRect(this._unVisibleRectRegionNode, this.expandBtnSize, width, height, this) } } @@ -476,8 +476,6 @@ class Node { return } let { - enableNodeTransitionMove, - nodeTransitionMoveDuration, alwaysShowExpandBtn } = this.mindMap.opt if (alwaysShowExpandBtn) { @@ -503,13 +501,7 @@ class Node { let t = this.group.transform() // 如果节点位置没有变化,则返回 if (this.left === t.translateX && this.top === t.translateY) return - if (!isLayout && enableNodeTransitionMove) { - this.group - .animate(nodeTransitionMoveDuration) - .translate(this.left - t.translateX, this.top - t.translateY) - } else { - this.group.translate(this.left - t.translateX, this.top - t.translateY) - } + this.group.translate(this.left - t.translateX, this.top - t.translateY) } // 重新渲染节点,即重新创建节点内容、计算节点大小、计算节点内容布局、更新展开收起按钮,概要及位置 @@ -531,8 +523,6 @@ class Node { // 递归渲染 render(callback = () => {}) { - let { enableNodeTransitionMove, nodeTransitionMoveDuration } = - this.mindMap.opt // 节点 // 重新渲染连线 this.renderLine() @@ -580,13 +570,7 @@ class Node { }) ) } else { - if (enableNodeTransitionMove && !isLayout) { - setTimeout(() => { - callback() - }, nodeTransitionMoveDuration) - } else { - callback() - } + callback() } // 手动插入的节点立即获得焦点并且开启编辑模式 if (this.nodeData.inserting) { diff --git a/simple-mind-map/src/core/render/node/nodeGeneralization.js b/simple-mind-map/src/core/render/node/nodeGeneralization.js index 2a2a585d..ba204186 100644 --- a/simple-mind-map/src/core/render/node/nodeGeneralization.js +++ b/simple-mind-map/src/core/render/node/nodeGeneralization.js @@ -1,4 +1,5 @@ import Node from './Node' +import { createUid } from '../../../utils/index' // 检查是否存在概要 function checkHasGeneralization () { @@ -18,7 +19,7 @@ function createGeneralizationNode () { data: { data: this.nodeData.data.generalization }, - uid: this.mindMap.uid++, + uid: createUid(), renderer: this.renderer, mindMap: this.mindMap, draw: this.draw, diff --git a/simple-mind-map/src/layouts/Base.js b/simple-mind-map/src/layouts/Base.js index ca27fcd4..f3876262 100644 --- a/simple-mind-map/src/layouts/Base.js +++ b/simple-mind-map/src/layouts/Base.js @@ -1,6 +1,7 @@ import Node from '../core/render/node/Node' import { CONSTANTS, initRootNodePositionMap } from '../constants/constant' import Lru from '../utils/Lru' +import { createUid } from '../utils/index' // 布局基类 class Base { @@ -101,7 +102,7 @@ class Base { } } else { // 创建新节点 - let uid = this.mindMap.uid++ + 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/plugins/NodeImgAdjust.js b/simple-mind-map/src/plugins/NodeImgAdjust.js index 5a6ab838..a9b9d947 100644 --- a/simple-mind-map/src/plugins/NodeImgAdjust.js +++ b/simple-mind-map/src/plugins/NodeImgAdjust.js @@ -47,7 +47,7 @@ class NodeImgAdjust { // 节点图片鼠标移动事件 onNodeImgMousemove(node, img) { // 如果当前正在拖动调整中那么直接返回 - if (this.isMousedown || this.isAdjusted) return + if (this.isMousedown || this.isAdjusted || this.mindMap.opt.readonly) return // 如果在当前节点内移动,以及自定义元素已经是显示状态,那么直接返回 if (this.node === node && this.isShowHandleEl) return // 更新当前节点信息 diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index f84f7fd2..462b1913 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -1,3 +1,5 @@ +import { v4 as uuidv4 } from 'uuid' + // 深度优先遍历树 export const walk = ( root, @@ -31,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 @@ -41,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 } }) @@ -424,3 +429,8 @@ export const getImageSize = src => { } }) } + +// 创建节点唯一的id +export const createUid = () => { + return uuidv4() +} \ No newline at end of file diff --git a/web/src/assets/icon-font/iconfont.css b/web/src/assets/icon-font/iconfont.css index 3deb5479..d216721f 100644 --- a/web/src/assets/icon-font/iconfont.css +++ b/web/src/assets/icon-font/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 2479351 */ - src: url('iconfont.woff2?t=1689210173189') format('woff2'), - url('iconfont.woff?t=1689210173189') format('woff'), - url('iconfont.ttf?t=1689210173189') format('truetype'); + src: url('iconfont.woff2?t=1689407546912') format('woff2'), + url('iconfont.woff?t=1689407546912') format('woff'), + url('iconfont.ttf?t=1689407546912') format('truetype'); } .iconfont { @@ -13,6 +13,22 @@ -moz-osx-font-smoothing: grayscale; } +.iconjiantouyou:before { + content: "\e62d"; +} + +.iconbianji1:before { + content: "\e60a"; +} + +.icondaohang1:before { + content: "\e632"; +} + +.iconyanjing:before { + content: "\e8bf"; +} + .iconwangzhan:before { content: "\e628"; } diff --git a/web/src/assets/icon-font/iconfont.ttf b/web/src/assets/icon-font/iconfont.ttf index b3ed3c3e..9c801c08 100644 Binary files a/web/src/assets/icon-font/iconfont.ttf and b/web/src/assets/icon-font/iconfont.ttf differ diff --git a/web/src/assets/icon-font/iconfont.woff b/web/src/assets/icon-font/iconfont.woff index 93558610..4d446856 100644 Binary files a/web/src/assets/icon-font/iconfont.woff and b/web/src/assets/icon-font/iconfont.woff differ diff --git a/web/src/assets/icon-font/iconfont.woff2 b/web/src/assets/icon-font/iconfont.woff2 index 0323b32b..1d170d95 100644 Binary files a/web/src/assets/icon-font/iconfont.woff2 and b/web/src/assets/icon-font/iconfont.woff2 differ diff --git a/web/src/lang/en_us.js b/web/src/lang/en_us.js index c4050794..235ebd1d 100644 --- a/web/src/lang/en_us.js +++ b/web/src/lang/en_us.js @@ -114,8 +114,9 @@ export default { }, navigatorToolbar: { openMiniMap: 'Open mini map', - readonly: 'Readonly', - edit: 'Edit' + closeMiniMap: 'Close mini map', + readonly: 'Change to eadonly', + edit: 'Change to edit' }, nodeHyperlink: { title: 'Link', diff --git a/web/src/lang/zh_cn.js b/web/src/lang/zh_cn.js index d99a06e3..c050b0f4 100644 --- a/web/src/lang/zh_cn.js +++ b/web/src/lang/zh_cn.js @@ -114,8 +114,9 @@ export default { }, navigatorToolbar: { openMiniMap: '开启小地图', - readonly: '只读模式', - edit: '编辑模式' + closeMiniMap: '关闭小地图', + readonly: '切换为只读模式', + edit: '切换为编辑模式' }, nodeHyperlink: { title: '超链接', diff --git a/web/src/pages/Doc/components/Header.vue b/web/src/pages/Doc/components/Header.vue index ccf58ed2..59bb265d 100644 --- a/web/src/pages/Doc/components/Header.vue +++ b/web/src/pages/Doc/components/Header.vue @@ -1,7 +1,7 @@