Compare commits

...

26 Commits

Author SHA1 Message Date
街角小林
5fb35d656f 打包0.10.5 2024-08-02 10:04:20 +08:00
街角小林
cec1f59189 Doc: update 2024-08-02 09:46:17 +08:00
街角小林
a6a890362e Dmoe:修复大纲里点击节点进行拖拽会触发页面的文件拖拽蒙层的问题 2024-08-01 10:36:03 +08:00
街角小林
83b6d5793b Fix:修复画布尺寸调整后第一次触发渲染画布会发生跳动的问题 2024-07-31 10:53:56 +08:00
街角小林
9b40a7bedd Doc: update 2024-07-30 09:19:10 +08:00
街角小林
11f2078ee0 Demo:编辑本地文件时如果未保存关闭页面增加拦截提示 2024-07-29 17:20:21 +08:00
街角小林
4fb9bd5135 Demo:打开本地文件编辑的情况下不再将数据写入浏览器缓存 2024-07-29 17:00:39 +08:00
街角小林
cf56b5db24 Demo:节点下级数量大于100收起时显示省略号 2024-07-29 15:39:51 +08:00
街角小林
40ea595e62 Feat:移动节点或复制节点到收起的节点上自动展开该节点 2024-07-29 15:13:11 +08:00
街角小林
91a9d7b556 Doc: update 2024-07-29 09:54:50 +08:00
街角小林
0669e73a5b Feat:支持点击画布取消创建关联线 2024-07-29 09:49:05 +08:00
街角小林
fde6fc2583 Fix:修复开启性能模式后,演示插件无法正常工作的问题 2024-07-29 09:28:51 +08:00
街角小林
f92146a1f4 Fix:修复跨层级复制节点时,节点的富文本样式没有更新的问题 2024-07-26 17:05:09 +08:00
街角小林
38c6966d13 Feat:移动节点且节点层级发生了改变,设置过自定义富文本样式的节点不需要更新样式 2024-07-26 16:39:19 +08:00
街角小林
4894d9e6e6 Fix:修复开启性能模式后拖动滚动条报错的问题 2024-07-26 15:51:30 +08:00
街角小林
9a64094f14 打包0.10.4 2024-07-26 10:32:39 +08:00
街角小林
95fdb35f7b Fix:优化性能模式的懒加载 2024-07-26 10:15:54 +08:00
街角小林
497c2606df Feat:懒加载节点树时增加触发渲染开始和结束事件的派发 2024-07-26 09:38:22 +08:00
街角小林
d735be1204 Doc: update 2024-07-25 18:33:36 +08:00
街角小林
45d2da1337 update package.json 2024-07-25 18:32:04 +08:00
街角小林
194571d5fe Fix:修复在@svgdotjs/svg.js库版本为3.0.16时报错的问题 2024-07-25 18:05:22 +08:00
街角小林
418b24b039 Doc: update 2024-07-25 17:38:01 +08:00
街角小林
b32a8b5a85 Demo:基础配置里增加开启性能模式的开关 2024-07-25 16:41:21 +08:00
街角小林
2dee415a64 Feat:新增性能模式 2024-07-25 16:40:47 +08:00
街角小林
4e7d59b328 Fix:删除无用代码,修复鼠标悬浮节点上报错不显示展开收起按钮的问题 2024-07-24 17:13:49 +08:00
街角小林
9bde9ffaf3 Doc: update 2024-07-22 09:25:22 +08:00
84 changed files with 1002 additions and 226 deletions

View File

@@ -103,7 +103,9 @@ const mindMap = new MindMap({
# 微信交流群
群聊人数较多,无法通过二维码入群,可以微信添加`wanglinguanfang`拉你入群。思维导图相关问题皆可在群里提问,不必私聊作者。
一群已满,可以扫描如下二维码进入二群,如已过期,可以微信添加`wanglinguanfang`拉你入群。思维导图相关问题皆可在群里提问,不必私聊作者。
<img src="./qrcode.jpg" style="width: 300px" />
# star
@@ -431,4 +433,20 @@ const mindMap = new MindMap({
<img src="./web/src/assets/avatar/晴空.jpg" style="width: 50px;height: 50px;" />
<span>晴空</span>
</span>
<span>
<img src="./web/src/assets/avatar/default.png" style="width: 50px;height: 50px;" />
<span>黄泳</span>
</span>
<span>
<img src="./web/src/assets/avatar/ccccs.jpg" style="width: 50px;height: 50px;" />
<span>ccccs</span>
</span>
<span>
<img src="./web/src/assets/avatar/。.png" style="width: 50px;height: 50px;" />
<span>。</span>
</span>
<span>
<img src="./web/src/assets/avatar/Jeffrey.jpg" style="width: 50px;height: 50px;" />
<span>Jeffrey</span>
</span>
</p>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
dist/img/Jeffrey.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
dist/img/ccccs.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
dist/img/qrcode.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
dist/img/。.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

2
dist/js/app.js vendored

File diff suppressed because one or more lines are too long

1
dist/js/chunk-18bcf3fc.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d20f68f"],{b407:function(n,u,t){"use strict";t.r(u);var c=function(){var n=this,u=n._self._c;return u("div")},e=[],l={},s=l,i=t("2877"),o=Object(i["a"])(s,c,e,!1,null,null,null);u["default"]=o.exports}}]);

File diff suppressed because one or more lines are too long

1
dist/js/chunk-3324bc8a.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/js/chunk-47ab6502.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/js/chunk-6f12c8fe.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -9,7 +9,7 @@
})
} catch (error) {
console.log(error)
}</script><link href="dist/css/chunk-vendors.css?dca8675d85e0a079cc96" rel="stylesheet"><link href="dist/css/app.css?dca8675d85e0a079cc96" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
}</script><link href="dist/css/chunk-vendors.css?23a496a1094c82432df0" rel="stylesheet"><link href="dist/css/app.css?23a496a1094c82432df0" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
@@ -74,4 +74,4 @@
// 可以通过window.$bus.$on()来监听应用的一些事件
// 实例化页面
window.initApp()
}</script><script src="dist/js/chunk-vendors.js?dca8675d85e0a079cc96"></script><script src="dist/js/app.js?dca8675d85e0a079cc96"></script></body></html>
}</script><script src="dist/js/chunk-vendors.js?23a496a1094c82432df0"></script><script src="dist/js/app.js?23a496a1094c82432df0"></script></body></html>

BIN
qrcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -31,7 +31,7 @@ MindMap.iconList = icons.nodeIconList
MindMap.constants = constants
MindMap.themes = themes
MindMap.defaultTheme = defaultTheme
MindMap.version = '0.10.3'
MindMap.version = '0.10.5'
MindMap.usePlugin(MiniMap)
.usePlugin(Watermark)

View File

