Compare commits

...

39 Commits

Author SHA1 Message Date
街角小林
b04469649a Merge pull request #145 from clh021/main
add MIT LICENSE
2023-06-08 08:59:04 +08:00
chenlianghong
ee57dbdcc5 add MIT LICENSE 2023-06-07 17:40:47 +08:00
wanglin2
bca744f6fc 更新群二维码 2023-06-06 09:14:18 +08:00
wanglin2
442408dacf 更新群二维码 2023-05-30 08:54:11 +08:00
wanglin2
7297f0a082 更新群二维码 2023-05-23 14:24:29 +08:00
wanglin2
f0d90941fb 合并 2023-05-15 10:26:33 +08:00
wanglin2
830962c044 更新群二维码 2023-05-15 10:25:34 +08:00
wanglin2
eeec71dc65 更新群二维码 2023-05-05 21:48:58 +08:00
wanglin2
9bd87a22f3 更新群二维码 2023-05-05 21:39:43 +08:00
wanglin2
88c9f22a15 Merge branch 'feature' into main 2023-05-05 21:34:40 +08:00
wanglin2
7380fc60d5 打包 2023-05-05 21:34:26 +08:00
wanglin2
a178b99d73 更新群二维码 2023-05-05 16:10:31 +08:00
wanglin2
af9ee04aaf Merge branch 'feature' into main 2023-05-02 10:05:39 +08:00
wanglin2
01dc98f1f8 打包0.5.11 2023-05-02 10:01:08 +08:00
wanglin2
cbd07246bd 更新文档 2023-05-02 10:00:13 +08:00
wanglin2
5bb23ca738 优化主题配置更新,改变不涉及节点大小的配置不触发节点重新计算 2023-04-28 22:07:53 +08:00
wanglin2
0886ba7698 完善关联线文本编辑 2023-04-28 21:51:58 +08:00
wanglin2
a65cffa58b 完善关联线文本编辑 2023-04-28 17:26:37 +08:00
wanglin2
02e2d432dd Feature:关联线支持文本开发中 2023-04-28 17:10:39 +08:00
wanglin2
c8d23cab40 更新README 2023-04-28 09:04:20 +08:00
wanglin2
244ced83bc 更新群二维码 2023-04-28 08:59:54 +08:00
wanglin2
5c9c3d7934 打包0.5.10-fix.2 2023-04-26 16:02:47 +08:00
wanglin2
4ca6713675 更新文档 2023-04-26 15:54:28 +08:00
wanglin2
3d18404fd6 Fix:修复富文本模式下,切换主题、导入数据后没有触发数据改变的问题 2023-04-26 15:49:52 +08:00
wanglin2
98dda26bf8 新增三种主题 2023-04-26 15:48:58 +08:00
wanglin2
cd4c5ecd83 'Fix:修复导入出错的问题' 2023-04-26 11:20:34 +08:00
wanglin2
fdc0017ccb '打包0.5.10' 2023-04-26 11:02:51 +08:00
wanglin2
20a5c12bbb '更新文档' 2023-04-26 10:58:01 +08:00
wanglin2
4eacec125e Feature:使用LRU缓存算法优化节点复用 2023-04-26 10:37:32 +08:00
wanglin2
34322ba6d1 更新文档 2023-04-25 17:29:56 +08:00
wanglin2
8210151a7b 打包0.5.9 2023-04-25 17:19:14 +08:00
wanglin2
1e00088608 更新文档 2023-04-25 17:14:19 +08:00
wanglin2
ee59b8002a 修改导出,使用FileReader代替URL.createObjectURL转换blob数据 2023-04-25 17:13:39 +08:00
wanglin2
b2ca5d0fba 打包0.5.8 2023-04-25 10:12:41 +08:00
wanglin2
470604e567 更新文档 2023-04-25 10:00:40 +08:00
wanglin2
f5f665ec0a Demo:扩展节点图标列表 2023-04-25 09:05:46 +08:00
wanglin2
5e865a4e33 Feature:支持扩展节点图标 2023-04-25 09:05:10 +08:00
wanglin2
38ad33b604 修复隐藏模式下展开收起按钮的缺陷 2023-04-24 15:29:52 +08:00
wanglin2
e1b4146171 Feature:默认改为鼠标移上节点才显示展开收起按钮 2023-04-24 14:25:36 +08:00
94 changed files with 2192 additions and 500 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2021-2023 The MindMap Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -19,6 +19,12 @@
在线地址:[https://wanglin2.github.io/mind-map/](https://wanglin2.github.io/mind-map/)
另外也提供了客户端可供下载使用,支持`Windows``Mac``Linux`,下载地址:
Github[releases](https://github.com/wanglin2/mind-map/releases)。
百度云盘:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
# 特性
- [x] 插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积
@@ -84,4 +90,13 @@ MIT
# 微信交流群
![](./qrcode.jpg)
<img src="./qrcode.jpg" style="width: 300px" />
# 请作者喝杯咖啡
> 厚椰乳一盒 + 纯牛奶半盒 + 冰块 + 咖啡液 = 生椰拿铁 yyds
<p>
<img src="./web/src/assets/img/alipay.jpg" style="width: 300px" />
<img src="./web/src/assets/img/wechat.jpg" style="width: 300px" />
</p>

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -9,9 +9,11 @@ import AssociativeLine from './src/AssociativeLine'
import RichText from './src/RichText'
import xmind from './src/parse/xmind.js'
import markdown from './src/parse/markdown.js'
import icons from './src/svg/icons.js'
MindMap.xmind = xmind
MindMap.markdown = markdown
MindMap.iconList = icons.nodeIconList
MindMap
.usePlugin(MiniMap)

View File

@@ -10,7 +10,7 @@ import BatchExecution from './src/BatchExecution'
import { layoutValueList, CONSTANTS } from './src/utils/constant'
import { SVG } from '@svgdotjs/svg.js'
import { simpleDeepClone } from './src/utils'
import defaultTheme from './src/themes/default'
import defaultTheme, { checkIsNodeSizeIndependenceConfig } from './src/themes/default'
// 默认选项配置
const defaultOpt = {
@@ -103,7 +103,26 @@ const defaultOpt = {
// 是否在点击了画布外的区域时结束节点文本的编辑状态
isEndNodeTextEditOnClickOuter: true,
// 最大历史记录数
maxHistoryCount: 1000
maxHistoryCount: 1000,
// 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示
alwaysShowExpandBtn: false,
// 扩展节点可插入的图标
iconList: [
// {
// name: '',// 分组名称
// type: '',// 分组的值
// list: [// 分组下的图标列表
// {
// name: '',// 图标名称
// icon:''// 图标可以传svg或图片
// }
// ]
// }
],
// 节点最大缓存数量
maxNodeCacheCount: 1000,
// 关联线默认文字
defaultAssociativeLineText: '关联'
}
// 思维导图
@@ -193,12 +212,12 @@ class MindMap {
}
// 重新渲染
reRender(callback) {
reRender(callback, source = '') {
this.batchExecution.push('render', () => {
this.draw.clear()
this.initTheme()
this.renderer.reRender = true
this.renderer.render(callback)
this.renderer.render(callback, source)
})
}
@@ -248,7 +267,9 @@ class MindMap {
// 设置主题配置
setThemeConfig(config) {
this.opt.themeConfig = config
this.render(null, CONSTANTS.CHANGE_THEME)
// 检查改变的是否是节点大小无关的主题属性
let res = checkIsNodeSizeIndependenceConfig(config)
this.render(null, res ? '' : CONSTANTS.CHANGE_THEME)
}
// 获取自定义主题配置
@@ -303,7 +324,7 @@ class MindMap {
} else {
this.renderer.renderTree = data
}
this.reRender()
this.reRender(() => {}, CONSTANTS.SET_DATA)
}
// 动态设置思维导图数据,包括节点数据、布局、主题、视图

View File

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

View File

@@ -3,13 +3,13 @@ import { v4 as uuid } from 'uuid'
import {
getAssociativeLineTargetIndex,
computeCubicBezierPathPoints,
joinCubicBezierPath,
cubicBezierPath,
getNodePoint,
computeNodePoints,
getNodeLinePath,
getDefaultControlPointOffsets
getNodeLinePath
} from './utils/associativeLineUtils'
import associativeLineControlsMethods from './utils/associativeLineControls'
import associativeLineTextMethods from './utils/associativeLineText'
// 关联线类
class AssociativeLine {
@@ -46,6 +46,14 @@ class AssociativeLine {
}
// 节流一下,不然很卡
this.checkOverlapNode = throttle(this.checkOverlapNode, 100, this)
// 控制点相关方法
Object.keys(associativeLineControlsMethods).forEach(item => {
this[item] = associativeLineControlsMethods[item].bind(this)
})
// 关联线文字相关方法
Object.keys(associativeLineTextMethods).forEach(item => {
this[item] = associativeLineTextMethods[item].bind(this)
})
this.bindEvent()
}
@@ -89,6 +97,8 @@ class AssociativeLine {
window.addEventListener('mouseup', e => {
this.onControlPointMouseup(e)
})
// 缩放事件
this.mindMap.on('scale', this.onScale)
}
// 创建箭头
@@ -177,36 +187,46 @@ class AssociativeLine {
.stroke({ width: associativeLineActiveWidth, color: 'transparent' })
.fill({ color: 'none' })
clickPath.plot(pathStr)
// 文字
let text = this.createText({ path, clickPath, node, toNode, startPoint, endPoint, controlPoints })
// 点击事件
clickPath.click(e => {
e.stopPropagation()
// 如果当前存在激活节点,那么取消激活节点
if (this.mindMap.renderer.activeNodeList.length > 0) {
this.clearActiveNodes()
} else {
// 否则清除当前的关联线的激活状态,如果有的话
this.clearActiveLine()
// 保存当前激活的关联线信息
this.activeLine = [path, clickPath, node, toNode]
// 让不可见的点击线显示
clickPath.stroke({ color: associativeLineActiveColor })
// 渲染控制点和连线
this.renderControls(
startPoint,
endPoint,
controlPoints[0],
controlPoints[1]
)
this.mindMap.emit(
'associative_line_click',
path,
clickPath,
node,
toNode
)
}
this.setActiveLine({ path, clickPath, text, node, toNode, startPoint, endPoint, controlPoints })
})
this.lineList.push([path, clickPath, node, toNode])
// 渲染关联线文字
this.renderText(this.getText(node, toNode), path, text)
this.lineList.push([path, clickPath, text, node, toNode])
}
// 激活某根关联线
setActiveLine({ path, clickPath, text, node, toNode, startPoint, endPoint, controlPoints }) {
let {
associativeLineActiveColor
} = this.mindMap.themeConfig
// 如果当前存在激活节点,那么取消激活节点
if (this.mindMap.renderer.activeNodeList.length > 0) {
this.clearActiveNodes()
} else {
// 否则清除当前的关联线的激活状态,如果有的话
this.clearActiveLine()
// 保存当前激活的关联线信息
this.activeLine = [path, clickPath, text, node, toNode]
// 让不可见的点击线显示
clickPath.stroke({ color: associativeLineActiveColor })
// 如果没有输入过关联线文字,那么显示默认文字
if (!this.getText(node, toNode)) {
this.renderText(this.mindMap.opt.defaultAssociativeLineText, path, text)
}
// 渲染控制点和连线
this.renderControls(
startPoint,
endPoint,
controlPoints[0],
controlPoints[1]
)
this.mindMap.emit('associative_line_click', path, clickPath, node, toNode)
}
}
// 移除所有连接线
@@ -214,6 +234,7 @@ class AssociativeLine {
this.lineList.forEach(line => {
line[0].remove()
line[1].remove()
line[2].remove()
})
this.lineList = []
}
@@ -253,7 +274,8 @@ class AssociativeLine {
updateCreatingLine(e) {
let { x, y } = this.getTransformedEventPos(e)
let startPoint = getNodePoint(this.creatingStartNode)
let pathStr = cubicBezierPath(startPoint.x, startPoint.y, x, y)
let offsetX = x > startPoint.x ? -10 : 10
let pathStr = cubicBezierPath(startPoint.x, startPoint.y, x + offsetX, y)
this.creatingLine.plot(pathStr)
this.checkOverlapNode(x, y)
}
@@ -349,20 +371,33 @@ class AssociativeLine {
// 删除连接线
removeLine() {
if (!this.activeLine) return
let [, , node, toNode] = this.activeLine
let [, , , node, toNode] = this.activeLine
this.removeControls()
let { associativeLineTargets, associativeLineTargetControlOffsets } =
let { associativeLineTargets, associativeLineTargetControlOffsets, associativeLineText } =
node.nodeData.data
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
// 更新关联线文本数据
let newAssociativeLineText = {}
if (associativeLineText) {
Object.keys(associativeLineText).forEach((item) => {
if (item !== toNode.nodeData.data.id) {
newAssociativeLineText[item] = associativeLineText[item]
}
})
}
this.mindMap.execCommand('SET_NODE_DATA', node, {
// 目标
associativeLineTargets: associativeLineTargets.filter((_, index) => {
return index !== targetIndex
}),
// 偏移量
associativeLineTargetControlOffsets: associativeLineTargetControlOffsets
? associativeLineTargetControlOffsets.filter((_, index) => {
return index !== targetIndex
})
: []
: [],
// 文本
associativeLineText: newAssociativeLineText
})
}
@@ -376,9 +411,16 @@ class AssociativeLine {
// 清除激活的线
clearActiveLine() {
if (this.activeLine) {
this.activeLine[1].stroke({
let [, clickPath, text, node, toNode] = this.activeLine
clickPath.stroke({
color: 'transparent'
})
// 隐藏关联线文本编辑框
this.hideEditTextBox()
// 如果当前关联线没有文字,则清空文字节点
if (!this.getText(node, toNode)) {
text.clear()
}
this.activeLine = null
this.removeControls()
}
@@ -391,6 +433,7 @@ class AssociativeLine {
this.lineList.forEach(line => {
line[0].hide()
line[1].hide()
line[2].hide()
})
this.hideControls()
}
@@ -401,225 +444,11 @@ class AssociativeLine {
this.lineList.forEach(line => {
line[0].show()
line[1].show()
line[2].show()
})
this.showControls()
this.isNodeDragging = false
}
// 创建控制点、连线节点
createControlNodes() {
let { associativeLineActiveColor } = this.mindMap.themeConfig
// 连线
this.controlLine1 = this.draw
.line()
.stroke({ color: associativeLineActiveColor, width: 2 })
this.controlLine2 = this.draw
.line()
.stroke({ color: associativeLineActiveColor, width: 2 })
// 控制点
this.controlPoint1 = this.createOneControlNode('controlPoint1')
this.controlPoint2 = this.createOneControlNode('controlPoint2')
}
// 创建控制点
createOneControlNode(pointKey) {
let { associativeLineActiveColor } = this.mindMap.themeConfig
return this.draw
.circle(this.controlPointDiameter)
.stroke({ color: associativeLineActiveColor })
.fill({ color: '#fff' })
.click(e => {
e.stopPropagation()
})
.mousedown(e => {
this.onControlPointMousedown(e, pointKey)
})
}
// 控制点的鼠标按下事件
onControlPointMousedown(e, pointKey) {
e.stopPropagation()
this.isControlPointMousedown = true
this.mousedownControlPointKey = pointKey
}
// 控制点的鼠标移动事件
onControlPointMousemove(e) {
if (
!this.isControlPointMousedown ||
!this.mousedownControlPointKey ||
!this[this.mousedownControlPointKey]
)
return
e.stopPropagation()
e.preventDefault()
let radius = this.controlPointDiameter / 2
// 转换鼠标当前的位置
let { x, y } = this.getTransformedEventPos(e)
this.controlPointMousemoveState.pos = {
x,
y
}
// 更新当前拖拽的控制点的位置
this[this.mousedownControlPointKey].x(x - radius).y(y - radius)
let [path, clickPath, node, toNode] = this.activeLine
let [startPoint, endPoint] = computeNodePoints(node, toNode)
this.controlPointMousemoveState.startPoint = startPoint
this.controlPointMousemoveState.endPoint = endPoint
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
this.controlPointMousemoveState.targetIndex = targetIndex
let offsets = []
let associativeLineTargetControlOffsets = node.nodeData.data.associativeLineTargetControlOffsets
if (!associativeLineTargetControlOffsets) {
// 兼容0.4.5版本没有associativeLineTargetControlOffsets的情况
offsets = getDefaultControlPointOffsets(startPoint, endPoint)
} else {
offsets = associativeLineTargetControlOffsets[targetIndex]
}
let point1 = null
let point2 = null
// 拖拽的是控制点1
if (this.mousedownControlPointKey === 'controlPoint1') {
point1 = {
x,
y
}
point2 = {
x: endPoint.x + offsets[1].x,
y: endPoint.y + offsets[1].y
}
// 更新控制点1的连线
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
} else {
// 拖拽的是控制点2
point1 = {
x: startPoint.x + offsets[0].x,
y: startPoint.y + offsets[0].y
}
point2 = {
x,
y
}
// 更新控制点2的连线
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
}
// 更新关联线
let pathStr = joinCubicBezierPath(startPoint, endPoint, point1, point2)
path.plot(pathStr)
clickPath.plot(pathStr)
}
// 控制点的鼠标移动事件
onControlPointMouseup(e) {
if (!this.isControlPointMousedown) return
e.stopPropagation()
e.preventDefault()
let { pos, startPoint, endPoint, targetIndex } =
this.controlPointMousemoveState
let [, , node] = this.activeLine
let offsetList = []
let associativeLineTargetControlOffsets = node.nodeData.data.associativeLineTargetControlOffsets
if (!associativeLineTargetControlOffsets) {
// 兼容0.4.5版本没有associativeLineTargetControlOffsets的情况
offsetList[targetIndex] = getDefaultControlPointOffsets(startPoint, endPoint)
} else {
offsetList = associativeLineTargetControlOffsets
}
let offset1 = null
let offset2 = null
if (this.mousedownControlPointKey === 'controlPoint1') {
// 更新控制点1数据
offset1 = {
x: pos.x - startPoint.x,
y: pos.y - startPoint.y
}
offset2 = offsetList[targetIndex][1]
} else {
// 更新控制点2数据
offset1 = offsetList[targetIndex][0]
offset2 = {
x: pos.x - endPoint.x,
y: pos.y - endPoint.y
}
}
offsetList[targetIndex] = [offset1, offset2]
this.mindMap.execCommand('SET_NODE_DATA', node, {
associativeLineTargetControlOffsets: offsetList
})
// 这里要加个setTimeout0是因为draw_click事件比mouseup事件触发的晚所以重置isControlPointMousedown需要等draw_click事件触发完以后
setTimeout(() => {
this.resetControlPoint()
}, 0)
}
// 复位控制点移动
resetControlPoint() {
this.isControlPointMousedown = false
this.mousedownControlPointKey = ''
this.controlPointMousemoveState = {
pos: null,
startPoint: null,
endPoint: null,
targetIndex: ''
}
}
// 渲染控制点
renderControls(startPoint, endPoint, point1, point2) {
if (!this.controlLine1) {
this.createControlNodes()
}
let radius = this.controlPointDiameter / 2
// 控制点和起终点的连线
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
// 控制点
this.controlPoint1.x(point1.x - radius).y(point1.y - radius)
this.controlPoint2.x(point2.x - radius).y(point2.y - radius)
}
// 删除控制点
removeControls() {
if (!this.controlLine1) return
;[
this.controlLine1,
this.controlLine2,
this.controlPoint1,
this.controlPoint2
].forEach(item => {
item.remove()
})
this.controlLine1 = null
this.controlLine2 = null
this.controlPoint1 = null
this.controlPoint2 = null
}
// 隐藏控制点
hideControls() {
if (!this.controlLine1) return
;[
this.controlLine1,
this.controlLine2,
this.controlPoint1,
this.controlPoint2
].forEach(item => {
item.hide()
})
}
// 显示控制点
showControls() {
if (!this.controlLine1) return
;[
this.controlLine1,
this.controlLine2,
this.controlPoint1,
this.controlPoint2
].forEach(item => {
item.show()
})
}
}
AssociativeLine.instanceName = 'associativeLine'

View File

@@ -1,4 +1,4 @@
import { imgToDataUrl, downloadFile } from './utils'
import { imgToDataUrl, downloadFile, readBlob } from './utils'
import JsPDF from 'jspdf'
import { SVG } from '@svgdotjs/svg.js'
import drawBackgroundImageToCanvas from './utils/simulateCSSBackgroundInCanvas'
@@ -127,6 +127,28 @@ class Export {
})
}
// 在svg上绘制思维导图背景
drawBackgroundToSvg(svg) {
return new Promise(async resolve => {
let {
backgroundColor = '#fff',
backgroundImage,
backgroundRepeat = 'repeat'
} = this.mindMap.themeConfig
// 背景颜色
svg.css('background-color', backgroundColor)
// 背景图片
if (backgroundImage && backgroundImage !== 'none') {
let imgDataUrl = await imgToDataUrl(backgroundImage)
svg.css('background-image', `url(${imgDataUrl})`)
svg.css('background-repeat', backgroundRepeat)
resolve()
} else {
resolve()
}
})
}
// 导出为png
/**
* 方法1.把svg的图片都转化成data:url格式再转换
@@ -145,11 +167,10 @@ class Export {
type: 'image/svg+xml'
})
// 转换成data:url数据
let svgUrl = URL.createObjectURL(blob)
let svgUrl = await readBlob(blob)
// 绘制到canvas上
let imgDataUrl = await this.svgToPng(svgUrl, transparent)
URL.revokeObjectURL(svgUrl)
return imgDataUrl
let res = await this.svgToPng(svgUrl, transparent)
return res
}
// 导出为pdf
@@ -184,28 +205,6 @@ class Export {
image.src = img
}
// 在svg上绘制思维导图背景
drawBackgroundToSvg(svg) {
return new Promise(async resolve => {
let {
backgroundColor = '#fff',
backgroundImage,
backgroundRepeat = 'repeat'
} = this.mindMap.themeConfig
// 背景颜色
svg.css('background-color', backgroundColor)
// 背景图片
if (backgroundImage && backgroundImage !== 'none') {
let imgDataUrl = await imgToDataUrl(backgroundImage)
svg.css('background-image', `url(${imgDataUrl})`)
svg.css('background-repeat', backgroundRepeat)
resolve()
} else {
resolve()
}
})
}
// 导出为svg
// plusCssText附加的css样式如果svg中存在dom节点想要设置一些针对节点的样式可以通过这个参数传入
async svg(name, plusCssText) {
@@ -226,28 +225,32 @@ class Export {
let blob = new Blob([str], {
type: 'image/svg+xml'
})
return URL.createObjectURL(blob)
let res = await readBlob(blob)
return res
}
// 导出为json
json(name, withConfig = true) {
async json(name, withConfig = true) {
let data = this.mindMap.getData(withConfig)
let str = JSON.stringify(data)
let blob = new Blob([str])
return URL.createObjectURL(blob)
let res = await readBlob(blob)
return res
}
// 专有文件其实就是json文件
smm(name, withConfig) {
return this.json(name, withConfig)
async smm(name, withConfig) {
let res = await this.json(name, withConfig)
return res
}
// markdown文件
md() {
async md() {
let data = this.mindMap.getData()
let content = transformToMarkdown(data)
let blob = new Blob([content])
return URL.createObjectURL(blob)
let res = await readBlob(blob)
return res
}
}

View File

@@ -46,7 +46,7 @@ export default class KeyCommand {
if (this.mindMap.richText && this.mindMap.richText.showTextEdit) {
return
}
if (this.mindMap.renderer.textEdit.showTextEdit) {
if (this.mindMap.renderer.textEdit.showTextEdit || (this.mindMap.associativeLine && this.mindMap.associativeLine.showTextEdit)) {
return
}
this.isInSvg = false

View File

@@ -1,7 +1,7 @@
import Style from './Style'
import Shape from './Shape'
import { asyncRun } from './utils'
import { G } from '@svgdotjs/svg.js'
import { G, Rect } from '@svgdotjs/svg.js'
import nodeGeneralizationMethods from './utils/nodeGeneralization'
import nodeExpandBtnMethods from './utils/nodeExpandBtn'
import nodeCommandWrapsMethods from './utils/nodeCommandWraps'
@@ -68,12 +68,15 @@ class Node {
this.noteEl = null
this._expandBtn = null
this._lastExpandBtnType = null
this._showExpandBtn = false
this._openExpandNode = null
this._closeExpandNode = null
this._fillExpandNode = null
this._lines = []
this._generalizationLine = null
this._generalizationNode = null
this._unVisibleRectRegionNode = null
this._isMouseenter = false
// 尺寸信息
this._rectInfo = {
imgContentWidth: 0,
@@ -242,13 +245,23 @@ class Node {
layout() {
// 清除之前的内容
this.group.clear()
let { width, textContentItemMargin } = this
let { width, height, textContentItemMargin } = this
let { paddingY } = this.getPaddingVale()
paddingY += this.shapePadding.paddingY
// 节点形状
this.shapeNode = this.shapeInstance.createShape()
this.group.add(this.shapeNode)
this.updateNodeShape()
// 渲染一个隐藏的矩形区域,用来触发展开收起按钮的显示
if (!this.mindMap.opt.alwaysShowExpandBtn) {
if (!this._unVisibleRectRegionNode) {
this._unVisibleRectRegionNode = new Rect()
}
this._unVisibleRectRegionNode.fill({
color: 'transparent'
}).size(this.expandBtnSize, height).x(width).y(0)
this.group.add(this._unVisibleRectRegionNode)
}
// 概要节点添加一个带所属节点id的类名
if (this.isGeneralization && this.generalizationBelongNode) {
this.group.addClass('generalization_' + this.generalizationBelongNode.uid)
@@ -374,9 +387,14 @@ class Node {
this.mindMap.emit('node_mouseup', this, e)
})
this.group.on('mouseenter', e => {
this._isMouseenter = true
// 显示展开收起按钮
this.showExpandBtn()
this.mindMap.emit('node_mouseenter', this, e)
})
this.group.on('mouseleave', e => {
this._isMouseenter = false
this.hideExpandBtn()
this.mindMap.emit('node_mouseleave', this, e)
})
// 双击事件
@@ -424,14 +442,24 @@ class Node {
if (!this.group) {
return
}
let { enableNodeTransitionMove, nodeTransitionMoveDuration } =
let { enableNodeTransitionMove, nodeTransitionMoveDuration, alwaysShowExpandBtn } =
this.mindMap.opt
// 需要移除展开收缩按钮
if (this._expandBtn && this.nodeData.children.length <= 0) {
this.removeExpandBtn()
if (alwaysShowExpandBtn) {
// 需要移除展开收缩按钮
if (this._expandBtn && this.nodeData.children.length <= 0) {
this.removeExpandBtn()
} else {
// 更新展开收起按钮
this.renderExpandBtn()
}
} else {
// 更新展开收起按钮
this.renderExpandBtn()
let { isActive, expand } = this.nodeData.data
// 展开状态且非激活状态,且当前鼠标不在它上面,才隐藏
if (expand && !isActive && !this._isMouseenter) {
this.hideExpandBtn()
} else {
this.showExpandBtn()
}
}
// 更新概要
this.renderGeneralization()
@@ -730,9 +758,10 @@ class Node {
// 获取padding值
getPaddingVale() {
let { isActive }= this.nodeData.data
return {
paddingX: this.getStyle('paddingX', true, this.nodeData.data.isActive),
paddingY: this.getStyle('paddingY', true, this.nodeData.data.isActive)
paddingX: this.getStyle('paddingX', true, isActive),
paddingY: this.getStyle('paddingY', true, isActive)
}
}

View File

@@ -266,7 +266,6 @@ class Render {
// 重新渲染需要清除激活状态
if (this.reRender) {
this.clearActive()
this.layout.clearNodePool()
}
// 计算布局
this.layout.doLayout(root => {
@@ -289,6 +288,11 @@ class Render {
if (this.hasWaitRendering) {
this.hasWaitRendering = false
this.render(callback, source)
} else {
// 触发一次保存,因为修改了渲染树的数据
if (this.mindMap.richText && [CONSTANTS.CHANGE_THEME, CONSTANTS.SET_DATA].includes(source)) {
this.mindMap.command.addHistory()
}
}
}
let { enableNodeTransitionMove, nodeTransitionMoveDuration } =
@@ -366,6 +370,8 @@ class Render {
if (!node.nodeData.data.isActive) {
node.nodeData.data.isActive = true
this.addActiveNode(node)
// 激活节点需要显示展开收起按钮
node.showExpandBtn()
setTimeout(() => {
node.updateNodeShape()
}, 0)
@@ -735,6 +741,12 @@ class Render {
this.setNodeData(node, {
isActive: active
})
// 切换激活状态,需要切换展开收起按钮的显隐
if (active) {
node.showExpandBtn()
} else {
node.hideExpandBtn()
}
node.updateNodeShape()
}
@@ -749,14 +761,14 @@ class Render {
item.render()
})
node.renderLine()
node.updateExpandBtnNode()
// node.updateExpandBtnNode()
} else {
// 收缩
node.children.forEach(item => {
item.remove()
})
node.removeLine()
node.updateExpandBtnNode()
// node.updateExpandBtnNode()
}
this.mindMap.render()
}

View File

@@ -1,5 +1,6 @@
import Node from '../Node'
import { CONSTANTS, initRootNodePositionMap } from '../utils/constant'
import Lru from '../utils/Lru'
// 布局基类
class Base {
@@ -13,8 +14,7 @@ class Base {
this.draw = this.mindMap.draw
// 根节点
this.root = null
// 保存所有uid和节点用于复用
this.nodePool = {}
this.lru = new Lru(this.mindMap.opt.maxNodeCacheCount)
}
// 计算节点位置
@@ -40,16 +40,7 @@ class Base {
// 记录本次渲染时的节点
this.renderer.nodeCache[uid] = node
// 记录所有渲染时的节点
this.nodePool[uid] = node
// 如果总缓存数量达到1000直接清空
if (Object.keys(this.nodePool).length > 1000) {
this.clearNodePool()
}
}
// 清空节点存储池
clearNodePool() {
this.nodePool = {}
this.lru.add(uid, node)
}
// 检查当前来源是否需要重新计算节点大小
@@ -72,9 +63,9 @@ class Base {
newNode.getSize()
newNode.needLayout = true
}
} else if (this.nodePool[data.data.uid] && !this.renderer.reRender) {
} else if (this.lru.has(data.data.uid) && !this.renderer.reRender) {
// 数据上没有保存节点引用但是通过uid找到了缓存的节点也可以复用
newNode = this.nodePool[data.data.uid]
newNode = this.lru.get(data.data.uid)
// 保存该节点上一次的数据
let lastData = JSON.stringify(newNode.nodeData.data)
newNode.reset()

View File

@@ -199,6 +199,9 @@ class CatalogOrganization extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let len = node.children.length
let marginX = this.getMarginX(node.layerIndex + 1)
if (node.isRoot) {

View File

@@ -231,6 +231,9 @@ class Fishbone extends Base {
return []
}
let { top, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let len = node.children.length
if (node.isRoot) {
// 当前节点是根节点

View File

@@ -159,6 +159,9 @@ class LogicalStructure extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let marginX = this.getMarginX(node.layerIndex + 1)
let s1 = (marginX - expandBtnSize) * 0.6
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
@@ -188,6 +191,9 @@ class LogicalStructure extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
node.children.forEach((item, index) => {
let x1 =
@@ -213,6 +219,9 @@ class LogicalStructure extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
node.children.forEach((item, index) => {
let x1 =

View File

@@ -198,6 +198,9 @@ class MindMap extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let marginX = this.getMarginX(node.layerIndex + 1)
let s1 = (marginX - expandBtnSize) * 0.6
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
@@ -235,6 +238,9 @@ class MindMap extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
node.children.forEach((item, index) => {
let x1 =
@@ -269,6 +275,9 @@ class MindMap extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
node.children.forEach((item, index) => {
let x1 =
@@ -276,7 +285,7 @@ class MindMap extends Base {
? left + width / 2
: item.dir === 'left'
? left - expandBtnSize
: left + width + 20
: left + width + expandBtnSize
let y1 = top + height / 2
let x2 = item.dir === 'left' ? item.left + item.width : item.left
let y2 = item.top + item.height / 2

View File

@@ -179,6 +179,9 @@ class OrganizationStructure extends Base {
return []
}
let { left, top, width, height, expandBtnSize, isRoot } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let x1 = left + width / 2
let y1 = top + height
let marginX = this.getMarginX(node.layerIndex + 1)

View File

@@ -238,6 +238,9 @@ class Timeline extends Base {
return []
}
let { left, top, width, height, expandBtnSize } = node
if (!this.mindMap.opt.alwaysShowExpandBtn) {
expandBtnSize = 0
}
let len = node.children.length
if (node.isRoot) {
// 当前节点是根节点

View File

@@ -279,9 +279,9 @@ export const nodeIconList = [
]
// 获取nodeIconList icon内容
const getNodeIconListIcon = name => {
const getNodeIconListIcon = (name, extendIconList = []) => {
let arr = name.split('_')
let typeData = nodeIconList.find(item => {
let typeData = [...nodeIconList, ...extendIconList].find(item => {
return item.type === arr[0]
})
return typeData.list.find(item => {

View File

@@ -0,0 +1,57 @@
import defaultTheme from './default'
import merge from 'deepmerge'
// 秋天
export default merge(defaultTheme, {
// 背景颜色
backgroundColor: '#fff2df',
// 连线的颜色
lineColor: '#b0bc47',
lineWidth: 3,
// 概要连线的粗细
generalizationLineWidth: 3,
// 概要连线的颜色
generalizationLineColor: '#b0bc47',
// 根节点样式
root: {
fillColor: '#e68112',
color: '#fff',
borderColor: '#e68112',
borderWidth: 0,
fontSize: 24,
active: {
borderColor: '#b0bc47',
borderWidth: 3
}
},
// 二级节点样式
second: {
fillColor: '#ffd683',
color: '#8c5416',
borderColor: '#b0bc47',
borderWidth: 2,
fontSize: 18,
active: {
borderColor: '#e68112'
}
},
// 三级及以下节点样式
node: {
fontSize: 14,
color: '#8c5416',
active: {
borderColor: '#b0bc47'
}
},
// 概要节点样式
generalization: {
fontSize: 14,
fillColor: '#ffd683',
borderColor: '#b0bc47',
borderWidth: 2,
color: '#8c5416',
active: {
borderColor: '#e68112'
}
}
})

View File

@@ -0,0 +1,57 @@
import defaultTheme from './default'
import merge from 'deepmerge'
// 牛油果
export default merge(defaultTheme, {
// 背景颜色
backgroundColor: '#e6f1de',
// 连线的颜色
lineColor: '#f5ffad',
lineWidth: 4,
// 概要连线的粗细
generalizationLineWidth: 3,
// 概要连线的颜色
generalizationLineColor: '#749336',
// 根节点样式
root: {
fillColor: '#94c143',
color: '#fff',
borderColor: '#94c143',
borderWidth: 0,
fontSize: 24,
active: {
borderColor: '#749336',
borderWidth: 3
}
},
// 二级节点样式
second: {
fillColor: '#cee498',
color: '#749336',
borderColor: '#aec668',
borderWidth: 2,
fontSize: 18,
active: {
borderColor: '#749336'
}
},
// 三级及以下节点样式
node: {
fontSize: 14,
color: '#749336',
active: {
borderColor: '#749336'
}
},
// 概要节点样式
generalization: {
fontSize: 14,
fillColor: '#cee498',
borderColor: '#aec668',
borderWidth: 2,
color: '#749336',
active: {
borderColor: '#749336'
}
}
})

View File

@@ -34,6 +34,14 @@ export default {
associativeLineActiveWidth: 8,
// 关联线激活状态的颜色
associativeLineActiveColor: 'rgba(2, 167, 240, 1)',
// 关联线文字颜色
associativeLineTextColor: 'rgb(51, 51, 51)',
// 关联线文字大小
associativeLineTextFontSize: 14,
// 关联线文字行高
associativeLineTextLineHeight: 1.2,
// 关联线文字字体
associativeLineTextFontFamily: '微软雅黑, Microsoft YaHei',
// 背景颜色
backgroundColor: '#fafafa',
// 背景图片
@@ -148,4 +156,38 @@ export const supportActiveStyle = [
'borderRadius'
]
// 检测主题配置是否是节点大小无关的
const nodeSizeIndependenceList = [
'lineWidth',
'lineColor',
'lineDasharray',
'lineStyle',
'generalizationLineWidth',
'generalizationLineColor',
'associativeLineWidth',
'associativeLineColor',
'associativeLineActiveWidth',
'associativeLineActiveColor',
'associativeLineTextColor',
'associativeLineTextFontSize',
'associativeLineTextLineHeight',
'associativeLineTextFontFamily',
'backgroundColor',
'backgroundImage',
'backgroundRepeat',
'backgroundPosition',
'backgroundSize'
]
export const checkIsNodeSizeIndependenceConfig = (config) => {
let keys = Object.keys(config)
for(let i = 0; i < keys.length; i++) {
if (!nodeSizeIndependenceList.find((item) => {
return item === keys[i]
})) {
return false
}
}
return true
}
export const lineStyleProps = ['lineColor', 'lineDasharray', 'lineWidth']

View File

@@ -27,6 +27,9 @@ import redSpirit from './redSpirit'
import blackHumour from './blackHumour'
import lateNightOffice from './lateNightOffice'
import blackGold from './blackGold'
import avocado from './avocado'
import autumn from './autumn'
import orangeJuice from './orangeJuice'
export default {
default: defaultTheme,
@@ -57,5 +60,8 @@ export default {
redSpirit,
blackHumour,
lateNightOffice,
blackGold
blackGold,
avocado,
autumn,
orangeJuice
}

View File

@@ -0,0 +1,57 @@
import defaultTheme from './default'
import merge from 'deepmerge'
// 橙汁
export default merge(defaultTheme, {
// 背景颜色
backgroundColor: '#070616',
// 连线的颜色
lineColor: '#fff',
lineWidth: 3,
// 概要连线的粗细
generalizationLineWidth: 3,
// 概要连线的颜色
generalizationLineColor: '#fff',
// 根节点样式
root: {
fillColor: '#ff6811',
color: '#110501',
borderColor: '#ff6811',
borderWidth: 0,
fontSize: 24,
active: {
borderColor: '#a9a4a9',
borderWidth: 3
}
},
// 二级节点样式
second: {
fillColor: '#070616',
color: '#a9a4a9',
borderColor: '#ff6811',
borderWidth: 2,
fontSize: 18,
active: {
borderColor: '#110501'
}
},
// 三级及以下节点样式
node: {
fontSize: 14,
color: '#a9a4a9',
active: {
borderColor: '#ff6811'
}
},
// 概要节点样式
generalization: {
fontSize: 14,
fillColor: '',
borderColor: '#ff6811',
borderWidth: 2,
color: '#a9a4a9',
active: {
borderColor: '#110501'
}
}
})

View File

@@ -0,0 +1,39 @@
// LRU缓存类
export default class CRU {
constructor(max) {
this.max = max || 1000
this.size = 0
this.pool = new Map()
}
add(key, value) {
// 如果该key是否已经存在则先删除
this.delete(key)
this.pool.set(key, value)
this.size++
// 如果数量超出最大值,则删除最早的
if (this.size > this.max) {
let keys = this.pool.keys()
let last = keys.next()
this.delete(last.value)
}
}
delete(key) {
if (this.pool.has(key)) {
this.pool.delete(key)
this.size--
}
}
has(key) {
return this.pool.has(key)
}
get(key) {
if (this.pool.has(key)) {
return this.pool.get(key)
}
}
}

View File

@@ -0,0 +1,241 @@
import {
getAssociativeLineTargetIndex,
joinCubicBezierPath,
computeNodePoints,
getDefaultControlPointOffsets
} from './associativeLineUtils'
// 创建控制点、连线节点
function createControlNodes() {
let { associativeLineActiveColor } = this.mindMap.themeConfig
// 连线
this.controlLine1 = this.draw
.line()
.stroke({ color: associativeLineActiveColor, width: 2 })
this.controlLine2 = this.draw
.line()
.stroke({ color: associativeLineActiveColor, width: 2 })
// 控制点
this.controlPoint1 = this.createOneControlNode('controlPoint1')
this.controlPoint2 = this.createOneControlNode('controlPoint2')
}
// 创建控制点
function createOneControlNode(pointKey) {
let { associativeLineActiveColor } = this.mindMap.themeConfig
return this.draw
.circle(this.controlPointDiameter)
.stroke({ color: associativeLineActiveColor })
.fill({ color: '#fff' })
.click(e => {
e.stopPropagation()
})
.mousedown(e => {
this.onControlPointMousedown(e, pointKey)
})
}
// 控制点的鼠标按下事件
function onControlPointMousedown(e, pointKey) {
e.stopPropagation()
this.isControlPointMousedown = true
this.mousedownControlPointKey = pointKey
}
// 控制点的鼠标移动事件
function onControlPointMousemove(e) {
if (
!this.isControlPointMousedown ||
!this.mousedownControlPointKey ||
!this[this.mousedownControlPointKey]
)
return
e.stopPropagation()
e.preventDefault()
let radius = this.controlPointDiameter / 2
// 转换鼠标当前的位置
let { x, y } = this.getTransformedEventPos(e)
this.controlPointMousemoveState.pos = {
x,
y
}
// 更新当前拖拽的控制点的位置
this[this.mousedownControlPointKey].x(x - radius).y(y - radius)
let [path, clickPath, text, node, toNode] = this.activeLine
let [startPoint, endPoint] = computeNodePoints(node, toNode)
this.controlPointMousemoveState.startPoint = startPoint
this.controlPointMousemoveState.endPoint = endPoint
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
this.controlPointMousemoveState.targetIndex = targetIndex
let offsets = []
let associativeLineTargetControlOffsets =
node.nodeData.data.associativeLineTargetControlOffsets
if (!associativeLineTargetControlOffsets) {
// 兼容0.4.5版本没有associativeLineTargetControlOffsets的情况
offsets = getDefaultControlPointOffsets(startPoint, endPoint)
} else {
offsets = associativeLineTargetControlOffsets[targetIndex]
}
let point1 = null
let point2 = null
// 拖拽的是控制点1
if (this.mousedownControlPointKey === 'controlPoint1') {
point1 = {
x,
y
}
point2 = {
x: endPoint.x + offsets[1].x,
y: endPoint.y + offsets[1].y
}
// 更新控制点1的连线
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
} else {
// 拖拽的是控制点2
point1 = {
x: startPoint.x + offsets[0].x,
y: startPoint.y + offsets[0].y
}
point2 = {
x,
y
}
// 更新控制点2的连线
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
}
// 更新关联线
let pathStr = joinCubicBezierPath(startPoint, endPoint, point1, point2)
path.plot(pathStr)
clickPath.plot(pathStr)
this.updateTextPos(path, text)
this.updateTextEditBoxPos(text)
}
// 控制点的鼠标移动事件
function onControlPointMouseup(e) {
if (!this.isControlPointMousedown) return
e.stopPropagation()
e.preventDefault()
let { pos, startPoint, endPoint, targetIndex } =
this.controlPointMousemoveState
let [, , , node] = this.activeLine
let offsetList = []
let associativeLineTargetControlOffsets =
node.nodeData.data.associativeLineTargetControlOffsets
if (!associativeLineTargetControlOffsets) {
// 兼容0.4.5版本没有associativeLineTargetControlOffsets的情况
offsetList[targetIndex] = getDefaultControlPointOffsets(
startPoint,
endPoint
)
} else {
offsetList = associativeLineTargetControlOffsets
}
let offset1 = null
let offset2 = null
if (this.mousedownControlPointKey === 'controlPoint1') {
// 更新控制点1数据
offset1 = {
x: pos.x - startPoint.x,
y: pos.y - startPoint.y
}
offset2 = offsetList[targetIndex][1]
} else {
// 更新控制点2数据
offset1 = offsetList[targetIndex][0]
offset2 = {
x: pos.x - endPoint.x,
y: pos.y - endPoint.y
}
}
offsetList[targetIndex] = [offset1, offset2]
this.mindMap.execCommand('SET_NODE_DATA', node, {
associativeLineTargetControlOffsets: offsetList
})
// 这里要加个setTimeout0是因为draw_click事件比mouseup事件触发的晚所以重置isControlPointMousedown需要等draw_click事件触发完以后
setTimeout(() => {
this.resetControlPoint()
}, 0)
}
// 复位控制点移动
function resetControlPoint() {
this.isControlPointMousedown = false
this.mousedownControlPointKey = ''
this.controlPointMousemoveState = {
pos: null,
startPoint: null,
endPoint: null,
targetIndex: ''
}
}
// 渲染控制点
function renderControls(startPoint, endPoint, point1, point2) {
if (!this.controlLine1) {
this.createControlNodes()
}
let radius = this.controlPointDiameter / 2
// 控制点和起终点的连线
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
// 控制点
this.controlPoint1.x(point1.x - radius).y(point1.y - radius)
this.controlPoint2.x(point2.x - radius).y(point2.y - radius)
}
// 删除控制点
function removeControls() {
if (!this.controlLine1) return
;[
this.controlLine1,
this.controlLine2,
this.controlPoint1,
this.controlPoint2
].forEach(item => {
item.remove()
})
this.controlLine1 = null
this.controlLine2 = null
this.controlPoint1 = null
this.controlPoint2 = null
}
// 隐藏控制点
function hideControls() {
if (!this.controlLine1) return
;[
this.controlLine1,
this.controlLine2,
this.controlPoint1,
this.controlPoint2
].forEach(item => {
item.hide()
})
}
// 显示控制点
function showControls() {
if (!this.controlLine1) return
;[
this.controlLine1,
this.controlLine2,
this.controlPoint1,
this.controlPoint2
].forEach(item => {
item.show()
})
}
export default {
createControlNodes,
createOneControlNode,
onControlPointMousedown,
onControlPointMousemove,
onControlPointMouseup,
resetControlPoint,
renderControls,
removeControls,
hideControls,
showControls
}

View File

@@ -0,0 +1,167 @@
import { Text } from '@svgdotjs/svg.js'
import { getStrWithBrFromHtml } from './index'
// 创建文字节点
function createText(data) {
let g = this.draw.group()
const setActive = () => {
if (
!this.activeLine ||
this.activeLine[3] !== data.node ||
this.activeLine[4] !== data.toNode
) {
this.setActiveLine({
...data,
text: g
})
}
}
g.click(e => {
e.stopPropagation()
setActive()
})
g.on('dblclick', e => {
e.stopPropagation()
setActive()
if (!this.activeLine) return
this.showEditTextBox(g)
})
return g
}
// 显示文本编辑框
function showEditTextBox(g) {
this.mindMap.emit('before_show_text_edit')
// 注册回车快捷键
this.mindMap.keyCommand.addShortcut('Enter', () => {
this.hideEditTextBox()
})
if (!this.textEditNode) {
this.textEditNode = document.createElement('div')
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
this.textEditNode.setAttribute('contenteditable', true)
this.textEditNode.addEventListener('keyup', e => {
e.stopPropagation()
})
this.textEditNode.addEventListener('click', e => {
e.stopPropagation()
})
document.body.appendChild(this.textEditNode)
}
let {
associativeLineTextFontSize,
associativeLineTextFontFamily,
associativeLineTextLineHeight
} = this.mindMap.themeConfig
let scale = this.mindMap.view.scale
let [, , , node, toNode] = this.activeLine
let textLines = (
this.getText(node, toNode) || this.mindMap.opt.defaultAssociativeLineText
).split(/\n/gim)
this.textEditNode.style.fontFamily = associativeLineTextFontFamily
this.textEditNode.style.fontSize = associativeLineTextFontSize * scale + 'px'
this.textEditNode.style.lineHeight = textLines.length > 1 ? associativeLineTextLineHeight : 'normal'
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
this.textEditNode.innerHTML = textLines.join('<br>')
this.textEditNode.style.display = 'block'
this.updateTextEditBoxPos(g)
this.showTextEdit = true
}
// 处理画布缩放
function onScale() {
this.hideEditTextBox()
}
// 更新文本编辑框位置
function updateTextEditBoxPos(g) {
let rect = g.node.getBoundingClientRect()
this.textEditNode.style.minWidth = rect.width + 10 + 'px'
this.textEditNode.style.minHeight = rect.height + 6 + 'px'
this.textEditNode.style.left = rect.left + 'px'
this.textEditNode.style.top = rect.top + 'px'
}
// 隐藏文本编辑框
function hideEditTextBox() {
if (!this.showTextEdit) {
return
}
let [path, , text, node, toNode] = this.activeLine
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
this.mindMap.execCommand('SET_NODE_DATA', node, {
associativeLineText: {
...(node.nodeData.data.associativeLineText || {}),
[toNode.nodeData.data.id]: str
}
})
this.textEditNode.style.display = 'none'
this.textEditNode.innerHTML = ''
this.showTextEdit = false
this.renderText(str, path, text)
this.mindMap.emit('hide_text_edit')
}
// 获取某根关联线的文字
function getText(node, toNode) {
let obj = node.nodeData.data.associativeLineText
if (!obj) {
return ''
}
return obj[toNode.nodeData.data.id] || ''
}
// 渲染关联线文字
function renderText(str, path, text) {
if (!str) return
let { associativeLineTextFontSize, associativeLineTextLineHeight } =
this.mindMap.themeConfig
text.clear()
let textArr = str.split(/\n/gim)
textArr.forEach((item, index) => {
let node = new Text().text(item)
node.y(associativeLineTextFontSize * associativeLineTextLineHeight * index)
this.styleText(node)
text.add(node)
})
updateTextPos(path, text)
}
// 给文本设置样式
function styleText(node) {
let {
associativeLineTextColor,
associativeLineTextFontSize,
associativeLineTextFontFamily
} = this.mindMap.themeConfig
node
.fill({
color: associativeLineTextColor
})
.css({
'font-family': associativeLineTextFontFamily,
'font-size': associativeLineTextFontSize
})
}
// 更新关联线文字位置
function updateTextPos(path, text) {
let pathLength = path.length()
let centerPoint = path.pointAt(pathLength / 2)
let { width: textWidth, height: textHeight } = text.bbox()
text.x(centerPoint.x - textWidth / 2)
text.y(centerPoint.y - textHeight / 2)
}
export default {
getText,
createText,
styleText,
onScale,
showEditTextBox,
hideEditTextBox,
updateTextEditBoxPos,
renderText,
updateTextPos
}

View File

@@ -28,34 +28,6 @@ export const themeList = [
name: '默认',
value: 'default',
},
{
name: '脑图经典',
value: 'classic',
},
{
name: '小黄人',
value: 'minions',
},
{
name: '粉红葡萄',
value: 'pinkGrape',
},
{
name: '薄荷',
value: 'mint',
},
{
name: '金色vip',
value: 'gold',
},
{
name: '活力橙',
value: 'vitalityOrange',
},
{
name: '绿叶',
value: 'greenLeaf',
},
{
name: '暗色2',
value: 'dark2',
@@ -72,10 +44,6 @@ export const themeList = [
name: '脑图经典3',
value: 'classic3',
},
{
name: '脑图经典4',
value: 'classic4',
},
{
name: '经典绿',
value: 'classicGreen',
@@ -112,6 +80,38 @@ export const themeList = [
name: '浪漫紫',
value: 'romanticPurple',
},
{
name: '粉红葡萄',
value: 'pinkGrape',
},
{
name: '薄荷',
value: 'mint',
},
{
name: '金色vip',
value: 'gold',
},
{
name: '活力橙',
value: 'vitalityOrange',
},
{
name: '绿叶',
value: 'greenLeaf',
},
{
name: '脑图经典',
value: 'classic',
},
{
name: '脑图经典4',
value: 'classic4',
},
{
name: '小黄人',
value: 'minions',
},
{
name: '简约黑',
value: 'simpleBlack',
@@ -139,12 +139,25 @@ export const themeList = [
{
name: '黑金',
value: 'blackGold',
},
{
name: '牛油果',
value: 'avocado',
},
{
name: '秋天',
value: 'autumn',
},
{
name: '橙汁',
value: 'orangeJuice',
}
]
// 常量
export const CONSTANTS = {
CHANGE_THEME: 'changeTheme',
SET_DATA: 'setData',
TRANSFORM_TO_NORMAL_NODE: 'transformAllNodesToNormalNode',
MODE: {
READONLY: 'readonly',

View File

@@ -342,4 +342,18 @@ export const getTextFromHtml = (html) => {
}
getTextFromHtmlEl.innerHTML = html
return getTextFromHtmlEl.textContent
}
// 将blob转成data:url
export const readBlob = (blob) => {
return new Promise((resolve, reject) => {
let reader = new FileReader()
reader.onload = (evt) => {
resolve(evt.target.result)
}
reader.onerror = (err) => {
reject(err)
}
reader.readAsDataURL(blob)
})
}

View File

@@ -42,8 +42,18 @@ function createIconNode() {
}
let iconSize = this.mindMap.themeConfig.iconSize
return _data.icon.map(item => {
let src = iconsSvg.getNodeIconListIcon(item, this.mindMap.opt.iconList || [])
let node = null
// svg图标
if (/^<svg/.test(src)) {
node = SVG(src)
} else {
// 图片图标
node = new Image().load(src)
}
node.size(iconSize, iconSize)
return {
node: SVG(iconsSvg.getNodeIconListIcon(item)).size(iconSize, iconSize),
node,
width: iconSize,
height: iconSize
}

View File

@@ -32,14 +32,15 @@ function createExpandNodeContent() {
// 创建或更新展开收缩按钮内容
function updateExpandBtnNode() {
let { expand } = this.nodeData.data
// 如果本次和上次的展开状态一样则返回
if (this.nodeData.data.expand === this._lastExpandBtnType) return
if (expand === this._lastExpandBtnType) return
if (this._expandBtn) {
this._expandBtn.clear()
}
this.createExpandNodeContent()
let node
if (this.nodeData.data.expand === false) {
if (expand === false) {
node = this._openExpandNode
this._lastExpandBtnType = false
} else {
@@ -97,14 +98,36 @@ function renderExpandBtn() {
})
this.group.add(this._expandBtn)
}
this._showExpandBtn = true
this.updateExpandBtnNode()
this.updateExpandBtnPos()
}
// 移除展开收缩按钮
function removeExpandBtn() {
if (this._expandBtn) {
if (this._expandBtn && this._showExpandBtn) {
this._expandBtn.remove()
this._showExpandBtn = false
}
}
// 显示展开收起按钮
function showExpandBtn() {
if (this.mindMap.opt.alwaysShowExpandBtn) return
setTimeout(() => {
this.renderExpandBtn()
}, 0)
}
// 隐藏展开收起按钮
function hideExpandBtn() {
if (this.mindMap.opt.alwaysShowExpandBtn || this._isMouseenter) return
// 非激活状态且展开状态鼠标移出才隐藏按钮
let { isActive, expand } = this.nodeData.data
if (!isActive && expand) {
setTimeout(() => {
this.removeExpandBtn()
}, 0)
}
}
@@ -113,5 +136,7 @@ export default {
updateExpandBtnNode,
updateExpandBtnPos,
renderExpandBtn,
removeExpandBtn
removeExpandBtn,
showExpandBtn,
hideExpandBtn
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -40,5 +40,8 @@ export const themeMap = {
blackHumour: require('../assets/img/blackHumour.jpg'),
lateNightOffice: require('../assets/img/lateNightOffice.jpg'),
blackGold: require('../assets/img/blackGold.jpg'),
autumn: require('../assets/img/autumn.jpg'),
avocado: require('../assets/img/avocado.jpg'),
orangeJuice: require('../assets/img/orangeJuice.jpg'),
}

64
web/src/config/icon.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -10,8 +10,8 @@ let langList = [
path: 'en'
}
]
let StartList = ['introduction', 'start', 'deploy', 'translate', 'changelog']
let CourseList = new Array(18).fill(0).map((_, index) => {
let StartList = ['introduction', 'start', 'deploy', 'client', 'translate', 'changelog']
let CourseList = new Array(19).fill(0).map((_, index) => {
return 'course' + (index + 1)
})
let APIList = [

View File

@@ -4,9 +4,9 @@
> The function of adjusting associated line control points is supported from v0.4.6+
This plugin is used to support the addition of associative lines.
> Relevance support for text editing starting from v0.5.11+
The plugin is currently not fully functional, and does not support adding text to association lines.
This plugin is used to support the addition of associative lines.
## Register

View File

@@ -7,8 +7,10 @@
<blockquote>
<p>The function of adjusting associated line control points is supported from v0.4.6+</p>
</blockquote>
<blockquote>
<p>Relevance support for text editing starting from v0.5.11+</p>
</blockquote>
<p>This plugin is used to support the addition of associative lines.</p>
<p>The plugin is currently not fully functional, and does not support adding text to association lines.</p>
<h2>Register</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> AssociativeLine <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/AssociativeLine.js&#x27;</span>

View File

@@ -1,5 +1,35 @@
# Changelog
## 0.5.11
New: Supports associative text editing.
optimization: Optimizing theme configuration updates, changing configurations that do not involve node size does not trigger node recalculation.
## 0.5.10
New: Optimize node reuse logic using LRU caching algorithm.
## 0.5.10-fix.1
Fix: Fix the issue of import errors.
## 0.5.10-fix.2
Fix: Fixed the issue of switching themes and importing data without triggering data changes in rich text mode.
New: Add three new themes.
## 0.5.9
Change: Unified export method format, using `FileReader` instead of `URL.createObjectURL` to convert `blob` data.
## 0.5.8
optimization: 1.The position setting is not triggered when the node position does not change. 2.The unfolding and folding status does not change and does not trigger button updates.
New: 1.The default setting is to move the mouse over the node to display the expand and collapse buttons. 2.Support the list of icons that can be inserted into extended nodes.
## 0.5.7
Breaking changeIn rich text mode, exporting png has been changed to using html2canvas to convert the entire svg, greatly improving the export speed. However, html2canvas has a bug where the text color inline with the dom node in the foreignObject element cannot be recognized. Therefore, the text color of the exported node is fixed. However, compared to the previously unavailable state of the export, it can at least be exported quickly and smoothly.

View File

@@ -1,6 +1,21 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.5.11</h2>
<p>New: Supports associative text editing.</p>
<p>optimization: Optimizing theme configuration updates, changing configurations that do not involve node size does not trigger node recalculation.</p>
<h2>0.5.10</h2>
<p>New: Optimize node reuse logic using LRU caching algorithm.</p>
<h2>0.5.10-fix.1</h2>
<p>Fix: Fix the issue of import errors.</p>
<h2>0.5.10-fix.2</h2>
<p>Fix: Fixed the issue of switching themes and importing data without triggering data changes in rich text mode.</p>
<p>New: Add three new themes.</p>
<h2>0.5.9</h2>
<p>Change: Unified export method format, using <code>FileReader</code> instead of <code>URL.createObjectURL</code> to convert <code>blob</code> data.</p>
<h2>0.5.8</h2>
<p>optimization: 1.The position setting is not triggered when the node position does not change. 2.The unfolding and folding status does not change and does not trigger button updates.</p>
<p>New: 1.The default setting is to move the mouse over the node to display the expand and collapse buttons. 2.Support the list of icons that can be inserted into extended nodes.</p>
<h2>0.5.7</h2>
<p>Breaking changeIn rich text mode, exporting png has been changed to using html2canvas to convert the entire svg, greatly improving the export speed. However, html2canvas has a bug where the text color inline with the dom node in the foreignObject element cannot be recognized. Therefore, the text color of the exported node is fixed. However, compared to the previously unavailable state of the export, it can at least be exported quickly and smoothly.</p>
<p>optimization: Optimize the rich text node editing experience.</p>

View File

@@ -28,7 +28,7 @@ const mindMap = new MindMap({
| data | Object | {} | Mind map data, refer to: https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js | |
| layout | String | logicalStructure | Layout type, options: logicalStructure (logical structure diagram), mindMap (mind map), catalogOrganization (catalog organization diagram), organizationStructure (organization structure diagram)、timelinev0.5.4+, timeline、timeline2v0.5.4+, up down alternating timeline、fishbonev0.5.4+, fishbone diagram | |
| fishboneDegv0.5.4+ | Number | 45 | Set the diagonal angle of the fishbone structure diagram | |
| theme | String | default | Theme, options: default, classic, minions, pinkGrape, mint, gold, vitalityOrange, greenLeaf, dark2, skyGreen, classic2, classic3, classic4(v0.2.0+), classicGreen, classicBlue, blueSky, brainImpairedPink, dark, earthYellow, freshGreen, freshRed, romanticPurple, simpleBlack(v0.5.4+), courseGreen(v0.5.4+), coffee(v0.5.4+), redSpirit(v0.5.4+), blackHumour(v0.5.4+), lateNightOffice(v0.5.4+), blackGold(v0.5.4+) | |
| theme | String | default | Theme, options: default, classic, minions, pinkGrape, mint, gold, vitalityOrange, greenLeaf, dark2, skyGreen, classic2, classic3, classic4(v0.2.0+), classicGreen, classicBlue, blueSky, brainImpairedPink, dark, earthYellow, freshGreen, freshRed, romanticPurple, simpleBlack(v0.5.4+), courseGreen(v0.5.4+), coffee(v0.5.4+), redSpirit(v0.5.4+), blackHumour(v0.5.4+), lateNightOffice(v0.5.4+), blackGold(v0.5.4+)、、avocado(v.5.10-fix.2+)、autumn(v.5.10-fix.2+)、orangeJuice(v.5.10-fix.2+) | |
| themeConfig | Object | {} | Theme configuration, will be merged with the selected theme, available fields refer to: https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js | |
| scaleRatio | Number | 0.1 | The incremental scaling ratio | |
| maxTag | Number | 5 | The maximum number of tags displayed in the node, any additional tags will be discarded | |
@@ -59,6 +59,9 @@ const mindMap = new MindMap({
| nodeNoteTooltipZIndexv0.5.5+ | Number | 3000 | z-index of floating layer elements in node comments | |
| isEndNodeTextEditOnClickOuterv0.5.5+ | Boolean | true | Whether to end the editing status of node text when clicking on an area outside the canvas | |
| maxHistoryCountv0.5.6+ | Number | 1000 | | Maximum number of history records |
| alwaysShowExpandBtnv0.5.8+ | Boolean | false | Whether to always display the expand and collapse buttons of nodes, which are only displayed when the mouse is moved up and activated by default | |
| iconListv0.5.8+ | Array | [] | The icons that can be inserted into the extension node, and each item in the array is an object. Please refer to the "Icon Configuration" table below for the detailed structure of the object | |
| maxNodeCacheCountv0.5.10+ | Number | 1000 | The maximum number of cached nodes. To optimize performance, an internal node cache pool is maintained to reuse nodes. This attribute allows you to specify the maximum number of caches in the pool | |
### Watermark config
@@ -70,6 +73,14 @@ const mindMap = new MindMap({
| angle | Number | 30 | Tilt angle of watermark, range: [0, 90] |
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | Watermark text style |
### Icon Configuration
| Field Name | Type | Default Value | Description |
| ----------- | ------ | ------------------------------------------- | ------------------------------------------------------------ |
| name | String | | The name of the icon group |
| type | String | | Values for icon grouping |
| list | Array | | A list of icons under grouping, with each item in the array being an object, `{ name: '', icon: '' }``name`represents the name of the icon, `icon`represents the icon, Can be an `svg` icon, such as `<svg ...><path></path></svg>`, also can be a image `url`, or `base64` icon, such as `data:image/png;base64,...` |
## Static methods
### defineTheme(name, config)
@@ -129,10 +140,14 @@ List of all currently registered plugins.
## Instance methods
### getSvgData()
### getSvgData({ paddingX = 0, paddingY = 0 })
> v0.3.0+
`paddingX`: Padding x
`paddingY`: Padding y
Get the `svg` data and return an object. The detailed structure is as follows:
```js

View File

@@ -60,7 +60,7 @@
<td>theme</td>
<td>String</td>
<td>default</td>
<td>Theme, options: default, classic, minions, pinkGrape, mint, gold, vitalityOrange, greenLeaf, dark2, skyGreen, classic2, classic3, classic4(v0.2.0+), classicGreen, classicBlue, blueSky, brainImpairedPink, dark, earthYellow, freshGreen, freshRed, romanticPurple, simpleBlack(v0.5.4+), courseGreen(v0.5.4+), coffee(v0.5.4+), redSpirit(v0.5.4+), blackHumour(v0.5.4+), lateNightOffice(v0.5.4+), blackGold(v0.5.4+)</td>
<td>Theme, options: default, classic, minions, pinkGrape, mint, gold, vitalityOrange, greenLeaf, dark2, skyGreen, classic2, classic3, classic4(v0.2.0+), classicGreen, classicBlue, blueSky, brainImpairedPink, dark, earthYellow, freshGreen, freshRed, romanticPurple, simpleBlack(v0.5.4+), courseGreen(v0.5.4+), coffee(v0.5.4+), redSpirit(v0.5.4+), blackHumour(v0.5.4+), lateNightOffice(v0.5.4+), blackGold(v0.5.4+)avocado(v.5.10-fix.2+)autumn(v.5.10-fix.2+)orangeJuice(v.5.10-fix.2+)</td>
<td></td>
</tr>
<tr>
@@ -273,6 +273,27 @@
<td></td>
<td>Maximum number of history records</td>
</tr>
<tr>
<td>alwaysShowExpandBtnv0.5.8+</td>
<td>Boolean</td>
<td>false</td>
<td>Whether to always display the expand and collapse buttons of nodes, which are only displayed when the mouse is moved up and activated by default</td>
<td></td>
</tr>
<tr>
<td>iconListv0.5.8+</td>
<td>Array</td>
<td>[]</td>
<td>The icons that can be inserted into the extension node, and each item in the array is an object. Please refer to the &quot;Icon Configuration&quot; table below for the detailed structure of the object</td>
<td></td>
</tr>
<tr>
<td>maxNodeCacheCountv0.5.10+</td>
<td>Number</td>
<td>1000</td>
<td>The maximum number of cached nodes. To optimize performance, an internal node cache pool is maintained to reuse nodes. This attribute allows you to specify the maximum number of caches in the pool</td>
<td></td>
</tr>
</tbody>
</table>
<h3>Watermark config</h3>
@@ -318,6 +339,37 @@
</tr>
</tbody>
</table>
<h3>Icon Configuration</h3>
<table>
<thead>
<tr>
<th>Field Name</th>
<th>Type</th>
<th>Default Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>name</td>
<td>String</td>
<td></td>
<td>The name of the icon group</td>
</tr>
<tr>
<td>type</td>
<td>String</td>
<td></td>
<td>Values for icon grouping</td>
</tr>
<tr>
<td>list</td>
<td>Array</td>
<td></td>
<td>A list of icons under grouping, with each item in the array being an object, <code>{ name: '', icon: '' }</code><code>name</code>represents the name of the icon, <code>icon</code>represents the icon, Can be an <code>svg</code> icon, such as <code>&lt;svg ...&gt;&lt;path&gt;&lt;/path&gt;&lt;/svg&gt;</code>, also can be a image <code>url</code>, or <code>base64</code> icon, such as <code>data:image/png;base64,...</code></td>
</tr>
</tbody>
</table>
<h2>Static methods</h2>
<h3>defineTheme(name, config)</h3>
<blockquote>
@@ -361,10 +413,12 @@ mindMap.setTheme(<span class="hljs-string">&#x27;Theme name&#x27;</span>)
</blockquote>
<p>List of all currently registered plugins.</p>
<h2>Instance methods</h2>
<h3>getSvgData()</h3>
<h3>getSvgData({ paddingX = 0, paddingY = 0 })</h3>
<blockquote>
<p>v0.3.0+</p>
</blockquote>
<p><code>paddingX</code>: Padding x</p>
<p><code>paddingY</code>: Padding y</p>
<p>Get the <code>svg</code> data and return an object. The detailed structure is as follows:</p>
<pre class="hljs"><code>{
svg, <span class="hljs-comment">// Element, the overall svg element of the mind map graphics, including: svg (canvas container), g (actual mind map group)</span>

View File

@@ -15,14 +15,35 @@ After registration and instantiation of `MindMap`, the instance can be obtained
## Methods
All exported methods are asynchronous and return an instance of `Promise`. You can use the `then` method to obtain data, or use the `async await` function to obtain:
```js
mindMap.doExport.png().then((data) => {
// ...
})
const export = async () => {
let data = await mindMap.doExport.png()
// ...
}
```
The returned data is in the format of `data:URL`. You can create an `a` tag to trigger the download:
```js
let a = document.createElement('a')
a.href = 'xxx.png'// .png、.svg、.pdf、.md、.json、.smm
a.download = 'xxx'
a.click()
```
### png(name, transparent = false)
- `name`: Name, optional
- `transparent`: v0.5.7+, Specify whether the background of the exported image is transparent
Exports as `png`, an async method that returns image data, `data:url` data which
can be downloaded or displayed.
Exports as `png`.
### svg(name, plusCssText)
@@ -42,20 +63,7 @@ svg(
)
```
Exports as `svg`, an async method that returns `svg` data, `data:url` data which
can be downloaded or displayed.
### getSvgData()
Gets `svg` data, an async method that returns an object:
```js
{
node; // svg object
str; // svg string, if rich text editing is enabled and domToImage is set to true, the dom node in the svg character returned by this value will be converted into the form of an image
nodeWithDomToImg// v0.4.0+The svg object after the DOM node is converted to an image has a value only when rich text editing is enabled and domToImage is set to true, otherwise null
}
```
Exports as `svg`.
### pdf(name)
@@ -63,7 +71,7 @@ Gets `svg` data, an async method that returns an object:
`name`File name
Export as `pdf`
Export as `pdf`. Unlike other export methods, this method does not return data and directly triggers the download.
### json(name, withConfig)
@@ -71,10 +79,21 @@ Export as `pdf`
`withConfig``Boolean`, default `true`, Whether the data contains configuration, otherwise it is pure mind map node data
Return `json` data, `data:url` type, you can download it yourself
Return `json` data.
### md()
> v0.4.7+
Export as `markdown` file, Return `json` data, `data:url` type, you can download it yourself
Export as `markdown` file.
### getSvgData()
Gets `svg` data, an async method that returns an object:
```js
{
node // svg node
str // svg string
}
```

View File

@@ -10,6 +10,22 @@ MindMap.usePlugin(Export)
</code></pre>
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.doExport</code>.</p>
<h2>Methods</h2>
<p>All exported methods are asynchronous and return an instance of <code>Promise</code>. You can use the <code>then</code> method to obtain data, or use the <code>async await</code> function to obtain:</p>
<pre class="hljs"><code>mindMap.doExport.png().then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
<span class="hljs-comment">// ...</span>
})
<span class="hljs-keyword">const</span> <span class="hljs-keyword">export</span> = <span class="hljs-keyword">async</span> () =&gt; {
<span class="hljs-keyword">let</span> data = <span class="hljs-keyword">await</span> mindMap.doExport.png()
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>The returned data is in the format of <code>data:URL</code>. You can create an <code>a</code> tag to trigger the download:</p>
<pre class="hljs"><code><span class="hljs-keyword">let</span> a = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">&#x27;a&#x27;</span>)
a.href = <span class="hljs-string">&#x27;xxx.png&#x27;</span><span class="hljs-comment">// .png、.svg、.pdf、.md、.json、.smm</span>
a.download = <span class="hljs-string">&#x27;xxx&#x27;</span>
a.click()
</code></pre>
<h3>png(name, transparent = false)</h3>
<ul>
<li>
@@ -19,8 +35,7 @@ MindMap.usePlugin(Export)
<p><code>transparent</code>: v0.5.7+, Specify whether the background of the exported image is transparent</p>
</li>
</ul>
<p>Exports as <code>png</code>, an async method that returns image data, <code>data:url</code> data which
can be downloaded or displayed.</p>
<p>Exports as <code>png</code>.</p>
<h3>svg(name, plusCssText)</h3>
<ul>
<li>
@@ -40,31 +55,29 @@ can be downloaded or displayed.</p>
}`</span>
)
</code></pre>
<p>Exports as <code>svg</code>, an async method that returns <code>svg</code> data, <code>data:url</code> data which
can be downloaded or displayed.</p>
<h3>getSvgData()</h3>
<p>Gets <code>svg</code> data, an async method that returns an object:</p>
<pre class="hljs"><code>{
node; <span class="hljs-comment">// svg object</span>
str; <span class="hljs-comment">// svg string, if rich text editing is enabled and domToImage is set to true, the dom node in the svg character returned by this value will be converted into the form of an image</span>
nodeWithDomToImg<span class="hljs-comment">// v0.4.0+The svg object after the DOM node is converted to an image has a value only when rich text editing is enabled and domToImage is set to true, otherwise null</span>
}
</code></pre>
<p>Exports as <code>svg</code>.</p>
<h3>pdf(name)</h3>
<blockquote>
<p>v0.2.1+</p>
</blockquote>
<p><code>name</code>File name</p>
<p>Export as <code>pdf</code></p>
<p>Export as <code>pdf</code>. Unlike other export methods, this method does not return data and directly triggers the download.</p>
<h3>json(name, withConfig)</h3>
<p><code>name</code>It is temporarily useless, just pass an empty string</p>
<p><code>withConfig``Boolean</code>, default <code>true</code>, Whether the data contains configuration, otherwise it is pure mind map node data</p>
<p>Return <code>json</code> data, <code>data:url</code> type, you can download it yourself</p>
<p>Return <code>json</code> data.</p>
<h3>md()</h3>
<blockquote>
<p>v0.4.7+</p>
</blockquote>
<p>Export as <code>markdown</code> file, Return <code>json</code> data, <code>data:url</code> type, you can download it yourself</p>
<p>Export as <code>markdown</code> file.</p>
<h3>getSvgData()</h3>
<p>Gets <code>svg</code> data, an async method that returns an object:</p>
<pre class="hljs"><code>{
node <span class="hljs-comment">// svg node</span>
str <span class="hljs-comment">// svg string</span>
}
</code></pre>
</div>
</template>

View File

@@ -3,6 +3,8 @@
`simple-mind-map` is a simple and powerful web mind map library, not dependent on any specific framework. Can help you quickly develop mind mapping products.
> If you just want to use mind mapping, you can also use the demo of this project as a regular online mind mapping tool. Click on the 【Online Demo】 in the upper right corner to start using it.
>
> Additionally, a client is provided for download, support `Windows`、`Mac` and `Linux`, [Click here to learn more](/mind-map/#/doc/zh/client)。
## Features
@@ -97,6 +99,18 @@ These open-source mind maps are also good, each with its own characteristics, bu
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.
## Browser Compatibility
We recommend using the latest version of the `Chrome` browser.
Limited testing situation:
Normal operation: `360` extreme speed browserv13.5.2036.0)、`opera` browserv71.0.3770.284)。
Abnormal operation: `Firefox`v98.0.2, Node content cannot be displayed in rich text mode. If you want to support the `Firefox` browser, please use non rich text mode.
Unsupported: `IE` browser.
## License
[MIT](https://opensource.org/licenses/MIT)

View File

@@ -4,24 +4,25 @@
<p><code>simple-mind-map</code> is a simple and powerful web mind map library, not dependent on any specific framework. Can help you quickly develop mind mapping products.</p>
<blockquote>
<p>If you just want to use mind mapping, you can also use the demo of this project as a regular online mind mapping tool. Click on the Online Demo in the upper right corner to start using it.</p>
<p>Additionally, a client is provided for download, support <code>Windows</code><code>Mac</code> and <code>Linux</code>, <a href="/mind-map/#/doc/zh/client">Click here to learn more</a></p>
</blockquote>
<h2>Features</h2>
<ul>
<li><input type="checkbox" id="checkbox18" checked="true" /><label for="checkbox18">Plugin architecture. In addition to core functions, other functions are provided as plugins, which can be used as needed to reduce the overall volume</label></li>
<li><input type="checkbox" id="checkbox19" checked="true" /><label for="checkbox19">Supports six types of structures: logical structure diagrams, mind maps,</label>
<li><input type="checkbox" id="checkbox90" checked="true" /><label for="checkbox90">Plugin architecture. In addition to core functions, other functions are provided as plugins, which can be used as needed to reduce the overall volume</label></li>
<li><input type="checkbox" id="checkbox91" checked="true" /><label for="checkbox91">Supports six types of structures: logical structure diagrams, mind maps,</label>
organizational structure diagrams, directory organization diagrams, timeline, and fishbone diagrams</li>
<li><input type="checkbox" id="checkbox20" checked="true" /><label for="checkbox20">Built-in multiple themes and allows for highly customized styles, and support register new themes</label></li>
<li><input type="checkbox" id="checkbox21" checked="true" /><label for="checkbox21">Supports shortcuts</label></li>
<li><input type="checkbox" id="checkbox22" checked="true" /><label for="checkbox22">Node content supports images, icons, hyperlinks, notes, tags, and</label>
<li><input type="checkbox" id="checkbox92" checked="true" /><label for="checkbox92">Built-in multiple themes and allows for highly customized styles, and support register new themes</label></li>
<li><input type="checkbox" id="checkbox93" checked="true" /><label for="checkbox93">Supports shortcuts</label></li>
<li><input type="checkbox" id="checkbox94" checked="true" /><label for="checkbox94">Node content supports images, icons, hyperlinks, notes, tags, and</label>
summaries</li>
<li><input type="checkbox" id="checkbox23" checked="true" /><label for="checkbox23">Supports forward and backward navigation</label></li>
<li><input type="checkbox" id="checkbox24" checked="true" /><label for="checkbox24">Supports dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox25" checked="true" /><label for="checkbox25">Supports right-click and Ctrl + left-click to select multiple items</label></li>
<li><input type="checkbox" id="checkbox26" checked="true" /><label for="checkbox26">Supports free dragging and dragging to adjust nodes</label></li>
<li><input type="checkbox" id="checkbox27" checked="true" /><label for="checkbox27">Supports various node shapes</label></li>
<li><input type="checkbox" id="checkbox28" checked="true" /><label for="checkbox28">Supports export to json, png, svg, pdf markdown, and import from json, xmind, markdown</label></li>
<li><input type="checkbox" id="checkbox29" checked="true" /><label for="checkbox29">Supports mini mapsupport watermark</label></li>
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Supports associative lines</label></li>
<li><input type="checkbox" id="checkbox95" checked="true" /><label for="checkbox95">Supports forward and backward navigation</label></li>
<li><input type="checkbox" id="checkbox96" checked="true" /><label for="checkbox96">Supports dragging and scaling</label></li>
<li><input type="checkbox" id="checkbox97" checked="true" /><label for="checkbox97">Supports right-click and Ctrl + left-click to select multiple items</label></li>
<li><input type="checkbox" id="checkbox98" checked="true" /><label for="checkbox98">Supports free dragging and dragging to adjust nodes</label></li>
<li><input type="checkbox" id="checkbox99" checked="true" /><label for="checkbox99">Supports various node shapes</label></li>
<li><input type="checkbox" id="checkbox100" checked="true" /><label for="checkbox100">Supports export to json, png, svg, pdf markdown, and import from json, xmind, markdown</label></li>
<li><input type="checkbox" id="checkbox101" checked="true" /><label for="checkbox101">Supports mini mapsupport watermark</label></li>
<li><input type="checkbox" id="checkbox102" checked="true" /><label for="checkbox102">Supports associative lines</label></li>
</ul>
<h2>Repository Catalog Introduction</h2>
<p>1.<code>simple-mind-map</code></p>
@@ -31,16 +32,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="checkbox31" checked="true" /><label for="checkbox31">Toolbar, which supports inserting and deleting nodes, and editing node</label>
<li><input type="checkbox" id="checkbox103" checked="true" /><label for="checkbox103">Toolbar, which supports inserting and deleting nodes, and editing node</label>
images, icons, hyperlinks, notes, tags, and summaries</li>
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">Sidebar, with panels for basic style settings, node style settings,</label>
<li><input type="checkbox" id="checkbox104" checked="true" /><label for="checkbox104">Sidebar, with panels for basic style settings, node style settings,</label>
outline, theme selection, and structure selection</li>
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">Import and export functionality; data is saved in the browser's local</label>
<li><input type="checkbox" id="checkbox105" checked="true" /><label for="checkbox105">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="checkbox34" checked="true" /><label for="checkbox34">Right-click menu, which supports operations such as expanding, collapsing,</label>
<li><input type="checkbox" id="checkbox106" checked="true" /><label for="checkbox106">Right-click menu, which supports operations such as expanding, collapsing,</label>
and organizing layout</li>
<li><input type="checkbox" id="checkbox35" checked="true" /><label for="checkbox35">Bottom bar, which supports node and word count statistics, switching</label>
<li><input type="checkbox" id="checkbox107" checked="true" /><label for="checkbox107">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>
@@ -69,6 +70,12 @@ full screen, support mini map</li>
<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>...</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>
<h2>Browser Compatibility</h2>
<p>We recommend using the latest version of the <code>Chrome</code> browser.</p>
<p>Limited testing situation:</p>
<p>Normal operation: <code>360</code> extreme speed browserv13.5.2036.0<code>opera</code> browserv71.0.3770.284</p>
<p>Abnormal operation: <code>Firefox</code>v98.0.2, Node content cannot be displayed in rich text mode. If you want to support the <code>Firefox</code> browser, please use non rich text mode.</p>
<p>Unsupported: <code>IE</code> browser.</p>
<h2>License</h2>
<p><a href="https://opensource.org/licenses/MIT">MIT</a></p>
<h2>Invite the author to a cup of coffee</h2>

View File

@@ -17,7 +17,7 @@ If you are using the file in the format of `umd`, you can obtain it in the follo
```
```js
MindMap.markdown
simpleMindMap.markdown
```
## Methods

View File

@@ -11,7 +11,7 @@
<p>If you are using the file in the format of <code>umd</code>, you can obtain it in the following way:</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;simple-mind-map/dist/simpleMindMap.umd.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<pre class="hljs"><code>MindMap.markdown
<pre class="hljs"><code>simpleMindMap.markdown
</code></pre>
<h2>Methods</h2>
<h3>transformToMarkdown(data)</h3>

View File

@@ -91,6 +91,7 @@ If you only use library, you don't need to read this section.
```bash
git clone https://github.com/wanglin2/mind-map.git
cd mind-map
cd simple-mind-map
npm i
npm link

View File

@@ -64,6 +64,7 @@ compile this dependency:</p>
<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

View File

@@ -1,6 +1,10 @@
# Participate in translation
Thanks for the first version English translation provided by [Emircan ERKUL](https://github.com/emircanerkul).
> Thanks for the first version English translation provided by [Emircan ERKUL](https://github.com/emircanerkul).
>
> Due to limited energy, most translations currently use machine translation, so accuracy is inevitably problematic.
>
> At present, the 【Course】 section is not translated. If you are interested, please join us.
If you want to participate in the translation of this document, you can clone this repository first.

View File

@@ -1,7 +1,11 @@
<template>
<div>
<h1>Participate in translation</h1>
<blockquote>
<p>Thanks for the first version English translation provided by <a href="https://github.com/emircanerkul">Emircan ERKUL</a>.</p>
<p>Due to limited energy, most translations currently use machine translation, so accuracy is inevitably problematic.</p>
<p>At present, the Course section is not translated. If you are interested, please join us.</p>
</blockquote>
<p>If you want to participate in the translation of this document, you can clone this repository first.</p>
<p>The translated documents are in the <code>/web/src/pages/Doc/</code> directory, and currently support English(<code>en</code>) and Simplified Chinese(<code>zh</code>).</p>
<p>If you are adding a new language type, you can create a new directory under the <code>/web/src/pages/Doc/</code> directory, Then create a folder for each chapter, You can also directly copy all chapter directories under the existing language directory for translation, Note that you only need to write the <code>index.md</code> file, The <code>index.vue</code> file under the chapter directory is automatically generated by the script according to <code>index.md</code>.</p>

View File

@@ -129,6 +129,16 @@ Measure the width and height of the text, return value:
{ width, height }
```
#### getTextFromHtml(html)
Extract plain text content from an HTML string.
#### readBlob(blob)
> v0.5.9+
Convert `blob` data to `data:url` data.
## Simulate CSS background in Canvas
Import:
@@ -157,4 +167,50 @@ drawBackgroundImageToCanvas(ctx, width, height, img, {
// success
}
})
```
```
## LRU cache class
> v0.5.10+
Import:
```js
import Lru from 'simple-mind-map/src/utils/Lru.js'
```
### Constructor
```js
let lru = new Lru(max)
```
`max`: Specify the maximum number of caches.
### Instance properties
#### size
The current number of caches.
#### pool
Get cache pool.
### Instance methods
#### add(key, value)
Add cache.
#### delete(key)
Delete cache.
#### has(key)
Check if a cache exists.
#### get(key)
Gets the value of a cache.

View File

@@ -82,6 +82,13 @@ and copying the <code>data</code> of the data object, example:</p>
<p>Measure the width and height of the text, return value:</p>
<pre class="hljs"><code>{ width, height }
</code></pre>
<h4>getTextFromHtml(html)</h4>
<p>Extract plain text content from an HTML string.</p>
<h4>readBlob(blob)</h4>
<blockquote>
<p>v0.5.9+</p>
</blockquote>
<p>Convert <code>blob</code> data to <code>data:url</code> data.</p>
<h2>Simulate CSS background in Canvas</h2>
<p>Import:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/utils/simulateCSSBackgroundInCanvas&#x27;</span>
@@ -105,6 +112,31 @@ drawBackgroundImageToCanvas(ctx, width, height, img, {
}
})
</code></pre>
<h2>LRU cache class</h2>
<blockquote>
<p>v0.5.10+</p>
</blockquote>
<p>Import:</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> Lru <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/utils/Lru.js&#x27;</span>
</code></pre>
<h3>Constructor</h3>
<pre class="hljs"><code><span class="hljs-keyword">let</span> lru = <span class="hljs-keyword">new</span> Lru(max)
</code></pre>
<p><code>max</code>: Specify the maximum number of caches.</p>
<h3>Instance properties</h3>
<h4>size</h4>
<p>The current number of caches.</p>
<h4>pool</h4>
<p>Get cache pool.</p>
<h3>Instance methods</h3>
<h4>add(key, value)</h4>
<p>Add cache.</p>
<h4>delete(key)</h4>
<p>Delete cache.</p>
<h4>has(key)</h4>
<p>Check if a cache exists.</p>
<h4>get(key)</h4>
<p>Gets the value of a cache.</p>
</div>
</template>

View File

@@ -17,7 +17,7 @@ If you are using the file in the format of `umd`, you can obtain it in the follo
```
```js
MindMap.xmind
simpleMindMap.xmind
```
## Methods

View File

@@ -11,7 +11,7 @@
<p>If you are using the file in the format of <code>umd</code>, you can obtain it in the following way:</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;simple-mind-map/dist/simpleMindMap.umd.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<pre class="hljs"><code>MindMap.xmind
<pre class="hljs"><code>simpleMindMap.xmind
</code></pre>
<h2>Methods</h2>
<h3>xmind.parseXmindFile(file)</h3>

View File

@@ -25,6 +25,7 @@ export default [
{ path: 'course16', title: '如何渲染富文本的悬浮工具栏' },
{ path: 'course17', title: '导入和导出' },
{ path: 'course18', title: '如何持久化数据' },
{ path: 'course19', title: '插入和扩展节点图标' },
{ path: 'doExport', title: 'Export 插件' },
{ path: 'drag', title: 'Drag插件' },
{ path: 'introduction', title: '简介' },
@@ -42,7 +43,8 @@ export default [
{ path: 'view', title: 'View实例' },
{ path: 'watermark', title: 'Watermark插件' },
{ path: 'xmind', title: 'XMind解析' },
{ path: 'deploy', title: '部署' }
{ path: 'deploy', title: '部署' },
{ path: 'client', title: '客户端' }
]
},
{

View File

@@ -4,9 +4,9 @@
> 调整关联线控制点的功能从v0.4.6+开始支持
该插件用于支持添加关联线。
> 关联性支持文本编辑从v0.5.11+开始支持
该插件目前功能还不完善,不支持在关联线上添加文字
该插件用于支持添加关联线
## 注册

View File

@@ -7,8 +7,10 @@
<blockquote>
<p>调整关联线控制点的功能从v0.4.6+开始支持</p>
</blockquote>
<blockquote>
<p>关联性支持文本编辑从v0.5.11+开始支持</p>
</blockquote>
<p>该插件用于支持添加关联线</p>
<p>该插件目前功能还不完善不支持在关联线上添加文字</p>
<h2>注册</h2>
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map&#x27;</span>
<span class="hljs-keyword">import</span> AssociativeLine <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/AssociativeLine.js&#x27;</span>

View File

@@ -1,5 +1,35 @@
# Changelog
## 0.5.11
新增:支持关联性文本编辑。
优化:优化主题配置更新,改变不涉及节点大小的配置不触发节点重新计算。
## 0.5.10
新增使用LRU缓存算法优化节点复用逻辑。
## 0.5.10-fix.1
修复:修复导入出错的问题。
## 0.5.10-fix.2
修复:修复富文本模式下,切换主题、导入数据后没有触发数据改变的问题。
新增:新增三种主题。
## 0.5.9
修改:统一导出方法的格式,使用`FileReader`代替`URL.createObjectURL`转换`blob`数据。
## 0.5.8
优化1.节点位置没有变化不触发位置设置。 2.展开收起状态没有变化不触发按钮更新。
新增1.默认改为鼠标移上节点才显示展开收起按钮。 2.支持扩展节点可插入的图标列表。
## 0.5.7
破坏性更新富文本模式下导出png改为使用html2canvas转换整个svg大幅提高导出速度不过html2canvas存在一个bugforeignObject元素中的dom节点内联的文字颜色无法识别所以导出节点的文字颜色是固定的不过相对于之前的导出基本不可用状态目前至少能快速顺利的导出。

View File

@@ -1,6 +1,21 @@
<template>
<div>
<h1>Changelog</h1>
<h2>0.5.11</h2>
<p>新增支持关联性文本编辑</p>
<p>优化优化主题配置更新改变不涉及节点大小的配置不触发节点重新计算</p>
<h2>0.5.10</h2>
<p>新增使用LRU缓存算法优化节点复用逻辑</p>
<h2>0.5.10-fix.1</h2>
<p>修复修复导入出错的问题</p>
<h2>0.5.10-fix.2</h2>
<p>修复修复富文本模式下切换主题导入数据后没有触发数据改变的问题</p>
<p>新增新增三种主题</p>
<h2>0.5.9</h2>
<p>修改统一导出方法的格式使用<code>FileReader</code>代替<code>URL.createObjectURL</code>转换<code>blob</code>数据</p>
<h2>0.5.8</h2>
<p>优化1.节点位置没有变化不触发位置设置 2.展开收起状态没有变化不触发按钮更新</p>
<p>新增1.默认改为鼠标移上节点才显示展开收起按钮 2.支持扩展节点可插入的图标列表</p>
<h2>0.5.7</h2>
<p>破坏性更新富文本模式下导出png改为使用html2canvas转换整个svg大幅提高导出速度不过html2canvas存在一个bugforeignObject元素中的dom节点内联的文字颜色无法识别所以导出节点的文字颜色是固定的不过相对于之前的导出基本不可用状态目前至少能快速顺利的导出</p>
<p>优化优化富文本节点编辑体验</p>

View File

@@ -0,0 +1,80 @@
# 客户端
本项目也提供了客户端版本,使用[Electron](https://www.electronjs.org/)开发。支持`Windows``Mac``Linux`
目前功能比较简单:
1.支持新建、打开文件进行编辑;
2.支持查看最近编辑文件列表;
3.支持文件的复制、删除、重命名;
## 下载
你可以直接下载对应的客户端安装使用,提供了两个下载地址:
Github[releases](https://github.com/wanglin2/mind-map/releases)。
百度云盘:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
## 开发
如果有需要,你也可以进行二次开发。
### clone
```bash
git clone https://github.com/wanglin2/mind-map.git
cd mind-map
git checkout electron
```
### 启动服务
在项目根目录下执行:
```bash
cd simple-mind-map
npm i
npm link
cd ..
cd web
npm i
npm link simple-mind-map
npm run electron:serve
```
### 打包客户端
你至少需要两台电脑,一台`Windows`和一台`Mac`
打包`Windows`应用:
```bash
npm run electron:build-win
```
打包`Mac`应用:
```bash
npm run electron:build-mac
```
打包`Linux`应用:
```bash
npm run electron:build-linux
```
打包全部应用:
```bash
npm run electron:build-all
```
根据你的电脑系统自动打包:
```bash
npm run electron:build
```

View File

@@ -0,0 +1,60 @@
<template>
<div>
<h1>客户端</h1>
<p>本项目也提供了客户端版本使用<a href="https://www.electronjs.org/">Electron</a>开发支持<code>Windows</code><code>Mac</code><code>Linux</code></p>
<p>目前功能比较简单</p>
<p>1.支持新建打开文件进行编辑</p>
<p>2.支持查看最近编辑文件列表</p>
<p>3.支持文件的复制删除重命名</p>
<h2>下载</h2>
<p>你可以直接下载对应的客户端安装使用提供了两个下载地址</p>
<p>Github<a href="https://github.com/wanglin2/mind-map/releases">releases</a></p>
<p>百度云盘<a href="https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3">地址</a></p>
<h2>开发</h2>
<p>如果有需要你也可以进行二次开发</p>
<h3>clone</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
git checkout electron
</code></pre>
<h3>启动服务</h3>
<p>在项目根目录下执行</p>
<pre class="hljs"><code><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 electron:serve
</code></pre>
<h3>打包客户端</h3>
<p>你至少需要两台电脑一台<code>Windows</code>和一台<code>Mac</code></p>
<p>打包<code>Windows</code>应用</p>
<pre class="hljs"><code>npm run electron:build-win
</code></pre>
<p>打包<code>Mac</code>应用</p>
<pre class="hljs"><code>npm run electron:build-mac
</code></pre>
<p>打包<code>Linux</code>应用</p>
<pre class="hljs"><code>npm run electron:build-linux
</code></pre>
<p>打包全部应用</p>
<pre class="hljs"><code>npm run electron:build-all
</code></pre>
<p>根据你的电脑系统自动打包</p>
<pre class="hljs"><code>npm run electron:build
</code></pre>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@@ -28,7 +28,7 @@ const mindMap = new MindMap({
| data | Object | {} | 思维导图数据,可参考:[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) | |
| layout | String | logicalStructure | 布局类型可选列表logicalStructure逻辑结构图、mindMap思维导图、catalogOrganization目录组织图、organizationStructure组织结构图、timelinev0.5.4+时间轴、timeline2v0.5.4+上下交替型时间轴、fishbonev0.5.4+,鱼骨图) | |
| fishboneDegv0.5.4+ | Number | 45 | 设置鱼骨结构图的斜线角度 | |
| theme | String | default | 主题可选列表default默认、classic脑图经典、minions小黄人、pinkGrape粉红葡萄、mint薄荷、gold金色vip、vitalityOrange活力橙、greenLeaf绿叶、dark2暗色2、skyGreen天清绿、classic2脑图经典2、classic3脑图经典3、classic4脑图经典4v0.2.0+、classicGreen经典绿、classicBlue经典蓝、blueSky天空蓝、brainImpairedPink脑残粉、dark暗色、earthYellow泥土黄、freshGreen清新绿、freshRed清新红、romanticPurple浪漫紫、simpleBlackv0.5.4+简约黑、courseGreenv0.5.4+课程绿、coffeev0.5.4+咖啡、redSpiritv0.5.4+红色精神、blackHumourv0.5.4+黑色幽默、lateNightOfficev0.5.4+深夜办公室、blackGoldv0.5.4+黑金) | |
| theme | String | default | 主题可选列表default默认、classic脑图经典、minions小黄人、pinkGrape粉红葡萄、mint薄荷、gold金色vip、vitalityOrange活力橙、greenLeaf绿叶、dark2暗色2、skyGreen天清绿、classic2脑图经典2、classic3脑图经典3、classic4脑图经典4v0.2.0+、classicGreen经典绿、classicBlue经典蓝、blueSky天空蓝、brainImpairedPink脑残粉、dark暗色、earthYellow泥土黄、freshGreen清新绿、freshRed清新红、romanticPurple浪漫紫、simpleBlackv0.5.4+简约黑、courseGreenv0.5.4+课程绿、coffeev0.5.4+咖啡、redSpiritv0.5.4+红色精神、blackHumourv0.5.4+黑色幽默、lateNightOfficev0.5.4+深夜办公室、blackGoldv0.5.4+黑金)、avocadov.5.10-fix.2+牛油果、autumnv.5.10-fix.2+秋天、orangeJuicev.5.10-fix.2+橙汁) | |
| themeConfig | Object | {} | 主题配置,会和所选择的主题进行合并,可用字段可参考:[https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js) | |
| scaleRatio | Number | 0.1 | 放大缩小的增量比例 | |
| maxTag | Number | 5 | 节点里最多显示的标签数量,多余的会被丢弃 | |
@@ -59,6 +59,9 @@ const mindMap = new MindMap({
| nodeNoteTooltipZIndexv0.5.5+ | Number | 3000 | 节点备注浮层元素的z-index | |
| isEndNodeTextEditOnClickOuterv0.5.5+ | Boolean | true | 是否在点击了画布外的区域时结束节点文本的编辑状态 | |
| maxHistoryCountv0.5.6+ | Number | 1000 | 最大历史记录数 | |
| alwaysShowExpandBtnv0.5.8+ | Boolean | false | 是否一直显示节点的展开收起按钮,默认为鼠标移上去和激活时才显示 | |
| iconListv0.5.8+ | Array | [] | 扩展节点可插入的图标,数组的每一项为一个对象,对象详细结构请参考下方【图标配置】表格 | |
| maxNodeCacheCountv0.5.10+ | Number | 1000 | 节点最大缓存数量。为了优化性能,内部会维护一个节点缓存池,用来复用节点,通过该属性可以指定池的最大缓存数量 | |
### 水印配置
@@ -70,7 +73,13 @@ const mindMap = new MindMap({
| angle | Number | 30 | 水印的倾斜角度,范围:[0, 90] |
| textStyle | Object | {color: '#999', opacity: 0.5, fontSize: 14} | 水印文字样式 |
### 图标配置
| 字段名称 | 类型 | 默认值 | 描述 |
| ----------- | ------ | ------------------------------------------- | ------------------------------------ |
| name | String | | 图标分组的名称 |
| type | String | | 图标分组的值 |
| list | Array | | 分组下的图标列表,数组的每一项为一个对象,`{ name: '', icon: '' }``name`代表图标的名称,`icon`代表图标,可以是`svg`图标,比如`<svg ...><path></path></svg>`,也可以是图片`url`,或者是`base64`图标,比如`data:image/png;base64,...` |
## 静态方法
@@ -129,10 +138,14 @@ mindMap.setTheme('主题名称')
## 实例方法
### getSvgData()
### getSvgData({ paddingX = 0, paddingY = 0 })
> v0.3.0+
`paddingX`:水平内边距
`paddingY`:垂直内边距
获取`svg`数据,返回一个对象,详细结构如下:
```js

View File

@@ -60,7 +60,7 @@
<td>theme</td>
<td>String</td>
<td>default</td>
<td>主题可选列表default默认classic脑图经典minions小黄人pinkGrape粉红葡萄mint薄荷gold金色vipvitalityOrange活力橙greenLeaf绿叶dark2暗色2skyGreen天清绿classic2脑图经典2classic3脑图经典3classic4脑图经典4v0.2.0+classicGreen经典绿classicBlue经典蓝blueSky天空蓝brainImpairedPink脑残粉dark暗色earthYellow泥土黄freshGreen清新绿freshRed清新红romanticPurple浪漫紫simpleBlackv0.5.4+简约黑courseGreenv0.5.4+课程绿coffeev0.5.4+咖啡redSpiritv0.5.4+红色精神blackHumourv0.5.4+黑色幽默lateNightOfficev0.5.4+深夜办公室blackGoldv0.5.4+黑金</td>
<td>主题可选列表default默认classic脑图经典minions小黄人pinkGrape粉红葡萄mint薄荷gold金色vipvitalityOrange活力橙greenLeaf绿叶dark2暗色2skyGreen天清绿classic2脑图经典2classic3脑图经典3classic4脑图经典4v0.2.0+classicGreen经典绿classicBlue经典蓝blueSky天空蓝brainImpairedPink脑残粉dark暗色earthYellow泥土黄freshGreen清新绿freshRed清新红romanticPurple浪漫紫simpleBlackv0.5.4+简约黑courseGreenv0.5.4+课程绿coffeev0.5.4+咖啡redSpiritv0.5.4+红色精神blackHumourv0.5.4+黑色幽默lateNightOfficev0.5.4+深夜办公室blackGoldv0.5.4+黑金avocadov.5.10-fix.2+牛油果autumnv.5.10-fix.2+秋天orangeJuicev.5.10-fix.2+橙汁</td>
<td></td>
</tr>
<tr>
@@ -273,6 +273,27 @@
<td>最大历史记录数</td>
<td></td>
</tr>
<tr>
<td>alwaysShowExpandBtnv0.5.8+</td>
<td>Boolean</td>
<td>false</td>
<td>是否一直显示节点的展开收起按钮默认为鼠标移上去和激活时才显示</td>
<td></td>
</tr>
<tr>
<td>iconListv0.5.8+</td>
<td>Array</td>
<td>[]</td>
<td>扩展节点可插入的图标数组的每一项为一个对象对象详细结构请参考下方图标配置表格</td>
<td></td>
</tr>
<tr>
<td>maxNodeCacheCountv0.5.10+</td>
<td>Number</td>
<td>1000</td>
<td>节点最大缓存数量为了优化性能内部会维护一个节点缓存池用来复用节点通过该属性可以指定池的最大缓存数量</td>
<td></td>
</tr>
</tbody>
</table>
<h3>水印配置</h3>
@@ -318,6 +339,37 @@
</tr>
</tbody>
</table>
<h3>图标配置</h3>
<table>
<thead>
<tr>
<th>字段名称</th>
<th>类型</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>name</td>
<td>String</td>
<td></td>
<td>图标分组的名称</td>
</tr>
<tr>
<td>type</td>
<td>String</td>
<td></td>
<td>图标分组的值</td>
</tr>
<tr>
<td>list</td>
<td>Array</td>
<td></td>
<td>分组下的图标列表数组的每一项为一个对象<code>{ name: '', icon: '' }</code><code>name</code>代表图标的名称<code>icon</code>代表图标可以是<code>svg</code>图标比如<code>&lt;svg ...&gt;&lt;path&gt;&lt;/path&gt;&lt;/svg&gt;</code><code>url</code><code>base64</code><code>data:image/png;base64,...</code></td>
</tr>
</tbody>
</table>
<h2>静态方法</h2>
<h3>defineTheme(name, config)</h3>
<blockquote>
@@ -361,10 +413,12 @@ mindMap.setTheme(<span class="hljs-string">&#x27;主题名称&#x27;</span>)
</blockquote>
<p>当前注册的所有插件列表</p>
<h2>实例方法</h2>
<h3>getSvgData()</h3>
<h3>getSvgData({ paddingX = 0, paddingY = 0 })</h3>
<blockquote>
<p>v0.3.0+</p>
</blockquote>
<p><code>paddingX</code>水平内边距</p>
<p><code>paddingY</code>垂直内边距</p>
<p>获取<code>svg</code>数据返回一个对象详细结构如下</p>
<pre class="hljs"><code>{
svg, <span class="hljs-comment">// Element思维导图图形的整体svg元素包括svg画布容器、g实际的思维导图组</span>

View File

@@ -55,7 +55,7 @@
}
```
`icon`目前只能使用内置的图标,完整图标可以在[icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件中查看。
`icon`可以使用内置的图标,完整图标可以在[icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件中查看。也可以扩展图标,参考[扩展图标](https://wanglin2.github.io/mind-map/#/doc/zh/course19/%E6%89%A9%E5%B1%95%E5%9B%BE%E6%A0%87)。
创建实例时还支持传递其他很多选项参数,完整选项列表可以在[实例化选项](https://wanglin2.github.io/mind-map/#/doc/zh/constructor/%E5%AE%9E%E4%BE%8B%E5%8C%96%E9%80%89%E9%A1%B9)查看。

View File

@@ -46,7 +46,7 @@
<span class="hljs-attr">children</span>: []<span class="hljs-comment">// 子节点</span>
}
</code></pre>
<p><code>icon</code>目前只能使用内置的图标完整图标可以在<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js">icons.js</a>文件中查看</p>
<p><code>icon</code>可以使用内置的图标完整图标可以在<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js">icons.js</a>文件中查看也可以扩展图标参考<a href="https://wanglin2.github.io/mind-map/#/doc/zh/course19/%E6%89%A9%E5%B1%95%E5%9B%BE%E6%A0%87">扩展图标</a></p>
<p>创建实例时还支持传递其他很多选项参数完整选项列表可以在<a href="https://wanglin2.github.io/mind-map/#/doc/zh/constructor/%E5%AE%9E%E4%BE%8B%E5%8C%96%E9%80%89%E9%A1%B9">实例化选项</a>查看</p>
<p>这样得到的思维导图可以通过鼠标和快捷键进行操作比如单击某个节点可以激活它双击某个节点可以编辑节点文本按下<code>Tab</code>键会给当前激活的节点添加一个子节点按下<code>Enter</code>键会给当前激活的节点添加一个兄弟节点等等完整的快捷键列表可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/web/src/config/zh.js#L246">快捷键列表</a></p>
<p>当然有些功能还是需要UI界面的比如图标列表编辑超链接等等需要注意的是<code>simple-mind-map</code>库并不包含UI界面所以需要你自己开发然后通过<code>simple-mind-map</code>提供的相关API来操作本教程的其他章节会向你介绍如何使用</p>

View File

@@ -8,7 +8,17 @@
`.smm``simple-mind-map`自己定义的一种文件,其实就是`json`文件,换了一个扩展名而已。
导出直接调用`export`方法即可
导出直接调用`export`方法即可
```js
mindMap.export(type, isDownload, fileName, ...)
```
`type`:文件类型
`isDownload`:传`true`会触发下载,`false`则不会,函数会返回导出文件的数据,`data:url`格式,你可以自行下载,`pdf`不支持该参数,默认会直接下载。
`fileName`:下载的文件名称
### 导出为smm、json

View File

@@ -7,7 +7,12 @@
</blockquote>
<p>目前支持导出为<code>.smm</code><code>.json</code><code>.svg</code><code>.png</code><code>.pdf</code><code>.md</code>文件</p>
<p><code>.smm</code><code>simple-mind-map</code>自己定义的一种文件其实就是<code>json</code>文件换了一个扩展名而已</p>
<p>导出直接调用<code>export</code>方法即可</p>
<p>导出直接调用<code>export</code>方法即可</p>
<pre class="hljs"><code>mindMap.export(type, isDownload, fileName, ...)
</code></pre>
<p><code>type</code>文件类型</p>
<p><code>isDownload</code><code>true</code>会触发下载<code>false</code>则不会函数会返回导出文件的数据<code>data:url</code>格式你可以自行下载<code>pdf</code>不支持该参数默认会直接下载</p>
<p><code>fileName</code>下载的文件名称</p>
<h3>导出为smmjson</h3>
<p>这两种文件的导出是一样的</p>
<pre class="hljs"><code>mindMap.export(type, isDownload, fileName, withConfig)

View File

@@ -0,0 +1,74 @@
# 插入和扩展节点图标
## 插入图标
`simple-mind-map`内置了一些图标:
<img src="../../../../assets/img/iconList.jpg" />
你可以通过如下方式获取:
```js
import { nodeIconList } from 'simple-mind-map/src/svg/icons'
```
如果你使用的是`umd`格式的文件可以通过如下方式获取v0.5.8+
```js
simpleMindMap.iconList
```
结构如下:
```js
[
{
name: '优先级图标',
type: 'priority',
list: [
{
name: '1',
icon: `<svg viewBox="0 0 1024 1024"><path d="M512.042667 1024C229.248 1024 0 794.794667 0 511.957333 0 229.205333 229.248 0 512.042667 0 794.752 0 1024 229.205333 1024 511.957333 1024 794.794667 794.752 1024 512.042667 1024z" fill="#E93B30"></path><path d="M580.309333 256h-75.52c-10.666667 29.824-30.165333 55.765333-58.709333 78.165333-28.416 22.314667-54.869333 37.418667-79.146667 45.397334v84.608a320 320 0 0 0 120.234667-70.698667v352.085333H580.266667V256z" fill="#FFFFFF"></path></svg>`
}
]
}
]
```
你可以通过UI界面展示出来要给一个节点设置图标可以使用`node.setIcon([])`方法,要获取节点当前的图标,可以使用`node.getData('icon')`方法。
一个图标由`type_name`构成,比如前面的图标要插入节点,那么图标的值为`priority_1`
通常一个分组的图标只允许插入一个,所以存在一个替换的逻辑,完整示例如下:
<iframe style="width: 100%; height: 455px; border: none;" src="https://wanglin2.github.io/playground/#eNrFVltvG0UU/ivDIrRrcNZ2xZOxowLtQySCUF+9UbTZHdtDd2dWO7NJrNRSqYooVSpQkVBLkAjQFIRU9ZFeBP0zsWP+Befs7M0bV2qe+mBr51y+78y5zMyB8XEU2bsJNbpGT3oxixSRVCXRusNZGIlYkQMS02GTCL4pEq6o3yRy7AaB2LtGh2RKhrEIiQkIZuGxybi/6UZa5RgSxAFdC0G6FrqRYzicEIcHVBGUoWWf8CQIHO5wT3CpiOsptks/Fz6VoCv5rMFWQ3t6SRxTrjbA/jMGHn0y2Cr9YQuoAamlJhFtEu6GtEH66+QAyRHgOp2AGrXkA2Jum/CPRqhutcj895vzX05m//ww+/be4u6ts1vP5w+ezr5/PHvyYPbzn4unJ7Ojf+fH3+RgsA26D3C1qOwhKDZQZzFFw4KfQEpVEnOipf0+RoOKKewu5dc8szsPZ3eO/3v4iAEgatiQWJrrHXBa6zRyvDqxjALmUW3bJJ0UdkpoIGnugSSwH2R4NP/xid6q3lW21fuHi8dfzb+7P/v65Oyn24Xq9NnN02d/nb28DUINhRnARKY7vUgWlvKQxqwsKEVj0N5Ks4Kg2lInRpdmOQTYweLV0eLXw/nRq/m937QZ5qmMqJar12ar8ICMNbEkGely4iqpm//9cnb3OC/OKuQokWOrgpTWAf8qHW7vukFC7aGIr7re2OIgq+QIl3bWz9bAtu0aBQ6Ezg/gOrwYU8sq+70yZnQvH08rI6BBl/jCS0IAtUdUXQ0ofn4y2fAtM/P8VHDlMk5js9HUXr6r3G6ZEsdAgWNURFqs6L5CsWPMj5/rSdIHQJqODAwNvTELfNgYGg9KjBrcSpY60+mLw7MXf9TJlglXkML5scruLUWQf2ay3I9xpq4JobBzvhCSKSY4eJoBHSqzSUwPSgdl2krNp42P9FlbtIANTWRiS23rBgQXC3rKjUeybJcV3QmtgzaDThYODtj5Fg4oH6kxWSftyrDh6TBksUxDRpy6G0z7a8YHrAtPbM0rkHvLxHkzG+TGjSJh9QFdfTmUA4jDAr9eS994cNfBAo6gKHAVhRUhPZ/tEi9wpew7Rpa7KzQUjpGqMwPml9piRMCk1wJt1TBHUkIEOy6a5KH2dhKl4Ka67MERdB1M8lE3o5iJmKkJVrVjNsAnl2x3ei3tdkGYS8swly4EI0YxlbIajZZcMJoSJo8mg6lHUyYx/+q1KjWCpVSTQJfrcvbycAy7pZ8b2SFnUxnanpSOUUyCXSln3jJ7zFfjLum02++ldoRExWzFFBihY1NF2j/4e7de9hyqdHR3pAgSpR1xDoaqS9rZSomoXJynH1M2GoP5h+12tJ8zr+Z9P2cOYUIZ8Oaokev7jI9yQRG6nXXhG0bcySPIgi7WAAgTlNbAaBq6AvjAs7+UgsN7MoV3MgVUoDgzHQOei/qgtFvwacdwY7GQYrHWdmKxJ2kMII6RnXkrnpDa93yp0SuLbWpM/wfhELfG" />
## 扩展图标
> v0.5.8+
除了使用内置的图标外,你也可以扩展图标,实例化`simple-mind-map`时传入你要扩展的图标列表即可:
```js
new MindMap({
// ...
iconList: [
{
name: '',// 分组名称
type: '',// 分组的值
list: [// 分组下的图标列表
{
name: '',// 图标名称
icon:''// 图标可以传svg或图片
}
]
}
]
})
```
然后和插入内置图标一样,通过`setIcon`方法插入图标的`key`即可。
完整示例:
<iframe style="width: 100%; height: 455px; border: none;" src="https://wanglin2.github.io/playground/#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" />

View File

@@ -0,0 +1,66 @@
<template>
<div>
<h1>插入和扩展节点图标</h1>
<h2>插入图标</h2>
<p><code>simple-mind-map</code>内置了一些图标</p>
<img src="../../../../assets/img/iconList.jpg" />
<p>你可以通过如下方式获取</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> { nodeIconList } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/svg/icons&#x27;</span>
</code></pre>
<p>如果你使用的是<code>umd</code>格式的文件可以通过如下方式获取v0.5.8+</p>
<pre class="hljs"><code>simpleMindMap.iconList
</code></pre>
<p>结构如下</p>
<pre class="hljs"><code>[
{
<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;优先级图标&#x27;</span>,
<span class="hljs-attr">type</span>: <span class="hljs-string">&#x27;priority&#x27;</span>,
<span class="hljs-attr">list</span>: [
{
<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;1&#x27;</span>,
<span class="hljs-attr">icon</span>: <span class="hljs-string">`&lt;svg viewBox=&quot;0 0 1024 1024&quot;&gt;&lt;path d=&quot;M512.042667 1024C229.248 1024 0 794.794667 0 511.957333 0 229.205333 229.248 0 512.042667 0 794.752 0 1024 229.205333 1024 511.957333 1024 794.794667 794.752 1024 512.042667 1024z&quot; fill=&quot;#E93B30&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M580.309333 256h-75.52c-10.666667 29.824-30.165333 55.765333-58.709333 78.165333-28.416 22.314667-54.869333 37.418667-79.146667 45.397334v84.608a320 320 0 0 0 120.234667-70.698667v352.085333H580.266667V256z&quot; fill=&quot;#FFFFFF&quot;&gt;&lt;/path&gt;&lt;/svg&gt;`</span>
}
]
}
]
</code></pre>
<p>你可以通过UI界面展示出来要给一个节点设置图标可以使用<code>node.setIcon([])</code>方法要获取节点当前的图标可以使用<code>node.getData('icon')</code>方法</p>
<p>一个图标由<code>type_name</code>构成比如前面的图标要插入节点那么图标的值为<code>priority_1</code></p>
<p>通常一个分组的图标只允许插入一个所以存在一个替换的逻辑完整示例如下</p>
<iframe style="width: 100%; height: 455px; border: none;" src="https://wanglin2.github.io/playground/#eNrFVltvG0UU/ivDIrRrcNZ2xZOxowLtQySCUF+9UbTZHdtDd2dWO7NJrNRSqYooVSpQkVBLkAjQFIRU9ZFeBP0zsWP+Befs7M0bV2qe+mBr51y+78y5zMyB8XEU2bsJNbpGT3oxixSRVCXRusNZGIlYkQMS02GTCL4pEq6o3yRy7AaB2LtGh2RKhrEIiQkIZuGxybi/6UZa5RgSxAFdC0G6FrqRYzicEIcHVBGUoWWf8CQIHO5wT3CpiOsptks/Fz6VoCv5rMFWQ3t6SRxTrjbA/jMGHn0y2Cr9YQuoAamlJhFtEu6GtEH66+QAyRHgOp2AGrXkA2Jum/CPRqhutcj895vzX05m//ww+/be4u6ts1vP5w+ezr5/PHvyYPbzn4unJ7Ojf+fH3+RgsA26D3C1qOwhKDZQZzFFw4KfQEpVEnOipf0+RoOKKewu5dc8szsPZ3eO/3v4iAEgatiQWJrrHXBa6zRyvDqxjALmUW3bJJ0UdkpoIGnugSSwH2R4NP/xid6q3lW21fuHi8dfzb+7P/v65Oyn24Xq9NnN02d/nb28DUINhRnARKY7vUgWlvKQxqwsKEVj0N5Ks4Kg2lInRpdmOQTYweLV0eLXw/nRq/m937QZ5qmMqJar12ar8ICMNbEkGely4iqpm//9cnb3OC/OKuQokWOrgpTWAf8qHW7vukFC7aGIr7re2OIgq+QIl3bWz9bAtu0aBQ6Ezg/gOrwYU8sq+70yZnQvH08rI6BBl/jCS0IAtUdUXQ0ofn4y2fAtM/P8VHDlMk5js9HUXr6r3G6ZEsdAgWNURFqs6L5CsWPMj5/rSdIHQJqODAwNvTELfNgYGg9KjBrcSpY60+mLw7MXf9TJlglXkML5scruLUWQf2ay3I9xpq4JobBzvhCSKSY4eJoBHSqzSUwPSgdl2krNp42P9FlbtIANTWRiS23rBgQXC3rKjUeybJcV3QmtgzaDThYODtj5Fg4oH6kxWSftyrDh6TBksUxDRpy6G0z7a8YHrAtPbM0rkHvLxHkzG+TGjSJh9QFdfTmUA4jDAr9eS994cNfBAo6gKHAVhRUhPZ/tEi9wpew7Rpa7KzQUjpGqMwPml9piRMCk1wJt1TBHUkIEOy6a5KH2dhKl4Ka67MERdB1M8lE3o5iJmKkJVrVjNsAnl2x3ei3tdkGYS8swly4EI0YxlbIajZZcMJoSJo8mg6lHUyYx/+q1KjWCpVSTQJfrcvbycAy7pZ8b2SFnUxnanpSOUUyCXSln3jJ7zFfjLum02++ldoRExWzFFBihY1NF2j/4e7de9hyqdHR3pAgSpR1xDoaqS9rZSomoXJynH1M2GoP5h+12tJ8zr+Z9P2cOYUIZ8Oaokev7jI9yQRG6nXXhG0bcySPIgi7WAAgTlNbAaBq6AvjAs7+UgsN7MoV3MgVUoDgzHQOei/qgtFvwacdwY7GQYrHWdmKxJ2kMII6RnXkrnpDa93yp0SuLbWpM/wfhELfG" />
<h2>扩展图标</h2>
<blockquote>
<p>v0.5.8+</p>
</blockquote>
<p>除了使用内置的图标外你也可以扩展图标实例化<code>simple-mind-map</code>时传入你要扩展的图标列表即可</p>
<pre class="hljs"><code><span class="hljs-keyword">new</span> MindMap({
<span class="hljs-comment">// ...</span>
<span class="hljs-attr">iconList</span>: [
{
<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// 分组名称</span>
<span class="hljs-attr">type</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// 分组的值</span>
<span class="hljs-attr">list</span>: [<span class="hljs-comment">// 分组下的图标列表</span>
{
<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;&#x27;</span>,<span class="hljs-comment">// 图标名称</span>
<span class="hljs-attr">icon</span>:<span class="hljs-string">&#x27;&#x27;</span><span class="hljs-comment">// 图标可以传svg或图片</span>
}
]
}
]
})
</code></pre>
<p>然后和插入内置图标一样通过<code>setIcon</code>方法插入图标的<code>key</code>即可</p>
<p>完整示例</p>
<iframe style="width: 100%; height: 455px; border: none;" src="https://wanglin2.github.io/playground/#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" />
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@@ -15,13 +15,35 @@ MindMap.usePlugin(Export)
## 方法
所有导出的方法都是异步方法,返回一个`Promise`实例,你可以使用`then`方法获取数据,或者使用`async await`函数获取:
```js
mindMap.doExport.png().then((data) => {
// ...
})
const export = async () => {
let data = await mindMap.doExport.png()
// ...
}
```
返回的数据为`data:url`格式的,你可以创建一个`a`标签来触发下载:
```js
let a = document.createElement('a')
a.href = 'xxx.png'// .png、.svg、.pdf、.md、.json、.smm
a.download = 'xxx'
a.click()
```
### png(name, transparent = false)
- `name`:名称,可不传
- `transparent`v0.5.7+,指定导出图片的背景是否是透明的
导出为`png`,异步方法,返回图片数据,`data:url`数据,可以自行下载或显示
导出为`png`
### svg(name, plusCssText)
@@ -41,19 +63,7 @@ svg(
)
```
导出为`svg`,异步方法,返回`svg`数据,`data:url`数据,可以自行下载或显示
### getSvgData()
获取`svg`数据,异步方法,返回一个对象:
```js
{
node// svg对象
str// svg字符串如果开启了富文本编辑且domToImage设为true那么该值返回的svg字符内的dom节点会被转换成图片的形式
nodeWithDomToImg// v0.4.0+DOM节点转换为图片后的svg对象只有当开启了富文本编辑且domToImage设为true才有值否则为null
}
```
导出为`svg`
### pdf(name)
@@ -61,7 +71,7 @@ svg(
`name`:文件名称
导出为`pdf`
导出为`pdf`,和其他导出方法不一样,这个方法不会返回数据,会直接触发下载。
### json(name, withConfig)
@@ -69,10 +79,25 @@ svg(
`withConfig``Boolean`, 默认为`true`,数据中是否包含配置,否则为纯思维导图节点数据
返回`json`数据`data:url`数据,可以自行下载
返回`json`数据
### smm(name, withConfig)
`simple-mind-map`自定义的文件格式,其实就是`json`,和`json`方法返回的数据一模一样。
### md()
> v0.4.7+
导出`markdown`文件,返回`data:url`数据,可以自行下载
导出`markdown`文件
### getSvgData()
获取`svg`数据,异步方法,返回一个对象:
```js
{
node// svg节点
str// svg字符串
}
```

View File

@@ -10,6 +10,22 @@ MindMap.usePlugin(Export)
</code></pre>
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.doExport</code>获取到该实例</p>
<h2>方法</h2>
<p>所有导出的方法都是异步方法返回一个<code>Promise</code>实例你可以使用<code>then</code>方法获取数据或者使用<code>async await</code>函数获取</p>
<pre class="hljs"><code>mindMap.doExport.png().then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
<span class="hljs-comment">// ...</span>
})
<span class="hljs-keyword">const</span> <span class="hljs-keyword">export</span> = <span class="hljs-keyword">async</span> () =&gt; {
<span class="hljs-keyword">let</span> data = <span class="hljs-keyword">await</span> mindMap.doExport.png()
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>返回的数据为<code>data:url</code>格式的你可以创建一个<code>a</code>标签来触发下载</p>
<pre class="hljs"><code><span class="hljs-keyword">let</span> a = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">&#x27;a&#x27;</span>)
a.href = <span class="hljs-string">&#x27;xxx.png&#x27;</span><span class="hljs-comment">// .png、.svg、.pdf、.md、.json、.smm</span>
a.download = <span class="hljs-string">&#x27;xxx&#x27;</span>
a.click()
</code></pre>
<h3>png(name, transparent = false)</h3>
<ul>
<li>
@@ -19,7 +35,7 @@ MindMap.usePlugin(Export)
<p><code>transparent</code>v0.5.7+指定导出图片的背景是否是透明的</p>
</li>
</ul>
<p>导出为<code>png</code>异步方法返回图片数据<code>data:url</code>数据可以自行下载或显示</p>
<p>导出为<code>png</code></p>
<h3>svg(name, plusCssText)</h3>
<ul>
<li>
@@ -39,30 +55,31 @@ MindMap.usePlugin(Export)
}`</span>
)
</code></pre>
<p>导出为<code>svg</code>异步方法返回<code>svg</code>数据<code>data:url</code>数据可以自行下载或显示</p>
<h3>getSvgData()</h3>
<p>获取<code>svg</code>数据异步方法返回一个对象</p>
<pre class="hljs"><code>{
node<span class="hljs-comment">// svg对象</span>
str<span class="hljs-comment">// svg字符串如果开启了富文本编辑且domToImage设为true那么该值返回的svg字符内的dom节点会被转换成图片的形式</span>
nodeWithDomToImg<span class="hljs-comment">// v0.4.0+DOM节点转换为图片后的svg对象只有当开启了富文本编辑且domToImage设为true才有值否则为null</span>
}
</code></pre>
<p>导出为<code>svg</code></p>
<h3>pdf(name)</h3>
<blockquote>
<p>v0.2.1+</p>
</blockquote>
<p><code>name</code>文件名称</p>
<p>导出为<code>pdf</code></p>
<p>导出为<code>pdf</code>和其他导出方法不一样这个方法不会返回数据会直接触发下载</p>
<h3>json(name, withConfig)</h3>
<p><code>name</code>暂时没有用处传空字符串即可</p>
<p><code>withConfig``Boolean</code>, 默认为<code>true</code>数据中是否包含配置否则为纯思维导图节点数据</p>
<p>返回<code>json</code>数据<code>data:url</code>数据可以自行下载</p>
<p>返回<code>json</code>数据</p>
<h3>smm(name, withConfig)</h3>
<p><code>simple-mind-map</code>自定义的文件格式其实就是<code>json</code><code>json</code>方法返回的数据一模一样</p>
<h3>md()</h3>
<blockquote>
<p>v0.4.7+</p>
</blockquote>
<p>导出<code>markdown</code>文件返回<code>data:url</code>数据可以自行下载</p>
<p>导出<code>markdown</code>文件</p>
<h3>getSvgData()</h3>
<p>获取<code>svg</code>数据异步方法返回一个对象</p>
<pre class="hljs"><code>{
node<span class="hljs-comment">// svg节点</span>
str<span class="hljs-comment">// svg字符串</span>
}
</code></pre>
</div>
</template>

View File

@@ -3,6 +3,8 @@
`simple-mind-map`是一个简单&强大的Web思维导图库不依赖任何特定框架。可以帮助你快速开发思维导图产品。
> 如果你只是想使用思维导图你也完全可以把本项目的demo作为一个普通的在线思维导图工具使用。点击右上角的【在线示例】开始使用吧。
>
> 另外也提供了客户端可供下载,支持`Windows`、`Mac`及`Linux`[点此了解更多](/mind-map/#/doc/zh/client)。
## 特性
@@ -86,6 +88,17 @@
综上,在开源的思维导图中,你很难找到一个比`simple-mind-map`更好的选择。当然,`simple-mind-map`也远远谈不上最好,它也有很多不足,如你在前面的【特别说明】所看到的那样,不过`simple-mind-map`一直处于快速迭代中,欢迎你加入进来一起完善它。
## 浏览器兼容性
推荐使用最新版`chrome`浏览器。
有限测试情况:
正常运行:`360`极速浏览器v13.5.2036.0)、`opera`浏览器v71.0.3770.284)。
非正常运行:`Firefox`v98.0.2),富文本模式下节点内容无法显示,如果要支持`Firefox`浏览器,请使用非富文本模式。
不支持:`IE`浏览器。
## License

View File

@@ -4,22 +4,23 @@
<p><code>simple-mind-map</code>是一个简单&amp;强大的Web思维导图库不依赖任何特定框架可以帮助你快速开发思维导图产品</p>
<blockquote>
<p>如果你只是想使用思维导图你也完全可以把本项目的demo作为一个普通的在线思维导图工具使用点击右上角的在线示例开始使用吧</p>
<p>另外也提供了客户端可供下载支持<code>Windows</code><code>Mac</code><code>Linux</code><a href="/mind-map/#/doc/zh/client">点此了解更多</a></p>
</blockquote>
<h2>特性</h2>
<ul>
<li><input type="checkbox" id="checkbox216" checked="true" /><label for="checkbox216">插件化架构除核心功能外其他功能作为插件提供按需使用减小整体体积</label></li>
<li><input type="checkbox" id="checkbox217" checked="true" /><label for="checkbox217">支持逻辑结构图思维导图组织结构图目录组织图时间轴鱼骨图六种结构</label></li>
<li><input type="checkbox" id="checkbox218" checked="true" /><label for="checkbox218">内置多种主题允许高度自定义样式支持注册新主题</label></li>
<li><input type="checkbox" id="checkbox219" checked="true" /><label for="checkbox219">支持快捷键</label></li>
<li><input type="checkbox" id="checkbox220" checked="true" /><label for="checkbox220">节点内容支持图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox221" checked="true" /><label for="checkbox221">支持前进后退</label></li>
<li><input type="checkbox" id="checkbox222" checked="true" /><label for="checkbox222">支持拖动缩放</label></li>
<li><input type="checkbox" id="checkbox223" checked="true" /><label for="checkbox223">支持右键和Ctrl+左键两种多选方式</label></li>
<li><input type="checkbox" id="checkbox224" checked="true" /><label for="checkbox224">支持节点自由拖拽拖拽调整</label></li>
<li><input type="checkbox" id="checkbox225" checked="true" /><label for="checkbox225">支持多种节点形状</label></li>
<li><input type="checkbox" id="checkbox226" checked="true" /><label for="checkbox226">支持导出为</label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code>支持从<code>json</code><code>xmind</code><code>markdown</code>导入</li>
<li><input type="checkbox" id="checkbox227" checked="true" /><label for="checkbox227">支持小地图支持水印</label></li>
<li><input type="checkbox" id="checkbox228" checked="true" /><label for="checkbox228">支持关联线</label></li>
<li><input type="checkbox" id="checkbox72" checked="true" /><label for="checkbox72">插件化架构除核心功能外其他功能作为插件提供按需使用减小整体体积</label></li>
<li><input type="checkbox" id="checkbox73" checked="true" /><label for="checkbox73">支持逻辑结构图思维导图组织结构图目录组织图时间轴鱼骨图六种结构</label></li>
<li><input type="checkbox" id="checkbox74" checked="true" /><label for="checkbox74">内置多种主题允许高度自定义样式支持注册新主题</label></li>
<li><input type="checkbox" id="checkbox75" checked="true" /><label for="checkbox75">支持快捷键</label></li>
<li><input type="checkbox" id="checkbox76" checked="true" /><label for="checkbox76">节点内容支持图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox77" checked="true" /><label for="checkbox77">支持前进后退</label></li>
<li><input type="checkbox" id="checkbox78" checked="true" /><label for="checkbox78">支持拖动缩放</label></li>
<li><input type="checkbox" id="checkbox79" checked="true" /><label for="checkbox79">支持右键和Ctrl+左键两种多选方式</label></li>
<li><input type="checkbox" id="checkbox80" checked="true" /><label for="checkbox80">支持节点自由拖拽拖拽调整</label></li>
<li><input type="checkbox" id="checkbox81" checked="true" /><label for="checkbox81">支持多种节点形状</label></li>
<li><input type="checkbox" id="checkbox82" checked="true" /><label for="checkbox82">支持导出为</label><code>json</code><code>png</code><code>svg</code><code>pdf</code><code>markdown</code>支持从<code>json</code><code>xmind</code><code>markdown</code>导入</li>
<li><input type="checkbox" id="checkbox83" checked="true" /><label for="checkbox83">支持小地图支持水印</label></li>
<li><input type="checkbox" id="checkbox84" checked="true" /><label for="checkbox84">支持关联线</label></li>
</ul>
<h2>仓库目录介绍</h2>
<p>1.<code>simple-mind-map</code></p>
@@ -27,11 +28,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="checkbox229" checked="true" /><label for="checkbox229">工具栏支持插入节点删除节点编辑节点图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox230" checked="true" /><label for="checkbox230">侧边栏基础样式设置面板节点样式设置面板大纲面板主题选择面板结构选择面板</label></li>
<li><input type="checkbox" id="checkbox231" checked="true" /><label for="checkbox231">导入导出功能数据默认保存在浏览器本地存储也支持直接创建打开编辑电脑本地文件</label></li>
<li><input type="checkbox" id="checkbox232" checked="true" /><label for="checkbox232">右键菜单支持展开收起整理布局等操作</label></li>
<li><input type="checkbox" id="checkbox233" checked="true" /><label for="checkbox233">底部栏支持节点数量字数统计支持切换编辑和只读模式支持放大缩小支持全屏切换支持小地图</label></li>
<li><input type="checkbox" id="checkbox85" checked="true" /><label for="checkbox85">工具栏支持插入节点删除节点编辑节点图片图标超链接备注标签概要</label></li>
<li><input type="checkbox" id="checkbox86" checked="true" /><label for="checkbox86">侧边栏基础样式设置面板节点样式设置面板大纲面板主题选择面板结构选择面板</label></li>
<li><input type="checkbox" id="checkbox87" checked="true" /><label for="checkbox87">导入导出功能数据默认保存在浏览器本地存储也支持直接创建打开编辑电脑本地文件</label></li>
<li><input type="checkbox" id="checkbox88" checked="true" /><label for="checkbox88">右键菜单支持展开收起整理布局等操作</label></li>
<li><input type="checkbox" id="checkbox89" checked="true" /><label for="checkbox89">底部栏支持节点数量字数统计支持切换编辑和只读模式支持放大缩小支持全屏切换支持小地图</label></li>
</ul>
<p>提供文档页面服务</p>
<p>3.<code>dist</code></p>
@@ -58,6 +59,12 @@
<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>...</p>
<p>这些开源的思维导图也都不错各有各的特点但是它们也都有一定缺点比如停止更新界面美观度一般功能比较少依赖某个框架等等</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>
<p>正常运行<code>360</code>极速浏览器v13.5.2036.0<code>opera</code>浏览器v71.0.3770.284</p>
<p>非正常运行<code>Firefox</code>v98.0.2富文本模式下节点内容无法显示如果要支持<code>Firefox</code>浏览器请使用非富文本模式</p>
<p>不支持<code>IE</code>浏览器</p>
<h2>License</h2>
<p><a href="https://opensource.org/licenses/MIT">MIT</a></p>
<h2>请作者喝杯咖啡</h2>

View File

@@ -17,7 +17,7 @@ import markdown from 'simple-mind-map/src/parse/markdown.js'
```
```js
MindMap.markdown
simpleMindMap.markdown
```
## 方法

View File

@@ -11,7 +11,7 @@
<p>如果使用的是<code>umd</code>格式的文件那么可以通过如下方式获取</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;simple-mind-map/dist/simpleMindMap.umd.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<pre class="hljs"><code>MindMap.markdown
<pre class="hljs"><code>simpleMindMap.markdown
</code></pre>
<h2>方法</h2>
<h3>transformToMarkdown(data)</h3>

View File

@@ -86,6 +86,7 @@ const mindMap = new MindMap({
```bash
git clone https://github.com/wanglin2/mind-map.git
cd mind-map
cd simple-mind-map
npm i
npm link

View File

@@ -58,6 +58,7 @@
<p>如果你只是使用库的话可以不用阅读此小节</p>
<h3>本地开发</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

View File

@@ -1,6 +1,10 @@
# 参与翻译
感谢[Emircan ERKUL](https://github.com/emircanerkul)提供的第一版英文翻译。
> 感谢[Emircan ERKUL](https://github.com/emircanerkul)提供的第一版英文翻译。
>
>因为精力有限,目前大部分翻译都是使用机翻的,所以准确度难免有问题。
>
>目前【教程】部分是没有进行翻译的,如果你有兴趣,欢迎加入我们。
如果你也想参与翻译本文档的话,可以先克隆本仓库。

View File

@@ -1,7 +1,11 @@
<template>
<div>
<h1>参与翻译</h1>
<blockquote>
<p>感谢<a href="https://github.com/emircanerkul">Emircan ERKUL</a>提供的第一版英文翻译</p>
<p>因为精力有限目前大部分翻译都是使用机翻的所以准确度难免有问题</p>
<p>目前教程部分是没有进行翻译的如果你有兴趣欢迎加入我们</p>
</blockquote>
<p>如果你也想参与翻译本文档的话可以先克隆本仓库</p>
<p>翻译的文档在<code>/web/src/pages/Doc/</code>目录下目前支持英文(<code>en</code>)简体中文(<code>zh</code>)两种语言</p>
<p>如果是新增一种语言类型那么可以在<code>/web/src/pages/Doc/</code>目录下创建一个新目录然后给每个章节创建一个文件夹你也可以直接复制已存在的语言目录下的所有章节目录进行翻译注意你只需要编写<code>index.md</code>文件章节目录下的<code>index.vue</code>文件是脚本根据<code>index.md</code>自动生成的</p>

View File

@@ -124,6 +124,16 @@ copyNodeTree({}, node)
{ width, height }
```
#### getTextFromHtml(html)
提取html字符串里的纯文本内容。
#### readBlob(blob)
> v0.5.9+
`blob`数据转成`data:url`数据。
## 在canvas中模拟css的背景属性
引入:
@@ -153,3 +163,49 @@ drawBackgroundImageToCanvas(ctx, width, height, img, {
}
})
```
## LRU缓存类
> v0.5.10+
引入:
```js
import Lru from 'simple-mind-map/src/utils/Lru.js'
```
### 构造函数
```js
let lru = new Lru(max)
```
`max`:指定最大缓存数量。
### 实例属性
#### size
当前缓存的数量。
#### pool
获取缓存池。
### 实例方法
#### add(key, value)
添加缓存。
#### delete(key)
删除指定缓存。
#### has(key)
检查某个缓存是否存在。
#### get(key)
获取某个缓存的值。

View File

@@ -77,6 +77,13 @@
<p>测量文本的宽高返回值</p>
<pre class="hljs"><code>{ width, height }
</code></pre>
<h4>getTextFromHtml(html)</h4>
<p>提取html字符串里的纯文本内容</p>
<h4>readBlob(blob)</h4>
<blockquote>
<p>v0.5.9+</p>
</blockquote>
<p><code>blob</code>数据转成<code>data:url</code>数据</p>
<h2>在canvas中模拟css的背景属性</h2>
<p>引入</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/utils/simulateCSSBackgroundInCanvas&#x27;</span>
@@ -100,6 +107,31 @@ drawBackgroundImageToCanvas(ctx, width, height, img, {
}
})
</code></pre>
<h2>LRU缓存类</h2>
<blockquote>
<p>v0.5.10+</p>
</blockquote>
<p>引入</p>
<pre class="hljs"><code><span class="hljs-keyword">import</span> Lru <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;simple-mind-map/src/utils/Lru.js&#x27;</span>
</code></pre>
<h3>构造函数</h3>
<pre class="hljs"><code><span class="hljs-keyword">let</span> lru = <span class="hljs-keyword">new</span> Lru(max)
</code></pre>
<p><code>max</code>指定最大缓存数量</p>
<h3>实例属性</h3>
<h4>size</h4>
<p>当前缓存的数量</p>
<h4>pool</h4>
<p>获取缓存池</p>
<h3>实例方法</h3>
<h4>add(key, value)</h4>
<p>添加缓存</p>
<h4>delete(key)</h4>
<p>删除指定缓存</p>
<h4>has(key)</h4>
<p>检查某个缓存是否存在</p>
<h4>get(key)</h4>
<p>获取某个缓存的值</p>
</div>
</template>

View File

@@ -17,7 +17,7 @@ import xmind from 'simple-mind-map/src/parse/xmind.js'
```
```js
MindMap.xmind
simpleMindMap.xmind
```
## 方法

View File

@@ -11,7 +11,7 @@
<p>如果使用的是<code>umd</code>格式的文件那么可以通过如下方式获取</p>
<pre class="hljs"><code><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;simple-mind-map/dist/simpleMindMap.umd.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<pre class="hljs"><code>MindMap.xmind
<pre class="hljs"><code>simpleMindMap.xmind
</code></pre>
<h2>方法</h2>
<h3>xmind.parseXmindFile(file)</h3>

View File

@@ -295,6 +295,67 @@
</el-select>
</div>
</div>
<!-- 关联线文字 -->
<div class="title noTop">关联线文字</div>
<div class="row">
<div class="rowItem">
<span class="name">字体</span>
<el-select
size="mini"
v-model="style.associativeLineTextFontFamily"
placeholder=""
@change="update('associativeLineTextFontFamily', $event)"
>
<el-option
v-for="item in fontFamilyList"
:key="item.value"
:label="item.name"
:value="item.value"
:style="{ fontFamily: item.value }"
>
</el-option>
</el-select>
</div>
</div>
<div class="row">
<div class="rowItem">
<span class="name">颜色</span>
<span
class="block"
v-popover:popover6
:style="{ backgroundColor: style.associativeLineTextColor }"
></span>
<el-popover ref="popover6" placement="bottom" trigger="click">
<Color
:color="style.associativeLineTextColor"
@change="
color => {
update('associativeLineTextColor', color)
}
"
></Color>
</el-popover>
</div>
<div class="rowItem">
<span class="name">字号</span>
<el-select
size="mini"
style="width: 80px"
v-model="style.associativeLineTextFontSize"
placeholder=""
@change="update('associativeLineTextFontSize', $event)"
>
<el-option
v-for="item in fontSizeList"
:key="item"
:label="item"
:value="item"
:style="{ fontSize: item + 'px' }"
>
</el-option>
</el-select>
</div>
</div>
<!-- 节点边框风格 -->
<div class="title noTop">{{ $t('baseStyle.nodeBorderType') }}</div>
<div class="row">
@@ -546,7 +607,7 @@
<script>
import Sidebar from './Sidebar'
import Color from './Color'
import { lineWidthList, lineStyleList, backgroundRepeatList, backgroundPositionList, backgroundSizeList } from '@/config'
import { lineWidthList, lineStyleList, backgroundRepeatList, backgroundPositionList, backgroundSizeList, fontFamilyList, fontSizeList } from '@/config'
import ImgUpload from '@/components/ImgUpload'
import { storeConfig } from '@/api'
import { mapState, mapMutations } from 'vuex'
@@ -575,6 +636,7 @@ export default {
data() {
return {
lineWidthList,
fontSizeList,
activeTab: 'color',
marginActiveTab: 'second',
style: {
@@ -588,6 +650,9 @@ export default {
associativeLineWidth: 0,
associativeLineActiveWidth: 0,
associativeLineActiveColor: '',
associativeLineTextFontSize: 0,
associativeLineTextColor: '',
associativeLineTextFontFamily: '',
paddingX: 0,
paddingY: 0,
imgMaxWidth: 0,
@@ -636,6 +701,9 @@ export default {
backgroundSizeList() {
return backgroundSizeList[this.$i18n.locale] || backgroundSizeList.zh
},
fontFamilyList() {
return fontFamilyList[this.$i18n.locale] || fontFamilyList.zh
},
},
watch: {
activeSidebar(val) {
@@ -673,6 +741,9 @@ export default {
'associativeLineWidth',
'associativeLineActiveWidth',
'associativeLineActiveColor',
'associativeLineTextFontSize',
'associativeLineTextColor',
'associativeLineTextFontFamily',
'paddingX',
'paddingY',
'imgMaxWidth',

View File

@@ -48,6 +48,7 @@ import NodeImgPreview from './NodeImgPreview.vue'
import SidebarTrigger from './SidebarTrigger.vue'
import { mapState } from 'vuex'
import customThemeList from '@/customThemes'
import icon from '@/config/icon'
// 注册插件
MindMap
@@ -287,7 +288,8 @@ export default {
// this.$bus.$emit('hideNoteContent')
}
},
...(config || {})
...(config || {}),
iconList: icon
})
if (this.openNodeRichText) this.addRichTextPlugin()
this.mindMap.keyCommand.addShortcut('Control+s', () => {

View File

@@ -62,7 +62,6 @@
</div>
</div>
<div class="tip">{{ $t('export.tips') }}</div>
<div class="tip warning" v-if="openNodeRichText && exportType === 'svg' && domToImage">{{ $t('export.svgTips') }}</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>

View File

@@ -12,7 +12,7 @@
class="icon"
v-for="icon in item.list"
:key="icon.name"
v-html="icon.icon"
v-html="getHtml(icon.icon)"
:class="{
selected: iconList.includes(item.type + '_' + icon.name)
}"
@@ -25,6 +25,7 @@
<script>
import { nodeIconList } from 'simple-mind-map/src/svg/icons'
import icon from '@/config/icon'
/**
* @Author: 王林
@@ -35,7 +36,7 @@ export default {
name: 'NodeIcon',
data() {
return {
nodeIconList,
nodeIconList: [...nodeIconList, ...icon],
dialogVisible: false,
iconList: [],
activeNodes: []
@@ -56,6 +57,10 @@ export default {
})
},
methods: {
getHtml(icon) {
return /^<svg/.test(icon) ? icon : `<img src="${icon}" />`
},
/**
* @Author: 王林
* @Date: 2021-06-23 23:16:56
@@ -119,6 +124,16 @@ export default {
cursor: pointer;
position: relative;
/deep/ img {
width: 100%;
height: 100%;
}
/deep/ svg {
width: 100%;
height: 100%;
}
&.selected {
&::after {
content: '';

View File

@@ -42,7 +42,7 @@ export default {
},
data() {
return {
themeList: [...themeList],// ...customThemeList
themeList: [...themeList].reverse(),// ...customThemeList
themeMap,
theme: ''
}

View File

@@ -4,6 +4,25 @@ import EditPage from '@/pages/Edit/Index'
import DocPage from '@/pages/Doc/Index'
import routerList from '@/pages/Doc/routerList'
// 处理没有翻译的章节路由
const handleRouterList = () => {
let zhList = routerList[0].children
for(let i = 1; i < routerList.length; i++) {
let list = routerList[i].children
zhList.forEach(item => {
if (!list.find((item2) => {
return item2.path === item.path
})) {
list.push({
...item,
lang: 'zh'
})
}
})
}
}
handleRouterList()
Vue.use(VueRouter)
const routes = [
@@ -25,7 +44,7 @@ const routes = [
children: item.children.map((child) => {
return {
path: `${child.path}/:h?`,
component: () => import(`./pages/Doc/${item.lang}/${child.path}/index.vue`)
component: () => import(`./pages/Doc/${child.lang || item.lang}/${child.path}/index.vue`)
}
})
}