mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 18:37:43 +08:00
Merge branch 'feature' into main
This commit is contained in:
commit
89983f9f47
File diff suppressed because one or more lines are too long
@ -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 = {
|
||||
|
||||
4
simple-mind-map/package-lock.json
generated
4
simple-mind-map/package-lock.json
generated
@ -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",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.6.6",
|
||||
"version": "0.6.7",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@ -79,10 +79,6 @@ export const defaultOpt = {
|
||||
},
|
||||
// 是否只有当鼠标在画布内才响应快捷键事件
|
||||
enableShortcutOnlyWhenMouseInSvg: true,
|
||||
// 是否开启节点动画过渡
|
||||
enableNodeTransitionMove: true,
|
||||
// 如果开启节点动画过渡,可以通过该属性设置过渡的时间,单位ms
|
||||
nodeTransitionMoveDuration: 300,
|
||||
// 初始根节点的位置
|
||||
initRootNodePosition: null,
|
||||
// 导出png、svg、pdf时的图形内边距
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
// 更新当前节点信息
|
||||
|
||||
@ -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()
|
||||
}
|
||||
@ -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";
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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',
|
||||
|
||||
@ -114,8 +114,9 @@ export default {
|
||||
},
|
||||
navigatorToolbar: {
|
||||
openMiniMap: '开启小地图',
|
||||
readonly: '只读模式',
|
||||
edit: '编辑模式'
|
||||
closeMiniMap: '关闭小地图',
|
||||
readonly: '切换为只读模式',
|
||||
edit: '切换为编辑模式'
|
||||
},
|
||||
nodeHyperlink: {
|
||||
title: '超链接',
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="headerContainer">
|
||||
<div class="left">
|
||||
<div class="title">
|
||||
<div class="title" @click="toIndex">
|
||||
<img src="../../../assets/img/logo2.png" alt="">
|
||||
SimpleMindMap
|
||||
</div>
|
||||
@ -74,6 +74,10 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
toIndex() {
|
||||
this.$router.push('/index')
|
||||
},
|
||||
|
||||
toDemo() {
|
||||
this.$router.push('/')
|
||||
},
|
||||
@ -108,6 +112,7 @@ export default {
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 30px;
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## 0.6.7
|
||||
|
||||
Fix: 1.Fixed the issue of missing placeholder elements for the expand and collapse button after node collapse and expansion. 2.Fixed the issue of being able to scale images in read-only mode.
|
||||
|
||||
New: 1.Support locating to a node based on node instance or node uid. 2.Modify the creation method of node uids and export data to add node uids.
|
||||
|
||||
Remove: 1.Remove the node transition effect.
|
||||
|
||||
Demo: 1.Add website homepage. 2.Fixed the issue of missing node styles when creating new nodes in the outline. 3.Fixed the issue of missing edited text after pressing Enter or Tab after editing nodes in the outline. 4.Optimize the node positioning of the outline, and the collapsed nodes will automatically expand. 5.The sidebar button supports folding. 6.Optimize small screen adaptation.
|
||||
|
||||
## 0.6.6
|
||||
|
||||
New: 1.Support exporting to Xmind new version files. 2.Importing the new version of Xmind file supports importing images from nodes. 3.Add a vertical timeline structure.
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.6.7</h2>
|
||||
<p>Fix: 1.Fixed the issue of missing placeholder elements for the expand and collapse button after node collapse and expansion. 2.Fixed the issue of being able to scale images in read-only mode.</p>
|
||||
<p>New: 1.Support locating to a node based on node instance or node uid. 2.Modify the creation method of node uids and export data to add node uids.</p>
|
||||
<p>Remove: 1.Remove the node transition effect.</p>
|
||||
<p>Demo: 1.Add website homepage. 2.Fixed the issue of missing node styles when creating new nodes in the outline. 3.Fixed the issue of missing edited text after pressing Enter or Tab after editing nodes in the outline. 4.Optimize the node positioning of the outline, and the collapsed nodes will automatically expand. 5.The sidebar button supports folding. 6.Optimize small screen adaptation.</p>
|
||||
<h2>0.6.6</h2>
|
||||
<p>New: 1.Support exporting to Xmind new version files. 2.Importing the new version of Xmind file supports importing images from nodes. 3.Add a vertical timeline structure.</p>
|
||||
<p>Fix: 1.The TouchEvent plugin no longer sends click events, solving the problem of two windows opening when clicking on a hyperlink on the mobile end. 2.Fix the issue of dragging and moving a node to become a child node of another node, where the parent node of that node points to not being updated. 3.Fixed an issue where the node border style was not updated when dragging a second level node into a third level node. 4.Fix the issue where the mouse will not trigger the button display when moving into the unfolded or retracted button position, except for the structure growing to the right.</p>
|
||||
|
||||
@ -51,8 +51,8 @@ const mindMap = new MindMap({
|
||||
| expandBtnStyle(v0.5.0+) | Object | { color: '#808080', fill: '#fff' } | Expand the color of the stow button | |
|
||||
| expandBtnIcon(v0.5.0+) | Object | { open: '', close: '' } | Customize the icon of the expand/collapse button, and you can transfer the svg string of the icon | |
|
||||
| enableShortcutOnlyWhenMouseInSvg(v0.5.1+) | Boolean | true | Only respond to shortcut key events when the mouse is inside the canvas | |
|
||||
| enableNodeTransitionMove(v0.5.1+) | Boolean | true | Whether to enable node animation transition | |
|
||||
| nodeTransitionMoveDuration(v0.5.1+) | Number | 300 | If node animation transition is enabled, the transition time can be set using this attribute, in milliseconds | |
|
||||
| enableNodeTransitionMove(v0.5.1+)(v0.6.7+ is remove this feature) | Boolean | true | Whether to enable node animation transition | |
|
||||
| nodeTransitionMoveDuration(v0.5.1+)(v0.6.7+ is remove this feature) | Number | 300 | If node animation transition is enabled, the transition time can be set using this attribute, in milliseconds | |
|
||||
| initRootNodePosition(v0.5.3+) | Array | null | The position of the initial root node can be passed as an array, default is `['center', 'center']`, Represents the root node at the center of the canvas, In addition to `center`, keywords can also be set to `left`, `top`, `right`, and `bottom`, In addition to passing keywords, each item in the array can also pass a number representing a specific pixel, Can pass a percentage string, such as `['40%', '60%']`, Represents a horizontal position at `40%` of the canvas width, and a vertical position at `60%` of the canvas height | |
|
||||
| exportPaddingX(v0.5.5+) | Number | 10 | Horizontal padding of graphics when exporting PNG, SVG, and PDF | |
|
||||
| exportPaddingY(v0.5.5+) | Number | 10 | Vertical padding of graphics when exporting PNG, SVG, and PDF | |
|
||||
@ -347,6 +347,7 @@ redo. All commands are as follows:
|
||||
| SET_NODE_CUSTOM_POSITION (v0.2.0+) | Set a custom position for a node | node (the node to set), left (custom x coordinate, default is undefined), top (custom y coordinate, default is undefined) |
|
||||
| RESET_LAYOUT (v0.2.0+) | Arrange layout with one click | |
|
||||
| SET_NODE_SHAPE (v0.2.4+) | Set the shape of a node | node (the node to set), shape (the shape, all shapes: [Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js)) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | Navigate to a node, and if the node is collapsed, it will automatically expand to that node | node(Node instance or node uid to locate) |
|
||||
|
||||
### setData(data)
|
||||
|
||||
|
||||
@ -218,14 +218,14 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableNodeTransitionMove(v0.5.1+)</td>
|
||||
<td>enableNodeTransitionMove(v0.5.1+)(v0.6.7+ is remove this feature)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>Whether to enable node animation transition</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeTransitionMoveDuration(v0.5.1+)</td>
|
||||
<td>nodeTransitionMoveDuration(v0.5.1+)(v0.6.7+ is remove this feature)</td>
|
||||
<td>Number</td>
|
||||
<td>300</td>
|
||||
<td>If node animation transition is enabled, the transition time can be set using this attribute, in milliseconds</td>
|
||||
@ -920,6 +920,11 @@ redo. All commands are as follows:</p>
|
||||
<td>Set the shape of a node</td>
|
||||
<td>node (the node to set), shape (the shape, all shapes: <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js">Shape.js</a>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GO_TARGET_NODE(v0.6.7+)</td>
|
||||
<td>Navigate to a node, and if the node is collapsed, it will automatically expand to that node</td>
|
||||
<td>node(Node instance or node uid to locate)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>setData(data)</h3>
|
||||
|
||||
@ -91,4 +91,22 @@ Move a node behind another node
|
||||
|
||||
Move a node to the center of the canvas.
|
||||
|
||||
Currently, if there is zoom, returning to the center will reset the zoom.
|
||||
Currently, if there is zoom, returning to the center will reset the zoom.
|
||||
|
||||
### expandToNodeUid(uid, callback)
|
||||
|
||||
> v0.6.7+
|
||||
|
||||
- `uid`: uid of node
|
||||
|
||||
- `callback`: Expand completed callback function
|
||||
|
||||
Expand to the node of the specified uid.
|
||||
|
||||
### findNodeByUid(uid)
|
||||
|
||||
> v0.6.7+
|
||||
|
||||
- `uid`: uid of node
|
||||
|
||||
Find the corresponding node instance based on the uid.
|
||||
@ -62,6 +62,27 @@ is an object, e.g. <code>{text: 'I am new text'}</code></p>
|
||||
</blockquote>
|
||||
<p>Move a node to the center of the canvas.</p>
|
||||
<p>Currently, if there is zoom, returning to the center will reset the zoom.</p>
|
||||
<h3>expandToNodeUid(uid, callback)</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.7+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>uid</code>: uid of node</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>callback</code>: Expand completed callback function</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Expand to the node of the specified uid.</p>
|
||||
<h3>findNodeByUid(uid)</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.7+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>uid</code>: uid of node</li>
|
||||
</ul>
|
||||
<p>Find the corresponding node instance based on the uid.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## 0.6.7
|
||||
|
||||
修复:1.修复节点收起再展开后展开收起按钮占位元素丢失的问题。 2.修复只读模式下可以缩放图片的问题。
|
||||
|
||||
新增:1.支持根据节点实例或节点uid定位到某个节点。 2.修改节点uid的创建方式,导出数据添加节点的uid。
|
||||
|
||||
移除:1.移除节点过渡效果。
|
||||
|
||||
Demo:1.添加网站首页。 2.修复大纲里创建新节点时节点样式丢失的问题。 3.修复大纲里编辑节点后按回车或Tab键后编辑文本丢失的问题。 4.优化大纲的节点定位,被收起的节点会自动展开。 5.侧边栏按钮支持收起。 6.优化小屏适配。
|
||||
|
||||
## 0.6.6
|
||||
|
||||
新增:1.支持导出为Xmind新版文件。2.导入Xmind新版文件支持导入节点中的图片。 3.新增竖向时间轴结构。
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.6.7</h2>
|
||||
<p>修复:1.修复节点收起再展开后展开收起按钮占位元素丢失的问题。 2.修复只读模式下可以缩放图片的问题。</p>
|
||||
<p>新增:1.支持根据节点实例或节点uid定位到某个节点。 2.修改节点uid的创建方式,导出数据添加节点的uid。</p>
|
||||
<p>移除:1.移除节点过渡效果。</p>
|
||||
<p>Demo:1.添加网站首页。 2.修复大纲里创建新节点时节点样式丢失的问题。 3.修复大纲里编辑节点后按回车或Tab键后编辑文本丢失的问题。 4.优化大纲的节点定位,被收起的节点会自动展开。 5.侧边栏按钮支持收起。 6.优化小屏适配。</p>
|
||||
<h2>0.6.6</h2>
|
||||
<p>新增:1.支持导出为Xmind新版文件。2.导入Xmind新版文件支持导入节点中的图片。 3.新增竖向时间轴结构。</p>
|
||||
<p>修复:1.TouchEvent插件不再派发click事件,解决移动端点击超链接会打开两个窗口的问题。 2.修复拖拽移动一个节点成为另一个节点的子节点时该节点的父节点指向未更新的问题。 3.修复二级节点拖拽成三级节点时节点边框样式未更新的问题。 4.修复向右生长的结构外其他结构鼠标移入展开收起按钮位置时不会触发按钮显示的问题。</p>
|
||||
|
||||
@ -51,8 +51,8 @@ const mindMap = new MindMap({
|
||||
| expandBtnStyle(v0.5.0+) | Object | { color: '#808080', fill: '#fff' } | 展开收起按钮的颜色 | |
|
||||
| expandBtnIcon(v0.5.0+) | Object | { open: '', close: '' } | 自定义展开收起按钮的图标,可以传图标的svg字符串 | |
|
||||
| enableShortcutOnlyWhenMouseInSvg(v0.5.1+) | Boolean | true | 是否只有当鼠标在画布内才响应快捷键事件 | |
|
||||
| enableNodeTransitionMove(v0.5.1+) | Boolean | true | 是否开启节点动画过渡 | |
|
||||
| nodeTransitionMoveDuration(v0.5.1+) | Number | 300 | 如果开启节点动画过渡,可以通过该属性设置过渡的时间,单位ms | |
|
||||
| enableNodeTransitionMove(v0.5.1+)(v0.6.7+已去除该特性) | Boolean | true | 是否开启节点动画过渡 | |
|
||||
| nodeTransitionMoveDuration(v0.5.1+)(v0.6.7+已去除该特性) | Number | 300 | 如果开启节点动画过渡,可以通过该属性设置过渡的时间,单位ms | |
|
||||
| initRootNodePosition(v0.5.3+) | Array | null | 初始根节点的位置,可传一个数组,默认为`['center', 'center']`,代表根节点处于画布中心位置,除了`center`,关键词还可以设置`left`、`top`、`right`、`bottom`,除了可以传关键词,数组的每项还可以传递一个数字,代表具体的像素,可以传递一个百分比字符串,比如`['40%', '60%']`,代表水平位置在画布宽度的`40%`的位置,垂直位置在画布高度的`60%`的位置 | |
|
||||
| exportPaddingX(v0.5.5+) | Number | 10 | 导出png、svg、pdf时的图形水平内边距 | |
|
||||
| exportPaddingY(v0.5.5+) | Number | 10 | 导出png、svg、pdf时的图形垂直内边距 | |
|
||||
@ -340,6 +340,7 @@ mindMap.updateConfig({
|
||||
| SET_NODE_CUSTOM_POSITION(v0.2.0+) | 设置节点自定义位置 | node(要设置的节点)、 left(自定义的x坐标,默认为undefined)、 top(自定义的y坐标,默认为undefined) |
|
||||
| RESET_LAYOUT(v0.2.0+) | 一键整理布局 | |
|
||||
| SET_NODE_SHAPE(v0.2.4+) | 设置节点形状 | node(要设置的节点)、shape(形状,全部形状:[Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js)) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | 定位到某个节点,如果该节点被收起,那么会自动展开到该节点 | node(要定位到的节点实例或节点uid) |
|
||||
|
||||
### setData(data)
|
||||
|
||||
|
||||
@ -218,14 +218,14 @@
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>enableNodeTransitionMove(v0.5.1+)</td>
|
||||
<td>enableNodeTransitionMove(v0.5.1+)(v0.6.7+已去除该特性)</td>
|
||||
<td>Boolean</td>
|
||||
<td>true</td>
|
||||
<td>是否开启节点动画过渡</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nodeTransitionMoveDuration(v0.5.1+)</td>
|
||||
<td>nodeTransitionMoveDuration(v0.5.1+)(v0.6.7+已去除该特性)</td>
|
||||
<td>Number</td>
|
||||
<td>300</td>
|
||||
<td>如果开启节点动画过渡,可以通过该属性设置过渡的时间,单位ms</td>
|
||||
@ -915,6 +915,11 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<td>设置节点形状</td>
|
||||
<td>node(要设置的节点)、shape(形状,全部形状:<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js">Shape.js</a>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GO_TARGET_NODE(v0.6.7+)</td>
|
||||
<td>定位到某个节点,如果该节点被收起,那么会自动展开到该节点</td>
|
||||
<td>node(要定位到的节点实例或节点uid)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>setData(data)</h3>
|
||||
|
||||
@ -18,6 +18,9 @@ mindMap.on('data_change', (data) => {
|
||||
const node = data._node
|
||||
mindMap.renderer.moveNodeToCenter(node)
|
||||
node.active()
|
||||
|
||||
// 在v0.6.7+版本可以这么做:
|
||||
mindMap.execCommand('GO_TARGET_NODE', node)// 或者传节点的uid
|
||||
```
|
||||
|
||||
当在大纲树上编辑了某个节点的内容,需要同步到思维导图树上:
|
||||
|
||||
@ -13,6 +13,9 @@
|
||||
<pre class="hljs"><code><span class="hljs-keyword">const</span> node = data._node
|
||||
mindMap.renderer.moveNodeToCenter(node)
|
||||
node.active()
|
||||
|
||||
<span class="hljs-comment">// 在v0.6.7+版本可以这么做:</span>
|
||||
mindMap.execCommand(<span class="hljs-string">'GO_TARGET_NODE'</span>, node)<span class="hljs-comment">// 或者传节点的uid</span>
|
||||
</code></pre>
|
||||
<p>当在大纲树上编辑了某个节点的内容,需要同步到思维导图树上:</p>
|
||||
<pre class="hljs"><code>data._node.setText(<span class="hljs-string">'xxx'</span>)
|
||||
|
||||
@ -82,4 +82,22 @@
|
||||
|
||||
移动节点到画布中心。
|
||||
|
||||
目前如果是存在缩放的情况下回到中心会重置缩放。
|
||||
目前如果是存在缩放的情况下回到中心会重置缩放。
|
||||
|
||||
### expandToNodeUid(uid, callback)
|
||||
|
||||
> v0.6.7+
|
||||
|
||||
- `uid`:节点uid
|
||||
|
||||
- `callback`:展开完成的回调函数
|
||||
|
||||
展开到指定uid的节点。
|
||||
|
||||
### findNodeByUid(uid)
|
||||
|
||||
> v0.6.7+
|
||||
|
||||
- `uid`:节点uid
|
||||
|
||||
根据uid找到对应的节点实例。
|
||||
@ -51,6 +51,27 @@
|
||||
</blockquote>
|
||||
<p>移动节点到画布中心。</p>
|
||||
<p>目前如果是存在缩放的情况下回到中心会重置缩放。</p>
|
||||
<h3>expandToNodeUid(uid, callback)</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.7+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>uid</code>:节点uid</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>callback</code>:展开完成的回调函数</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>展开到指定uid的节点。</p>
|
||||
<h3>findNodeByUid(uid)</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.7+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>uid</code>:节点uid</li>
|
||||
</ul>
|
||||
<p>根据uid找到对应的节点实例。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -95,4 +95,10 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 635px) {
|
||||
.countContainer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -74,6 +74,7 @@ export default {
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -19,25 +19,51 @@
|
||||
<MouseAction :mindMap="mindMap"></MouseAction>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-checkbox v-model="openMiniMap" @change="toggleMiniMap">{{
|
||||
$t('navigatorToolbar.openMiniMap')
|
||||
}}</el-checkbox>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="
|
||||
openMiniMap
|
||||
? $t('navigatorToolbar.closeMiniMap')
|
||||
: $t('navigatorToolbar.openMiniMap')
|
||||
"
|
||||
placement="top"
|
||||
>
|
||||
<div
|
||||
class="btn iconfont icondaohang1"
|
||||
@click="toggleMiniMap"
|
||||
></div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-switch
|
||||
<!-- <el-switch
|
||||
v-model="isReadonly"
|
||||
:active-text="$t('navigatorToolbar.readonly')"
|
||||
:inactive-text="$t('navigatorToolbar.edit')"
|
||||
@change="readonlyChange"
|
||||
>
|
||||
</el-switch>
|
||||
</div>
|
||||
<div class="item">
|
||||
<Scale :mindMap="mindMap"></Scale>
|
||||
</el-switch> -->
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="
|
||||
isReadonly
|
||||
? $t('navigatorToolbar.edit')
|
||||
: $t('navigatorToolbar.readonly')
|
||||
"
|
||||
placement="top"
|
||||
>
|
||||
<div
|
||||
class="btn iconfont"
|
||||
:class="[isReadonly ? 'iconyanjing' : 'iconbianji1']"
|
||||
@click="readonlyChange"
|
||||
></div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="item">
|
||||
<Fullscreen :mindMap="mindMap"></Fullscreen>
|
||||
</div>
|
||||
<div class="item">
|
||||
<Scale :mindMap="mindMap"></Scale>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a href="https://github.com/wanglin2/mind-map" target="_blank">
|
||||
<span class="iconfont icongithub"></span>
|
||||
@ -79,16 +105,15 @@ export default {
|
||||
openMiniMap: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.toggleMiniMap(this.openMiniMap)
|
||||
},
|
||||
methods: {
|
||||
readonlyChange(value) {
|
||||
this.mindMap.setMode(value ? 'readonly' : 'edit')
|
||||
readonlyChange() {
|
||||
this.isReadonly = !this.isReadonly
|
||||
this.mindMap.setMode(this.isReadonly ? 'readonly' : 'edit')
|
||||
},
|
||||
|
||||
toggleMiniMap(show) {
|
||||
this.$bus.$emit('toggle_mini_map', show)
|
||||
toggleMiniMap() {
|
||||
this.openMiniMap = !this.openMiniMap
|
||||
this.$bus.$emit('toggle_mini_map', this.openMiniMap)
|
||||
},
|
||||
|
||||
onLangChange(lang) {
|
||||
@ -124,6 +149,18 @@ export default {
|
||||
color: #303133;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 502px) {
|
||||
.navigatorContainer {
|
||||
left: 20px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -46,11 +46,10 @@ export default {
|
||||
data: [],
|
||||
defaultProps: {
|
||||
label(data) {
|
||||
return data.data.text.replaceAll(/\n/g, '</br>')
|
||||
return data.data.richText ? data.data.text : data.data.text.replaceAll(/\n/g, '</br>')
|
||||
}
|
||||
},
|
||||
notHandleDataChange: false,
|
||||
isCreateNode: false
|
||||
notHandleDataChange: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -77,11 +76,12 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
onBlur(e, node) {
|
||||
if (this.isCreateNode) {
|
||||
this.isCreateNode = false
|
||||
return
|
||||
const richText = node.data.data.richText
|
||||
if (richText) {
|
||||
node.data._node.setText(e.target.innerHTML, true)
|
||||
} else {
|
||||
node.data._node.setText(e.target.innerText)
|
||||
}
|
||||
node.data._node.setText(e.target.innerText)
|
||||
},
|
||||
|
||||
getKey() {
|
||||
@ -102,24 +102,21 @@ export default {
|
||||
// 插入兄弟节点
|
||||
insertNode() {
|
||||
this.notHandleDataChange = false
|
||||
this.isCreateNode = true
|
||||
this.mindMap.execCommand('INSERT_NODE', false)
|
||||
},
|
||||
|
||||
// 插入下级节点
|
||||
insertChildNode() {
|
||||
this.notHandleDataChange = false
|
||||
this.isCreateNode = true
|
||||
this.mindMap.execCommand('INSERT_CHILD_NODE', false)
|
||||
},
|
||||
|
||||
// 激活当前节点且移动当前节点到画布中间
|
||||
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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,11 @@
|
||||
<div
|
||||
class="sidebarTriggerContainer"
|
||||
@click.stop
|
||||
:class="{ show: activeSidebar }"
|
||||
:class="{ hasActive: show && activeSidebar, show: show }"
|
||||
>
|
||||
<div class="toggleShowBtn" :class="{hide: !show}" @click="show = !show">
|
||||
<span class="iconfont iconjiantouyou"></span>
|
||||
</div>
|
||||
<div class="trigger">
|
||||
<div
|
||||
class="triggerItem"
|
||||
@ -32,7 +35,7 @@ export default {
|
||||
name: 'SidebarTrigger',
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
show: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -55,17 +58,57 @@ export default {
|
||||
<style lang="less" scoped>
|
||||
.sidebarTriggerContainer {
|
||||
position: fixed;
|
||||
right: 0px;
|
||||
right: -60px;
|
||||
margin-top: 110px;
|
||||
transition: all 0.3s;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
&.show {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&.hasActive {
|
||||
right: 305px;
|
||||
}
|
||||
|
||||
.toggleShowBtn {
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
width: 35px;
|
||||
height: 60px;
|
||||
background: #409eff;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
cursor: pointer;
|
||||
transition: left .1s linear;
|
||||
z-index: 0;
|
||||
border-top-left-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 4px;
|
||||
|
||||
&.hide {
|
||||
left: -8px;
|
||||
|
||||
span {
|
||||
transform: rotateZ(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
left: -18px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #fff;
|
||||
transition: all 0.1s;
|
||||
}
|
||||
}
|
||||
|
||||
.trigger {
|
||||
position: relative;
|
||||
width: 60px;
|
||||
border-color: #eee;
|
||||
background-color: #fff;
|
||||
|
||||
@ -520,4 +520,17 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1040px) {
|
||||
|
||||
.toolbarContainer {
|
||||
.toolbar {
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
transform: translateX(0);
|
||||
width: auto;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user