@@ -194,7 +194,7 @@ class MindMap {
this.renderer.reRender = true // 标记为重新渲染
this.renderer.clearCache() // 清空节点缓存池
this.clearDraw() // 清空画布
this.render(callback, (source = ''))
this.render(callback, source)
}
// 获取或更新容器尺寸位置信息
@@ -208,8 +208,14 @@ class MindMap {
// 容器尺寸变化,调整尺寸
resize() {
const oldWidth = this.width
const oldHeight = this.height
this.getElRectInfo()
this.svg.size(this.width, this.height)
if (oldWidth !== this.width || oldHeight !== this.height) {
// 如果画布宽高改变了需要触发一次渲染
this.render()
}
this.emit('resize')
}
@@ -288,7 +294,9 @@ class MindMap {
// 更新配置
updateConfig(opt = {}) {
this.emit('before_update_config', this.opt)
this.opt = this.handleOpt(merge.all([defaultOpt, this.opt, opt]))
this.emit('after_update_config', this.opt)
}
// 获取当前布局结构
@@ -379,6 +387,9 @@ class MindMap {
// 导出
async export(...args) {
try {
if (!this.doExport) {
throw new Error('请注册Export插件')
}
let result = await this.doExport.export(...args)
return result
} catch (error) {
@@ -416,6 +427,11 @@ class MindMap {
addContentToFooter,
node
} = {}) {
const { watermarkConfig, openPerformance } = this.opt
// 如果开启了性能模式,那么需要先渲染所有节点
if (openPerformance) {
this.renderer.forceLoadNode(node)
}
const { cssTextList, header, headerHeight, footer, footerHeight } =
handleGetSvgDataExtraContent({
addContentToHeader,
@@ -459,7 +475,7 @@ class MindMap {
if (!ignoreWatermark && hasWatermark) {
this.watermark.isInExport = true
// 是否是仅导出时需要水印
const { onlyExport } = this.opt.watermarkConfig
const { onlyExport } = watermarkConfig
// 是否需要重新绘制水印
const needReDrawWatermark =
rect.width > origWidth || rect.height > origHeight

View File

@@ -1,14 +1,14 @@
{
"name": "simple-mind-map",
"version": "0.10.0-fix.1",
"version": "0.10.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.10.0-fix.1",
"version": "0.10.4",
"license": "MIT",
"dependencies": {
"@svgdotjs/svg.js": "^3.0.16",
"@svgdotjs/svg.js": "^3.2.0",
"deepmerge": "^1.5.2",
"eventemitter3": "^4.0.7",
"jszip": "^3.10.1",

View File

@@ -1,6 +1,6 @@
{
"name": "simple-mind-map",
"version": "0.10.3",
"version": "0.10.5",
"description": "一个简单的web在线思维导图",
"authors": [
{
@@ -28,7 +28,7 @@
"module": "index.js",
"main": "./dist/simpleMindMap.umd.min.js",
"dependencies": {
"@svgdotjs/svg.js": "^3.0.16",
"@svgdotjs/svg.js": "^3.2.0",
"deepmerge": "^1.5.2",
"eventemitter3": "^4.0.7",
"jszip": "^3.10.1",

View File

@@ -228,6 +228,14 @@ export const defaultOpt = {
// 自定义超链接的跳转
// 如果不传默认会以新窗口的方式打开超链接可以传递一个函数函数接收两个参数link超链接的url、node所属节点实例只要传递了函数就会阻止默认的跳转
customHyperlinkJump: null,
// 是否开启性能模式默认情况下所有节点都会直接渲染无论是否处于画布可视区域这样当节点数量比较多时1000+会比较卡如果你的数据量比较大那么可以通过该配置开启性能模式即只渲染画布可视区域内的节点超出的节点不渲染这样会大幅提高渲染速度当然同时也会带来一些其他问题比如1.当拖动或是缩放画布时会实时计算并渲染未节点的节点所以会带来一定卡顿2.导出图片、svg、pdf时需要先渲染全部节点所以会比较慢3.其他目前未发现的问题
openPerformance: false,
// 性能优化模式配置
performanceConfig: {
time: 250,// 当视图改变后多久刷新一次节点单位ms
padding: 100,// 超出画布四周指定范围内依旧渲染节点
removeNodeWhenOutCanvas: true,// 节点移除画布可视区域后从画布删除
},
// 【Select插件】
// 多选节点时鼠标移动到边缘时的画布移动偏移量

View File

@@ -32,7 +32,8 @@ import {
checkIsNodeStyleDataKey,
removeRichTextStyes,
formatGetNodeGeneralization,
sortNodeList
sortNodeList,
throttle
} from '../../utils'
import { shapeList } from './node/Shape'
import { lineStyleProps } from '../../themes/default'
@@ -144,13 +145,54 @@ class Render {
if (!this.mindMap.opt.enableDblclickBackToRootNode) return
this.setRootNodeCenter()
})
// let timer = null
// this.mindMap.on('view_data_change', () => {
// clearTimeout(timer)
// timer = setTimeout(() => {
// this.render()
// }, 300)
// })
// 性能模式
this.performanceMode()
}
// 性能模式,懒加载节点
performanceMode() {
const { openPerformance, performanceConfig } = this.mindMap.opt
const onViewDataChange = throttle(() => {
if (this.root) {
this.mindMap.emit('node_tree_render_start')
this.root.render(
() => {
this.mindMap.emit('node_tree_render_end')
},
false,
true
)
}
}, performanceConfig.time)
let lastOpen = false
this.mindMap.on('before_update_config', opt => {
lastOpen = opt.openPerformance
})
this.mindMap.on('after_update_config', opt => {
if (opt.openPerformance && !lastOpen) {
// 动态开启性能模式
this.mindMap.on('view_data_change', onViewDataChange)
this.forceLoadNode()
}
if (!opt.openPerformance && lastOpen) {
// 动态关闭性能模式
this.mindMap.off('view_data_change', onViewDataChange)
this.forceLoadNode()
}
})
if (!openPerformance) return
this.mindMap.on('view_data_change', onViewDataChange)
}
// 强制渲染节点,不考虑是否在画布可视区域内
forceLoadNode(node) {
node = node || this.root
if (node) {
this.mindMap.emit('node_tree_render_start')
node.render(() => {
this.mindMap.emit('node_tree_render_end')
}, true)
}
}
// 注册命令
@@ -453,6 +495,7 @@ class Render {
}
this.mindMap.emit('node_tree_render_start')
// 计算布局
this.root = null
this.layout.doLayout(root => {
// 删除本次渲染时不再需要的节点
Object.keys(this.lastNodeCache).forEach(uid => {
@@ -1221,6 +1264,10 @@ class Render {
// 如果是富文本模式,那么某些层级变化需要更新样式
checkNodeLayerChange(node, toNode, toNodeIsParent = false) {
if (this.mindMap.richText) {
// 如果设置了自定义样式那么不需要更新
if (this.mindMap.richText.checkNodeHasCustomRichTextStyle(node)) {
return
}
const toIndex = toNodeIsParent ? toNode.layerIndex + 1 : toNode.layerIndex
let nodeLayerChanged =
(node.layerIndex === 1 && toIndex !== 1) ||
@@ -1419,6 +1466,9 @@ class Render {
this.checkNodeLayerChange(item, toNode, true)
this.removeNodeFromActiveList(item)
removeFromParentNodeData(item)
toNode.setData({
expand: true
})
toNode.nodeData.children.push(item.nodeData)
})
this.emitNodeActiveEvent()
@@ -1432,10 +1482,24 @@ class Render {
return
}
this.activeNodeList.forEach(node => {
node.setData({
expand: true
})
node.nodeData.children.push(
...data.map(item => {
const newData = simpleDeepClone(item)
createUidForAppointNodes([newData], true)
createUidForAppointNodes([newData], true, node => {
// 可能跨层级复制,那么富文本样式需要更新
if (this.mindMap.richText) {
// 如果设置了自定义样式那么不需要更新
if (
this.mindMap.richText.checkNodeHasCustomRichTextStyle(node.data)
) {
return
}
node.data.resetRichText = true
}
})
return newData
})
)

View File

@@ -528,6 +528,7 @@ class Node {
textContentNested.add(foreignObject)
textContentOffsetX += this._postfixData.width
}
this.group.add(textContentNested)
// 文字内容整体
textContentNested.translate(
width / 2 - textContentNested.bbox().width / 2,
@@ -535,7 +536,6 @@ class Node {
imgHeight + // 图片高度
(imgHeight > 0 && textContentHeight > 0 ? this.blockContentMargin : 0) // 和图片的间距
)
this.group.add(textContentNested)
addHoverNode()
this.mindMap.emit('node_layout_end', this)
}
@@ -683,7 +683,7 @@ class Node {
}
// 更新节点
update() {
update(forceRender) {
if (!this.group) {
return
}
@@ -710,36 +710,11 @@ class Node {
}
}
// 更新概要
this.renderGeneralization()
this.renderGeneralization(forceRender)
// 更新协同头像
if (this.updateUserListNode) this.updateUserListNode()
// 更新节点位置
let t = this.group.transform()
// // 如果上次不在可视区内,且本次也不在,那么直接返回
// let { left: ox, top: oy } = this.getNodePosInClient(
// t.translateX,
// t.translateY
// )
// let oldIsInClient =
// ox > 0 && oy > 0 && ox < this.mindMap.width && oy < this.mindMap.height
// let { left: nx, top: ny } = this.getNodePosInClient(this.left, this.top)
// let newIsNotInClient =
// nx + this.width < 0 ||
// ny + this.height < 0 ||
// nx > this.mindMap.width ||
// ny > this.mindMap.height
// if (!oldIsInClient && newIsNotInClient) {
// if (!this.isHide) {
// this.isHide = true
// this.group.hide()
// }
// return
// }
// // 如果当前是隐藏状态,那么先显示
// if (this.isHide) {
// this.isHide = false
// this.group.show()
// }
// 如果节点位置没有变化,则返回
if (this.left === t.translateX && this.top === t.translateY) return
this.group.translate(this.left - t.translateX, this.top - t.translateY)
@@ -757,6 +732,17 @@ class Node {
}
}
// 判断节点是否可见
checkIsInClient(padding = 0) {
const { left: nx, top: ny } = this.getNodePosInClient(this.left, this.top)
return (
nx + this.width > 0 - padding &&
ny + this.height > 0 - padding &&
nx < this.mindMap.width + padding &&
ny < this.mindMap.height + padding
)
}
// 重新渲染节点,即重新创建节点内容、计算节点大小、计算节点内容布局、更新展开收起按钮,概要及位置
reRender() {
let sizeChange = this.getSize()
@@ -785,32 +771,46 @@ class Node {
}
}
// 递归渲染
render(callback = () => {}) {
// 递归渲染
// forceRender强制渲染无论是否处于画布可视区域
// async异步渲染
render(callback = () => {}, forceRender = false, async = false) {
// 节点
// 重新渲染连线
this.renderLine()
if (!this.group) {
// 创建组
this.group = new G()
this.group.addClass('smm-node')
this.group.css({
cursor: 'default'
})
this.bindGroupEvent()
this.nodeDraw.add(this.group)
this.layout()
this.update()
} else {
if (!this.nodeDraw.has(this.group)) {
const { openPerformance, performanceConfig } = this.mindMap.opt
// 强制渲染、或没有开启性能模式、或不在画布可视区域内不渲染节点内容
// 根节点不进行懒加载,始终渲染,因为滚动条插件依赖根节点进行计算
if (
forceRender ||
!openPerformance ||
this.checkIsInClient(performanceConfig.padding) ||
this.isRoot
) {
if (!this.group) {
// 创建组
this.group = new G()
this.group.addClass('smm-node')
this.group.css({
cursor: 'default'
})
this.bindGroupEvent()
this.nodeDraw.add(this.group)
}
if (this.needLayout) {
this.needLayout = false
this.layout()
this.update(forceRender)
} else {
if (!this.nodeDraw.has(this.group)) {
this.nodeDraw.add(this.group)
}
if (this.needLayout) {
this.needLayout = false
this.layout()
}
this.updateExpandBtnPlaceholderRect()
this.update(forceRender)
}
this.updateExpandBtnPlaceholderRect()
this.update()
} else if (openPerformance && performanceConfig.removeNodeWhenOutCanvas) {
this.removeSelf()
}
// 子节点
if (
@@ -820,12 +820,23 @@ class Node {
) {
let index = 0
this.children.forEach(item => {
item.render(() => {
index++
if (index >= this.children.length) {
callback()
}
})
const renderChild = () => {
item.render(
() => {
index++
if (index >= this.children.length) {
callback()
}
},
forceRender,
async
)
}
if (async) {
setTimeout(renderChild, 0)
} else {
renderChild()
}
})
} else {
callback()
@@ -840,6 +851,13 @@ class Node {
}
}
// 删除自身,只是从画布删除,节点容器还在,后续还可以重新插回画布
removeSelf() {
if (!this.group) return
this.group.remove()
this.removeGeneralization()
}
// 递归删除,只是从画布删除,节点容器还在,后续还可以重新插回画布
remove() {
if (!this.group) return
@@ -856,6 +874,10 @@ class Node {
// 销毁节点,不但会从画布删除,而且原节点直接置空,后续无法再插回画布
destroy() {
this.removeLine()
if (this.parent) {
this.parent.removeLine()
}
if (!this.group) return
if (this.emptyUser) {
this.emptyUser()
@@ -863,11 +885,7 @@ class Node {
this.resetWhenDelete()
this.group.remove()
this.removeGeneralization()
this.removeLine()
this.group = null
if (this.parent) {
this.parent.removeLine()
}
this.style.onRemove()
}

View File

@@ -1,5 +1,5 @@
import btnsSvg from '../../../svg/btns'
import { SVG, Circle, G } from '@svgdotjs/svg.js'
import { SVG, Circle, G, Text } from '@svgdotjs/svg.js'
// 创建展开收起按钮的内容节点
function createExpandNodeContent() {
@@ -10,9 +10,7 @@ function createExpandNodeContent() {
// 根据配置判断是否显示数量按钮
if (this.mindMap.opt.isShowExpandNum) {
// 展开的节点
this._openExpandNode = SVG()
.text()
.size(this.expandBtnSize, this.expandBtnSize)
this._openExpandNode = new Text()
// 文本垂直居中
this._openExpandNode.attr({
'text-anchor': 'middle',
@@ -81,7 +79,7 @@ function updateExpandBtnNode() {
// 计算子节点数量
let count = this.sumNode(this.nodeData.children)
count = expandBtnNumHandler(count)
node.text(count)
node.text(String(count))
} else {
this._fillExpandNode.stroke('none')
}
@@ -126,11 +124,7 @@ function renderExpandBtn() {
this._expandBtn.on('click', e => {
e.stopPropagation()
// 展开收缩
this.mindMap.execCommand(
'SET_NODE_EXPAND',
this,
!this.getData('expand')
)
this.mindMap.execCommand('SET_NODE_EXPAND', this, !this.getData('expand'))
this.mindMap.emit('expand_btn_click', this)
})
this._expandBtn.on('dblclick', e => {

View File

@@ -85,7 +85,7 @@ function updateGeneralization() {
}
// 渲染概要节点
function renderGeneralization() {
function renderGeneralization(forceRender) {
if (this.isGeneralization) return
this.updateGeneralizationData()
const list = this.formatGetGeneralization()
@@ -100,7 +100,7 @@ function renderGeneralization() {
this.renderer.layout.renderGeneralization(this._generalizationList)
this._generalizationList.forEach(item => {
this.style.generalizationLine(item.generalizationLine)
item.generalizationNode.render()
item.generalizationNode.render(() => {}, forceRender)
})
}

View File

@@ -68,6 +68,7 @@ class AssociativeLine {
this.onNodeDragging = this.onNodeDragging.bind(this)
this.onNodeDragend = this.onNodeDragend.bind(this)
this.onControlPointMouseup = this.onControlPointMouseup.bind(this)
this.cancelCreateLine = this.cancelCreateLine.bind(this)
// 节点树渲染完毕后渲染连接线
this.mindMap.on('node_tree_render_end', this.renderAllLines)
@@ -76,6 +77,7 @@ class AssociativeLine {
// 监听画布和节点点击事件,用于清除当前激活的连接线
this.mindMap.on('draw_click', this.onDrawClick)
this.mindMap.on('node_click', this.onNodeClick)
this.mindMap.on('contextmenu', this.cancelCreateLine)
// 注册删除快捷键
this.mindMap.keyCommand.addShortcut('Del|Backspace', this.removeLine)
// 注册添加连接线的命令
@@ -97,6 +99,7 @@ class AssociativeLine {
this.mindMap.off('data_change', this.renderAllLines)
this.mindMap.off('draw_click', this.onDrawClick)
this.mindMap.off('node_click', this.onNodeClick)
this.mindMap.off('contextmenu', this.cancelCreateLine)
this.mindMap.keyCommand.removeShortcut('Del|Backspace', this.removeLine)
this.mindMap.command.remove('ADD_ASSOCIATIVE_LINE', this.addLine)
this.mindMap.off('mousemove', this.onMousemove)
@@ -108,10 +111,14 @@ class AssociativeLine {
// 画布点击事件
onDrawClick() {
if (this.isControlPointMousedown) {
return
// 取消创建关联线
if (this.isCreatingLine) {
this.cancelCreateLine()
}
// 取消激活关联线
if (this.isControlPointMousedown) {
this.clearActiveLine()
}
this.clearActiveLine()
}
// 节点点击事件
@@ -346,6 +353,16 @@ class AssociativeLine {
this.creatingLine.marker('end', this.marker)
}
// 取消创建关联线
cancelCreateLine() {
this.isCreatingLine = false
this.creatingStartNode = null
this.creatingLine.remove()
this.creatingLine = null
this.overlapNode = null
this.back()
}
// 鼠标移动事件
onMousemove(e) {
this.onControlPointMousemove(e)
@@ -420,12 +437,7 @@ class AssociativeLine {
if (this.overlapNode && this.overlapNode.getData('isActive')) {
this.mindMap.execCommand('SET_NODE_ACTIVE', this.overlapNode, false)
}
this.isCreatingLine = false
this.creatingStartNode = null
this.creatingLine.remove()
this.creatingLine = null
this.overlapNode = null
this.back()
this.cancelCreateLine()
}
// 添加连接线

View File

@@ -40,6 +40,7 @@ class Demonstrate {
{ ...defaultConfig },
this.mindMap.opt.demonstrateConfig || {}
)
this.needRestorePerformanceMode = false
}
// 进入演示模式
@@ -56,6 +57,8 @@ class Demonstrate {
}
_enter() {
// 如果开启了性能模式,那么需要暂停
this.pausePerformanceMode()
// 添加演示用的临时的样式
this.addTmpStyles()
// 记录演示前的画布状态
@@ -97,9 +100,27 @@ class Demonstrate {
this.removeHighlightEl()
this.mindMap.command.recovery()
this.mindMap.keyCommand.recovery()
this.restorePerformanceMode()
this.mindMap.emit('exit_demonstrate')
}
// 暂停性能模式
pausePerformanceMode() {
const { openPerformance } = this.mindMap.opt
if (openPerformance) {
this.needRestorePerformanceMode = true
this.mindMap.opt.openPerformance = false
this.mindMap.renderer.forceLoadNode()
}
}
// 恢复性能模式
restorePerformanceMode() {
if (!this.needRestorePerformanceMode) return
this.mindMap.opt.openPerformance = true
this.mindMap.renderer.forceLoadNode()
}
// 添加临时的样式
addTmpStyles() {
this.tmpStyleEl = document.createElement('style')

View File

@@ -297,6 +297,13 @@ class OuterFrame {
if (range[0] === -1 || range[1] === -1) return
const { left, top, width, height } =
getNodeListBoundingRect(nodeList)
if (
!Number.isFinite(left) ||
!Number.isFinite(top) ||
!Number.isFinite(width) ||
!Number.isFinite(height)
)
return
const el = this.createOuterFrameEl(
(left -
outerFramePaddingX -

View File

@@ -13,6 +13,7 @@ import {
nodeRichTextToTextWithWrap
} from '../utils'
import { CONSTANTS } from '../constants/constant'
import Node from '../core/render/node/Node'
let extended = false
@@ -666,6 +667,25 @@ class RichText {
}
}
// 检查指定节点是否存在自定义的富文本样式
checkNodeHasCustomRichTextStyle(node) {
const list = [
'fontFamily',
'fontSize',
'fontWeight',
'fontStyle',
'textDecoration',
'color'
]
const nodeData = node instanceof Node ? node.getData() : node
for (let i = 0; i < list.length; i++) {
if (nodeData[list[i]] !== undefined) {
return true
}
}
return false
}
// 将所有节点转换成非富文本节点
transformAllNodesToNormalNode() {
if (!this.mindMap.renderer.renderTree) return

View File

@@ -948,7 +948,7 @@ export const addDataToAppointNodes = (appointNodes, data = {}) => {
// 给指定的节点列表树数据添加uid会修改原数据
// createNewId默认为false即如果节点不存在uid的话会创建新的uid。如果传true那么无论节点数据原来是否存在uid都会创建新的uid
export const createUidForAppointNodes = (appointNodes, createNewId = false) => {
export const createUidForAppointNodes = (appointNodes, createNewId = false, handle = null) => {
const walk = list => {
list.forEach(node => {
if (!node.data) {
@@ -957,6 +957,7 @@ export const createUidForAppointNodes = (appointNodes, createNewId = false) => {
if (createNewId || isUndef(node.data.uid)) {
node.data.uid = createUid()
}
handle && handle(node)
if (node.children && node.children.length > 0) {
walk(node.children)
}
@@ -1382,22 +1383,24 @@ export const getNodeTreeBoundingRect = (
let minY = Infinity
let maxY = -Infinity
const walk = (root, isRoot) => {
if (!(isRoot && excludeSelf)) {
const { x, y, width, height } = root.group
.findOne('.smm-node-shape')
.rbox()
if (x < minX) {
minX = x
}
if (x + width > maxX) {
maxX = x + width
}
if (y < minY) {
minY = y
}
if (y + height > maxY) {
maxY = y + height
}
if (!(isRoot && excludeSelf) && root.group) {
try {
const { x, y, width, height } = root.group
.findOne('.smm-node-shape')
.rbox()
if (x < minX) {
minX = x
}
if (x + width > maxX) {
maxX = x + width
}
if (y < minY) {
minY = y
}
if (y + height > maxY) {
maxY = y + height
}
} catch (e) {}
}
if (!excludeGeneralization && root._generalizationList.length > 0) {
root._generalizationList.forEach(item => {

View File

@@ -1,6 +1,7 @@
import exampleData from 'simple-mind-map/example/exampleData'
import { simpleDeepClone } from 'simple-mind-map/src/utils/index'
import Vue from 'vue'
import vuexStore from '@/store'
const SIMPLE_MIND_MAP_DATA = 'SIMPLE_MIND_MAP_DATA'
const SIMPLE_MIND_MAP_LANG = 'SIMPLE_MIND_MAP_LANG'
@@ -36,6 +37,9 @@ export const getData = () => {
mindMapData = window.takeOverAppMethods.getMindMapData()
return mindMapData
}
if (vuexStore.state.isHandleLocalFile) {
return Vue.prototype.getCurrentData()
}
let store = localStorage.getItem(SIMPLE_MIND_MAP_DATA)
if (store === null) {
return simpleDeepClone(exampleData)
@@ -68,6 +72,9 @@ export const storeData = data => {
return
}
Vue.prototype.$bus.$emit('write_local_file', originData)
if (vuexStore.state.isHandleLocalFile) {
return
}
let dataStr = JSON.stringify(originData)
localStorage.setItem(SIMPLE_MIND_MAP_DATA, dataStr)
} catch (error) {
@@ -98,6 +105,9 @@ export const storeConfig = config => {
return
}
Vue.prototype.$bus.$emit('write_local_file', originData)
if (vuexStore.state.isHandleLocalFile) {
return
}
let dataStr = JSON.stringify(originData)
localStorage.setItem(SIMPLE_MIND_MAP_DATA, dataStr)
} catch (error) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -26,7 +26,8 @@ export default {
nodeBorderType: 'Node border style',
nodeUseLineStyle: 'Use only has bottom border style',
otherConfig: 'Other config',
enableFreeDrag: 'Enable node free drag',
enableFreeDrag: 'Enable node free drag(Beta)',
openPerformance: 'Enable performance mode',
watermark: 'Watermark',
showWatermark: 'Is show watermark',
onlyExport: 'Only export',
@@ -289,9 +290,9 @@ export default {
creatingTip: 'Creating file',
directory: 'Directory',
newFileTip:
'Please export the currently edited file before creating a new one, otherwise the content will be lost',
'Please export the currently edited file before creating a new one, Beware of content loss',
openFileTip:
'Please export the currently edited file before opening it, otherwise the content will be lost'
'Please export the currently edited file before opening it, Beware of content loss'
},
edit: {
newFeatureNoticeTitle: 'New feature reminder',

View File

@@ -27,6 +27,7 @@ export default {
nodeUseLineStyle: '是否使用只有底边框的风格',
otherConfig: '其他配置',
enableFreeDrag: '是否开启节点自由拖拽',
openPerformance: '开启性能模式(Beta)',
watermark: '水印',
showWatermark: '是否显示水印',
watermarkDefaultText: '水印文字',
@@ -284,8 +285,8 @@ export default {
defaultFileName: '思维导图',
creatingTip: '正在创建文件',
directory: '目录',
newFileTip: '新建文件前请先导出当前编辑的文件,否则内容丢失',
openFileTip: '打开文件前请先导出当前编辑的文件,否则内容会丢'
newFileTip: '新建文件前请先导出当前编辑的文件,谨防内容丢失',
openFileTip: '打开文件前请先导出当前编辑的文件,谨防内容丢失'
},
edit: {
newFeatureNoticeTitle: '新特性提醒',

View File

@@ -55,6 +55,12 @@ The currently active connection line and array type are the same as the structur
## Methods
### cancelCreateLine()
> v0.10.5+
Cancel the creation of the associated line midway.
### renderAllLines()
Re-render all associated lines.

View File

@@ -49,6 +49,11 @@ MindMap.usePlugin(AssociativeLine)
<h3>mindMap.associativeLine.activeLine</h3>
<p>The currently active connection line and array type are the same as the structure of each item in the <code>lineList</code> array.</p>
<h2>Methods</h2>
<h3>cancelCreateLine()</h3>
<blockquote>
<p>v0.10.5+</p>
</blockquote>
<p>Cancel the creation of the associated line midway.</p>
<h3>renderAllLines()</h3>
<p>Re-render all associated lines.</p>
<h3>removeAllLines()</h3>

View File

@@ -1,5 +1,47 @@
# Changelog
## 0.10.5
> 2024.8.2
Fix:
> 1.Fixed the issue of error when dragging the scrollbar after enabling the scrollbar plugin and performance mode;
>
> 2.Fixed the issue where the rich text style of nodes was not updated when copying across levels;
>
> 3.Fixed the issue where the demo plugin did not work properly after enabling performance mode;
>
> 4.Fixed the issue of canvas jumping when the first rendering canvas is triggered after adjusting the canvas size;
New:
> 1.Move the node and change the node hierarchy. Nodes that have set custom rich text styles do not need to update the styles;
>
> 2.Support clicking on the canvas to cancel the creation of associated lines;
>
> 3.Automatically expand a node by moving it or copying it to a collapsed node;
Demo:
> 1.When the number of subordinate nodes is greater than 100, the collapse button displays ellipsis;
>
> 2.No longer write data to the browser cache when opening local file editing, to avoid the problem of local file data loss caused by triggering storage restrictions;
>
> 3.If the local file is not saved, close the page and add an interception prompt;
>
> 4.Fixed the issue in the outline where clicking and dragging a node would trigger a file drag mask on the page;
## 0.10.4
> 2024.7.25
This update mainly adds a performance mode. When enabled, only nodes within the visible area of the canvas will be rendered, and nodes outside the area will be deleted from the canvas, improving usability in the case of large data volumes (1000+nodes). The first rendering time for 2000 nodes has been reduced from 5s+to 0.5s. However, this also brings some problems, such as a slight lag when dragging the animation canvas, as nodes will be rendered in real time, and exporting images will be slower because all nodes need to be rendered first, as well as other temporarily undiscovered issues.
Fix:
> 1.Delete useless code and fix the issue where the mouse hover node reports an error and does not display the expand and collapse buttons;
## 0.10.3
> 2024.7.19

View File

@@ -1,6 +1,39 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.10.5</h2>
<blockquote>
<p>2024.8.2</p>
</blockquote>
<p>Fix:</p>
<blockquote>
<p>1.Fixed the issue of error when dragging the scrollbar after enabling the scrollbar plugin and performance mode;</p>
<p>2.Fixed the issue where the rich text style of nodes was not updated when copying across levels;</p>
<p>3.Fixed the issue where the demo plugin did not work properly after enabling performance mode;</p>
<p>4.Fixed the issue of canvas jumping when the first rendering canvas is triggered after adjusting the canvas size;</p>
</blockquote>
<p>New:</p>
<blockquote>
<p>1.Move the node and change the node hierarchy. Nodes that have set custom rich text styles do not need to update the styles;</p>
<p>2.Support clicking on the canvas to cancel the creation of associated lines;</p>
<p>3.Automatically expand a node by moving it or copying it to a collapsed node;</p>
</blockquote>
<p>Demo:</p>
<blockquote>
<p>1.When the number of subordinate nodes is greater than 100, the collapse button displays ellipsis;</p>
<p>2.No longer write data to the browser cache when opening local file editing, to avoid the problem of local file data loss caused by triggering storage restrictions;</p>
<p>3.If the local file is not saved, close the page and add an interception prompt;</p>
<p>4.Fixed the issue in the outline where clicking and dragging a node would trigger a file drag mask on the page;</p>
</blockquote>
<h2>0.10.4</h2>
<blockquote>
<p>2024.7.25</p>
</blockquote>
<p>This update mainly adds a performance mode. When enabled, only nodes within the visible area of the canvas will be rendered, and nodes outside the area will be deleted from the canvas, improving usability in the case of large data volumes (1000+nodes). The first rendering time for 2000 nodes has been reduced from 5s+to 0.5s. However, this also brings some problems, such as a slight lag when dragging the animation canvas, as nodes will be rendered in real time, and exporting images will be slower because all nodes need to be rendered first, as well as other temporarily undiscovered issues.</p>
<p>Fix:</p>
<blockquote>
<p>1.Delete useless code and fix the issue where the mouse hover node reports an error and does not display the expand and collapse buttons;</p>
</blockquote>
<h2>0.10.3</h2>
<blockquote>
<p>2024.7.19</p>

View File

@@ -99,6 +99,8 @@ const mindMap = new MindMap({
| createNodePostfixContentv0.9.12+ | Function、null | null | Add additional node post content.Post content refers to the post content in the area of the same line as the text, excluding the node image section. The usage is the same as createNodePrefixContent | |
| disabledClipboardv0.10.2+ | Boolean | false | Is prohibit pasting data from the user's clipboard and writing copied node data to the user's clipboard. At this time, only node data from the canvas can be copied and pasted | |
| customHyperlinkJumpv0.10.2+ | null、Function | false | Customize the jump of hyperlinks. If not passed, the hyperlink will be opened as a new window by default, and a function can be passed, The function takes two parameters: linkThe URL of the hyperlink、nodeNode instance to which it belongs, As long as a function is passed, it will block the default jump | |
| openPerformancev0.10.4+ | Boolean | false | Whether to enable performance mode or not, by default, all nodes will be rendered directly, regardless of whether they are in the visible area of the canvas. This will cause a lag when there are a large number of nodes (1000+). If your data volume is large, you can enable performance mode through this configuration, that is, only rendering nodes within the visible area of the canvas, and not rendering nodes beyond it. This will greatly improve rendering speed, but of course, it will also bring some other problems, such as: 1. When dragging or scaling the canvas, real-time calculation and rendering of nodes without nodes will be performed, which will bring some lag; When exporting images, SVG, and PDF, all nodes need to be rendered first, so it may be slower; 3. Other currently undiscovered issues | |
| performanceConfigv0.10.4+ | Object | { time: 250, padding: 100, removeNodeWhenOutCanvas: true } | Performance optimization mode configuration. timeHow often do nodes refresh after a view change. Unit:ms、paddingStill rendering nodes beyond the specified range around the canvas、removeNodeWhenOutCanvasIs the node deleted from the canvas after being moved out of the visible area of the canvas | |
### 1.1Data structure
@@ -618,6 +620,8 @@ Listen to an event. Event list:
| node_layout_endv0.10.1+ | Event where the content layout of a single node is completed | this(Current node instance) |
| node_attachmentClickv0.9.10+ | Click event for node attachment icon | this(Current node instance)、eEvent Object、nodeIcon node |
| node_attachmentContextmenuv0.9.10+ | Right click event on node attachment icon | this(Current node instance)、eEvent Object、nodeIcon node |
| before_update_configv0.10.4+ | Triggered before updating the configuration, that is, when the 'mindMap.updateConfig' method is called to update the configuration | optThe configuration object before updating refers to an object, not a copy, so when the after_uupdate_comfig event is triggered, the object will also change synchronously. Therefore, it is necessary to cache a certain configuration field that you need |
| after_update_configv0.10.4+ | Triggered after updating configuration | optUpdated configuration object |
### emit(event, ...args)

View File

@@ -540,6 +540,20 @@
<td>Customize the jump of hyperlinks. If not passed, the hyperlink will be opened as a new window by default, and a function can be passed, The function takes two parameters: linkThe URL of the hyperlink、nodeNode instance to which it belongs, As long as a function is passed, it will block the default jump</td>
<td></td>
</tr>
<tr>
<td>openPerformancev0.10.4+</td>
<td>Boolean</td>
<td>false</td>
<td>Whether to enable performance mode or not, by default, all nodes will be rendered directly, regardless of whether they are in the visible area of the canvas. This will cause a lag when there are a large number of nodes (1000+). If your data volume is large, you can enable performance mode through this configuration, that is, only rendering nodes within the visible area of the canvas, and not rendering nodes beyond it. This will greatly improve rendering speed, but of course, it will also bring some other problems, such as: 1. When dragging or scaling the canvas, real-time calculation and rendering of nodes without nodes will be performed, which will bring some lag; When exporting images, SVG, and PDF, all nodes need to be rendered first, so it may be slower; 3. Other currently undiscovered issues</td>
<td></td>
</tr>
<tr>
<td>performanceConfigv0.10.4+</td>
<td>Object</td>
<td>{ time: 250, padding: 100, removeNodeWhenOutCanvas: true }</td>
<td>Performance optimization mode configuration. timeHow often do nodes refresh after a view change. Unit:ms、paddingStill rendering nodes beyond the specified range around the canvas、removeNodeWhenOutCanvasIs the node deleted from the canvas after being moved out of the visible area of the canvas</td>
<td></td>
</tr>
</tbody>
</table>
<h3>1.1Data structure</h3>
@@ -1698,6 +1712,16 @@ poor performance and should be used sparingly.</p>
<td>Right click event on node attachment icon</td>
<td>this(Current node instance)eEvent ObjectnodeIcon node</td>
</tr>
<tr>
<td>before_update_configv0.10.4+</td>
<td>Triggered before updating the configuration, that is, when the 'mindMap.updateConfig' method is called to update the configuration</td>
<td>optThe configuration object before updating refers to an object, not a copy, so when the after_uupdate_comfig event is triggered, the object will also change synchronously. Therefore, it is necessary to cache a certain configuration field that you need</td>
</tr>
<tr>
<td>after_update_configv0.10.4+</td>
<td>Triggered after updating configuration</td>
<td>optUpdated configuration object</td>
</tr>
</tbody>
</table>
<h3>emit(event, ...args)</h3>

View File

@@ -84,10 +84,12 @@ The folder containing the packaged resources for the `web` folder.
## Special Note
This project can be used for learning and reference. Please deeply experience whether it can meet your needs when using it for actual projects.
When applying this project to actual projects, please first experience in depth whether it can meet your needs.
This project may not have fully tested every function point, so there may be bugs. In addition, when the number of nodes is very large, there may be some performance issues. Because everyone can accept different levels of congestion, you can test the maximum number of nodes yourself. Generally speaking, within 500 nodes, it is more smooth, while over 1000 nodes have more noticeable lag.
In v0.10.4+version, a performance mode has been added to only render nodes within the visible area of the canvas, which can improve rendering speed under large data volumes. You can experience it by turning on the 'openPerformance' instantiation option, and in the online demo, you can turn on the 'Basic Styles' - 'Enable Performance Mode' switch.
If you have suggestions or find bugs, you can submit [issues](https://github.com/wanglin2/mind-map/issues) here.
The built-in themes and icons in the project part come from:[Baidu Mind Map](https://naotu.baidu.com/)、[Zhixi Mind Map](https://www.zhixi.com/)。Respect the copyright, and do not use the theme and icons directly for commercial projects.
@@ -108,7 +110,7 @@ There are many other online mind mapping products similar to Zhixi, such as [Git
These open-source mind maps are also good, each with its own characteristics, but they also have certain drawbacks, such as stopping updates, average interface aesthetics, less functionality, relying on a certain framework, and so on.
In summary, in open-source mind maps, it is difficult to find a better choice than `simple-mind-map`. Of course, `simple-mind-map` is far from being the best, and it also has many shortcomings, as you saw in the previous [special note]. However, `simple-mind-map` has always been in a fast iteration process, and we welcome you to join and improve it together.
In summary, in open-source mind maps, it is difficult to find a better choice than `simple-mind-map`. Of course, `simple-mind-map` is far from being the best, and it also has many shortcomings. However, `simple-mind-map` has always been in a fast iteration process, and we welcome you to join and improve it together.
## Browser Compatibility
@@ -126,7 +128,7 @@ Unsupported: `IE` browser.
## Invite the author to a cup of coffee
Open source is not easy. If this project is helpful to you, you can invite the author to have a cup of coffee~
Open source is not easy. If this project is helpful to you, you can invite the author to have a cup of coffee, Your support is the biggest driving force for developers to continuously maintain~
> Please note the 【mind map】 for transfer.
@@ -450,4 +452,22 @@ Open source is not easy. If this project is helpful to you, you can invite the a
<img src="../../../../assets/avatar/晴空.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>晴空</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>黄泳</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/ccccs.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>ccccs</p>
</div>
</div>
<div style="display: flex;">
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/。.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>。</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/Jeffrey.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>Jeffrey</p>
</div>
</div>

View File

@@ -8,18 +8,18 @@
</blockquote>
<h2>Features</h2>
<ul>
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">Support logical structure chart(Left and Right Logical Structure Diagram), mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, Support for expanding node content, and fully customize node content using DDM</label></li>
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Support canvas dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Supoorts to export as </label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code><code>txt</code>, support import from <code>json</code><code>xmind</code><code>markdown</code></li>
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, scrollbar, Hand drawn style, and rainbow lines</label></li>
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Provide rich configurations to meet various scenarios and usage habits</label></li>
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Support collaborative editing</label></li>
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Support demonstration mode</label></li>
<li><input type="checkbox" id="checkbox34" checked="true" /><label for="checkbox34">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
<li><input type="checkbox" id="checkbox35" checked="true" /><label for="checkbox35">Support logical structure chart(Left and Right Logical Structure Diagram), mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
<li><input type="checkbox" id="checkbox36" checked="true" /><label for="checkbox36">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
<li><input type="checkbox" id="checkbox37" checked="true" /><label for="checkbox37">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
<li><input type="checkbox" id="checkbox38" checked="true" /><label for="checkbox38">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, Support for expanding node content, and fully customize node content using DDM</label></li>
<li><input type="checkbox" id="checkbox39" checked="true" /><label for="checkbox39">Support canvas dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox40" checked="true" /><label for="checkbox40">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
<li><input type="checkbox" id="checkbox41" checked="true" /><label for="checkbox41">Supoorts to export as </label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code><code>txt</code>, support import from <code>json</code><code>xmind</code><code>markdown</code></li>
<li><input type="checkbox" id="checkbox42" checked="true" /><label for="checkbox42">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, scrollbar, Hand drawn style, and rainbow lines</label></li>
<li><input type="checkbox" id="checkbox43" checked="true" /><label for="checkbox43">Provide rich configurations to meet various scenarios and usage habits</label></li>
<li><input type="checkbox" id="checkbox44" checked="true" /><label for="checkbox44">Support collaborative editing</label></li>
<li><input type="checkbox" id="checkbox45" checked="true" /><label for="checkbox45">Support demonstration mode</label></li>
</ul>
<p>The official provides the following plugins, which can be introduced as needed (a certain function may not be effective because you did not introduce the corresponding plugin). Please refer to the documentation for specific usage methods:</p>
<blockquote>
@@ -39,16 +39,16 @@ frameworks such as Vue and React, or without a framework.</p>
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
<ul>
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Toolbar, which supports inserting and deleting nodes, and editing node</label>
<li><input type="checkbox" id="checkbox46" checked="true" /><label for="checkbox46">Toolbar, which supports inserting and deleting nodes, and editing node</label>
images, icons, hyperlinks, notes, tags, and summaries</li>
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Sidebar, with panels for basic style settings, node style settings,</label>
<li><input type="checkbox" id="checkbox47" checked="true" /><label for="checkbox47">Sidebar, with panels for basic style settings, node style settings,</label>
outline, theme selection, and structure selection</li>
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">Import and export functionality; data is saved in the browser's local</label>
<li><input type="checkbox" id="checkbox48" checked="true" /><label for="checkbox48">Import and export functionality; data is saved in the browser's local</label>
storage by default, but it also supports creating, opening, and editing
local files on the computer directly</li>
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">Right-click menu, which supports operations such as expanding, collapsing,</label>
<li><input type="checkbox" id="checkbox49" checked="true" /><label for="checkbox49">Right-click menu, which supports operations such as expanding, collapsing,</label>
and organizing layout</li>
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">Bottom bar, which supports node and word count statistics, switching</label>
<li><input type="checkbox" id="checkbox50" checked="true" /><label for="checkbox50">Bottom bar, which supports node and word count statistics, switching</label>
between edit and read-only modes, zooming in and out, and switching to
full screen, support mini map</li>
</ul>
@@ -65,8 +65,9 @@ full screen, support mini map</li>
<p><a href="https://juejin.cn/post/7287913415803764747">How does the dom-to-image library convert HTML into images</a></p>
<p><a href="https://juejin.cn/post/7295669711533998117">Two days to achieve collaborative editing of mind maps? It's really possible to use Yjs</a></p>
<h2>Special Note</h2>
<p>This project can be used for learning and reference. Please deeply experience whether it can meet your needs when using it for actual projects.</p>
<p>When applying this project to actual projects, please first experience in depth whether it can meet your needs.</p>
<p>This project may not have fully tested every function point, so there may be bugs. In addition, when the number of nodes is very large, there may be some performance issues. Because everyone can accept different levels of congestion, you can test the maximum number of nodes yourself. Generally speaking, within 500 nodes, it is more smooth, while over 1000 nodes have more noticeable lag.</p>
<p>In v0.10.4+version, a performance mode has been added to only render nodes within the visible area of the canvas, which can improve rendering speed under large data volumes. You can experience it by turning on the 'openPerformance' instantiation option, and in the online demo, you can turn on the 'Basic Styles' - 'Enable Performance Mode' switch.</p>
<p>If you have suggestions or find bugs, you can submit <a href="https://github.com/wanglin2/mind-map/issues">issues</a> here.</p>
<p>The built-in themes and icons in the project part come from:<a href="https://naotu.baidu.com/">Baidu Mind Map</a><a href="https://www.zhixi.com/">Zhixi Mind Map</a>Respect the copyright, and do not use the theme and icons directly for commercial projects.</p>
<h2>Why not</h2>
@@ -77,7 +78,7 @@ full screen, support mini map</li>
<p><code>kityminder-core</code> is an open source brain mapping tool developed by Baidu. It has powerful functions and good performance, but it is no longer maintained. Therefore, the code is relatively old, and the interface beauty is relatively ordinary. In addition, bugs can only be fixed by yourself, and the functions can only be developed by yourself. It has high requirements for front-end development capabilities.</p>
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a><a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a><a href="https://github.com/ondras/my-mind">my-mind</a><a href="https://github.com/awehook/blink-mind">blink-mind</a><a href="https://github.com/luvsic3/remind">remind</a><a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a><a href="https://github.com/zyascend/ZMindMap">ZMindMap</a><a href="https://github.com/RockyRen/mindmaptree">mindmaptree</a>...</p>
<p>These open-source mind maps are also good, each with its own characteristics, but they also have certain drawbacks, such as stopping updates, average interface aesthetics, less functionality, relying on a certain framework, and so on.</p>
<p>In summary, in open-source mind maps, it is difficult to find a better choice than <code>simple-mind-map</code>. Of course, <code>simple-mind-map</code> is far from being the best, and it also has many shortcomings, as you saw in the previous [special note]. However, <code>simple-mind-map</code> has always been in a fast iteration process, and we welcome you to join and improve it together.</p>
<p>In summary, in open-source mind maps, it is difficult to find a better choice than <code>simple-mind-map</code>. Of course, <code>simple-mind-map</code> is far from being the best, and it also has many shortcomings. However, <code>simple-mind-map</code> has always been in a fast iteration process, and we welcome you to join and improve it together.</p>
<h2>Browser Compatibility</h2>
<p>We recommend using the latest version of the <code>Chrome</code> browser.</p>
<p>Limited testing situation:</p>
@@ -86,7 +87,7 @@ full screen, support mini map</li>
<h2>License</h2>
<p><a href="https://github.com/wanglin2/mind-map/blob/main/LICENSE">MIT</a>. You can use it for commercial purposes without retaining the copyright statement of 'mind-map'. If you don't want to keep it, you can contact the author.</p>
<h2>Invite the author to a cup of coffee</h2>
<p>Open source is not easy. If this project is helpful to you, you can invite the author to have a cup of coffee~</p>
<p>Open source is not easy. If this project is helpful to you, you can invite the author to have a cup of coffee, Your support is the biggest driving force for developers to continuously maintain~</p>
<blockquote>
<p>Please note the mind map for transfer.</p>
</blockquote>
@@ -407,8 +408,25 @@ full screen, support mini map</li>
<img src="../../../../assets/avatar/晴空.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>晴空</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>黄泳</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/ccccs.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>ccccs</p>
</div>
</div>
<div style="display: flex;">
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/。.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p></p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/Jeffrey.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>Jeffrey</p>
</div>
</div>
</div>
</template>

View File

@@ -56,6 +56,14 @@ Whether the node is currently being dragged
## Methods
### checkIsInClient(padding = 0)
> v0.10.4+
- `padding`: Number, The size of the area extending around the canvas
Determine whether the node is within the visible area of the canvas.
### deactivate()
> 0.9.11+

View File

@@ -31,6 +31,14 @@
</blockquote>
<p>Whether the node is currently being dragged</p>
<h2>Methods</h2>
<h3>checkIsInClient(padding = 0)</h3>
<blockquote>
<p>v0.10.4+</p>
</blockquote>
<ul>
<li><code>padding</code>: Number, The size of the area extending around the canvas</li>
</ul>
<p>Determine whether the node is within the visible area of the canvas.</p>
<h3>deactivate()</h3>
<blockquote>
<p>0.9.11+</p>

View File

@@ -78,16 +78,25 @@ import('simple-mind-map/src/plugins/Export.js').then(res => {
})
```
If you need a file in the format of `umd` module, such as `CDN` in the browser, Then you can find the `simpleMindMap.umd.min.js` file and `simpleMindMap.css` file in the `/simple-mind-map/dist/` directory, copy it to your project, and then import it into the page:
If you need a file in the format of `umd` module, such as `CDN` in the browser, So you can first install `npm i simple-mind-map` through npm,, Then you can find the `simpleMindMap.umd.min.js` file and `simpleMindMap.esm.min.css` file in the `node_modules/simple-mind-map/dist/` directory, copy it to your project, and then import it into the page:
```html
<link rel="stylesheet" href="simpleMindMap.css">
<link rel="stylesheet" href="simpleMindMap.esm.min.css">
<script scr="simpleMindMap.umd.min.js"></script>
```
A global variable `window.simpleMindMap` will be created. you can get `MindMap` constructor by `window.simpleMindMap.default`, for more detail info you can log `window.simpleMindMap`.
A global variable `window.simpleMindMap` will be created. you can get `MindMap` constructor by `window.simpleMindMap.default`, Then it can be instantiated normally, for more detail info you can log `window.simpleMindMap`.
The disadvantage of this method is that it will contain all the content, including the plugins you have not registered, so the overall volume will be relatively large.
If it is inconvenient to install using 'npm', you can also obtain these two files through some online 'CDN' services, such as:
```
https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.esm.css
https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.umd.min.js
```
You can replace the version number in it.
The disadvantage of this method is that it will contain all the content, including the plugins you have not registered(You can find it here [full.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/full.js#L36) View plugins packaged into files by default), so the overall volume will be relatively large. If you only want to package the specified plugin, you can modify the file and repackage it. If necessary, you can also contact the developer.
v0.5.4+If you want to use the `ES` module directly on the browser side, you can find the `simpleMindMap.esm.js` and `simpleMindMap.esm.css` files in the `/simple-mind-map/dist/` directory.
@@ -216,7 +225,7 @@ The browser uses API [window.showOpenFilePicker](https://developer.mozilla.org/z
This is because your build environment does not support this JavaScript syntax, which comes from the '@svgdotjs/svg.js' library. The solution is as follows:
1.Manually reduce the version of the '@svgdotjs/svg.js' library. You can manually install the lower version in your project, such as: `npm i @svgdotjs/svg.js@3.0.16`
1.Manually reduce the version of the '@svgdotjs/svg.js' library. You can manually install the lower version in your project, such as: `npm i @svgdotjs/svg.js@3.2.0`
2.If you don't reduce the version, you can modify the relevant configuration of your build tool, modify the configuration of 'babel', and have it compile the 'simple-mind-map' library in 'node.modules' or the '@svgdotjs/svg.js' library. If you are using 'vue-cli' or 'vite', they also provide the relevant configuration directly. In addition, it is necessary to install the 'babel' plugin that compiles this syntax and configure it in the 'babel' configuration file:

View File

@@ -1,6 +1,157 @@
<template>
<div>
<h1>Start</h1>
<h2>Installation</h2>
<blockquote>
<p>Things to note before version 0.2.0:</p>
</blockquote>
<pre class="hljs"><code>npm i simple-mind-map
</code></pre>
<p><code>0.2.0</code> Notes for previous versions:</p>
<blockquote>
<p>Note: This project is directly published in source code form and has not been
packaged. If compilation fails, a Vue CLI-created project can add the
following configuration to the vue.config.js file to allow babel-loader to
compile this dependency:</p>
<pre class="hljs"><code><span class="hljs-built_in">module</span>.exports = {
<span class="hljs-attr">transpileDependencies</span>: [<span class="hljs-string">&quot;simple-mind-map&quot;</span>],
};
</code></pre>
<p>Other projects should modify the packaging configuration as needed.</p>
</blockquote>
<h2>Usage</h2>
<blockquote>
<p>The <code>web</code> directory of this repository provides a complete project based on <code>Vue2</code>. If you encounter any doubts about using it, you can refer to the implementation of this project.</p>
</blockquote>
<blockquote>
<p>To learn about its use in other frameworks, you can refer to the following unofficial implementations:</p>
<p>1.<a href="https://github.com/huangyuanyin/hyy-vue3-mindMap">https://github.com/huangyuanyin/hyy-vue3-mindMap</a>: A mind map based on Vue3.2+ElementPlus.</p>
</blockquote>
<p>Firstly, provide a container element with a width and height not equal to 0:</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;mindMapContainer&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Also, set the <code>CSS</code> style again:</p>
<pre class="hljs"><code><span class="hljs-selector-id">#mindMapContainer</span> * {
<span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}
</code></pre>
<p>Then introduce the <code>simple-mind-map</code> library and create an instance:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;simple-mind-map&quot;</span>;
<span class="hljs-keyword">const</span> mindMap = <span class="hljs-keyword">new</span> MindMap({
<span class="hljs-attr">el</span>: <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">&#x27;mindMapContainer&#x27;</span>),
<span class="hljs-attr">data</span>: {
<span class="hljs-string">&quot;data&quot;</span>: {
<span class="hljs-string">&quot;text&quot;</span>: <span class="hljs-string">&quot;Root Node&quot;</span>
},
<span class="hljs-string">&quot;children&quot;</span>: []
}
});
</code></pre>
<p>This will result in a mind map.</p>
<p>If you want to implement a complete mind map, you usually need to develop some UI interfaces to achieve more functions through the interfaces provided by the <code>simple-mind-map</code> library.</p>
<p><code>simple-mind-map</code> supports rich configurations, events, commands, and some additional plugin extensions. Read the subsequent documentation to learn more.</p>
<p>The non-packaged 'ES' module is introduced by default, and only contains core functions, not unregistered plugin content, which can effectively reduce the size. However, you need to configure the <code>babel</code> compilation <code>simple mind-map</code> in your project to prevent some newer <code>js</code> syntax some browsers not supporting it.</p>
<p>If you don't want to load all plugins from the beginning and want to load and register plugins asynchronously after instantiation, you can do this:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span>(<span class="hljs-string">&#x27;simple-mind-map/src/plugins/Export.js&#x27;</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
mindMap.addPlugin(res.default)
})
</code></pre>
<p>If you need a file in the format of <code>umd</code> module, such as <code>CDN</code> in the browser, So you can first install <code>npm i simple-mind-map</code> through npm,, Then you can find the <code>simpleMindMap.umd.min.js</code> file and <code>simpleMindMap.esm.min.css</code> file in the <code>node_modules/simple-mind-map/dist/</code> directory, copy it to your project, and then import it into the page:</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;simpleMindMap.esm.min.css&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">scr</span>=<span class="hljs-string">&quot;simpleMindMap.umd.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>A global variable <code>window.simpleMindMap</code> will be created. you can get <code>MindMap</code> constructor by <code>window.simpleMindMap.default</code>, Then it can be instantiated normally, for more detail info you can log <code>window.simpleMindMap</code>.</p>
<p>If it is inconvenient to install using 'npm', you can also obtain these two files through some online 'CDN' services, such as:</p>
<pre class="hljs"><code>https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.esm.css
https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.umd.min.js
</code></pre>
<p>You can replace the version number in it.</p>
<p>The disadvantage of this method is that it will contain all the content, including the plugins you have not registered(You can find it here <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/full.js#L36">full.js</a> View plugins packaged into files by default), so the overall volume will be relatively large. If you only want to package the specified plugin, you can modify the file and repackage it. If necessary, you can also contact the developer.</p>
<p>v0.5.4+If you want to use the <code>ES</code> module directly on the browser side, you can find the <code>simpleMindMap.esm.js</code> and <code>simpleMindMap.esm.css</code> files in the <code>/simple-mind-map/dist/</code> directory.</p>
<p>Online CDN services can also be used, such as:</p>
<pre class="hljs"><code>https://unpkg.com/browse/simple-mind-map@0.9.2/dist/
</code></pre>
<p>You can find all the packaged files for a certain version.</p>
<h2>Development</h2>
<p>If you only use library, you don't need to read this section.</p>
<h3>Local Development</h3>
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
<span class="hljs-built_in">cd</span> mind-map
<span class="hljs-built_in">cd</span> simple-mind-map
npm i
npm link
<span class="hljs-built_in">cd</span> ..
<span class="hljs-built_in">cd</span> web
npm i
npm link simple-mind-map
npm run serve
</code></pre>
<blockquote>
<p>If there is an installation dependency error, you can try adjusting the node version. The author is using version 14. x.</p>
</blockquote>
<h3>Packaging the Library</h3>
<p>Since version <code>0.2.0</code>, we have added support for packaging the core library
simple-mind-map. This uses the same packaging tool as the sample project web.</p>
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
npm run buildLibrary
</code></pre>
<p>The packaging entry is <code>simple-mind-map/full.js</code>, which will introduce all plugins by default. If you don't need all plugins, you can modify the file to only introduce the plugins you need, which can reduce the size of the packaged file.</p>
<p>The <code>package.json</code> file in the <code>simple-mind-map</code> library provides two export
fields:</p>
<pre class="hljs"><code>{
<span class="hljs-attr">&quot;module&quot;</span>: <span class="hljs-string">&quot;index.js&quot;</span>,
<span class="hljs-attr">&quot;main&quot;</span>: <span class="hljs-string">&quot;./dist/simpleMindMap.umd.min.js&quot;</span>
}
</code></pre>
<p>Environments that support the <code>module</code> field will use <code>index.js</code> as the entry
point, otherwise the packed <code>simpleMindMap.umd.min.js</code> will be used as the entry
point.</p>
<h4>Generate TypeScript type files</h4>
<pre class="hljs"><code><span class="hljs-built_in">cd</span> simple-mind-map
npm run types
</code></pre>
<p>You can obtain the type files in the 'simple-mind-map/types/' directory.</p>
<h3>Compile the doc</h3>
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
npm run buildDoc
</code></pre>
<h3>Packaging the Demo</h3>
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
npm run build
</code></pre>
<p>The <code>index.html</code> file will be automatically moved to the root directory.</p>
<h2>Problems</h2>
<h3>Error when using in Vite, indicating xml-js dependency error</h3>
<p>Solution: use the following import method:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;simple-mind-map/dist/simpleMindMap.umd.min&quot;</span>;
</code></pre>
<p>The <code>simple-mind-map</code> package provides the unpacked entry field <code>module</code>, and
the <code>xml-js</code> package dependency needs to import the package in the <code>node</code>
environment. Therefore, it cannot be obtained in <code>Vite</code> and an error will be
reported. Therefore, specify the import of the packed entry, and all relevant
packages are packed into the product, so there will be no error.</p>
<p>If you need to do further development, that is, you must use the unpacked code,
and if you do not need to parse the <code>xmind</code> file, you can remove the <code>xmind</code>
module. If you need it, you can try using other libraries to parse <code>xml</code> to
<code>json</code>.</p>
<h3>Error <code>Getting bbox of element &quot;text&quot; is not possible: TypeError: Cannot read properties of undefined (reading 'apply')</code></h3>
<p>The reason is that the installed version of <code>@svgdotjs/svg.js</code> is too high. You can manually reduce it to the version of <code>3.0.16</code>.</p>
<h3>TypeError: Cannot read properties of undefined (reading 'prototype') at sax.js:222:46</h3>
<p>The following configurations can be added to the packaging configuration file:</p>
<pre class="hljs"><code>resolve: { <span class="hljs-attr">alias</span>: { <span class="hljs-attr">stream</span>: <span class="hljs-string">&quot;stream-browserify&quot;</span> } }
</code></pre>
<p>Different packaging tools may have different specific configurations, with the principle of excluding 'stream' dependencies.</p>
<h3>When clicking the [New], [Open], or [Save As] buttons, it will prompt that the browser does not support it or is not using the HTTPS protocol.</h3>
<p>The browser uses API <a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Window/showOpenFilePicker">window.showOpenFilePicker</a> to operate local files on the computer. If it is not supported, either the browser does not support this API or the page is not using the HTTPS protocol, You can press F12, or open the browser console through the right-click menu on the page and enter 'window.showOpenFilePicker' in the 'Console' tab. If it returns 'undefined', it means it is not supported. If it does not return this message and the page still prompts that the browser does not support it or is not using the HTTPS protocol, you can submit an issue or contact the author.</p>
<h3>5.Import simple-mind-map error message, the error message is as follows:</h3>
<img src="../../../../assets/img/docs/错误.jpg" style="width: 850px" />
<p>This is because your build environment does not support this JavaScript syntax, which comes from the '@svgdotjs/svg.js' library. The solution is as follows:</p>
<p>1.Manually reduce the version of the '@svgdotjs/svg.js' library. You can manually install the lower version in your project, such as: <code>npm i @svgdotjs/svg.js@3.2.0</code></p>
<p>2.If you don't reduce the version, you can modify the relevant configuration of your build tool, modify the configuration of 'babel', and have it compile the 'simple-mind-map' library in 'node.modules' or the '@svgdotjs/svg.js' library. If you are using 'vue-cli' or 'vite', they also provide the relevant configuration directly. In addition, it is necessary to install the 'babel' plugin that compiles this syntax and configure it in the 'babel' configuration file:</p>
<p><code>@babel/plugin-proposal-nullish-coalescing-operator</code><code>@babel/plugin-proposal-optional-chaining</code></p>
</div>
</template>

View File

@@ -298,7 +298,7 @@ Focus and select all specified input boxes.
Adding additional data to the specified node list tree data will modify the original data.
#### createUidForAppointNodes(appointNodes, createNewId)
#### createUidForAppointNodes(appointNodes, createNewId, handle)
> v0.7.2+
@@ -306,6 +306,8 @@ Adding additional data to the specified node list tree data will modify the orig
- `createNewId`v0.7.3-fix.1+, `Boolean`, default is `false`, If the node does not have a 'uid', a new 'uid' will be created. If 'true' is passed, a new 'uid' will be created regardless of whether the node data originally exists or not`
- `handle`v0.10.5+, `null、Function`, default is `null`, You can pass a function that will be called when traversing each node, with the callback parameter being the current node being traversed.
Adding a uid to the specified node list tree data (if the uid does not exist) will modify the original data.
#### getNodeIndex(node)

View File

@@ -235,7 +235,7 @@ and copying the <code>data</code> of the data object, example:</p>
</li>
</ul>
<p>Adding additional data to the specified node list tree data will modify the original data.</p>
<h4>createUidForAppointNodes(appointNodes, createNewId)</h4>
<h4>createUidForAppointNodes(appointNodes, createNewId, handle)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
@@ -246,6 +246,9 @@ and copying the <code>data</code> of the data object, example:</p>
<li>
<p><code>createNewId</code>v0.7.3-fix.1+, <code>Boolean</code>, default is <code>false</code>, If the node does not have a 'uid', a new 'uid' will be created. If 'true' is passed, a new 'uid' will be created regardless of whether the node data originally exists or not`</p>
</li>
<li>
<p><code>handle</code>v0.10.5+, <code>null、Function</code>, default is <code>null</code>, You can pass a function that will be called when traversing each node, with the callback parameter being the current node being traversed.</p>
</li>
</ul>
<p>Adding a uid to the specified node list tree data (if the uid does not exist) will modify the original data.</p>
<h4>getNodeIndex(node)</h4>

View File

@@ -55,6 +55,12 @@ MindMap.usePlugin(AssociativeLine)
## 方法
### cancelCreateLine()
> v0.10.5+
中途取消创建关联线。
### renderAllLines()
重新渲染所有关联线。

View File

@@ -49,6 +49,11 @@ MindMap.usePlugin(AssociativeLine)
<h3>mindMap.associativeLine.activeLine</h3>
<p>当前激活的连接线数组类型<code>lineList</code>数组的每一项的结构</p>
<h2>方法</h2>
<h3>cancelCreateLine()</h3>
<blockquote>
<p>v0.10.5+</p>
</blockquote>
<p>中途取消创建关联线</p>
<h3>renderAllLines()</h3>
<p>重新渲染所有关联线</p>
<h3>removeAllLines()</h3>

View File

@@ -1,5 +1,47 @@
# Changelog
## 0.10.5
> 2024.8.2
修复:
> 1.修复开启滚动条插件和性能模式后拖动滚动条报错的问题;
>
> 2.修复跨层级复制节点时,节点的富文本样式没有更新的问题;
>
> 3.修复开启性能模式后,演示插件无法正常工作的问题;
>
> 4.修复画布尺寸调整后第一次触发渲染画布会发生跳动的问题;
新增:
> 1.移动节点且节点层级发生了改变,设置过自定义富文本样式的节点不需要更新样式;
>
> 2.支持点击画布取消创建关联线;
>
> 3.移动节点或复制节点到收起的节点上自动展开该节点;
Demo
> 1.节点下级数量大于100时收起按钮显示省略号
>
> 2.打开本地文件编辑的情况下不再将数据写入浏览器缓存,避免因触发存储限制导致本地文件数据丢失的问题;
>
> 3.编辑本地文件时如果未保存关闭页面增加拦截提示;
>
> 4.修复大纲里点击节点进行拖拽会触发页面的文件拖拽蒙层的问题;
## 0.10.4
> 2024.7.25
本次更新主要是增加了一个性能模式开启后只会渲染画布可视区域内的节点超出区域的节点会从画布删除提升大数据量1000+节点情况下的可用性2000节点首次渲染时间由5s+减少到0.5s,当然由此也会带来一些问题,比如拖动画布时会有一点卡顿,因为会实时渲染节点,导出图片等会变慢,因为需要先渲染所有节点,以及其他一些暂时未发现的问题。
修复:
> 1.删除无用代码,修复鼠标悬浮节点上报错不显示展开收起按钮的问题;
## 0.10.3
> 2024.7.19

View File

@@ -1,6 +1,39 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.10.5</h2>
<blockquote>
<p>2024.8.2</p>
</blockquote>
<p>修复</p>
<blockquote>
<p>1.修复开启滚动条插件和性能模式后拖动滚动条报错的问题</p>
<p>2.修复跨层级复制节点时节点的富文本样式没有更新的问题</p>
<p>3.修复开启性能模式后演示插件无法正常工作的问题</p>
<p>4.修复画布尺寸调整后第一次触发渲染画布会发生跳动的问题</p>
</blockquote>
<p>新增</p>
<blockquote>
<p>1.移动节点且节点层级发生了改变设置过自定义富文本样式的节点不需要更新样式</p>
<p>2.支持点击画布取消创建关联线</p>
<p>3.移动节点或复制节点到收起的节点上自动展开该节点</p>
</blockquote>
<p>Demo</p>
<blockquote>
<p>1.节点下级数量大于100时收起按钮显示省略号</p>
<p>2.打开本地文件编辑的情况下不再将数据写入浏览器缓存避免因触发存储限制导致本地文件数据丢失的问题</p>
<p>3.编辑本地文件时如果未保存关闭页面增加拦截提示</p>
<p>4.修复大纲里点击节点进行拖拽会触发页面的文件拖拽蒙层的问题</p>
</blockquote>
<h2>0.10.4</h2>
<blockquote>
<p>2024.7.25</p>
</blockquote>
<p>本次更新主要是增加了一个性能模式开启后只会渲染画布可视区域内的节点超出区域的节点会从画布删除提升大数据量1000+节点情况下的可用性2000节点首次渲染时间由5s+减少到0.5s当然由此也会带来一些问题比如拖动画布时会有一点卡顿因为会实时渲染节点导出图片等会变慢因为需要先渲染所有节点以及其他一些暂时未发现的问题</p>
<p>修复</p>
<blockquote>
<p>1.删除无用代码修复鼠标悬浮节点上报错不显示展开收起按钮的问题</p>
</blockquote>
<h2>0.10.3</h2>
<blockquote>
<p>2024.7.19</p>

View File

@@ -99,6 +99,8 @@ const mindMap = new MindMap({
| createNodePostfixContentv0.9.12+ | Function、null | null | 添加附加的节点后置内容。后置内容指和文本同一行的区域中的后置内容不包括节点图片部分。用法同createNodePrefixContent |
| disabledClipboardv0.10.2+ | Boolean | false | 是否禁止粘贴用户剪贴板中的数据,禁止将复制的节点数据写入用户的剪贴板中,此时只能复制和粘贴画布内的节点数据 |
| customHyperlinkJumpv0.10.2+ | null、Function | false | 自定义超链接的跳转。如果不传默认会以新窗口的方式打开超链接可以传递一个函数函数接收两个参数link超链接的url、node所属节点实例只要传递了函数就会阻止默认的跳转 |
| openPerformancev0.10.4+ | Boolean | false | 是否开启性能模式默认情况下所有节点都会直接渲染无论是否处于画布可视区域这样当节点数量比较多时1000+会比较卡如果你的数据量比较大那么可以通过该配置开启性能模式即只渲染画布可视区域内的节点超出的节点不渲染这样会大幅提高渲染速度当然同时也会带来一些其他问题比如1.当拖动或是缩放画布时会实时计算并渲染未节点的节点所以会带来一定卡顿2.导出图片、svg、pdf时需要先渲染全部节点所以会比较慢3.其他目前未发现的问题 |
| performanceConfigv0.10.4+ | Object | { time: 250, padding: 100, removeNodeWhenOutCanvas: true } | 性能优化模式配置。time当视图改变后多久刷新一次节点单位ms、padding超出画布四周指定范围内依旧渲染节点、removeNodeWhenOutCanvas节点移出画布可视区域后是否从画布删除 |
#### 1.1数据结构
@@ -617,6 +619,8 @@ mindMap.setTheme('主题名称')
| node_layout_endv0.10.1+ | 单个节点内容布局完成的事件 | this(当前节点实例) |
| node_attachmentClickv0.9.10+ | 节点附件图标的点击事件 | this(当前节点实例)、e事件对象、node图标节点 |
| node_attachmentContextmenuv0.9.10+ | 节点附件图标的右键点击事件 | this(当前节点实例)、e事件对象、node图标节点 |
| before_update_configv0.10.4+ | 更新配置前触发,即当调用了`mindMap.updateConfig`方法更新配置时触发 | opt未更新前的配置对象引用对象而非拷贝所以当after_update_config事件触发后该对象也会同步变化所以需要缓存你需要的某个配置字段 |
| after_update_configv0.10.4+ | 更新配置后触发 | opt更新后的配置对象 |
### emit(event, ...args)

View File

@@ -466,6 +466,18 @@
<td>false</td>
<td>自定义超链接的跳转如果不传默认会以新窗口的方式打开超链接可以传递一个函数函数接收两个参数link超链接的urlnode所属节点实例只要传递了函数就会阻止默认的跳转</td>
</tr>
<tr>
<td>openPerformancev0.10.4+</td>
<td>Boolean</td>
<td>false</td>
<td>是否开启性能模式默认情况下所有节点都会直接渲染无论是否处于画布可视区域这样当节点数量比较多时1000+会比较卡如果你的数据量比较大那么可以通过该配置开启性能模式即只渲染画布可视区域内的节点超出的节点不渲染这样会大幅提高渲染速度当然同时也会带来一些其他问题比如1.当拖动或是缩放画布时会实时计算并渲染未节点的节点所以会带来一定卡顿2.导出图片svgpdf时需要先渲染全部节点所以会比较慢3.其他目前未发现的问题</td>
</tr>
<tr>
<td>performanceConfigv0.10.4+</td>
<td>Object</td>
<td>{ time: 250, padding: 100, removeNodeWhenOutCanvas: true }</td>
<td>性能优化模式配置time当视图改变后多久刷新一次节点单位mspadding超出画布四周指定范围内依旧渲染节点removeNodeWhenOutCanvas节点移出画布可视区域后是否从画布删除</td>
</tr>
</tbody>
</table>
<h4>1.1数据结构</h4>
@@ -1609,6 +1621,16 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
<td>节点附件图标的右键点击事件</td>
<td>this(当前节点实例)e事件对象node图标节点</td>
</tr>
<tr>
<td>before_update_configv0.10.4+</td>
<td>更新配置前触发即当调用了<code>mindMap.updateConfig</code>方法更新配置时触发</td>
<td>opt未更新前的配置对象引用对象而非拷贝所以当after_update_config事件触发后该对象也会同步变化所以需要缓存你需要的某个配置字段</td>
</tr>
<tr>
<td>after_update_configv0.10.4+</td>
<td>更新配置后触发</td>
<td>opt更新后的配置对象</td>
</tr>
</tbody>
</table>
<h3>emit(event, ...args)</h3>

View File

@@ -76,9 +76,11 @@
## 特别说明
本项目可用于学习和参考,用于实际项目时请先深度体验一下是否能满足您的需求。
本项目用于实际项目时请先深度体验一下是否能满足您的需求。
本项目可能没有完整测试到每一个功能点,所以可能存在bug另外当节点数量非常多的时候性能也存在一些问题因为每个人能接受的卡顿程度不一样所以你可以自行测试节点数量上限。一般来说500个节点以内比较流畅1000个节点以上卡顿比较明显。
本项目可能没有完整测试到每一个功能点可能存在bug另外当节点数量非常多的时候性能也存在一些问题因为每个人能接受的卡顿程度不一样所以你可以自行测试节点数量上限。一般来说500个节点以内比较流畅1000个节点以上卡顿比较明显。
在v0.10.4+版本新增了性能模式,只渲染画布可视区域内的节点,可以提升大数据量下的渲染速度,可以通过开启`openPerformance`实例化选项进行体验在线Demo里可以通过打开【基础样式】-【开启性能模式】开关进行体验。
如果有建议或发现了bug可以在此提交[issues](https://github.com/wanglin2/mind-map/issues)。
@@ -100,7 +102,7 @@
这些开源的思维导图也都不错,各有各的特点,但是它们也都有一定缺点,比如停止更新、界面美观度一般、功能比较少、依赖某个框架等等。
综上,在开源的思维导图中,你很难找到一个比`simple-mind-map`更好的选择。当然,`simple-mind-map`也远远谈不上最好,它也有很多不足,如你在前面的【特别说明】所看到的那样,不过`simple-mind-map`一直处于快速迭代中,欢迎你加入进来一起完善它。
综上,在开源的思维导图中,你很难找到一个比`simple-mind-map`更好的选择。当然,`simple-mind-map`也远远谈不上最好,它也有很多不足,不过`simple-mind-map`一直处于快速迭代中,欢迎你加入进来一起完善它。
## 浏览器兼容性
@@ -118,11 +120,13 @@
# 微信交流群
群聊人数较多,无法通过二维码入群,可以微信添加`wanglinguanfang`拉你入群。思维导图相关问题皆可在群里提问,不必私聊作者。
一群已满,可以扫描如下二维码进入二群,如已过期,可以微信添加`wanglinguanfang`拉你入群。思维导图相关问题皆可在群里提问,不必私聊作者。
<img src="../../../../../../qrcode.jpg" style="width: 300px" />
## 请作者喝杯咖啡
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡~
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡,你的支持是开发者持续维护的最大动力~
> 推荐使用支付宝,微信获取不到头像。转账请备注【思维导图】。
@@ -446,4 +450,22 @@
<img src="../../../../assets/avatar/晴空.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>晴空</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>黄泳</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/ccccs.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>ccccs</p>
</div>
</div>
<div style="display: flex;">
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/。.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>。</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/Jeffrey.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>Jeffrey</p>
</div>
</div>

View File

@@ -8,18 +8,18 @@
</blockquote>
<h2>特性</h2>
<ul>
<li><input type="checkbox" id="checkbox0" checked="true" /><label for="checkbox0">插件化架构除核心功能外其他功能作为插件提供按需使用减小打包体积</label></li>
<li><input type="checkbox" id="checkbox1" checked="true" /><label for="checkbox1">支持逻辑结构图向左向右逻辑结构图思维导图组织结构图目录组织图时间轴横向竖向鱼骨图等结构</label></li>
<li><input type="checkbox" id="checkbox2" checked="true" /><label for="checkbox2">内置多种主题允许高度自定义样式支持注册新主题</label></li>
<li><input type="checkbox" id="checkbox3" checked="true" /><label for="checkbox3">节点内容支持文本普通文本富文本图片图标超链接备注标签概要数学公式</label></li>
<li><input type="checkbox" id="checkbox4" checked="true" /><label for="checkbox4">节点支持拖拽拖拽移动自由调整多种节点形状支持扩展节点内容支持使用 DDM 完全自定义节点内容</label></li>
<li><input type="checkbox" id="checkbox5" checked="true" /><label for="checkbox5">支持画布拖动缩放</label></li>
<li><input type="checkbox" id="checkbox6" checked="true" /><label for="checkbox6">支持鼠标按键拖动选择和 Ctrl+左键两种多选节点方式</label></li>
<li><input type="checkbox" id="checkbox7" checked="true" /><label for="checkbox7">支持导出为</label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code><code>txt</code>支持从<code>json</code><code>xmind</code><code>markdown</code>导入</li>
<li><input type="checkbox" id="checkbox8" checked="true" /><label for="checkbox8">支持快捷键前进后退关联线搜索替换小地图水印滚动条手绘风格彩虹线条</label></li>
<li><input type="checkbox" id="checkbox9" checked="true" /><label for="checkbox9">提供丰富的配置满足各种场景各种使用习惯</label></li>
<li><input type="checkbox" id="checkbox10" checked="true" /><label for="checkbox10">支持协同编辑</label></li>
<li><input type="checkbox" id="checkbox11" checked="true" /><label for="checkbox11">支持演示模式</label></li>
<li><input type="checkbox" id="checkbox17" checked="true" /><label for="checkbox17">插件化架构除核心功能外其他功能作为插件提供按需使用减小打包体积</label></li>
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">支持逻辑结构图向左向右逻辑结构图思维导图组织结构图目录组织图时间轴横向竖向鱼骨图等结构</label></li>
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">内置多种主题允许高度自定义样式支持注册新主题</label></li>
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">节点内容支持文本普通文本富文本图片图标超链接备注标签概要数学公式</label></li>
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">节点支持拖拽拖拽移动自由调整多种节点形状支持扩展节点内容支持使用 DDM 完全自定义节点内容</label></li>
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">支持画布拖动缩放</label></li>
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">支持鼠标按键拖动选择和 Ctrl+左键两种多选节点方式</label></li>
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">支持导出为</label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code><code>xmind</code><code>txt</code>支持从<code>json</code><code>xmind</code><code>markdown</code>导入</li>
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">支持快捷键前进后退关联线搜索替换小地图水印滚动条手绘风格彩虹线条</label></li>
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">提供丰富的配置满足各种场景各种使用习惯</label></li>
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">支持协同编辑</label></li>
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">支持演示模式</label></li>
</ul>
<p>官方提供了如下插件可根据需求按需引入某个功能不生效大概率是因为你没有引入对应的插件具体使用方式请查看文档</p>
<blockquote>
@@ -37,11 +37,11 @@
<p>2.<code>web</code></p>
<p>使用<code>simple-mind-map</code>基于<code>vue2.x</code><code>ElementUI</code>搭建的在线思维导图特性</p>
<ul>
<li><input type="checkbox" id="checkbox12" checked="true" /><label for="checkbox12">工具栏支持插入节点删除节点编辑节点图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox13" checked="true" /><label for="checkbox13">侧边栏基础样式设置面板节点样式设置面板大纲面板主题选择面板结构选择面板</label></li>
<li><input type="checkbox" id="checkbox14" checked="true" /><label for="checkbox14">导入导出功能数据默认保存在浏览器本地存储也支持直接创建打开编辑电脑本地文件</label></li>
<li><input type="checkbox" id="checkbox15" checked="true" /><label for="checkbox15">右键菜单支持展开收起整理布局等操作</label></li>
<li><input type="checkbox" id="checkbox16" checked="true" /><label for="checkbox16">底部栏支持节点数量字数统计支持切换编辑和只读模式支持放大缩小支持全屏切换支持小地图</label></li>
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">工具栏支持插入节点删除节点编辑节点图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">侧边栏基础样式设置面板节点样式设置面板大纲面板主题选择面板结构选择面板</label></li>
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">导入导出功能数据默认保存在浏览器本地存储也支持直接创建打开编辑电脑本地文件</label></li>
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">右键菜单支持展开收起整理布局等操作</label></li>
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">底部栏支持节点数量字数统计支持切换编辑和只读模式支持放大缩小支持全屏切换支持小地图</label></li>
</ul>
<p>提供文档页面服务</p>
<p>3.<code>dist</code></p>
@@ -56,8 +56,9 @@
<p><a href="https://juejin.cn/post/7287913415803764747">dom-to-image库是如何将html转换成图片的</a></p>
<p><a href="https://juejin.cn/post/7295669711533998117">两天实现思维导图的协同编辑用Yjs真的可以</a></p>
<h2>特别说明</h2>
<p>本项目可用于学习和参考用于实际项目时请先深度体验一下是否能满足您的需求</p>
<p>本项目可能没有完整测试到每一个功能点所以可能存在bug另外当节点数量非常多的时候性能也存在一些问题因为每个人能接受的卡顿程度不一样所以你可以自行测试节点数量上限一般来说500个节点以内比较流畅1000个节点以上卡顿比较明显</p>
<p>本项目用于实际项目时请先深度体验一下是否能满足您的需求</p>
<p>本项目可能没有完整测试到每一个功能点可能存在bug另外当节点数量非常多的时候性能也存在一些问题因为每个人能接受的卡顿程度不一样所以你可以自行测试节点数量上限一般来说500个节点以内比较流畅1000个节点以上卡顿比较明显</p>
<p>在v0.10.4+版本新增了性能模式只渲染画布可视区域内的节点可以提升大数据量下的渲染速度可以通过开启<code>openPerformance</code>实例化选项进行体验在线Demo里可以通过打开基础样式-开启性能模式开关进行体验</p>
<p>如果有建议或发现了bug可以在此提交<a href="https://github.com/wanglin2/mind-map/issues">issues</a></p>
<p>项目内置的主题和图标部分来自于<a href="https://naotu.baidu.com/">百度脑图</a><a href="https://www.zhixi.com/">知犀思维导图</a>尊重版权主题和图标请勿直接用于商业项目</p>
<h2>为什么不是</h2>
@@ -68,7 +69,7 @@
<p><code>kityminder-core</code>是百度开发的开源的脑图工具功能很强大性能也很好但是它已经不维护了所以代码比较陈旧界面美观度也比较一般另外bug只能自己修功能只能自己开发对前端开发能力要求比较高</p>
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a><a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a><a href="https://github.com/ondras/my-mind">my-mind</a><a href="https://github.com/awehook/blink-mind">blink-mind</a><a href="https://github.com/luvsic3/remind">remind</a><a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a><a href="https://github.com/zyascend/ZMindMap">ZMindMap</a><a href="https://github.com/RockyRen/mindmaptree">mindmaptree</a>...</p>
<p>这些开源的思维导图也都不错各有各的特点但是它们也都有一定缺点比如停止更新界面美观度一般功能比较少依赖某个框架等等</p>
<p>综上在开源的思维导图中你很难找到一个比<code>simple-mind-map</code>更好的选择当然<code>simple-mind-map</code>也远远谈不上最好它也有很多不足如你在前面的特别说明所看到的那样不过<code>simple-mind-map</code>一直处于快速迭代中欢迎你加入进来一起完善它</p>
<p>综上在开源的思维导图中你很难找到一个比<code>simple-mind-map</code>更好的选择当然<code>simple-mind-map</code>也远远谈不上最好它也有很多不足不过<code>simple-mind-map</code>一直处于快速迭代中欢迎你加入进来一起完善它</p>
<h2>浏览器兼容性</h2>
<p>推荐使用最新版<code>chrome</code>浏览器</p>
<p>有限测试情况</p>
@@ -77,9 +78,10 @@
<h2>License</h2>
<p><a href="https://github.com/wanglin2/mind-map/blob/main/LICENSE">MIT</a>保留<code>mind-map</code>版权声明的情况下可随意商用如不想保留可联系作者</p>
<h1>微信交流群</h1>
<p>群聊人数较多无法通过二维码入群可以微信添加<code>wanglinguanfang</code>拉你入群思维导图相关问题皆可在群里提问不必私聊作者</p>
<p>一群已满可以扫描如下二维码进入二群如已过期可以微信添加<code>wanglinguanfang</code>拉你入群思维导图相关问题皆可在群里提问不必私聊作者</p>
<img src="../../../../../../qrcode.jpg" style="width: 300px" />
<h2>请作者喝杯咖啡</h2>
<p>开源不易如果本项目有帮助到你的话可以考虑请作者喝杯咖啡~</p>
<p>开源不易如果本项目有帮助到你的话可以考虑请作者喝杯咖啡你的支持是开发者持续维护的最大动力~</p>
<blockquote>
<p>推荐使用支付宝微信获取不到头像转账请备注思维导图</p>
</blockquote>
@@ -400,8 +402,25 @@
<img src="../../../../assets/avatar/晴空.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>晴空</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/default.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>黄泳</p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/ccccs.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>ccccs</p>
</div>
</div>
<div style="display: flex;">
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/。.png" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p></p>
</div>
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
<img src="../../../../assets/avatar/Jeffrey.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
<p>Jeffrey</p>
</div>
</div>
</div>
</template>

View File

@@ -56,6 +56,14 @@
## 方法
### checkIsInClient(padding = 0)
> v0.10.4+
- `padding`: Number, 向画布四周延伸的区域大小
判断节点是否处于画布可视区域。
### deactivate()
> 0.9.11+

View File

@@ -31,6 +31,14 @@
</blockquote>
<p>节点是否正在拖拽中</p>
<h2>方法</h2>
<h3>checkIsInClient(padding = 0)</h3>
<blockquote>
<p>v0.10.4+</p>
</blockquote>
<ul>
<li><code>padding</code>: Number, 向画布四周延伸的区域大小</li>
</ul>
<p>判断节点是否处于画布可视区域</p>
<h3>deactivate()</h3>
<blockquote>
<p>0.9.11+</p>

View File

@@ -73,16 +73,25 @@ import('simple-mind-map/src/plugins/Export.js').then(res => {
})
```
如果你需要`umd`模块格式的文件,比如以`CDN`的方式在浏览器上使用,那么你可以`/simple-mind-map/dist/`目录中找到`simpleMindMap.umd.min.js`文件和`simpleMindMap.css`文件,复制到你的项目中,然后在页面中引入:
如果你需要`umd`模块格式的文件,比如以`CDN`的方式在浏览器上使用,那么你可以先通过npm安装`npm i simple-mind-map`,然后在`node_modules/simple-mind-map/dist/`目录中找到`simpleMindMap.umd.min.js`文件和`simpleMindMap.esm.min.css`文件,复制到你的项目中,然后在页面中引入:
```html
<link rel="stylesheet" href="simpleMindMap.css">
<link rel="stylesheet" href="simpleMindMap.esm.min.css">
<script scr="simpleMindMap.umd.min.js"></script>
```
会创建一个全局变量`window.simpleMindMap`,可以通过`window.simpleMindMap.default`获取到`MindMap`构造函数,详细信息可以把`window.simpleMindMap`打印出来看一下。
会创建一个全局变量`window.simpleMindMap`,可以通过`window.simpleMindMap.default`获取到`MindMap`构造函数,然后正常实例化即可,详细信息可以把`window.simpleMindMap`打印出来看一下。
这种方式的缺点是会包含所有的内容,包括你没有注册的插件,所以整体体积会比较大。
如果不方便使用`npm`来安装,也可以通过一些在线`CDN`服务来获取到这两个文件,比如:
```
https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.esm.css
https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.umd.min.js
```
你可以替换其中的版本号。
这种方式的缺点是会包含所有的内容,包括你没有注册的插件(可以在这里[full.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/full.js#L36)查看默认打包进文件的插件),所以整体体积会比较大,如果只想要打包指定的插件,你可以修改该文件,然后重新打包,如有需要也可以联系开发者。
v0.5.4+)如果你想直接在浏览器端通过`ES`模块的方式来使用,你可以在`/simple-mind-map/dist/`目录中找到`simpleMindMap.esm.js``simpleMindMap.esm.css`文件。
@@ -200,7 +209,7 @@ resolve: { alias: { stream: "stream-browserify" } }
这是因为你的构建环境不支持该js语法该语法出自`@svgdotjs/svg.js`库,解决方法如下:
1.手动降低`@svgdotjs/svg.js`库的版本,你可以在你的项目中手动安装低版本,比如:`npm i @svgdotjs/svg.js@3.0.16`
1.手动降低`@svgdotjs/svg.js`库的版本,你可以在你的项目中手动安装低版本,比如:`npm i @svgdotjs/svg.js@3.2.0`
2.不降低版本的话,可以通过修改你的构建工具的相关配置,修改`babel`的配置,让它编译一下`node_modules`中的`simple-mind-map`库,或`@svgdotjs/svg.js`库,如果用的是`vue-cli``vite`,它们也直接提供了相关配置。另外需要安装编译该语法的`babel`插件,并且配置到`babel`的配置文件中:

View File

@@ -52,12 +52,17 @@
mindMap.addPlugin(res.default)
})
</code></pre>
<p>如果你需要<code>umd</code>模块格式的文件比如以<code>CDN</code>的方式在浏览器上使用那么你可以<code>/simple-mind-map/dist/</code>目录中找到<code>simpleMindMap.umd.min.js</code>文件和<code>simpleMindMap.css</code>文件复制到你的项目中然后在页面中引入</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;simpleMindMap.css&quot;</span>&gt;</span>
<p>如果你需要<code>umd</code>模块格式的文件比如以<code>CDN</code>的方式在浏览器上使用那么你可以先通过npm安装<code>npm i simple-mind-map</code>然后在<code>node_modules/simple-mind-map/dist/</code>目录中找到<code>simpleMindMap.umd.min.js</code>文件和<code>simpleMindMap.esm.min.css</code>文件复制到你的项目中然后在页面中引入</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;simpleMindMap.esm.min.css&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">scr</span>=<span class="hljs-string">&quot;simpleMindMap.umd.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>会创建一个全局变量<code>window.simpleMindMap</code>可以通过<code>window.simpleMindMap.default</code>获取到<code>MindMap</code>构造函数详细信息可以把<code>window.simpleMindMap</code>打印出来看一下</p>
<p>这种方式的缺点是会包含所有的内容包括你没有注册的插件所以整体体积会比较大</p>
<p>会创建一个全局变量<code>window.simpleMindMap</code>可以通过<code>window.simpleMindMap.default</code>获取到<code>MindMap</code>构造函数然后正常实例化即可详细信息可以把<code>window.simpleMindMap</code>打印出来看一下</p>
<p>如果不方便使用<code>npm</code>来安装也可以通过一些在线<code>CDN</code>服务来获取到这两个文件比如</p>
<pre class="hljs"><code>https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.esm.css
https://unpkg.com/simple-mind-map@0.10.2/dist/simpleMindMap.umd.min.js
</code></pre>
<p>你可以替换其中的版本号</p>
<p>这种方式的缺点是会包含所有的内容包括你没有注册的插件可以在这里<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/full.js#L36">full.js</a>查看默认打包进文件的插件所以整体体积会比较大如果只想要打包指定的插件你可以修改该文件然后重新打包如有需要也可以联系开发者</p>
<p>v0.5.4+如果你想直接在浏览器端通过<code>ES</code>模块的方式来使用你可以在<code>/simple-mind-map/dist/</code>目录中找到<code>simpleMindMap.esm.js</code><code>simpleMindMap.esm.css</code>文件</p>
<p>也可以使用在线cdn服务比如</p>
<pre class="hljs"><code>https://unpkg.com/browse/simple-mind-map@0.9.2/dist/
@@ -126,7 +131,7 @@ npm run build
<h3>5.引入simple-mind-map报错报错信息如下</h3>
<img src="../../../../assets/img/docs/错误.jpg" style="width: 850px" />
<p>这是因为你的构建环境不支持该js语法该语法出自<code>@svgdotjs/svg.js</code>解决方法如下</p>
<p>1.手动降低<code>@svgdotjs/svg.js</code>库的版本你可以在你的项目中手动安装低版本比如<code>npm i @svgdotjs/svg.js@3.0.16</code></p>
<p>1.手动降低<code>@svgdotjs/svg.js</code>库的版本你可以在你的项目中手动安装低版本比如<code>npm i @svgdotjs/svg.js@3.2.0</code></p>
<p>2.不降低版本的话可以通过修改你的构建工具的相关配置修改<code>babel</code>的配置让它编译一下<code>node_modules</code>中的<code>simple-mind-map</code><code>@svgdotjs/svg.js</code>如果用的是<code>vue-cli</code><code>vite</code>它们也直接提供了相关配置另外需要安装编译该语法的<code>babel</code>插件并且配置到<code>babel</code>的配置文件中</p>
<p><code>@babel/plugin-proposal-nullish-coalescing-operator</code><code>@babel/plugin-proposal-optional-chaining</code></p>

View File

@@ -302,7 +302,7 @@ copyNodeTree({}, node)
给指定的节点列表树数据添加附加数据,会修改原数据。
#### createUidForAppointNodes(appointNodes, createNewId)
#### createUidForAppointNodes(appointNodes, createNewId, handle)
> v0.7.2+
@@ -310,6 +310,8 @@ copyNodeTree({}, node)
- `createNewId`v0.7.3-fix.1+`Boolean`,默认为`false`,即如果节点不存在`uid`的话,会创建新的`uid`。如果传`true`,那么无论节点数据原来是否存在`uid`,都会创建新的`uid`
- `handle`v0.10.5+`null、Function`,默认为`null`,可以传递一个函数,遍历到每个节点时会调用该函数,回调参数为当前遍历到的节点。
给指定的节点列表树数据添加 uid如果 uid 不存在的话),会修改原数据。
#### getNodeIndex(node)

View File

@@ -239,7 +239,7 @@
</li>
</ul>
<p>给指定的节点列表树数据添加附加数据会修改原数据</p>
<h4>createUidForAppointNodes(appointNodes, createNewId)</h4>
<h4>createUidForAppointNodes(appointNodes, createNewId, handle)</h4>
<blockquote>
<p>v0.7.2+</p>
</blockquote>
@@ -250,6 +250,9 @@
<li>
<p><code>createNewId</code>v0.7.3-fix.1+<code>Boolean</code>默认为<code>false</code>即如果节点不存在<code>uid</code>的话会创建新的<code>uid</code>如果传<code>true</code>那么无论节点数据原来是否存在<code>uid</code>都会创建新的<code>uid</code></p>
</li>
<li>
<p><code>handle</code>v0.10.5+<code>nullFunction</code>默认为<code>null</code>可以传递一个函数遍历到每个节点时会调用该函数回调参数为当前遍历到的节点</p>
</li>
</ul>
<p>给指定的节点列表树数据添加 uid如果 uid 不存在的话会修改原数据</p>
<h4>getNodeIndex(node)</h4>

View File

@@ -845,6 +845,20 @@
</div>
<!-- 其他配置 -->
<div class="title noTop">{{ $t('baseStyle.otherConfig') }}</div>
<!-- 配置性能模式 -->
<div class="row">
<div class="rowItem">
<el-checkbox
v-model="config.openPerformance"
@change="
value => {
updateOtherConfig('openPerformance', value)
}
"
>{{ $t('baseStyle.openPerformance') }}</el-checkbox
>
</div>
</div>
<!-- 配置开启自由拖拽 -->
<div class="row">
<div class="rowItem">
@@ -1062,6 +1076,7 @@ export default {
nodeUseLineStyle: false
},
config: {
openPerformance: false,
enableFreeDrag: false,
mousewheelAction: 'zoom',
mousewheelZoomActionReverse: false,
@@ -1244,6 +1259,7 @@ export default {
// 初始化其他配置
initConfig() {
;[
'openPerformance',
'enableFreeDrag',
'mousewheelAction',
'mousewheelZoomActionReverse',

View File

@@ -192,7 +192,8 @@ export default {
state.localConfig.useLeftKeySelectionRightKeyDrag,
isUseHandDrawnLikeStyle: state =>
state.localConfig.isUseHandDrawnLikeStyle,
extraTextOnExport: state => state.extraTextOnExport
extraTextOnExport: state => state.extraTextOnExport,
isDragOutlineTreeNode: state => state.isDragOutlineTreeNode
})
},
watch: {
@@ -412,6 +413,9 @@ export default {
cssText,
height: 30
}
},
expandBtnNumHandler: num => {
return num >= 100 ? '…' : num
}
// createNodePrefixContent: (node) => {
// const el = document.createElement('div')
@@ -578,6 +582,12 @@ export default {
if (hasFileURL) {
this.$bus.$emit('handle_file_url')
}
// api/index.js文件使用
// 当正在编辑本地文件时通过该方法获取最新数据
Vue.prototype.getCurrentData = () => {
const fullData = this.mindMap.getData(true)
return { ...fullData, config: this.mindMapData.config }
}
// 协同测试
this.cooperateTest()
// 销毁
@@ -848,6 +858,7 @@ export default {
// 拖拽文件到页面导入
onDragenter() {
if (this.isDragOutlineTreeNode) return
this.showDragMask = true
},
onDragleave() {
@@ -857,6 +868,7 @@ export default {
this.showDragMask = false
const dt = e.dataTransfer
const file = dt.files && dt.files[0]
if (!file) return
this.$bus.$emit('importFile', file)
}
}

View File

@@ -12,6 +12,8 @@
:expand-on-click-node="false"
:allow-drag="checkAllowDrag"
@node-drop="onNodeDrop"
@node-drag-start="onNodeDragStart"
@node-drag-end="onNodeDragEnd"
@current-change="onCurrentChange"
@mouseenter.native="isInTreArea = true"
@mouseleave.native="isInTreArea = false"
@@ -37,7 +39,7 @@
</template>
<script>
import { mapState } from 'vuex'
import { mapState, mapMutations } from 'vuex'
import {
nodeRichTextToTextWithWrap,
textToNodeRichTextWithWrap,
@@ -91,6 +93,8 @@ export default {
this.$bus.$off('hide_text_edit', this.handleHideTextEdit)
},
methods: {
...mapMutations(['setIsDragOutlineTreeNode']),
handleHideTextEdit() {
if (this.notHandleDataChange) {
this.notHandleDataChange = false
@@ -281,6 +285,14 @@ export default {
})
},
onNodeDragStart() {
this.setIsDragOutlineTreeNode(true)
},
onNodeDragEnd() {
this.setIsDragOutlineTreeNode(false)
},
// 拖拽结束事件
onNodeDrop(data, target, postion) {
this.notHandleDataChange = true

View File

@@ -208,7 +208,8 @@ export default {
},
fileTreeVisible: false,
rootDirName: '',
fileTreeExpand: true
fileTreeExpand: true,
waitingWriteToLocalFile: false
}
},
computed: {
@@ -232,11 +233,13 @@ export default {
this.computeToolbarShowThrottle = throttle(this.computeToolbarShow, 300)
window.addEventListener('resize', this.computeToolbarShowThrottle)
this.$bus.$on('lang_change', this.computeToolbarShowThrottle)
window.addEventListener('beforeunload', this.onUnload)
},
beforeDestroy() {
this.$bus.$off('write_local_file', this.onWriteLocalFile)
window.removeEventListener('resize', this.computeToolbarShowThrottle)
this.$bus.$off('lang_change', this.computeToolbarShowThrottle)
window.removeEventListener('beforeunload', this.onUnload)
},
methods: {
// 计算工具按钮如何显示
@@ -269,11 +272,22 @@ export default {
// 监听本地文件读写
onWriteLocalFile(content) {
clearTimeout(this.timer)
if (fileHandle && this.isHandleLocalFile) {
this.waitingWriteToLocalFile = true
}
this.timer = setTimeout(() => {
this.writeLocalFile(content)
}, 1000)
},
onUnload(e) {
if (this.waitingWriteToLocalFile) {
const msg = '存在未保存的数据'
e.returnValue = msg
return msg
}
},
// 加载本地文件树
async loadFileTreeNode(node, resolve) {
try {
@@ -429,6 +443,7 @@ export default {
// 写入本地文件
async writeLocalFile(content) {
if (!fileHandle || !this.isHandleLocalFile) {
this.waitingWriteToLocalFile = false
return
}
if (!this.isFullDataFile) {
@@ -438,6 +453,7 @@ export default {
const writable = await fileHandle.createWritable()
await writable.write(string)
await writable.close()
this.waitingWriteToLocalFile = false
},
// 创建本地文件

View File

@@ -42,15 +42,15 @@ export default {
dataList: [
{
icon: 'iconstar',
value: 'Github star数量4000+'
value: 'Github star数量5000+'
},
{
icon: 'iconfork',
value: 'Github fork数量500+'
value: 'Github fork数量700+'
},
{
icon: 'iconxiazai',
value: 'npm总下载次数20000+'
value: 'npm总下载次数30000+'
},
{
icon: 'iconteamwork',

View File

@@ -29,7 +29,8 @@ const store = new Vuex.Store({
isSourceCodeEdit: false, // 是否是源码编辑模式
extraTextOnExport: '', // 导出时底部添加的文字
supportHandDrawnLikeStyle: false, // 是否支持设置手绘风格
supportMark: false // 是否支持标记
supportMark: false, // 是否支持标记
isDragOutlineTreeNode: false // 当前是否正在拖拽大纲树的节点
},
mutations: {
// 设置思维导图数据
@@ -84,6 +85,11 @@ const store = new Vuex.Store({
// 设置是否支持标记
setSupportMark(state, data) {
state.supportMark = data
},
// 设置树节点拖拽
setIsDragOutlineTreeNode(state, data) {
state.isDragOutlineTreeNode = data
}
},
actions: {