Merge branch 'feature' into main

This commit is contained in:
wanglin2 2023-07-18 09:30:32 +08:00
commit 89983f9f47
40 changed files with 388 additions and 108 deletions

File diff suppressed because one or more lines are too long

View File

@ -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 = {

View File

@ -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",

View File

@ -1,6 +1,6 @@
{
"name": "simple-mind-map",
"version": "0.6.6",
"version": "0.6.7",
"description": "一个简单的web在线思维导图",
"authors": [
{

View File

@ -79,10 +79,6 @@ export const defaultOpt = {
},
// 是否只有当鼠标在画布内才响应快捷键事件
enableShortcutOnlyWhenMouseInSvg: true,
// 是否开启节点动画过渡
enableNodeTransitionMove: true,
// 如果开启节点动画过渡可以通过该属性设置过渡的时间单位ms
nodeTransitionMoveDuration: 300,
// 初始根节点的位置
initRootNodePosition: null,
// 导出png、svg、pdf时的图形内边距

View File

@ -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
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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,

View File

@ -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,

View File

@ -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)
}
}

View File

@ -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
// 更新当前节点信息

View File

@ -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()
}

View File

@ -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";
}

View File

@ -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',

View File

@ -114,8 +114,9 @@ export default {
},
navigatorToolbar: {
openMiniMap: '开启小地图',
readonly: '只读模式',
edit: '编辑模式'
closeMiniMap: '关闭小地图',
readonly: '切换为只读模式',
edit: '切换为编辑模式'
},
nodeHyperlink: {
title: '超链接',

View File

@ -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;

View File

@ -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.

View File

@ -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>

View File

@ -51,8 +51,8 @@ const mindMap = new MindMap({
| expandBtnStylev0.5.0+ | Object | { color: '#808080', fill: '#fff' } | Expand the color of the stow button | |
| expandBtnIconv0.5.0+ | Object | { open: '', close: '' } | Customize the icon of the expand/collapse button, and you can transfer the svg string of the icon | |
| enableShortcutOnlyWhenMouseInSvgv0.5.1+ | Boolean | true | Only respond to shortcut key events when the mouse is inside the canvas | |
| enableNodeTransitionMovev0.5.1+ | Boolean | true | Whether to enable node animation transition | |
| nodeTransitionMoveDurationv0.5.1+ | Number | 300 | If node animation transition is enabled, the transition time can be set using this attribute, in milliseconds | |
| enableNodeTransitionMovev0.5.1+v0.6.7+ is remove this feature | Boolean | true | Whether to enable node animation transition | |
| nodeTransitionMoveDurationv0.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 | |
| initRootNodePositionv0.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 | |
| exportPaddingXv0.5.5+ | Number | 10 | Horizontal padding of graphics when exporting PNG, SVG, and PDF | |
| exportPaddingYv0.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_NODEv0.6.7+ | Navigate to a node, and if the node is collapsed, it will automatically expand to that node | nodeNode instance or node uid to locate |
### setData(data)

View File

@ -218,14 +218,14 @@
<td></td>
</tr>
<tr>
<td>enableNodeTransitionMovev0.5.1+</td>
<td>enableNodeTransitionMovev0.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>nodeTransitionMoveDurationv0.5.1+</td>
<td>nodeTransitionMoveDurationv0.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_NODEv0.6.7+</td>
<td>Navigate to a node, and if the node is collapsed, it will automatically expand to that node</td>
<td>nodeNode instance or node uid to locate</td>
</tr>
</tbody>
</table>
<h3>setData(data)</h3>

View File

@ -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.

View File

@ -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>

View File

@ -1,5 +1,15 @@
# Changelog
## 0.6.7
修复1.修复节点收起再展开后展开收起按钮占位元素丢失的问题。 2.修复只读模式下可以缩放图片的问题。
新增1.支持根据节点实例或节点uid定位到某个节点。 2.修改节点uid的创建方式导出数据添加节点的uid。
移除1.移除节点过渡效果。
Demo1.添加网站首页。 2.修复大纲里创建新节点时节点样式丢失的问题。 3.修复大纲里编辑节点后按回车或Tab键后编辑文本丢失的问题。 4.优化大纲的节点定位,被收起的节点会自动展开。 5.侧边栏按钮支持收起。 6.优化小屏适配。
## 0.6.6
新增1.支持导出为Xmind新版文件。2.导入Xmind新版文件支持导入节点中的图片。 3.新增竖向时间轴结构。

View File

@ -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>Demo1.添加网站首页 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>

View File

@ -51,8 +51,8 @@ const mindMap = new MindMap({
| expandBtnStylev0.5.0+ | Object | { color: '#808080', fill: '#fff' } | 展开收起按钮的颜色 | |
| expandBtnIconv0.5.0+ | Object | { open: '', close: '' } | 自定义展开收起按钮的图标可以传图标的svg字符串 | |
| enableShortcutOnlyWhenMouseInSvgv0.5.1+ | Boolean | true | 是否只有当鼠标在画布内才响应快捷键事件 | |
| enableNodeTransitionMovev0.5.1+ | Boolean | true | 是否开启节点动画过渡 | |
| nodeTransitionMoveDurationv0.5.1+ | Number | 300 | 如果开启节点动画过渡可以通过该属性设置过渡的时间单位ms | |
| enableNodeTransitionMovev0.5.1+v0.6.7+已去除该特性) | Boolean | true | 是否开启节点动画过渡 | |
| nodeTransitionMoveDurationv0.5.1+v0.6.7+已去除该特性) | Number | 300 | 如果开启节点动画过渡可以通过该属性设置过渡的时间单位ms | |
| initRootNodePositionv0.5.3+ | Array | null | 初始根节点的位置,可传一个数组,默认为`['center', 'center']`,代表根节点处于画布中心位置,除了`center`,关键词还可以设置`left`、`top`、`right`、`bottom`,除了可以传关键词,数组的每项还可以传递一个数字,代表具体的像素,可以传递一个百分比字符串,比如`['40%', '60%']`,代表水平位置在画布宽度的`40%`的位置,垂直位置在画布高度的`60%`的位置 | |
| exportPaddingXv0.5.5+ | Number | 10 | 导出png、svg、pdf时的图形水平内边距 | |
| exportPaddingYv0.5.5+ | Number | 10 | 导出png、svg、pdf时的图形垂直内边距 | |
@ -340,6 +340,7 @@ mindMap.updateConfig({
| SET_NODE_CUSTOM_POSITIONv0.2.0+ | 设置节点自定义位置 | node要设置的节点、 left自定义的x坐标默认为undefined、 top自定义的y坐标默认为undefined |
| RESET_LAYOUTv0.2.0+ | 一键整理布局 | |
| SET_NODE_SHAPEv0.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_NODEv0.6.7+ | 定位到某个节点,如果该节点被收起,那么会自动展开到该节点 | node要定位到的节点实例或节点uid |
### setData(data)

View File

@ -218,14 +218,14 @@
<td></td>
</tr>
<tr>
<td>enableNodeTransitionMovev0.5.1+</td>
<td>enableNodeTransitionMovev0.5.1+v0.6.7+已去除该特性</td>
<td>Boolean</td>
<td>true</td>
<td>是否开启节点动画过渡</td>
<td></td>
</tr>
<tr>
<td>nodeTransitionMoveDurationv0.5.1+</td>
<td>nodeTransitionMoveDurationv0.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">&#x27;主题名称&#x27;</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_NODEv0.6.7+</td>
<td>定位到某个节点如果该节点被收起那么会自动展开到该节点</td>
<td>node要定位到的节点实例或节点uid</td>
</tr>
</tbody>
</table>
<h3>setData(data)</h3>

View File

@ -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
```
当在大纲树上编辑了某个节点的内容,需要同步到思维导图树上:

View File

@ -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">&#x27;GO_TARGET_NODE&#x27;</span>, node)<span class="hljs-comment">// uid</span>
</code></pre>
<p>当在大纲树上编辑了某个节点的内容需要同步到思维导图树上</p>
<pre class="hljs"><code>data._node.setText(<span class="hljs-string">&#x27;xxx&#x27;</span>)

View File

@ -82,4 +82,22 @@
移动节点到画布中心。
目前如果是存在缩放的情况下回到中心会重置缩放。
目前如果是存在缩放的情况下回到中心会重置缩放。
### expandToNodeUid(uid, callback)
> v0.6.7+
- `uid`节点uid
- `callback`:展开完成的回调函数
展开到指定uid的节点。
### findNodeByUid(uid)
> v0.6.7+
- `uid`节点uid
根据uid找到对应的节点实例。

View File

@ -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>

View File

@ -95,4 +95,10 @@ export default {
}
}
}
@media screen and (max-width: 635px) {
.countContainer {
display: none;
}
}
</style>

View File

@ -74,6 +74,7 @@ export default {
.btn {
cursor: pointer;
font-size: 18px;
}
}
</style>

View File

@ -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>

View File

@ -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)
},
}
}

View File

@ -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;

View File

@ -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>