mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 00:17:06 +08:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8441986ca7 | ||
|
|
c8b50908e1 | ||
|
|
7e11fde892 | ||
|
|
3d9f3bd7a8 | ||
|
|
46e11649b0 | ||
|
|
161ef7590c | ||
|
|
ca660a3c74 | ||
|
|
7a24872331 | ||
|
|
eb4ea9fb3a | ||
|
|
64228c02ff | ||
|
|
f184a5d948 | ||
|
|
0bf5b2d6f7 | ||
|
|
74a52ea386 | ||
|
|
9914eef5b9 | ||
|
|
f547f741f2 | ||
|
|
c26149fa42 | ||
|
|
b2aa3648eb | ||
|
|
b997604ab2 | ||
|
|
c6929b82ad | ||
|
|
b40da53aef | ||
|
|
1e5dfd97e1 | ||
|
|
97bcc22abd | ||
|
|
bd655839cb | ||
|
|
a53a4e8e1d | ||
|
|
eb01646747 | ||
|
|
d27eee0fae | ||
|
|
92ee241ed8 |
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="./dist/logo.png"><title>一个简单的web思维导图实现</title><link href="dist/js/chunk-2d0a3179.8bac0e6a.js" rel="prefetch"><link href="dist/js/chunk-2d0aa579.3848b480.js" rel="prefetch"><link href="dist/js/chunk-2d0aa978.0c0ab348.js" rel="prefetch"><link href="dist/js/chunk-2d0ab10b.89baf4c9.js" rel="prefetch"><link href="dist/js/chunk-2d0abe0f.ba566b9e.js" rel="prefetch"><link href="dist/js/chunk-2d0b361e.d57feb19.js" rel="prefetch"><link href="dist/js/chunk-2d0b91e5.9058553b.js" rel="prefetch"><link href="dist/js/chunk-2d0b92c3.ff912e01.js" rel="prefetch"><link href="dist/js/chunk-2d0bd54e.988f0b69.js" rel="prefetch"><link href="dist/js/chunk-2d0be174.b87008fb.js" rel="prefetch"><link href="dist/js/chunk-2d0c0a44.d53f93f5.js" rel="prefetch"><link href="dist/js/chunk-2d0c18d8.ef38347c.js" rel="prefetch"><link href="dist/js/chunk-2d0c191e.fe3d1357.js" rel="prefetch"><link href="dist/js/chunk-2d0c1a01.dc5d667f.js" rel="prefetch"><link href="dist/js/chunk-2d0d9fbc.7c0e8c3b.js" rel="prefetch"><link href="dist/js/chunk-2d0da701.7110cb06.js" rel="prefetch"><link href="dist/js/chunk-2d0dad5f.789c08d8.js" rel="prefetch"><link href="dist/js/chunk-2d0db0f2.773ee0f5.js" rel="prefetch"><link href="dist/js/chunk-2d0dddce.29899f8c.js" rel="prefetch"><link href="dist/js/chunk-2d0de01b.4f180262.js" rel="prefetch"><link href="dist/js/chunk-2d0e2326.7b20d38b.js" rel="prefetch"><link href="dist/js/chunk-2d0e268c.314fd603.js" rel="prefetch"><link href="dist/js/chunk-2d0e5089.cd1baa18.js" rel="prefetch"><link href="dist/js/chunk-2d0e9742.62e1ccbf.js" rel="prefetch"><link href="dist/js/chunk-2d0f026c.af35b5ce.js" rel="prefetch"><link href="dist/js/chunk-2d2082b9.ffe557f3.js" rel="prefetch"><link href="dist/js/chunk-2d208ffa.6b617b98.js" rel="prefetch"><link href="dist/js/chunk-2d20ec02.917aff76.js" rel="prefetch"><link href="dist/js/chunk-2d20f68f.66cba965.js" rel="prefetch"><link href="dist/js/chunk-2d210a7a.25884d5e.js" rel="prefetch"><link href="dist/js/chunk-2d216004.3416e02c.js" rel="prefetch"><link href="dist/js/chunk-2d216b67.2d06497a.js" rel="prefetch"><link href="dist/js/chunk-2d217907.96994ac6.js" rel="prefetch"><link href="dist/js/chunk-2d226d0a.d30a47fe.js" rel="prefetch"><link href="dist/js/chunk-2d2299c3.5aa1632c.js" rel="prefetch"><link href="dist/js/chunk-2d2308b0.d813ba33.js" rel="prefetch"><link href="dist/js/chunk-3a2f3e67.13278516.js" rel="prefetch"><link href="dist/css/app.a6908b68.css" rel="preload" as="style"><link href="dist/css/chunk-vendors.1790fe42.css" rel="preload" as="style"><link href="dist/js/app.2f5edb91.js" rel="preload" as="script"><link href="dist/js/chunk-vendors.7f3b8358.js" rel="preload" as="script"><link href="dist/css/chunk-vendors.1790fe42.css" rel="stylesheet"><link href="dist/css/app.a6908b68.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="dist/js/chunk-vendors.7f3b8358.js"></script><script src="dist/js/app.2f5edb91.js"></script></body></html>
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="./dist/logo.png"><title>一个简单的web思维导图实现</title><link href="dist/js/chunk-2d0a3179.f79d6590.js" rel="prefetch"><link href="dist/js/chunk-2d0aa579.d901cc5e.js" rel="prefetch"><link href="dist/js/chunk-2d0aa978.ae72a285.js" rel="prefetch"><link href="dist/js/chunk-2d0ab10b.13ffd981.js" rel="prefetch"><link href="dist/js/chunk-2d0abe0f.f7178a38.js" rel="prefetch"><link href="dist/js/chunk-2d0b361e.64d433a0.js" rel="prefetch"><link href="dist/js/chunk-2d0b91e5.de98db92.js" rel="prefetch"><link href="dist/js/chunk-2d0b92c3.a48a667e.js" rel="prefetch"><link href="dist/js/chunk-2d0bd54e.e56450f0.js" rel="prefetch"><link href="dist/js/chunk-2d0be174.1531a230.js" rel="prefetch"><link href="dist/js/chunk-2d0c0a44.d2768274.js" rel="prefetch"><link href="dist/js/chunk-2d0c14fc.a89a80b4.js" rel="prefetch"><link href="dist/js/chunk-2d0c18d8.647d892f.js" rel="prefetch"><link href="dist/js/chunk-2d0c191e.6fb13561.js" rel="prefetch"><link href="dist/js/chunk-2d0c1a01.49c23f9e.js" rel="prefetch"><link href="dist/js/chunk-2d0d9fbc.adce6374.js" rel="prefetch"><link href="dist/js/chunk-2d0da701.2e0766e2.js" rel="prefetch"><link href="dist/js/chunk-2d0dad5f.ec79eebe.js" rel="prefetch"><link href="dist/js/chunk-2d0db0f2.19efc7d4.js" rel="prefetch"><link href="dist/js/chunk-2d0dddce.6a579f6f.js" rel="prefetch"><link href="dist/js/chunk-2d0ddf37.d162efb9.js" rel="prefetch"><link href="dist/js/chunk-2d0de01b.21eae2e6.js" rel="prefetch"><link href="dist/js/chunk-2d0e2326.f3a9c7fc.js" rel="prefetch"><link href="dist/js/chunk-2d0e268c.57926a64.js" rel="prefetch"><link href="dist/js/chunk-2d0e5089.2b202405.js" rel="prefetch"><link href="dist/js/chunk-2d0e9742.a2d22497.js" rel="prefetch"><link href="dist/js/chunk-2d0f026c.67441d40.js" rel="prefetch"><link href="dist/js/chunk-2d2082b9.fe227afb.js" rel="prefetch"><link href="dist/js/chunk-2d208ffa.9df071bd.js" rel="prefetch"><link href="dist/js/chunk-2d20ec02.917aff76.js" rel="prefetch"><link href="dist/js/chunk-2d20f68f.acd7e356.js" rel="prefetch"><link href="dist/js/chunk-2d210a7a.5a4025ce.js" rel="prefetch"><link href="dist/js/chunk-2d216004.905379d5.js" rel="prefetch"><link href="dist/js/chunk-2d216b67.2d06497a.js" rel="prefetch"><link href="dist/js/chunk-2d217907.cc6917a4.js" rel="prefetch"><link href="dist/js/chunk-2d226d0a.3703455b.js" rel="prefetch"><link href="dist/js/chunk-2d2299c3.ffd15e65.js" rel="prefetch"><link href="dist/js/chunk-2d22bd06.cace3b1b.js" rel="prefetch"><link href="dist/js/chunk-2d2308b0.fb49d06b.js" rel="prefetch"><link href="dist/js/chunk-2d238428.266d8f0c.js" rel="prefetch"><link href="dist/js/chunk-3a2f3e67.13278516.js" rel="prefetch"><link href="dist/css/app.8a532989.css" rel="preload" as="style"><link href="dist/css/chunk-vendors.1790fe42.css" rel="preload" as="style"><link href="dist/js/app.52520638.js" rel="preload" as="script"><link href="dist/js/chunk-vendors.7f3b8358.js" rel="preload" as="script"><link href="dist/css/chunk-vendors.1790fe42.css" rel="stylesheet"><link href="dist/css/app.8a532989.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="dist/js/chunk-vendors.7f3b8358.js"></script><script src="dist/js/app.52520638.js"></script></body></html>
|
||||
20
simple-mind-map/full.js
Normal file
20
simple-mind-map/full.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import MindMap from './index'
|
||||
import MiniMap from './src/MiniMap.js'
|
||||
import Watermark from './src/Watermark.js'
|
||||
import KeyboardNavigation from './src/KeyboardNavigation.js'
|
||||
import Export from './src/Export.js'
|
||||
import Drag from './src/Drag.js'
|
||||
import Select from './src/Select.js'
|
||||
import xmind from './src/parse/xmind.js'
|
||||
|
||||
MindMap.xmind = xmind
|
||||
|
||||
MindMap
|
||||
.usePlugin(MiniMap)
|
||||
.usePlugin(Watermark)
|
||||
.usePlugin(Drag)
|
||||
.usePlugin(KeyboardNavigation)
|
||||
.usePlugin(Export)
|
||||
.usePlugin(Select)
|
||||
|
||||
export default MindMap
|
||||
@@ -7,16 +7,9 @@ import Style from './src/Style'
|
||||
import KeyCommand from './src/KeyCommand'
|
||||
import Command from './src/Command'
|
||||
import BatchExecution from './src/BatchExecution'
|
||||
import Export from './src/Export'
|
||||
import Select from './src/Select'
|
||||
import Drag from './src/Drag'
|
||||
import MiniMap from './src/MiniMap'
|
||||
import Watermark from './src/Watermark'
|
||||
import { layoutValueList } from './src/utils/constant'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import xmind from './src/parse/xmind'
|
||||
import { simpleDeepClone } from './src/utils'
|
||||
import KeyboardNavigation from './src/KeyboardNavigation'
|
||||
import defaultTheme from './src/themes/default'
|
||||
|
||||
// 默认选项配置
|
||||
@@ -66,7 +59,9 @@ const defaultOpt = {
|
||||
opacity: 0.5,
|
||||
fontSize: 14
|
||||
}
|
||||
}
|
||||
},
|
||||
// 达到该宽度文本自动换行
|
||||
textAutoWrapWidth: 500
|
||||
}
|
||||
|
||||
// 思维导图
|
||||
@@ -120,39 +115,16 @@ class MindMap {
|
||||
draw: this.draw
|
||||
})
|
||||
|
||||
// 小地图类
|
||||
this.miniMap = new MiniMap({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 导出类
|
||||
this.doExport = new Export({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 选择类
|
||||
this.select = new Select({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 拖动类
|
||||
this.drag = new Drag({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 键盘导航类
|
||||
this.keyboardNavigation = new KeyboardNavigation({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 水印类
|
||||
this.watermark = new Watermark({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 批量执行类
|
||||
this.batchExecution = new BatchExecution()
|
||||
|
||||
// 注册插件
|
||||
MindMap.pluginList.forEach((plugin) => {
|
||||
this[plugin.instanceName] = new plugin({
|
||||
mindMap: this
|
||||
})
|
||||
})
|
||||
|
||||
// 初始渲染
|
||||
this.reRender()
|
||||
setTimeout(() => {
|
||||
@@ -172,21 +144,21 @@ class MindMap {
|
||||
}
|
||||
|
||||
// 渲染,部分渲染
|
||||
render() {
|
||||
render(callback) {
|
||||
this.batchExecution.push('render', () => {
|
||||
this.initTheme()
|
||||
this.renderer.reRender = false
|
||||
this.renderer.render()
|
||||
this.renderer.render(callback)
|
||||
})
|
||||
}
|
||||
|
||||
// 重新渲染
|
||||
reRender() {
|
||||
reRender(callback) {
|
||||
this.batchExecution.push('render', () => {
|
||||
this.draw.clear()
|
||||
this.initTheme()
|
||||
this.renderer.reRender = true
|
||||
this.renderer.render()
|
||||
this.renderer.render(callback)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -355,9 +327,61 @@ class MindMap {
|
||||
}
|
||||
this.emit('mode_change', mode)
|
||||
}
|
||||
|
||||
// 获取svg数据
|
||||
getSvgData() {
|
||||
const svg = this.svg
|
||||
const draw = this.draw
|
||||
// 保存原始信息
|
||||
const origWidth = svg.width()
|
||||
const origHeight = svg.height()
|
||||
const origTransform = draw.transform()
|
||||
const elRect = this.el.getBoundingClientRect()
|
||||
// 去除放大缩小的变换效果
|
||||
draw.scale(1 / origTransform.scaleX, 1 / origTransform.scaleY)
|
||||
// 获取变换后的位置尺寸信息,其实是getBoundingClientRect方法的包装方法
|
||||
const rect = draw.rbox()
|
||||
// 将svg设置为实际内容的宽高
|
||||
svg.size(rect.width, rect.height)
|
||||
// 把实际内容变换
|
||||
draw.translate(-rect.x + elRect.left, -rect.y + elRect.top)
|
||||
// 克隆一份数据
|
||||
let clone = svg.clone()
|
||||
// 如果实际图形宽高超出了屏幕宽高,且存在水印的话需要重新绘制水印,否则会出现超出部分没有水印的问题
|
||||
if ((rect.width > origWidth || rect.height > origHeight) && this.watermark && this.watermark.hasWatermark()) {
|
||||
this.width = rect.width
|
||||
this.height = rect.height
|
||||
this.watermark.draw()
|
||||
clone = svg.clone()
|
||||
this.width = origWidth
|
||||
this.height = origHeight
|
||||
this.watermark.draw()
|
||||
}
|
||||
// 恢复原先的大小和变换信息
|
||||
svg.size(origWidth, origHeight)
|
||||
draw.transform(origTransform)
|
||||
|
||||
return {
|
||||
svg: clone, // 思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)
|
||||
svgHTML: clone.svg(), // svg字符串
|
||||
rect: {
|
||||
...rect, // 思维导图图形未缩放时的位置尺寸等信息
|
||||
ratio: rect.width / rect.height // 思维导图图形的宽高比
|
||||
},
|
||||
origWidth, // 画布宽度
|
||||
origHeight, // 画布高度
|
||||
scaleX: origTransform.scaleX, // 思维导图图形的水平缩放值
|
||||
scaleY: origTransform.scaleY // 思维导图图形的垂直缩放值
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MindMap.xmind = xmind
|
||||
// 插件列表
|
||||
MindMap.pluginList = []
|
||||
MindMap.usePlugin = (plugin) => {
|
||||
MindMap.pluginList.push(plugin)
|
||||
return MindMap
|
||||
}
|
||||
|
||||
// 定义新主题
|
||||
MindMap.defineTheme = (name, config = {}) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.2.24",
|
||||
"version": "0.3.4",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
@@ -22,7 +22,7 @@
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"module": "index.js",
|
||||
"main": "./dist/simpleMindMap.umd.min.js",
|
||||
"__main": "./dist/simpleMindMap.umd.min.js",
|
||||
"dependencies": {
|
||||
"@svgdotjs/svg.js": "^3.0.16",
|
||||
"canvg": "^3.0.7",
|
||||
|
||||
@@ -72,6 +72,9 @@ class Command {
|
||||
|
||||
// 添加回退数据
|
||||
addHistory() {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
let data = this.getCopyData()
|
||||
this.history.push(simpleDeepClone(data))
|
||||
this.activeHistoryIndex = this.history.length - 1
|
||||
@@ -85,6 +88,9 @@ class Command {
|
||||
|
||||
// 回退
|
||||
back(step = 1) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (this.activeHistoryIndex - step >= 0) {
|
||||
this.activeHistoryIndex -= step
|
||||
this.mindMap.emit(
|
||||
@@ -98,6 +104,9 @@ class Command {
|
||||
|
||||
// 前进
|
||||
forward(step = 1) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
let len = this.history.length
|
||||
if (this.activeHistoryIndex + step <= len - 1) {
|
||||
this.activeHistoryIndex += step
|
||||
|
||||
@@ -260,4 +260,6 @@ class Drag extends Base {
|
||||
}
|
||||
}
|
||||
|
||||
Drag.instanceName = 'drag'
|
||||
|
||||
export default Drag
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { imgToDataUrl, downloadFile } from './utils'
|
||||
import JsPDF from 'jspdf'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import drawBackgroundImageToCanvas from './utils/simulateCSSBackgroundInCanvas'
|
||||
const URL = window.URL || window.webkitURL || window
|
||||
|
||||
// 导出类
|
||||
@@ -26,7 +27,7 @@ class Export {
|
||||
|
||||
// 获取svg数据
|
||||
async getSvgData() {
|
||||
let { svg, svgHTML } = this.mindMap.miniMap.getMiniMap()
|
||||
let { svg, svgHTML } = this.mindMap.getSvgData()
|
||||
// 把图片的url转换成data:url类型,否则导出会丢失图片
|
||||
let imageList = svg.find('image')
|
||||
let task = imageList.map(async item => {
|
||||
@@ -85,7 +86,9 @@ class Export {
|
||||
let {
|
||||
backgroundColor = '#fff',
|
||||
backgroundImage,
|
||||
backgroundRepeat = 'repeat'
|
||||
backgroundRepeat = 'no-repeat',
|
||||
backgroundPosition = 'center center',
|
||||
backgroundSize = 'cover',
|
||||
} = this.mindMap.themeConfig
|
||||
// 背景颜色
|
||||
ctx.save()
|
||||
@@ -96,19 +99,18 @@ class Export {
|
||||
// 背景图片
|
||||
if (backgroundImage && backgroundImage !== 'none') {
|
||||
ctx.save()
|
||||
let img = new Image()
|
||||
img.src = backgroundImage
|
||||
img.onload = () => {
|
||||
let pat = ctx.createPattern(img, backgroundRepeat)
|
||||
ctx.rect(0, 0, width, height)
|
||||
ctx.fillStyle = pat
|
||||
ctx.fill()
|
||||
drawBackgroundImageToCanvas(ctx, width, height, backgroundImage, {
|
||||
backgroundRepeat,
|
||||
backgroundPosition,
|
||||
backgroundSize
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
ctx.restore()
|
||||
resolve()
|
||||
}
|
||||
img.onerror = e => {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
@@ -215,4 +217,6 @@ class Export {
|
||||
}
|
||||
}
|
||||
|
||||
Export.instanceName = 'doExport'
|
||||
|
||||
export default Export
|
||||
|
||||
@@ -2,7 +2,7 @@ import { isKey } from './utils/keyMap'
|
||||
import { bfsWalk } from './utils'
|
||||
|
||||
// 键盘导航类
|
||||
export default class KeyboardNavigation {
|
||||
class KeyboardNavigation {
|
||||
// 构造函数
|
||||
constructor(opt) {
|
||||
this.opt = opt
|
||||
@@ -224,3 +224,7 @@ export default class KeyboardNavigation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyboardNavigation.instanceName = 'keyboardNavigation'
|
||||
|
||||
export default KeyboardNavigation
|
||||
@@ -14,43 +14,6 @@ class MiniMap {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取小地图相关数据
|
||||
getMiniMap() {
|
||||
const svg = this.mindMap.svg
|
||||
const draw = this.mindMap.draw
|
||||
// 保存原始信息
|
||||
const origWidth = svg.width()
|
||||
const origHeight = svg.height()
|
||||
const origTransform = draw.transform()
|
||||
const elRect = this.mindMap.el.getBoundingClientRect()
|
||||
// 去除放大缩小的变换效果
|
||||
draw.scale(1 / origTransform.scaleX, 1 / origTransform.scaleY)
|
||||
// 获取变换后的位置尺寸信息,其实是getBoundingClientRect方法的包装方法
|
||||
const rect = draw.rbox()
|
||||
// 将svg设置为实际内容的宽高
|
||||
svg.size(rect.width, rect.height)
|
||||
// 把实际内容变换
|
||||
draw.translate(-rect.x + elRect.left, -rect.y + elRect.top)
|
||||
// 克隆一份数据
|
||||
const clone = svg.clone()
|
||||
// 恢复原先的大小和变换信息
|
||||
svg.size(origWidth, origHeight)
|
||||
draw.transform(origTransform)
|
||||
|
||||
return {
|
||||
svg: clone, // 思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)
|
||||
svgHTML: clone.svg(), // svg字符串
|
||||
rect: {
|
||||
...rect, // 思维导图图形未缩放时的位置尺寸等信息
|
||||
ratio: rect.width / rect.height // 思维导图图形的宽高比
|
||||
},
|
||||
origWidth, // 画布宽度
|
||||
origHeight, // 画布高度
|
||||
scaleX: origTransform.scaleX, // 思维导图图形的水平缩放值
|
||||
scaleY: origTransform.scaleY // 思维导图图形的垂直缩放值
|
||||
}
|
||||
}
|
||||
|
||||
// 计算小地图的渲染数据
|
||||
/**
|
||||
* boxWidth:小地图容器的宽度
|
||||
@@ -58,7 +21,7 @@ class MiniMap {
|
||||
*/
|
||||
calculationMiniMap(boxWidth, boxHeight) {
|
||||
let { svgHTML, rect, origWidth, origHeight, scaleX, scaleY } =
|
||||
this.getMiniMap()
|
||||
this.mindMap.getSvgData()
|
||||
// 计算数据
|
||||
let boxRatio = boxWidth / boxHeight
|
||||
let actWidth = 0
|
||||
@@ -144,4 +107,6 @@ class MiniMap {
|
||||
}
|
||||
}
|
||||
|
||||
MiniMap.instanceName = 'miniMap'
|
||||
|
||||
export default MiniMap
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -167,4 +167,6 @@ class Select {
|
||||
}
|
||||
}
|
||||
|
||||
Select.instanceName = 'select'
|
||||
|
||||
export default Select
|
||||
|
||||
@@ -1,167 +1,200 @@
|
||||
import { tagColorList } from './utils/constant'
|
||||
const rootProp = ['paddingX', 'paddingY']
|
||||
|
||||
// 样式类
|
||||
|
||||
class Style {
|
||||
// 设置背景样式
|
||||
|
||||
static setBackgroundStyle(el, themeConfig) {
|
||||
let { backgroundColor, backgroundImage, backgroundRepeat } = themeConfig
|
||||
el.style.backgroundColor = backgroundColor
|
||||
if (backgroundImage) {
|
||||
el.style.backgroundImage = `url(${backgroundImage})`
|
||||
el.style.backgroundRepeat = backgroundRepeat
|
||||
}
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
|
||||
constructor(ctx, themeConfig) {
|
||||
this.ctx = ctx
|
||||
this.themeConfig = themeConfig
|
||||
}
|
||||
|
||||
// 更新主题配置
|
||||
|
||||
updateThemeConfig(themeConfig) {
|
||||
this.themeConfig = themeConfig
|
||||
}
|
||||
|
||||
// 合并样式
|
||||
|
||||
merge(prop, root, isActive) {
|
||||
// 三级及以下节点
|
||||
let defaultConfig = this.themeConfig.node
|
||||
if (root || rootProp.includes(prop)) {
|
||||
// 直接使用最外层样式
|
||||
defaultConfig = this.themeConfig
|
||||
} else if (this.ctx.isGeneralization) {
|
||||
// 概要节点
|
||||
defaultConfig = this.themeConfig.generalization
|
||||
} else if (this.ctx.layerIndex === 0) {
|
||||
// 根节点
|
||||
defaultConfig = this.themeConfig.root
|
||||
} else if (this.ctx.layerIndex === 1) {
|
||||
// 二级节点
|
||||
defaultConfig = this.themeConfig.second
|
||||
}
|
||||
// 激活状态
|
||||
if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) {
|
||||
if (
|
||||
this.ctx.nodeData.data.activeStyle &&
|
||||
this.ctx.nodeData.data.activeStyle[prop] !== undefined
|
||||
) {
|
||||
return this.ctx.nodeData.data.activeStyle[prop]
|
||||
} else if (defaultConfig.active && defaultConfig.active[prop]) {
|
||||
return defaultConfig.active[prop]
|
||||
}
|
||||
}
|
||||
// 优先使用节点本身的样式
|
||||
return this.getSelfStyle(prop) !== undefined
|
||||
? this.getSelfStyle(prop)
|
||||
: defaultConfig[prop]
|
||||
}
|
||||
|
||||
// 获取某个样式值
|
||||
|
||||
getStyle(prop, root, isActive) {
|
||||
return this.merge(prop, root, isActive)
|
||||
}
|
||||
|
||||
// 获取自身自定义样式
|
||||
|
||||
getSelfStyle(prop) {
|
||||
return this.ctx.nodeData.data[prop]
|
||||
}
|
||||
|
||||
// 矩形
|
||||
|
||||
rect(node) {
|
||||
this.shape(node)
|
||||
node.radius(this.merge('borderRadius'))
|
||||
}
|
||||
|
||||
// 矩形外的其他形状
|
||||
|
||||
shape(node) {
|
||||
node.fill({
|
||||
color: this.merge('fillColor')
|
||||
})
|
||||
// 节点使用横线样式,不需要渲染非激活状态的边框样式
|
||||
if (
|
||||
!this.ctx.isRoot &&
|
||||
!this.ctx.isGeneralization &&
|
||||
this.themeConfig.nodeUseLineStyle &&
|
||||
!this.ctx.nodeData.data.isActive
|
||||
) {
|
||||
return
|
||||
}
|
||||
node.stroke({
|
||||
color: this.merge('borderColor'),
|
||||
width: this.merge('borderWidth'),
|
||||
dasharray: this.merge('borderDasharray')
|
||||
})
|
||||
}
|
||||
|
||||
// 文字
|
||||
|
||||
text(node) {
|
||||
node
|
||||
.fill({
|
||||
color: this.merge('color')
|
||||
})
|
||||
.css({
|
||||
'font-family': this.merge('fontFamily'),
|
||||
'font-size': this.merge('fontSize'),
|
||||
'font-weight': this.merge('fontWeight'),
|
||||
'font-style': this.merge('fontStyle'),
|
||||
'text-decoration': this.merge('textDecoration')
|
||||
})
|
||||
}
|
||||
|
||||
// html文字节点
|
||||
|
||||
domText(node, fontSizeScale = 1) {
|
||||
node.style.fontFamily = this.merge('fontFamily')
|
||||
node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px'
|
||||
node.style.fontWeight = this.merge('fontWeight') || 'normal'
|
||||
}
|
||||
|
||||
// 标签文字
|
||||
|
||||
tagText(node, index) {
|
||||
node
|
||||
.fill({
|
||||
color: tagColorList[index].color
|
||||
})
|
||||
.css({
|
||||
'font-size': '12px'
|
||||
})
|
||||
}
|
||||
|
||||
// 标签矩形
|
||||
|
||||
tagRect(node, index) {
|
||||
node.fill({
|
||||
color: tagColorList[index].background
|
||||
})
|
||||
}
|
||||
|
||||
// 内置图标
|
||||
|
||||
iconNode(node) {
|
||||
node.attr({
|
||||
fill: this.merge('color')
|
||||
})
|
||||
}
|
||||
|
||||
// 连线
|
||||
|
||||
line(node, { width, color, dasharray } = {}) {
|
||||
node.stroke({ width, color, dasharray }).fill({ color: 'none' })
|
||||
}
|
||||
|
||||
// 概要连线
|
||||
|
||||
generalizationLine(node) {
|
||||
import { tagColorList } from './utils/constant'
|
||||
const rootProp = ['paddingX', 'paddingY']
|
||||
|
||||
// 样式类
|
||||
|
||||
class Style {
|
||||
// 设置背景样式
|
||||
|
||||
static setBackgroundStyle(el, themeConfig) {
|
||||
let { backgroundColor, backgroundImage, backgroundRepeat, backgroundPosition, backgroundSize } = themeConfig
|
||||
el.style.backgroundColor = backgroundColor
|
||||
if (backgroundImage) {
|
||||
el.style.backgroundImage = `url(${backgroundImage})`
|
||||
el.style.backgroundRepeat = backgroundRepeat
|
||||
el.style.backgroundPosition = backgroundPosition
|
||||
el.style.backgroundSize = backgroundSize
|
||||
} else {
|
||||
el.style.backgroundImage = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
|
||||
constructor(ctx, themeConfig) {
|
||||
this.ctx = ctx
|
||||
this.themeConfig = themeConfig
|
||||
}
|
||||
|
||||
// 更新主题配置
|
||||
|
||||
updateThemeConfig(themeConfig) {
|
||||
this.themeConfig = themeConfig
|
||||
}
|
||||
|
||||
// 合并样式
|
||||
|
||||
merge(prop, root, isActive) {
|
||||
// 三级及以下节点
|
||||
let defaultConfig = this.themeConfig.node
|
||||
if (root || rootProp.includes(prop)) {
|
||||
// 直接使用最外层样式
|
||||
defaultConfig = this.themeConfig
|
||||
} else if (this.ctx.isGeneralization) {
|
||||
// 概要节点
|
||||
defaultConfig = this.themeConfig.generalization
|
||||
} else if (this.ctx.layerIndex === 0) {
|
||||
// 根节点
|
||||
defaultConfig = this.themeConfig.root
|
||||
} else if (this.ctx.layerIndex === 1) {
|
||||
// 二级节点
|
||||
defaultConfig = this.themeConfig.second
|
||||
}
|
||||
// 激活状态
|
||||
if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) {
|
||||
if (
|
||||
this.ctx.nodeData.data.activeStyle &&
|
||||
this.ctx.nodeData.data.activeStyle[prop] !== undefined
|
||||
) {
|
||||
return this.ctx.nodeData.data.activeStyle[prop]
|
||||
} else if (defaultConfig.active && defaultConfig.active[prop]) {
|
||||
return defaultConfig.active[prop]
|
||||
}
|
||||
}
|
||||
// 优先使用节点本身的样式
|
||||
return this.getSelfStyle(prop) !== undefined
|
||||
? this.getSelfStyle(prop)
|
||||
: defaultConfig[prop]
|
||||
}
|
||||
|
||||
// 获取某个样式值
|
||||
|
||||
getStyle(prop, root, isActive) {
|
||||
return this.merge(prop, root, isActive)
|
||||
}
|
||||
|
||||
// 获取自身自定义样式
|
||||
|
||||
getSelfStyle(prop) {
|
||||
return this.ctx.nodeData.data[prop]
|
||||
}
|
||||
|
||||
// 矩形
|
||||
|
||||
rect(node) {
|
||||
this.shape(node)
|
||||
node.radius(this.merge('borderRadius'))
|
||||
}
|
||||
|
||||
// 矩形外的其他形状
|
||||
|
||||
shape(node) {
|
||||
node.fill({
|
||||
color: this.merge('fillColor')
|
||||
})
|
||||
// 节点使用横线样式,不需要渲染非激活状态的边框样式
|
||||
if (
|
||||
!this.ctx.isRoot &&
|
||||
!this.ctx.isGeneralization &&
|
||||
this.themeConfig.nodeUseLineStyle &&
|
||||
!this.ctx.nodeData.data.isActive
|
||||
) {
|
||||
return
|
||||
}
|
||||
node.stroke({
|
||||
color: this.merge('borderColor'),
|
||||
width: this.merge('borderWidth'),
|
||||
dasharray: this.merge('borderDasharray')
|
||||
})
|
||||
}
|
||||
|
||||
// 文字
|
||||
|
||||
text(node) {
|
||||
node
|
||||
.fill({
|
||||
color: this.merge('color')
|
||||
})
|
||||
.css({
|
||||
'font-family': this.merge('fontFamily'),
|
||||
'font-size': this.merge('fontSize'),
|
||||
'font-weight': this.merge('fontWeight'),
|
||||
'font-style': this.merge('fontStyle'),
|
||||
'text-decoration': this.merge('textDecoration')
|
||||
})
|
||||
}
|
||||
|
||||
// 获取文本样式
|
||||
getTextFontStyle() {
|
||||
return {
|
||||
italic: this.merge('fontStyle') === 'italic',
|
||||
bold: this.merge('fontWeight'),
|
||||
fontSize: this.merge('fontSize'),
|
||||
fontFamily: this.merge('fontFamily')
|
||||
}
|
||||
}
|
||||
|
||||
// html文字节点
|
||||
|
||||
domText(node, fontSizeScale = 1) {
|
||||
node.style.fontFamily = this.merge('fontFamily')
|
||||
node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px'
|
||||
node.style.fontWeight = this.merge('fontWeight') || 'normal'
|
||||
node.style.lineHeight = this.merge('lineHeight')
|
||||
node.style.fontStyle = this.merge('fontStyle')
|
||||
}
|
||||
|
||||
// 标签文字
|
||||
|
||||
tagText(node, index) {
|
||||
node
|
||||
.fill({
|
||||
color: tagColorList[index].color
|
||||
})
|
||||
.css({
|
||||
'font-size': '12px'
|
||||
})
|
||||
}
|
||||
|
||||
// 标签矩形
|
||||
|
||||
tagRect(node, index) {
|
||||
node.fill({
|
||||
color: tagColorList[index].background
|
||||
})
|
||||
}
|
||||
|
||||
// 内置图标
|
||||
|
||||
iconNode(node) {
|
||||
node.attr({
|
||||
fill: this.merge('color')
|
||||
})
|
||||
}
|
||||
|
||||
// 连线
|
||||
|
||||
line(node, { width, color, dasharray } = {}) {
|
||||
node.stroke({ width, color, dasharray }).fill({ color: 'none' })
|
||||
}
|
||||
|
||||
// 概要连线
|
||||
|
||||
generalizationLine(node) {
|
||||
node
|
||||
.stroke({
|
||||
width: this.merge('generalizationLineWidth', true),
|
||||
color: this.merge('generalizationLineColor', true)
|
||||
})
|
||||
.fill({ color: 'none' })
|
||||
}
|
||||
|
||||
// 按钮
|
||||
|
||||
iconBtn(node, fillNode) {
|
||||
node.fill({ color: '#808080' })
|
||||
fillNode.fill({ color: '#fff' })
|
||||
}
|
||||
}
|
||||
|
||||
export default Style
|
||||
|
||||
@@ -59,14 +59,17 @@ export default class TextEdit {
|
||||
this.registerTmpShortcut()
|
||||
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;`
|
||||
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()
|
||||
})
|
||||
document.body.appendChild(this.textEditNode)
|
||||
}
|
||||
node.style.domText(this.textEditNode, this.mindMap.view.scale)
|
||||
let scale = this.mindMap.view.scale
|
||||
let lineHeight = node.style.merge('lineHeight')
|
||||
let fontSize = node.style.merge('fontSize')
|
||||
node.style.domText(this.textEditNode, scale)
|
||||
this.textEditNode.innerHTML = node.nodeData.data.text
|
||||
.split(/\n/gim)
|
||||
.join('<br>')
|
||||
@@ -75,6 +78,8 @@ export default class TextEdit {
|
||||
this.textEditNode.style.left = rect.left + 'px'
|
||||
this.textEditNode.style.top = rect.top + 'px'
|
||||
this.textEditNode.style.display = 'block'
|
||||
this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth * scale + 'px'
|
||||
this.textEditNode.style.transform = `translateY(${-(lineHeight * fontSize - fontSize) / 2 * scale}px)`
|
||||
this.showTextEdit = true
|
||||
// 选中文本
|
||||
this.selectNodeText()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { degToRad, camelCaseToHyphen } from './utils'
|
||||
import merge from 'deepmerge'
|
||||
|
||||
// 水印类
|
||||
export default class Watermark {
|
||||
class Watermark {
|
||||
constructor(opt = {}) {
|
||||
this.mindMap = opt.mindMap
|
||||
this.lineSpacing = 0 // 水印行间距
|
||||
@@ -20,6 +20,11 @@ export default class Watermark {
|
||||
this.updateWatermark(this.mindMap.opt.watermarkConfig || {})
|
||||
}
|
||||
|
||||
// 获取是否存在水印
|
||||
hasWatermark() {
|
||||
return !!this.text.trim()
|
||||
}
|
||||
|
||||
// 处理水印配置
|
||||
handleConfig({ text, lineSpacing, textSpacing, angle, textStyle }) {
|
||||
this.text = text === undefined ? '' : String(text).trim()
|
||||
@@ -36,7 +41,7 @@ export default class Watermark {
|
||||
// 非精确绘制,会绘制一些超出可视区域的水印
|
||||
draw() {
|
||||
this.watermarkDraw.clear()
|
||||
if (!this.text.trim()) {
|
||||
if (!this.hasWatermark()) {
|
||||
return
|
||||
}
|
||||
let x = 0
|
||||
@@ -109,3 +114,7 @@ export default class Watermark {
|
||||
this.draw()
|
||||
}
|
||||
}
|
||||
|
||||
Watermark.instanceName = 'watermark'
|
||||
|
||||
export default Watermark
|
||||
@@ -1,267 +1,289 @@
|
||||
import Base from './Base'
|
||||
import { walk, asyncRun } from '../utils'
|
||||
|
||||
// 逻辑结构图
|
||||
|
||||
class LogicalStructure extends Base {
|
||||
// 构造函数
|
||||
|
||||
constructor(opt = {}) {
|
||||
super(opt)
|
||||
}
|
||||
|
||||
// 布局
|
||||
|
||||
doLayout(callback) {
|
||||
let task = [
|
||||
() => {
|
||||
this.computedBaseValue()
|
||||
},
|
||||
() => {
|
||||
this.computedTopValue()
|
||||
},
|
||||
() => {
|
||||
this.adjustTopValue()
|
||||
},
|
||||
() => {
|
||||
callback(this.root)
|
||||
}
|
||||
]
|
||||
asyncRun(task)
|
||||
}
|
||||
|
||||
// 遍历数据计算节点的left、width、height
|
||||
|
||||
computedBaseValue() {
|
||||
walk(
|
||||
this.renderer.renderTree,
|
||||
null,
|
||||
(cur, parent, isRoot, layerIndex) => {
|
||||
let newNode = this.createNode(cur, parent, isRoot, layerIndex)
|
||||
// 根节点定位在画布中心位置
|
||||
if (isRoot) {
|
||||
this.setNodeCenter(newNode)
|
||||
} else {
|
||||
// 非根节点
|
||||
// 定位到父节点右侧
|
||||
newNode.left =
|
||||
parent._node.left + parent._node.width + this.getMarginX(layerIndex)
|
||||
}
|
||||
if (!cur.data.expand) {
|
||||
return true
|
||||
}
|
||||
},
|
||||
(cur, parent, isRoot, layerIndex) => {
|
||||
// 返回时计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距
|
||||
let len = cur.data.expand === false ? 0 : cur._node.children.length
|
||||
cur._node.childrenAreaHeight = len
|
||||
? cur._node.children.reduce((h, item) => {
|
||||
return h + item.height
|
||||
}, 0) +
|
||||
(len + 1) * this.getMarginY(layerIndex + 1)
|
||||
: 0
|
||||
},
|
||||
true,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
// 遍历节点树计算节点的top
|
||||
|
||||
computedTopValue() {
|
||||
walk(
|
||||
this.root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
if (
|
||||
node.nodeData.data.expand &&
|
||||
node.children &&
|
||||
node.children.length
|
||||
) {
|
||||
let marginY = this.getMarginY(layerIndex + 1)
|
||||
// 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半
|
||||
let top = node.top + node.height / 2 - node.childrenAreaHeight / 2
|
||||
let totalTop = top + marginY
|
||||
node.children.forEach(cur => {
|
||||
cur.top = totalTop
|
||||
totalTop += cur.height + marginY
|
||||
})
|
||||
}
|
||||
},
|
||||
null,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// 调整节点top
|
||||
|
||||
adjustTopValue() {
|
||||
walk(
|
||||
this.root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
if (!node.nodeData.data.expand) {
|
||||
return
|
||||
}
|
||||
// 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置
|
||||
let difference =
|
||||
node.childrenAreaHeight -
|
||||
this.getMarginY(layerIndex + 1) * 2 -
|
||||
node.height
|
||||
if (difference > 0) {
|
||||
this.updateBrothers(node, difference / 2)
|
||||
}
|
||||
},
|
||||
null,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// 更新兄弟节点的top
|
||||
|
||||
updateBrothers(node, addHeight) {
|
||||
if (node.parent) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex(item => {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item === node || item.hasCustomPosition()) {
|
||||
// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
// 上面的节点往上移
|
||||
if (_index < index) {
|
||||
_offset = -addHeight
|
||||
} else if (_index > index) {
|
||||
// 下面的节点往下移
|
||||
_offset = addHeight
|
||||
}
|
||||
item.top += _offset
|
||||
// 同步更新子节点的位置
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, 'top', _offset)
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothers(node.parent, addHeight)
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制连线,连接该节点到其子节点
|
||||
|
||||
renderLine(node, lines, style, lineStyle) {
|
||||
if (lineStyle === 'curve') {
|
||||
this.renderLineCurve(node, lines, style)
|
||||
} else if (lineStyle === 'direct') {
|
||||
this.renderLineDirect(node, lines, style)
|
||||
} else {
|
||||
this.renderLineStraight(node, lines, style)
|
||||
}
|
||||
}
|
||||
|
||||
// 直线风格连线
|
||||
|
||||
renderLineStraight(node, lines, style) {
|
||||
if (node.children.length <= 0) {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let marginX = this.getMarginX(node.layerIndex + 1)
|
||||
let s1 = (marginX - expandBtnSize) * 0.6
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0 ? left + width : left + width + expandBtnSize
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStyleOffset = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
? item.width
|
||||
: 0
|
||||
let path = `M ${x1},${y1} L ${x1 + s1},${y1} L ${x1 + s1},${y2} L ${
|
||||
x2 + nodeUseLineStyleOffset
|
||||
},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
})
|
||||
}
|
||||
|
||||
// 直连风格
|
||||
|
||||
renderLineDirect(node, lines, style) {
|
||||
if (node.children.length <= 0) {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStylePath = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
? ` L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
})
|
||||
}
|
||||
|
||||
// 曲线风格连线
|
||||
|
||||
renderLineCurve(node, lines, style) {
|
||||
if (node.children.length <= 0) {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = ''
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStylePath = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
? ` L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
if (node.isRoot) {
|
||||
path = this.quadraticCurvePath(x1, y1, x2, y2) + nodeUseLineStylePath
|
||||
} else {
|
||||
path = this.cubicBezierPath(x1, y1, x2, y2) + nodeUseLineStylePath
|
||||
}
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
})
|
||||
}
|
||||
|
||||
// 渲染按钮
|
||||
|
||||
renderExpandBtn(node, btn) {
|
||||
let { width, height } = node
|
||||
let { translateX, translateY } = btn.transform()
|
||||
// 节点使用横线风格,需要调整展开收起按钮位置
|
||||
let nodeUseLineStyleOffset = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
? height / 2
|
||||
: 0
|
||||
btn.translate(
|
||||
width - translateX,
|
||||
height / 2 - translateY + nodeUseLineStyleOffset
|
||||
)
|
||||
}
|
||||
|
||||
// 创建概要节点
|
||||
|
||||
renderGeneralization(node, gLine, gNode) {
|
||||
let {
|
||||
top,
|
||||
bottom,
|
||||
right,
|
||||
generalizationLineMargin,
|
||||
generalizationNodeMargin
|
||||
} = this.getNodeBoundaries(node, 'h')
|
||||
let x1 = right + generalizationLineMargin
|
||||
import Base from './Base'
|
||||
import { walk, asyncRun } from '../utils'
|
||||
|
||||
// 逻辑结构图
|
||||
|
||||
class LogicalStructure extends Base {
|
||||
// 构造函数
|
||||
|
||||
constructor(opt = {}) {
|
||||
super(opt)
|
||||
}
|
||||
|
||||
// 布局
|
||||
|
||||
doLayout(callback) {
|
||||
let task = [
|
||||
() => {
|
||||
this.computedBaseValue()
|
||||
},
|
||||
() => {
|
||||
this.computedTopValue()
|
||||
},
|
||||
() => {
|
||||
this.adjustTopValue()
|
||||
},
|
||||
() => {
|
||||
callback(this.root)
|
||||
}
|
||||
]
|
||||
asyncRun(task)
|
||||
}
|
||||
|
||||
// 遍历数据计算节点的left、width、height
|
||||
|
||||
computedBaseValue() {
|
||||
walk(
|
||||
this.renderer.renderTree,
|
||||
null,
|
||||
(cur, parent, isRoot, layerIndex) => {
|
||||
let newNode = this.createNode(cur, parent, isRoot, layerIndex)
|
||||
// 根节点定位在画布中心位置
|
||||
if (isRoot) {
|
||||
this.setNodeCenter(newNode)
|
||||
} else {
|
||||
// 非根节点
|
||||
// 定位到父节点右侧
|
||||
newNode.left =
|
||||
parent._node.left + parent._node.width + this.getMarginX(layerIndex)
|
||||
}
|
||||
if (!cur.data.expand) {
|
||||
return true
|
||||
}
|
||||
},
|
||||
(cur, parent, isRoot, layerIndex) => {
|
||||
// 返回时计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距
|
||||
let len = cur.data.expand === false ? 0 : cur._node.children.length
|
||||
cur._node.childrenAreaHeight = len
|
||||
? cur._node.children.reduce((h, item) => {
|
||||
return h + item.height
|
||||
}, 0) +
|
||||
(len + 1) * this.getMarginY(layerIndex + 1)
|
||||
: 0
|
||||
},
|
||||
true,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
// 遍历节点树计算节点的top
|
||||
|
||||
computedTopValue() {
|
||||
walk(
|
||||
this.root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
if (
|
||||
node.nodeData.data.expand &&
|
||||
node.children &&
|
||||
node.children.length
|
||||
) {
|
||||
let marginY = this.getMarginY(layerIndex + 1)
|
||||
// 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半
|
||||
let top = node.top + node.height / 2 - node.childrenAreaHeight / 2
|
||||
let totalTop = top + marginY
|
||||
node.children.forEach(cur => {
|
||||
cur.top = totalTop
|
||||
totalTop += cur.height + marginY
|
||||
})
|
||||
}
|
||||
},
|
||||
null,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// 调整节点top
|
||||
|
||||
adjustTopValue() {
|
||||
walk(
|
||||
this.root,
|
||||
null,
|
||||
(node, parent, isRoot, layerIndex) => {
|
||||
if (!node.nodeData.data.expand) {
|
||||
return
|
||||
}
|
||||
// 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置
|
||||
let difference =
|
||||
node.childrenAreaHeight -
|
||||
this.getMarginY(layerIndex + 1) * 2 -
|
||||
node.height
|
||||
if (difference > 0) {
|
||||
this.updateBrothers(node, difference / 2)
|
||||
}
|
||||
},
|
||||
null,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// 更新兄弟节点的top
|
||||
|
||||
updateBrothers(node, addHeight) {
|
||||
if (node.parent) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex(item => {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
if (item === node || item.hasCustomPosition()) {
|
||||
// 适配自定义位置
|
||||
return
|
||||
}
|
||||
let _offset = 0
|
||||
// 上面的节点往上移
|
||||
if (_index < index) {
|
||||
_offset = -addHeight
|
||||
} else if (_index > index) {
|
||||
// 下面的节点往下移
|
||||
_offset = addHeight
|
||||
}
|
||||
item.top += _offset
|
||||
// 同步更新子节点的位置
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, 'top', _offset)
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothers(node.parent, addHeight)
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制连线,连接该节点到其子节点
|
||||
|
||||
renderLine(node, lines, style, lineStyle) {
|
||||
if (lineStyle === 'curve') {
|
||||
this.renderLineCurve(node, lines, style)
|
||||
} else if (lineStyle === 'direct') {
|
||||
this.renderLineDirect(node, lines, style)
|
||||
} else {
|
||||
this.renderLineStraight(node, lines, style)
|
||||
}
|
||||
}
|
||||
|
||||
// 直线风格连线
|
||||
|
||||
renderLineStraight(node, lines, style) {
|
||||
if (node.children.length <= 0) {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let marginX = this.getMarginX(node.layerIndex + 1)
|
||||
let s1 = (marginX - expandBtnSize) * 0.6
|
||||
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0 ? left + width : left + width + expandBtnSize
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStyleOffset = nodeUseLineStyle
|
||||
? item.width
|
||||
: 0
|
||||
y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1
|
||||
y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2
|
||||
let path = `M ${x1},${y1} L ${x1 + s1},${y1} L ${x1 + s1},${y2} L ${
|
||||
x2 + nodeUseLineStyleOffset
|
||||
},${y2}`
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
})
|
||||
}
|
||||
|
||||
// 直连风格
|
||||
|
||||
renderLineDirect(node, lines, style) {
|
||||
if (node.children.length <= 0) {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1
|
||||
y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStylePath = nodeUseLineStyle
|
||||
? ` L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
})
|
||||
}
|
||||
|
||||
// 曲线风格连线
|
||||
|
||||
renderLineCurve(node, lines, style) {
|
||||
if (node.children.length <= 0) {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0 ? left + width / 2 : left + width + expandBtnSize
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = ''
|
||||
y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1
|
||||
y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStylePath = nodeUseLineStyle
|
||||
? ` L ${item.left + item.width},${y2}`
|
||||
: ''
|
||||
if (node.isRoot) {
|
||||
path = this.quadraticCurvePath(x1, y1, x2, y2) + nodeUseLineStylePath
|
||||
} else {
|
||||
path = this.cubicBezierPath(x1, y1, x2, y2) + nodeUseLineStylePath
|
||||
}
|
||||
lines[index].plot(path)
|
||||
style && style(lines[index], item)
|
||||
})
|
||||
}
|
||||
|
||||
// 渲染按钮
|
||||
|
||||
renderExpandBtn(node, btn) {
|
||||
let { width, height } = node
|
||||
let { translateX, translateY } = btn.transform()
|
||||
// 节点使用横线风格,需要调整展开收起按钮位置
|
||||
let nodeUseLineStyleOffset = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
? height / 2
|
||||
: 0
|
||||
btn.translate(
|
||||
width - translateX,
|
||||
height / 2 - translateY + nodeUseLineStyleOffset
|
||||
)
|
||||
}
|
||||
|
||||
// 创建概要节点
|
||||
|
||||
renderGeneralization(node, gLine, gNode) {
|
||||
let {
|
||||
top,
|
||||
bottom,
|
||||
right,
|
||||
generalizationLineMargin,
|
||||
generalizationNodeMargin
|
||||
} = this.getNodeBoundaries(node, 'h')
|
||||
let x1 = right + generalizationLineMargin
|
||||
let y1 = top
|
||||
let x2 = right + generalizationLineMargin
|
||||
let y2 = bottom
|
||||
let cx = x1 + 20
|
||||
let cy = y1 + (y2 - y1) / 2
|
||||
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
|
||||
gLine.plot(path)
|
||||
gNode.left = right + generalizationNodeMargin
|
||||
gNode.top = top + (bottom - top - gNode.height) / 2
|
||||
}
|
||||
}
|
||||
|
||||
export default LogicalStructure
|
||||
|
||||
@@ -208,11 +208,12 @@ class MindMap extends Base {
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let marginX = this.getMarginX(node.layerIndex + 1)
|
||||
let s1 = (marginX - expandBtnSize) * 0.6
|
||||
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 = 0
|
||||
let _s = 0
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStyleOffset = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
let nodeUseLineStyleOffset = nodeUseLineStyle
|
||||
? item.width
|
||||
: 0
|
||||
if (item.dir === 'left') {
|
||||
@@ -226,6 +227,8 @@ class MindMap extends Base {
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.dir === 'left' ? item.left + item.width : item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1
|
||||
y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2
|
||||
let path = `M ${x1},${y1} L ${x1 + _s},${y1} L ${x1 + _s},${y2} L ${
|
||||
x2 + nodeUseLineStyleOffset
|
||||
},${y2}`
|
||||
@@ -241,6 +244,7 @@ class MindMap extends Base {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0
|
||||
@@ -251,9 +255,11 @@ class MindMap extends Base {
|
||||
let y1 = top + height / 2
|
||||
let x2 = item.dir === 'left' ? item.left + item.width : item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1
|
||||
y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStylePath = ''
|
||||
if (this.mindMap.themeConfig.nodeUseLineStyle) {
|
||||
if (nodeUseLineStyle) {
|
||||
if (item.dir === 'left') {
|
||||
nodeUseLineStylePath = ` L ${item.left},${y2}`
|
||||
} else {
|
||||
@@ -273,6 +279,7 @@ class MindMap extends Base {
|
||||
return []
|
||||
}
|
||||
let { left, top, width, height, expandBtnSize } = node
|
||||
let nodeUseLineStyle = this.mindMap.themeConfig.nodeUseLineStyle
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 =
|
||||
node.layerIndex === 0
|
||||
@@ -284,6 +291,8 @@ class MindMap extends Base {
|
||||
let x2 = item.dir === 'left' ? item.left + item.width : item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = ''
|
||||
y1 = nodeUseLineStyle && !node.isRoot ? y1 + height / 2 : y1
|
||||
y2 = nodeUseLineStyle ? y2 + item.height / 2 : y2
|
||||
// 节点使用横线风格,需要额外渲染横线
|
||||
let nodeUseLineStylePath = ''
|
||||
if (this.mindMap.themeConfig.nodeUseLineStyle) {
|
||||
|
||||
@@ -1,142 +1,147 @@
|
||||
// 默认主题
|
||||
|
||||
export default {
|
||||
// 节点内边距
|
||||
paddingX: 15,
|
||||
paddingY: 5,
|
||||
// 图片显示的最大宽度
|
||||
imgMaxWidth: 100,
|
||||
// 图片显示的最大高度
|
||||
imgMaxHeight: 100,
|
||||
// icon的大小
|
||||
iconSize: 20,
|
||||
// 连线的粗细
|
||||
lineWidth: 1,
|
||||
// 连线的颜色
|
||||
lineColor: '#549688',
|
||||
// 连线样式
|
||||
lineDasharray: 'none',
|
||||
// 连线风格
|
||||
lineStyle: 'straight', // 针对logicalStructure、mindMap两种结构。曲线(curve)、直线(straight)、直连(direct)
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#549688',
|
||||
// 概要曲线距节点的距离
|
||||
generalizationLineMargin: 0,
|
||||
// 概要节点距节点的距离
|
||||
generalizationNodeMargin: 20,
|
||||
// 背景颜色
|
||||
backgroundColor: '#fafafa',
|
||||
// 背景图片
|
||||
backgroundImage: 'none',
|
||||
// 背景重复
|
||||
backgroundRepeat: 'no-repeat',
|
||||
// 节点使用横线样式
|
||||
nodeUseLineStyle: false,
|
||||
// 根节点样式
|
||||
root: {
|
||||
shape: 'rectangle',
|
||||
fillColor: '#549688',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
second: {
|
||||
shape: 'rectangle',
|
||||
marginX: 100,
|
||||
marginY: 40,
|
||||
fillColor: '#fff',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#565656',
|
||||
fontSize: 16,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: '#549688',
|
||||
borderWidth: 1,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
shape: 'rectangle',
|
||||
marginX: 50,
|
||||
marginY: 0,
|
||||
fillColor: 'transparent',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#6a6d6c',
|
||||
fontSize: 14,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderRadius: 5,
|
||||
borderDasharray: 'none',
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
shape: 'rectangle',
|
||||
marginX: 100,
|
||||
marginY: 40,
|
||||
fillColor: '#fff',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#565656',
|
||||
fontSize: 16,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: '#549688',
|
||||
borderWidth: 1,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 支持激活样式的属性
|
||||
// 简单来说,会改变节点大小的都不支持在激活时设置,为了性能考虑,节点切换激活态时不会重新计算节点大小
|
||||
export const supportActiveStyle = [
|
||||
'fillColor',
|
||||
'color',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'borderColor',
|
||||
'borderWidth',
|
||||
'borderDasharray',
|
||||
'borderRadius',
|
||||
'textDecoration'
|
||||
]
|
||||
|
||||
// 默认主题
|
||||
|
||||
export default {
|
||||
// 节点内边距
|
||||
paddingX: 15,
|
||||
paddingY: 5,
|
||||
// 图片显示的最大宽度
|
||||
imgMaxWidth: 100,
|
||||
// 图片显示的最大高度
|
||||
imgMaxHeight: 100,
|
||||
// icon的大小
|
||||
iconSize: 20,
|
||||
// 连线的粗细
|
||||
lineWidth: 1,
|
||||
// 连线的颜色
|
||||
lineColor: '#549688',
|
||||
// 连线样式
|
||||
lineDasharray: 'none',
|
||||
// 连线风格
|
||||
lineStyle: 'straight', // 针对logicalStructure、mindMap两种结构。曲线(curve)、直线(straight)、直连(direct)
|
||||
// 概要连线的粗细
|
||||
generalizationLineWidth: 1,
|
||||
// 概要连线的颜色
|
||||
generalizationLineColor: '#549688',
|
||||
// 概要曲线距节点的距离
|
||||
generalizationLineMargin: 0,
|
||||
// 概要节点距节点的距离
|
||||
generalizationNodeMargin: 20,
|
||||
// 背景颜色
|
||||
backgroundColor: '#fafafa',
|
||||
// 背景图片
|
||||
backgroundImage: 'none',
|
||||
// 背景重复
|
||||
backgroundRepeat: 'no-repeat',
|
||||
// 设置背景图像的起始位置
|
||||
backgroundPosition: 'center center',
|
||||
// 设置背景图片大小
|
||||
backgroundSize: 'cover',
|
||||
// 节点使用横线样式
|
||||
nodeUseLineStyle: false,
|
||||
// 根节点样式
|
||||
root: {
|
||||
shape: 'rectangle',
|
||||
fillColor: '#549688',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
},
|
||||
// 二级节点样式
|
||||
second: {
|
||||
shape: 'rectangle',
|
||||
marginX: 100,
|
||||
marginY: 40,
|
||||
fillColor: '#fff',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#565656',
|
||||
fontSize: 16,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: '#549688',
|
||||
borderWidth: 1,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
shape: 'rectangle',
|
||||
marginX: 50,
|
||||
marginY: 0,
|
||||
fillColor: 'transparent',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#6a6d6c',
|
||||
fontSize: 14,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: 'transparent',
|
||||
borderWidth: 0,
|
||||
borderRadius: 5,
|
||||
borderDasharray: 'none',
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
shape: 'rectangle',
|
||||
marginX: 100,
|
||||
marginY: 40,
|
||||
fillColor: '#fff',
|
||||
fontFamily: '微软雅黑, Microsoft YaHei',
|
||||
color: '#565656',
|
||||
fontSize: 16,
|
||||
fontWeight: 'noraml',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 1.5,
|
||||
borderColor: '#549688',
|
||||
borderWidth: 1,
|
||||
borderDasharray: 'none',
|
||||
borderRadius: 5,
|
||||
textDecoration: 'none',
|
||||
active: {
|
||||
borderColor: 'rgb(57, 80, 96)',
|
||||
borderWidth: 3,
|
||||
borderDasharray: 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 支持激活样式的属性
|
||||
// 简单来说,会改变节点大小的都不支持在激活时设置,为了性能考虑,节点切换激活态时不会重新计算节点大小
|
||||
export const supportActiveStyle = [
|
||||
'fillColor',
|
||||
'color',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'borderColor',
|
||||
'borderWidth',
|
||||
'borderDasharray',
|
||||
'borderRadius',
|
||||
'textDecoration'
|
||||
]
|
||||
|
||||
export const lineStyleProps = ['lineColor', 'lineDasharray', 'lineWidth']
|
||||
|
||||
@@ -235,4 +235,34 @@ export const camelCaseToHyphen = (str) => {
|
||||
return str.replace(/([a-z])([A-Z])/g, (...args) => {
|
||||
return args[1] + '-' + args[2].toLowerCase()
|
||||
})
|
||||
}
|
||||
|
||||
//计算节点的文本长宽
|
||||
let measureTextContext = null
|
||||
export const measureText = (text, { italic, bold, fontSize, fontFamily }) => {
|
||||
const font = joinFontStr({
|
||||
italic,
|
||||
bold,
|
||||
fontSize,
|
||||
fontFamily
|
||||
})
|
||||
if (!measureTextContext) {
|
||||
const canvas = document.createElement('canvas')
|
||||
measureTextContext = canvas.getContext('2d')
|
||||
}
|
||||
measureTextContext.save()
|
||||
measureTextContext.font = font
|
||||
const {
|
||||
width,
|
||||
actualBoundingBoxAscent,
|
||||
actualBoundingBoxDescent
|
||||
} = measureTextContext.measureText(text)
|
||||
measureTextContext.restore()
|
||||
const height = actualBoundingBoxAscent + actualBoundingBoxDescent
|
||||
return { width, height }
|
||||
}
|
||||
|
||||
// 拼接font字符串
|
||||
export const joinFontStr = ({ italic, bold, fontSize, fontFamily }) => {
|
||||
return `${italic ? 'italic ' : ''} ${bold ? 'bold ' : ''} ${fontSize}px ${fontFamily} `
|
||||
}
|
||||
354
simple-mind-map/src/utils/simulateCSSBackgroundInCanvas.js
Normal file
354
simple-mind-map/src/utils/simulateCSSBackgroundInCanvas.js
Normal file
@@ -0,0 +1,354 @@
|
||||
// 将以空格分隔的字符串值转换成成数字/单位/值数组
|
||||
const getNumberValueFromStr = value => {
|
||||
let arr = String(value).split(/\s+/)
|
||||
return arr.map(item => {
|
||||
if (/^[\d.]+/.test(item)) {
|
||||
// 数字+单位
|
||||
let res = /^([\d.]+)(.*)$/.exec(item)
|
||||
return [Number(res[1]), res[2]]
|
||||
} else {
|
||||
// 单个值
|
||||
return item
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 缩放宽度
|
||||
const zoomWidth = (ratio, height) => {
|
||||
// w / height = ratio
|
||||
return ratio * height
|
||||
}
|
||||
|
||||
// 缩放高度
|
||||
const zoomHeight = (ratio, width) => {
|
||||
// width / h = ratio
|
||||
return width / ratio
|
||||
}
|
||||
|
||||
// 关键词到百分比值的映射
|
||||
const keyWordToPercentageMap = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
center: 50,
|
||||
bottom: 100,
|
||||
right: 100
|
||||
}
|
||||
|
||||
// 模拟background-size
|
||||
const handleBackgroundSize = ({
|
||||
backgroundSize,
|
||||
drawOpt,
|
||||
imageRatio,
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
canvasRatio
|
||||
}) => {
|
||||
if (backgroundSize) {
|
||||
// 将值转换成数组
|
||||
let backgroundSizeValueArr = getNumberValueFromStr(backgroundSize)
|
||||
// 两个值都为auto,那就相当于不设置
|
||||
if (
|
||||
backgroundSizeValueArr[0] === 'auto' &&
|
||||
backgroundSizeValueArr[1] === 'auto'
|
||||
) {
|
||||
return
|
||||
}
|
||||
// 值为cover
|
||||
if (backgroundSizeValueArr[0] === 'cover') {
|
||||
if (imageRatio > canvasRatio) {
|
||||
// 图片的宽高比大于canvas的宽高比,那么图片高度缩放到和canvas的高度一致,宽度自适应
|
||||
drawOpt.height = canvasHeight
|
||||
drawOpt.width = zoomWidth(imageRatio, canvasHeight)
|
||||
} else {
|
||||
// 否则图片宽度缩放到和canvas的宽度一致,高度自适应
|
||||
drawOpt.width = canvasWidth
|
||||
drawOpt.height = zoomHeight(imageRatio, canvasWidth)
|
||||
}
|
||||
return
|
||||
}
|
||||
// 值为contain
|
||||
if (backgroundSizeValueArr[0] === 'contain') {
|
||||
if (imageRatio > canvasRatio) {
|
||||
// 图片的宽高比大于canvas的宽高比,那么图片宽度缩放到和canvas的宽度一致,高度自适应
|
||||
drawOpt.width = canvasWidth
|
||||
drawOpt.height = zoomHeight(imageRatio, canvasWidth)
|
||||
} else {
|
||||
// 否则图片高度缩放到和canvas的高度一致,宽度自适应
|
||||
drawOpt.height = canvasHeight
|
||||
drawOpt.width = zoomWidth(imageRatio, canvasHeight)
|
||||
}
|
||||
return
|
||||
}
|
||||
// 图片宽度
|
||||
let newNumberWidth = -1
|
||||
if (backgroundSizeValueArr[0]) {
|
||||
if (Array.isArray(backgroundSizeValueArr[0])) {
|
||||
// 数字+单位类型
|
||||
if (backgroundSizeValueArr[0][1] === '%') {
|
||||
// %单位
|
||||
drawOpt.width = (backgroundSizeValueArr[0][0] / 100) * canvasWidth
|
||||
newNumberWidth = drawOpt.width
|
||||
} else {
|
||||
// 其他都认为是px单位
|
||||
drawOpt.width = backgroundSizeValueArr[0][0]
|
||||
newNumberWidth = backgroundSizeValueArr[0][0]
|
||||
}
|
||||
} else if (backgroundSizeValueArr[0] === 'auto') {
|
||||
// auto类型,那么根据设置的新高度以图片原宽高比进行自适应
|
||||
if (backgroundSizeValueArr[1]) {
|
||||
if (backgroundSizeValueArr[1][1] === '%') {
|
||||
// 高度为%单位
|
||||
drawOpt.width = zoomWidth(
|
||||
imageRatio,
|
||||
(backgroundSizeValueArr[1][0] / 100) * canvasHeight
|
||||
)
|
||||
} else {
|
||||
// 其他都认为是px单位
|
||||
drawOpt.width = zoomWidth(imageRatio, backgroundSizeValueArr[1][0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置了图片高度
|
||||
if (backgroundSizeValueArr[1] && Array.isArray(backgroundSizeValueArr[1])) {
|
||||
// 数字+单位类型
|
||||
if (backgroundSizeValueArr[1][1] === '%') {
|
||||
// 高度为%单位
|
||||
drawOpt.height = (backgroundSizeValueArr[1][0] / 100) * canvasHeight
|
||||
} else {
|
||||
// 其他都认为是px单位
|
||||
drawOpt.height = backgroundSizeValueArr[1][0]
|
||||
}
|
||||
} else if (newNumberWidth !== -1) {
|
||||
// 没有设置图片高度或者设置为auto,那么根据设置的新宽度以图片原宽高比进行自适应
|
||||
drawOpt.height = zoomHeight(imageRatio, newNumberWidth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟background-position
|
||||
const handleBackgroundPosition = ({
|
||||
backgroundPosition,
|
||||
drawOpt,
|
||||
imgWidth,
|
||||
imgHeight,
|
||||
canvasWidth,
|
||||
canvasHeight
|
||||
}) => {
|
||||
if (backgroundPosition) {
|
||||
// 将值转换成数组
|
||||
let backgroundPositionValueArr = getNumberValueFromStr(backgroundPosition)
|
||||
// 将关键词转为百分比
|
||||
backgroundPositionValueArr = backgroundPositionValueArr.map(item => {
|
||||
if (typeof item === 'string') {
|
||||
return keyWordToPercentageMap[item] !== undefined
|
||||
? [keyWordToPercentageMap[item], '%']
|
||||
: item
|
||||
}
|
||||
return item
|
||||
})
|
||||
if (Array.isArray(backgroundPositionValueArr[0])) {
|
||||
if (backgroundPositionValueArr.length === 1) {
|
||||
// 如果只设置了一个值,第二个默认为50%
|
||||
backgroundPositionValueArr.push([50, '%'])
|
||||
}
|
||||
// 水平位置
|
||||
if (backgroundPositionValueArr[0][1] === '%') {
|
||||
// 单位为%
|
||||
let canvasX = (backgroundPositionValueArr[0][0] / 100) * canvasWidth
|
||||
let imgX = (backgroundPositionValueArr[0][0] / 100) * imgWidth
|
||||
// 计算差值
|
||||
drawOpt.x = canvasX - imgX
|
||||
} else {
|
||||
// 其他单位默认都为px
|
||||
drawOpt.x = backgroundPositionValueArr[0][0]
|
||||
}
|
||||
// 垂直位置
|
||||
if (backgroundPositionValueArr[1][1] === '%') {
|
||||
// 单位为%
|
||||
let canvasY = (backgroundPositionValueArr[1][0] / 100) * canvasHeight
|
||||
let imgY = (backgroundPositionValueArr[1][0] / 100) * imgHeight
|
||||
// 计算差值
|
||||
drawOpt.y = canvasY - imgY
|
||||
} else {
|
||||
// 其他单位默认都为px
|
||||
drawOpt.y = backgroundPositionValueArr[1][0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟background-repeat
|
||||
const handleBackgroundRepeat = ({
|
||||
ctx,
|
||||
image,
|
||||
backgroundRepeat,
|
||||
drawOpt,
|
||||
imgWidth,
|
||||
imgHeight,
|
||||
canvasWidth,
|
||||
canvasHeight
|
||||
}) => {
|
||||
if (backgroundRepeat) {
|
||||
// 保存在handleBackgroundPosition中计算出来的x、y
|
||||
let ox = drawOpt.x
|
||||
let oy = drawOpt.y
|
||||
// 计算ox和oy能平铺的图片数量
|
||||
let oxRepeatNum = Math.ceil(ox / imgWidth)
|
||||
let oyRepeatNum = Math.ceil(oy / imgHeight)
|
||||
// 计算ox和oy第一张图片的位置
|
||||
let oxRepeatX = ox - oxRepeatNum * imgWidth
|
||||
let oxRepeatY = oy - oyRepeatNum * imgHeight
|
||||
// 将值转换成数组
|
||||
let backgroundRepeatValueArr = getNumberValueFromStr(backgroundRepeat)
|
||||
// 不处理
|
||||
if (
|
||||
backgroundRepeatValueArr[0] === 'no-repeat' ||
|
||||
(imgWidth >= canvasWidth && imgHeight >= canvasHeight)
|
||||
) {
|
||||
return
|
||||
}
|
||||
// 水平平铺
|
||||
if (backgroundRepeatValueArr[0] === 'repeat-x') {
|
||||
if (canvasWidth > imgWidth) {
|
||||
let x = oxRepeatX
|
||||
while (x < canvasWidth) {
|
||||
drawImage(ctx, image, {
|
||||
...drawOpt,
|
||||
x
|
||||
})
|
||||
x += imgWidth
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
// 垂直平铺
|
||||
if (backgroundRepeatValueArr[0] === 'repeat-y') {
|
||||
if (canvasHeight > imgHeight) {
|
||||
let y = oxRepeatY
|
||||
while (y < canvasHeight) {
|
||||
drawImage(ctx, image, {
|
||||
...drawOpt,
|
||||
y
|
||||
})
|
||||
y += imgHeight
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
// 平铺
|
||||
if (backgroundRepeatValueArr[0] === 'repeat') {
|
||||
let x = oxRepeatX
|
||||
while (x < canvasWidth) {
|
||||
if (canvasHeight > imgHeight) {
|
||||
let y = oxRepeatY
|
||||
while (y < canvasHeight) {
|
||||
drawImage(ctx, image, {
|
||||
...drawOpt,
|
||||
x,
|
||||
y
|
||||
})
|
||||
y += imgHeight
|
||||
}
|
||||
}
|
||||
x += imgWidth
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据参数绘制图片
|
||||
const drawImage = (ctx, image, drawOpt) => {
|
||||
ctx.drawImage(
|
||||
image,
|
||||
drawOpt.sx,
|
||||
drawOpt.sy,
|
||||
drawOpt.swidth,
|
||||
drawOpt.sheight,
|
||||
drawOpt.x,
|
||||
drawOpt.y,
|
||||
drawOpt.width,
|
||||
drawOpt.height
|
||||
)
|
||||
}
|
||||
|
||||
const drawBackgroundImageToCanvas = (
|
||||
ctx,
|
||||
width,
|
||||
height,
|
||||
img,
|
||||
{ backgroundSize, backgroundPosition, backgroundRepeat },
|
||||
callback = () => {}
|
||||
) => {
|
||||
// 画布的长宽比
|
||||
let canvasRatio = width / height
|
||||
// 加载图片
|
||||
let image = new Image()
|
||||
image.src = img
|
||||
image.onload = () => {
|
||||
// 图片的宽度及长宽比
|
||||
let imgWidth = image.width
|
||||
let imgHeight = image.height
|
||||
let imageRatio = imgWidth / imgHeight
|
||||
// 绘制图片
|
||||
// drawImage方法的参数值
|
||||
let drawOpt = {
|
||||
sx: 0,
|
||||
sy: 0,
|
||||
swidth: imgWidth,
|
||||
sheight: imgHeight,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: imgWidth,
|
||||
height: imgHeight
|
||||
}
|
||||
// 模拟background-size
|
||||
handleBackgroundSize({
|
||||
backgroundSize,
|
||||
drawOpt,
|
||||
imageRatio,
|
||||
canvasWidth: width,
|
||||
canvasHeight: height,
|
||||
canvasRatio
|
||||
})
|
||||
|
||||
// 模拟background-position
|
||||
handleBackgroundPosition({
|
||||
backgroundPosition,
|
||||
drawOpt,
|
||||
imgWidth: drawOpt.width,
|
||||
imgHeight: drawOpt.height,
|
||||
imageRatio,
|
||||
canvasWidth: width,
|
||||
canvasHeight: height,
|
||||
canvasRatio
|
||||
})
|
||||
|
||||
// 模拟background-repeat
|
||||
let notNeedDraw = handleBackgroundRepeat({
|
||||
ctx,
|
||||
image,
|
||||
backgroundRepeat,
|
||||
drawOpt,
|
||||
imgWidth: drawOpt.width,
|
||||
imgHeight: drawOpt.height,
|
||||
imageRatio,
|
||||
canvasWidth: width,
|
||||
canvasHeight: height,
|
||||
canvasRatio
|
||||
})
|
||||
|
||||
// 绘制图片
|
||||
if (!notNeedDraw) {
|
||||
drawImage(ctx, image, drawOpt)
|
||||
}
|
||||
|
||||
callback()
|
||||
}
|
||||
image.onerror = e => {
|
||||
callback(e)
|
||||
}
|
||||
}
|
||||
|
||||
export default drawBackgroundImageToCanvas
|
||||
23
web/package-lock.json
generated
23
web/package-lock.json
generated
@@ -24,6 +24,7 @@
|
||||
"@vue/cli-plugin-eslint": "^4.5.0",
|
||||
"@vue/cli-service": "^4.5.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"less": "^3.12.2",
|
||||
@@ -3524,7 +3525,6 @@
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -4138,7 +4138,6 @@
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
],
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
@@ -4160,7 +4159,6 @@
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
@@ -4173,7 +4171,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
@@ -4186,7 +4183,6 @@
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
@@ -4199,7 +4195,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
@@ -4209,7 +4204,6 @@
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
@@ -8606,7 +8600,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
@@ -12109,7 +12102,6 @@
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
@@ -18943,8 +18935,7 @@
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.5.0",
|
||||
@@ -19454,7 +19445,6 @@
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
@@ -19471,7 +19461,6 @@
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
@@ -19481,7 +19470,6 @@
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
@@ -19491,7 +19479,6 @@
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
@@ -19500,15 +19487,13 @@
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
@@ -22941,7 +22926,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
@@ -25800,7 +25784,6 @@
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build && node ../copy.js",
|
||||
"lint": "vue-cli-service lint",
|
||||
"buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/index.js --dest ../simple-mind-map/dist",
|
||||
"buildLibrary": "vue-cli-service build --target lib --name simpleMindMap ../simple-mind-map/full.js --dest ../simple-mind-map/dist",
|
||||
"format": "prettier --write src/* src/*/* src/*/*/* src/*/*/*/*",
|
||||
"buildDoc": "node ./scripts/buildDoc.js"
|
||||
"buildDoc": "node ./scripts/buildDoc.js",
|
||||
"autoBuildDoc": "node ./scripts/autoBuildDoc.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@toast-ui/editor": "^3.1.5",
|
||||
@@ -27,6 +28,7 @@
|
||||
"@vue/cli-plugin-eslint": "^4.5.0",
|
||||
"@vue/cli-service": "^4.5.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"chokidar": "^3.5.3",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"less": "^3.12.2",
|
||||
|
||||
38
web/scripts/autoBuildDoc.js
Normal file
38
web/scripts/autoBuildDoc.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const chokidar = require('chokidar')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const { exec } = require('node:child_process')
|
||||
const { transformMdToVue } = require('./transformMdToVue')
|
||||
|
||||
const reBuildAll = () => {
|
||||
exec(
|
||||
'node ./buildDoc.js',
|
||||
{
|
||||
cwd: path.resolve(__dirname)
|
||||
},
|
||||
(error, msg) => {
|
||||
console.log(error, msg)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const buildOne = file => {
|
||||
let content = fs.readFileSync(file, 'utf-8')
|
||||
let doc = transformMdToVue(content)
|
||||
let destPath = path.join(path.dirname(file), './index.vue')
|
||||
fs.writeFileSync(destPath, doc)
|
||||
}
|
||||
|
||||
chokidar
|
||||
.watch(path.join(__dirname, '../src/pages/Doc/'), {
|
||||
ignoreInitial: true
|
||||
})
|
||||
.on('all', (event, file) => {
|
||||
if (/\.md$/.test(file)) {
|
||||
if (event === 'change') {
|
||||
buildOne(file)
|
||||
} else {
|
||||
reBuildAll()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,24 +1,7 @@
|
||||
// 编译文档
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const hljs = require('highlight.js')
|
||||
const md = require('markdown-it')({
|
||||
highlight: function(str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return (
|
||||
'<pre class="hljs"><code>' +
|
||||
hljs.highlight(lang, str, true).value +
|
||||
'</code></pre>'
|
||||
)
|
||||
} catch (__) {}
|
||||
}
|
||||
|
||||
return (
|
||||
'<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'
|
||||
)
|
||||
}
|
||||
}).use(require('markdown-it-checkbox'))
|
||||
const { transformMdToVue } = require('./transformMdToVue')
|
||||
|
||||
// 文档语言种类
|
||||
let langList = ['zh', 'en']
|
||||
@@ -48,15 +31,12 @@ const compilerDir = (dir, dirName, routerList) => {
|
||||
const compilerFile = (dir, file, dirName, routerList) => {
|
||||
let filePath = path.join(dir, file)
|
||||
let destPath = path.join(dir, './index.vue')
|
||||
let templatePath = path.join(__dirname, '../src/pages/Doc/Template.vue')
|
||||
let content = fs.readFileSync(filePath, 'utf-8')
|
||||
let title = /(^|\n\r)\s*#\s+([^\n\r]+)/g.exec(content)
|
||||
if (title && title[2]) {
|
||||
addRouter(dirName, routerList, title[2])
|
||||
}
|
||||
let result = md.render(content)
|
||||
let template = fs.readFileSync(templatePath, 'utf-8')
|
||||
let doc = template.replace('$$$$', result)
|
||||
let doc = transformMdToVue(content)
|
||||
fs.writeFileSync(destPath, doc)
|
||||
}
|
||||
|
||||
|
||||
31
web/scripts/transformMdToVue.js
Normal file
31
web/scripts/transformMdToVue.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const hljs = require('highlight.js')
|
||||
const md = require('markdown-it')({
|
||||
highlight: function(str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return (
|
||||
'<pre class="hljs"><code>' +
|
||||
hljs.highlight(str, {
|
||||
language: lang,
|
||||
ignoreIllegals: true
|
||||
}).value +
|
||||
'</code></pre>'
|
||||
)
|
||||
} catch (__) {}
|
||||
}
|
||||
|
||||
return (
|
||||
'<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'
|
||||
)
|
||||
}
|
||||
}).use(require('markdown-it-checkbox'))
|
||||
|
||||
const templatePath = path.join(__dirname, '../src/pages/Doc/Template.vue')
|
||||
|
||||
exports.transformMdToVue = (content) => {
|
||||
let result = md.render(content)
|
||||
let template = fs.readFileSync(templatePath, 'utf-8')
|
||||
return template.replace('$$$$', result)
|
||||
}
|
||||
@@ -166,6 +166,22 @@ export const backgroundPositionList = [
|
||||
}
|
||||
]
|
||||
|
||||
// 背景图片大小
|
||||
export const backgroundSizeList = [
|
||||
{
|
||||
name: 'Auto',
|
||||
value: 'auto'
|
||||
},
|
||||
{
|
||||
name: 'Cover',
|
||||
value: 'cover'
|
||||
},
|
||||
{
|
||||
name: 'Contain',
|
||||
value: 'contain'
|
||||
}
|
||||
]
|
||||
|
||||
// 快捷键列表
|
||||
export const shortcutKeyList = [
|
||||
{
|
||||
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
backgroundPositionList as backgroundPositionListZh,
|
||||
shortcutKeyList as shortcutKeyListZh,
|
||||
shapeList as shapeListZh,
|
||||
sidebarTriggerList as sidebarTriggerListZh
|
||||
sidebarTriggerList as sidebarTriggerListZh,
|
||||
backgroundSizeList as backgroundSizeListZh
|
||||
} from './zh'
|
||||
import {
|
||||
fontFamilyList as fontFamilyListEn,
|
||||
@@ -24,7 +25,8 @@ import {
|
||||
backgroundPositionList as backgroundPositionListEn,
|
||||
shortcutKeyList as shortcutKeyListEn,
|
||||
shapeList as shapeListEn,
|
||||
sidebarTriggerList as sidebarTriggerListEn
|
||||
sidebarTriggerList as sidebarTriggerListEn,
|
||||
backgroundSizeList as backgroundSizeListEn
|
||||
} from './en'
|
||||
|
||||
const fontFamilyList = {
|
||||
@@ -52,6 +54,11 @@ const backgroundPositionList = {
|
||||
en: backgroundPositionListEn
|
||||
}
|
||||
|
||||
const backgroundSizeList = {
|
||||
zh: backgroundSizeListZh,
|
||||
en: backgroundSizeListEn
|
||||
}
|
||||
|
||||
const shortcutKeyList = {
|
||||
zh: shortcutKeyListZh,
|
||||
en: shortcutKeyListEn
|
||||
@@ -81,6 +88,7 @@ export {
|
||||
lineStyleList,
|
||||
backgroundRepeatList,
|
||||
backgroundPositionList,
|
||||
backgroundSizeList,
|
||||
shortcutKeyList,
|
||||
shapeList,
|
||||
sidebarTriggerList
|
||||
|
||||
@@ -221,6 +221,22 @@ export const backgroundPositionList = [
|
||||
}
|
||||
]
|
||||
|
||||
// 背景图片大小
|
||||
export const backgroundSizeList = [
|
||||
{
|
||||
name: '自动',
|
||||
value: 'auto'
|
||||
},
|
||||
{
|
||||
name: '覆盖',
|
||||
value: 'cover'
|
||||
},
|
||||
{
|
||||
name: '保持',
|
||||
value: 'contain'
|
||||
}
|
||||
]
|
||||
|
||||
// 数据存储
|
||||
export const store = {
|
||||
sidebarZIndex: 1 //侧边栏zIndex
|
||||
|
||||
@@ -5,6 +5,8 @@ export default {
|
||||
color: 'Color',
|
||||
image: 'Image',
|
||||
imageRepeat: 'Image repeat',
|
||||
imagePosition: 'Image position',
|
||||
imageSize: 'Image size',
|
||||
line: 'Line',
|
||||
width: 'Width',
|
||||
style: 'Style',
|
||||
|
||||
@@ -5,6 +5,8 @@ export default {
|
||||
color: '颜色',
|
||||
image: '图片',
|
||||
imageRepeat: '图片重复',
|
||||
imagePosition: '图片位置',
|
||||
imageSize: '图片大小',
|
||||
line: '连线',
|
||||
width: '粗细',
|
||||
style: '风格',
|
||||
|
||||
@@ -16,14 +16,16 @@ let APIList = [
|
||||
'node',
|
||||
'render',
|
||||
'view',
|
||||
'miniMap',
|
||||
'doExport',
|
||||
'watermark',
|
||||
'keyCommand',
|
||||
'keyboardNavigation',
|
||||
'command',
|
||||
'select',
|
||||
'batchExecution',
|
||||
'select',
|
||||
'drag',
|
||||
'keyboardNavigation',
|
||||
'doExport',
|
||||
'miniMap',
|
||||
'watermark',
|
||||
'xmind',
|
||||
'utils'
|
||||
]
|
||||
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
## 0.3.4
|
||||
|
||||
New:Automatic line wrapping function is added to node text.
|
||||
|
||||
Fix: 1.Fix the problem of deletion exceptions if there are root nodes in the batch deleted nodes. 2.Fix the problem that high node height will overlap with other nodes in the case of bottom edge style.
|
||||
|
||||
## 0.3.3
|
||||
|
||||
Fix: The root node text cannot wrap.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
Fix: 1.Fix the problem that the node style is not updated when the secondary node is dragged to other nodes or other nodes are dragged to the secondary node; 2.Fix the problem that when the actual content of the mind map is larger than the screen width and height, the excess part is not watermarked when exporting.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
Fix: 1.The problem that deleting the background image does not take effect; 2.The problem that the connector runs above the root node when the node is dragged to the root node.
|
||||
|
||||
New: Add position and size settings for background image display. This setting is also supported for exported pictures.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
Upgrade to plugin architecture, pull out some non-core functions as plugins, register as needed, and reduce the overall volume.
|
||||
|
||||
## 0.2.24
|
||||
|
||||
New: Node free drag is changed to configurable, the default is `false`, not open; Support add watermark.
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.3.4</h2>
|
||||
<p>New:Automatic line wrapping function is added to node text.</p>
|
||||
<p>Fix: 1.Fix the problem of deletion exceptions if there are root nodes in the batch deleted nodes. 2.Fix the problem that high node height will overlap with other nodes in the case of bottom edge style.</p>
|
||||
<h2>0.3.3</h2>
|
||||
<p>Fix: The root node text cannot wrap.</p>
|
||||
<h2>0.3.2</h2>
|
||||
<p>Fix: 1.Fix the problem that the node style is not updated when the secondary node is dragged to other nodes or other nodes are dragged to the secondary node; 2.Fix the problem that when the actual content of the mind map is larger than the screen width and height, the excess part is not watermarked when exporting.</p>
|
||||
<h2>0.3.1</h2>
|
||||
<p>Fix: 1.The problem that deleting the background image does not take effect; 2.The problem that the connector runs above the root node when the node is dragged to the root node.</p>
|
||||
<p>New: Add position and size settings for background image display. This setting is also supported for exported pictures.</p>
|
||||
<h2>0.3.0</h2>
|
||||
<p>Upgrade to plugin architecture, pull out some non-core functions as plugins, register as needed, and reduce the overall volume.</p>
|
||||
<h2>0.2.24</h2>
|
||||
<p>New: Node free drag is changed to configurable, the default is <code>false</code>, not open; Support add watermark.</p>
|
||||
<h2>0.2.23</h2>
|
||||
|
||||
@@ -20,50 +20,6 @@ const mindMap = new MindMap({
|
||||
});
|
||||
```
|
||||
|
||||
## Xmind Parsing Method
|
||||
|
||||
> v0.2.7+
|
||||
|
||||
You can get the `Xmind` parsing method as follows:
|
||||
|
||||
```js
|
||||
import MindMap from "simple-mind-map";
|
||||
|
||||
console.log(MindMap.xmind);
|
||||
```
|
||||
|
||||
The `MindMap.xmind` object has two methods attached:
|
||||
|
||||
### parseXmindFile(file)
|
||||
|
||||
Parsing the `.xmind` file and returning the parsed data. Note that this is
|
||||
complete data, including the node tree, theme, and structure. You can use
|
||||
`mindMap.setFullData(data)` to render the returned data to the canvas.
|
||||
|
||||
`file`: `File` object
|
||||
|
||||
### transformXmind(content)
|
||||
|
||||
Convert `xmind` data. The `.xmind` file is essentially a `zip` file that can be
|
||||
decompressed by changing the suffix to zip. Inside, there is a `content.json`
|
||||
file. If you have parsed this file yourself, you can pass the contents of this
|
||||
file to this method for conversion. The converted data is the complete data,
|
||||
including the node tree, theme, structure, etc. You can use
|
||||
`mindMap.setFullData(data)` to render the returned data to the canvas.
|
||||
|
||||
`content`: the contents of the `content.json` file within the `.xmind` zip
|
||||
package
|
||||
|
||||
### transformOldXmind(content)
|
||||
|
||||
> v0.2.8+
|
||||
|
||||
For data parsing of the `xmind8` version, because the `.xmind` file in this
|
||||
version does not have a `content.json`, it corresponds to `content.xml`.
|
||||
|
||||
`content`: the contents of the `content.xml` file within the `.xmind` zip
|
||||
package
|
||||
|
||||
## Instantiation options
|
||||
|
||||
| Field Name | Type | Default Value | Description | Required |
|
||||
@@ -84,6 +40,7 @@ package
|
||||
| readonly(v0.1.7+) | Boolean | false | Whether it is read-only mode | |
|
||||
| enableFreeDrag(v0.2.4+) | Boolean | false | Enable node free drag | |
|
||||
| watermarkConfig(v0.2.4+) | Object | | Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration | |
|
||||
| textAutoWrapWidth(v0.3.4+) | Number | 500 | Each line of text in the node will wrap automatically when it reaches the width | |
|
||||
|
||||
### Watermark config
|
||||
|
||||
@@ -125,16 +82,54 @@ mindMap.setTheme('Theme name')
|
||||
|
||||
For all configurations of theme, please refer to [Default Topic](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js). The `defineTheme`method will merge the configuration you passed in with the default configuration. Most of the themes do not need custom many parts. For a typical customized theme configuration, please refer to [blueSky](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/blueSky.js).
|
||||
|
||||
### usePlugin(plugin)
|
||||
|
||||
> v0.3.0+
|
||||
|
||||
If you need to use some non-core functions, such as mini map, watermark, etc, you can register plugin through this method. Can be called in chain.
|
||||
|
||||
Note: The plugin needs to be registered before instantiating `MindMap`.
|
||||
|
||||
## Static props
|
||||
|
||||
### pluginList
|
||||
|
||||
> v0.3.0+
|
||||
|
||||
List of all currently registered plugins.
|
||||
|
||||
|
||||
|
||||
## Instance methods
|
||||
|
||||
### render()
|
||||
### getSvgData()
|
||||
|
||||
> v0.3.0+
|
||||
|
||||
Get the `svg` data and return an object. The detailed structure is as follows:
|
||||
|
||||
```js
|
||||
{
|
||||
svg, // Element, the overall svg element of the mind map graphics, including: svg (canvas container), g (actual mind map group)
|
||||
svgHTML, // String, svg string, i.e. html string, can be directly rendered to the small map container you prepared
|
||||
rect: // Object, position, size, etc. of mind map graphics before zoom
|
||||
origWidth, // Number, canvas width
|
||||
origHeight, // Number, canvas height
|
||||
scaleX, // Number, horizontal zoom value of mind map graphics
|
||||
scaleY, // Number, vertical zoom value of mind map graphics
|
||||
}
|
||||
```
|
||||
|
||||
### render(callback)
|
||||
|
||||
- `callback`: `v0.3.2+`, `Function`, Called when the re-rendering is complete
|
||||
|
||||
Triggers a full rendering, which will reuse nodes for better performance. If
|
||||
only the node positions have changed, this method can be called to `reRender`.
|
||||
|
||||
### reRender()
|
||||
### reRender(callback)
|
||||
|
||||
- `callback`: `v0.3.2+`, `Function`, Called when the re-rendering is complete
|
||||
|
||||
Performs a full re-render, clearing the canvas and creating new nodes. This has
|
||||
poor performance and should be used sparingly.
|
||||
@@ -311,6 +306,8 @@ view, etc. data
|
||||
|
||||
### export(type, isDownload, fileName)
|
||||
|
||||
> You need to register the `Export` plugin first
|
||||
|
||||
Export
|
||||
|
||||
`type`: the type to be exported, optional values: png, svg, json, pdf (v0.2.1+),
|
||||
|
||||
@@ -16,38 +16,6 @@
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
<h2>Xmind Parsing Method</h2>
|
||||
<blockquote>
|
||||
<p>v0.2.7+</p>
|
||||
</blockquote>
|
||||
<p>You can get the <code>Xmind</code> parsing method as follows:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">"simple-mind-map"</span>;
|
||||
|
||||
<span class="hljs-built_in">console</span>.log(MindMap.xmind);
|
||||
</code></pre>
|
||||
<p>The <code>MindMap.xmind</code> object has two methods attached:</p>
|
||||
<h3>parseXmindFile(file)</h3>
|
||||
<p>Parsing the <code>.xmind</code> file and returning the parsed data. Note that this is
|
||||
complete data, including the node tree, theme, and structure. You can use
|
||||
<code>mindMap.setFullData(data)</code> to render the returned data to the canvas.</p>
|
||||
<p><code>file</code>: <code>File</code> object</p>
|
||||
<h3>transformXmind(content)</h3>
|
||||
<p>Convert <code>xmind</code> data. The <code>.xmind</code> file is essentially a <code>zip</code> file that can be
|
||||
decompressed by changing the suffix to zip. Inside, there is a <code>content.json</code>
|
||||
file. If you have parsed this file yourself, you can pass the contents of this
|
||||
file to this method for conversion. The converted data is the complete data,
|
||||
including the node tree, theme, structure, etc. You can use
|
||||
<code>mindMap.setFullData(data)</code> to render the returned data to the canvas.</p>
|
||||
<p><code>content</code>: the contents of the <code>content.json</code> file within the <code>.xmind</code> zip
|
||||
package</p>
|
||||
<h3>transformOldXmind(content)</h3>
|
||||
<blockquote>
|
||||
<p>v0.2.8+</p>
|
||||
</blockquote>
|
||||
<p>For data parsing of the <code>xmind8</code> version, because the <code>.xmind</code> file in this
|
||||
version does not have a <code>content.json</code>, it corresponds to <code>content.xml</code>.</p>
|
||||
<p><code>content</code>: the contents of the <code>content.xml</code> file within the <code>.xmind</code> zip
|
||||
package</p>
|
||||
<h2>Instantiation options</h2>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -172,6 +140,13 @@ package</p>
|
||||
<td>Watermark config, Please refer to the table 【Watermark config】 below for detailed configuration</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>textAutoWrapWidth(v0.3.4+)</td>
|
||||
<td>Number</td>
|
||||
<td>500</td>
|
||||
<td>Each line of text in the node will wrap automatically when it reaches the width</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Watermark config</h3>
|
||||
@@ -239,11 +214,44 @@ MindMap.defineTheme(<span class="hljs-string">'Theme name'</span>, {})
|
||||
mindMap.setTheme(<span class="hljs-string">'Theme name'</span>)
|
||||
</code></pre>
|
||||
<p>For all configurations of theme, please refer to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js">Default Topic</a>. The <code>defineTheme</code>method will merge the configuration you passed in with the default configuration. Most of the themes do not need custom many parts. For a typical customized theme configuration, please refer to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/blueSky.js">blueSky</a>.</p>
|
||||
<h3>usePlugin(plugin)</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.0+</p>
|
||||
</blockquote>
|
||||
<p>If you need to use some non-core functions, such as mini map, watermark, etc, you can register plugin through this method. Can be called in chain.</p>
|
||||
<p>Note: The plugin needs to be registered before instantiating <code>MindMap</code>.</p>
|
||||
<h2>Static props</h2>
|
||||
<h3>pluginList</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.0+</p>
|
||||
</blockquote>
|
||||
<p>List of all currently registered plugins.</p>
|
||||
<h2>Instance methods</h2>
|
||||
<h3>render()</h3>
|
||||
<h3>getSvgData()</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.0+</p>
|
||||
</blockquote>
|
||||
<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>
|
||||
svgHTML, <span class="hljs-comment">// String, svg string, i.e. html string, can be directly rendered to the small map container you prepared</span>
|
||||
<span class="hljs-attr">rect</span>: <span class="hljs-comment">// Object, position, size, etc. of mind map graphics before zoom</span>
|
||||
origWidth, <span class="hljs-comment">// Number, canvas width</span>
|
||||
origHeight, <span class="hljs-comment">// Number, canvas height</span>
|
||||
scaleX, <span class="hljs-comment">// Number, horizontal zoom value of mind map graphics</span>
|
||||
scaleY, <span class="hljs-comment">// Number, vertical zoom value of mind map graphics</span>
|
||||
}
|
||||
</code></pre>
|
||||
<h3>render(callback)</h3>
|
||||
<ul>
|
||||
<li><code>callback</code>: <code>v0.3.2+</code>, <code>Function</code>, Called when the re-rendering is complete</li>
|
||||
</ul>
|
||||
<p>Triggers a full rendering, which will reuse nodes for better performance. If
|
||||
only the node positions have changed, this method can be called to <code>reRender</code>.</p>
|
||||
<h3>reRender()</h3>
|
||||
<h3>reRender(callback)</h3>
|
||||
<ul>
|
||||
<li><code>callback</code>: <code>v0.3.2+</code>, <code>Function</code>, Called when the re-rendering is complete</li>
|
||||
</ul>
|
||||
<p>Performs a full re-render, clearing the canvas and creating new nodes. This has
|
||||
poor performance and should be used sparingly.</p>
|
||||
<h3>resize()</h3>
|
||||
@@ -617,6 +625,9 @@ redo. All commands are as follows:</p>
|
||||
includes the node tree, if <code>true</code> is passed, it will also include theme, layout,
|
||||
view, etc. data</p>
|
||||
<h3>export(type, isDownload, fileName)</h3>
|
||||
<blockquote>
|
||||
<p>You need to register the <code>Export</code> plugin first</p>
|
||||
</blockquote>
|
||||
<p>Export</p>
|
||||
<p><code>type</code>: the type to be exported, optional values: png, svg, json, pdf (v0.2.1+),
|
||||
smm (essentially also json)</p>
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
# DoExport instance
|
||||
# Export plugin
|
||||
|
||||
The `doExport` instance is responsible for exporting and can be obtained through
|
||||
`mindMap.doExport`.
|
||||
The `Export` plugin provides the export function.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Export from 'simple-mind-map/src/Export.js'
|
||||
|
||||
MindMap.usePlugin(Export)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.doExport`.
|
||||
|
||||
## Methods
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>DoExport instance</h1>
|
||||
<p>The <code>doExport</code> instance is responsible for exporting and can be obtained through
|
||||
<code>mindMap.doExport</code>.</p>
|
||||
<h1>Export plugin</h1>
|
||||
<p>The <code>Export</code> plugin provides the export function.</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">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Export <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Export.js'</span>
|
||||
|
||||
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>
|
||||
<h3>png()</h3>
|
||||
<p>Exports as <code>png</code>, an async method that returns image data, <code>data:url</code> data which
|
||||
|
||||
21
web/src/pages/Doc/en/drag/index.md
Normal file
21
web/src/pages/Doc/en/drag/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Drag plugin
|
||||
|
||||
The `Drag` plugin provides the function of node dragging, including:
|
||||
|
||||
1.Drag the node to move and change its position in the node tree, That is, as a child node, sibling node, etc. of other nodes
|
||||
|
||||
2.Drag the node to the custom canvas location
|
||||
|
||||
Please refer to the [Instantiation Options](/mind-map/#/doc/zh/constructor) of the `MindMap` class for configuration.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Drag from 'simple-mind-map/src/Drag.js'
|
||||
|
||||
MindMap.usePlugin(Drag)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.drag`.
|
||||
|
||||
27
web/src/pages/Doc/en/drag/index.vue
Normal file
27
web/src/pages/Doc/en/drag/index.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Drag plugin</h1>
|
||||
<p>The <code>Drag</code> plugin provides the function of node dragging, including:</p>
|
||||
<p>1.Drag the node to move and change its position in the node tree, That is, as a child node, sibling node, etc. of other nodes</p>
|
||||
<p>2.Drag the node to the custom canvas location</p>
|
||||
<p>Please refer to the <a href="/mind-map/#/doc/zh/constructor">Instantiation Options</a> of the <code>MindMap</code> class for configuration.</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">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Drag <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Drag.js'</span>
|
||||
|
||||
MindMap.usePlugin(Drag)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.drag</code>.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
## Features
|
||||
|
||||
- [x] Plugin architecture. In addition to core functions, other functions are provided as plugins, which can be used as needed to reduce the overall volume
|
||||
- [x] Supports four types of structures: logical structure diagrams, mind maps,
|
||||
organizational structure diagrams, and directory organization diagrams
|
||||
- [x] Built-in multiple themes and allows for highly customized styles, and support register new themes
|
||||
@@ -16,7 +17,7 @@
|
||||
- [x] Supports free dragging and dragging to adjust nodes
|
||||
- [x] Supports various node shapes
|
||||
- [x] Supports export to json, png, svg, pdf, and import from json, xmind
|
||||
- [x] Supports mini map
|
||||
- [x] Supports mini map、support watermark
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -32,21 +33,19 @@ on `Vue2.x` and `ElementUI`. Features include:
|
||||
|
||||
- [x] Toolbar, which supports inserting and deleting nodes, and editing node
|
||||
images, icons, hyperlinks, notes, tags, and summaries
|
||||
|
||||
- [x] Sidebar, with panels for basic style settings, node style settings,
|
||||
outline, theme selection, and structure selection
|
||||
|
||||
- [x] Import and export functionality; data is saved in the browser's local
|
||||
storage by default, but it also supports creating, opening, and editing
|
||||
local files on the computer directly
|
||||
|
||||
- [x] Right-click menu, which supports operations such as expanding, collapsing,
|
||||
and organizing layout
|
||||
|
||||
- [x] Bottom bar, which supports node and word count statistics, switching
|
||||
between edit and read-only modes, zooming in and out, and switching to
|
||||
full screen, support mini map
|
||||
|
||||
Provide document page service.
|
||||
|
||||
3.`dist`
|
||||
|
||||
The folder containing the packaged resources for the `web` folder.
|
||||
@@ -61,11 +60,13 @@ Documentation, etc.
|
||||
|
||||
[Only a hundred lines of code are needed to add local file operation capability to your Web page. Are you sure not to try?](https://juejin.cn/post/7157681502506090510)
|
||||
|
||||
[When you press the direction key, how does the TV find the next focus](https://juejin.cn/post/7199666255883927612)
|
||||
|
||||
## Special Note
|
||||
|
||||
This project is rough and has not been thoroughly tested, its features are not
|
||||
yet fully developed, and there are some performance issues. It is only for
|
||||
learning and reference purposes and should not be used in actual projects.
|
||||
yet fully developed, and there are some performance issues, especially when the number of nodes is large. It is only for
|
||||
learning and reference purposes and please use it carefully for actual projects.
|
||||
|
||||
The built-in themes and icons in the project come from:
|
||||
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
<p><code>simple-mind-map</code> is a simple and powerful web mind map library, not dependent on any specific framework.</p>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox16" checked="true"><label for="checkbox16">Supports four types of structures: logical structure diagrams, mind maps,</label>
|
||||
<li><input type="checkbox" id="checkbox51" checked="true"><label for="checkbox51">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="checkbox52" checked="true"><label for="checkbox52">Supports four types of structures: logical structure diagrams, mind maps,</label>
|
||||
organizational structure diagrams, and directory organization diagrams</li>
|
||||
<li><input type="checkbox" id="checkbox17" checked="true"><label for="checkbox17">Built-in multiple themes and allows for highly customized styles, and support register new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox18" checked="true"><label for="checkbox18">Supports shortcuts</label></li>
|
||||
<li><input type="checkbox" id="checkbox19" checked="true"><label for="checkbox19">Node content supports images, icons, hyperlinks, notes, tags, and</label>
|
||||
<li><input type="checkbox" id="checkbox53" checked="true"><label for="checkbox53">Built-in multiple themes and allows for highly customized styles, and support register new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox54" checked="true"><label for="checkbox54">Supports shortcuts</label></li>
|
||||
<li><input type="checkbox" id="checkbox55" checked="true"><label for="checkbox55">Node content supports images, icons, hyperlinks, notes, tags, and</label>
|
||||
summaries</li>
|
||||
<li><input type="checkbox" id="checkbox20" checked="true"><label for="checkbox20">Supports forward and backward navigation</label></li>
|
||||
<li><input type="checkbox" id="checkbox21" checked="true"><label for="checkbox21">Supports dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox22" checked="true"><label for="checkbox22">Supports right-click and Ctrl + left-click to select multiple items</label></li>
|
||||
<li><input type="checkbox" id="checkbox23" checked="true"><label for="checkbox23">Supports free dragging and dragging to adjust nodes</label></li>
|
||||
<li><input type="checkbox" id="checkbox24" checked="true"><label for="checkbox24">Supports various node shapes</label></li>
|
||||
<li><input type="checkbox" id="checkbox25" checked="true"><label for="checkbox25">Supports export to json, png, svg, pdf, and import from json, xmind</label></li>
|
||||
<li><input type="checkbox" id="checkbox26" checked="true"><label for="checkbox26">Supports mini map</label></li>
|
||||
<li><input type="checkbox" id="checkbox56" checked="true"><label for="checkbox56">Supports forward and backward navigation</label></li>
|
||||
<li><input type="checkbox" id="checkbox57" checked="true"><label for="checkbox57">Supports dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox58" checked="true"><label for="checkbox58">Supports right-click and Ctrl + left-click to select multiple items</label></li>
|
||||
<li><input type="checkbox" id="checkbox59" checked="true"><label for="checkbox59">Supports free dragging and dragging to adjust nodes</label></li>
|
||||
<li><input type="checkbox" id="checkbox60" checked="true"><label for="checkbox60">Supports various node shapes</label></li>
|
||||
<li><input type="checkbox" id="checkbox61" checked="true"><label for="checkbox61">Supports export to json, png, svg, pdf, and import from json, xmind</label></li>
|
||||
<li><input type="checkbox" id="checkbox62" checked="true"><label for="checkbox62">Supports mini map、support watermark</label></li>
|
||||
</ul>
|
||||
<h2>Table of Contents</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
@@ -26,29 +27,20 @@ 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>
|
||||
<p><input type="checkbox" id="checkbox27" checked="true"><label for="checkbox27">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox28" checked="true"><label for="checkbox28">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox29" checked="true"><label for="checkbox29">Import and export functionality; data is saved in the browser's local</label>
|
||||
<li><input type="checkbox" id="checkbox63" checked="true"><label for="checkbox63">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</li>
|
||||
<li><input type="checkbox" id="checkbox64" checked="true"><label for="checkbox64">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</li>
|
||||
<li><input type="checkbox" id="checkbox65" checked="true"><label for="checkbox65">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</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox30" checked="true"><label for="checkbox30">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox31" checked="true"><label for="checkbox31">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
local files on the computer directly</li>
|
||||
<li><input type="checkbox" id="checkbox66" checked="true"><label for="checkbox66">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</li>
|
||||
<li><input type="checkbox" id="checkbox67" checked="true"><label for="checkbox67">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</p>
|
||||
</li>
|
||||
full screen, support mini map</li>
|
||||
</ul>
|
||||
<p>Provide document page service.</p>
|
||||
<p>3.<code>dist</code></p>
|
||||
<p>The folder containing the packaged resources for the <code>web</code> folder.</p>
|
||||
<p>4.<code>docs</code></p>
|
||||
@@ -56,10 +48,11 @@ full screen, support mini map</p>
|
||||
<h2>Related Articles</h2>
|
||||
<p><a href="https://juejin.cn/post/6987711560521089061">Technical Analysis of Web Mind Map Implementation (chi)</a></p>
|
||||
<p><a href="https://juejin.cn/post/7157681502506090510">Only a hundred lines of code are needed to add local file operation capability to your Web page. Are you sure not to try?</a></p>
|
||||
<p><a href="https://juejin.cn/post/7199666255883927612">When you press the direction key, how does the TV find the next focus</a></p>
|
||||
<h2>Special Note</h2>
|
||||
<p>This project is rough and has not been thoroughly tested, its features are not
|
||||
yet fully developed, and there are some performance issues. It is only for
|
||||
learning and reference purposes and should not be used in actual projects.</p>
|
||||
yet fully developed, and there are some performance issues, especially when the number of nodes is large. It is only for
|
||||
learning and reference purposes and please use it carefully for actual projects.</p>
|
||||
<p>The built-in themes and icons in the project come from:</p>
|
||||
<p><a href="https://naotu.baidu.com/">Baidu Mind Map</a></p>
|
||||
<p><a href="https://www.zhixi.com/">Zhixi Mind Map</a></p>
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
# KeyboardNavigation instance
|
||||
# KeyboardNavigation plugin
|
||||
|
||||
> v0.2.17+
|
||||
|
||||
`KeyboardNavigation` instance is responsible for handling keyboard navigation, that is, when you press the direction key, it will automatically find the next node and activate it, can be obtained through `mindMap.keyboardNavigation`
|
||||
`KeyboardNavigation` plugin provides keyboard navigation function, that is, when you press the direction key, it will automatically find the next node and activate it.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import KeyboardNavigation from 'simple-mind-map/src/KeyboardNavigation.js'
|
||||
|
||||
MindMap.usePlugin(KeyboardNavigation)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.keyboardNavigation`.
|
||||
|
||||
## Methods
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>KeyboardNavigation instance</h1>
|
||||
<h1>KeyboardNavigation plugin</h1>
|
||||
<blockquote>
|
||||
<p>v0.2.17+</p>
|
||||
</blockquote>
|
||||
<p><code>KeyboardNavigation</code> instance is responsible for handling keyboard navigation, that is, when you press the direction key, it will automatically find the next node and activate it, can be obtained through <code>mindMap.keyboardNavigation</code></p>
|
||||
<p><code>KeyboardNavigation</code> plugin provides keyboard navigation function, that is, when you press the direction key, it will automatically find the next node and activate it.</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">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> KeyboardNavigation <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/KeyboardNavigation.js'</span>
|
||||
|
||||
MindMap.usePlugin(KeyboardNavigation)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.keyboardNavigation</code>.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>focus(dir)</h3>
|
||||
<p><code>dir</code>:Which direction to find the next node,Optional value:<code>Left</code>、 <code>Up</code>、 <code>Right</code>、 <code>Down</code></p>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# MiniMap instance
|
||||
# MiniMap plugin
|
||||
|
||||
> v0.2.11+
|
||||
|
||||
@@ -8,27 +8,19 @@ When zoomed, moved, or there are too many elements, the canvas may only display
|
||||
part of the mind map content. The viewport frame can be used to view the current
|
||||
viewport location, and can be quickly positioned by dragging on the small map.
|
||||
|
||||
The `mindMap.miniMap` instance can be obtained through this.
|
||||
|
||||
## Methods
|
||||
|
||||
### getMiniMap()
|
||||
|
||||
Obtain small map related data, this function is generally not used directly, the
|
||||
function returns:
|
||||
## Register
|
||||
|
||||
```js
|
||||
{
|
||||
svg, // Element, the overall svg element of the mind map graphics, including: svg (canvas container), g (actual mind map group)
|
||||
svgHTML, // String, svg string, i.e. html string, can be directly rendered to the small map container you prepared
|
||||
rect: // Object, position, size, etc. of mind map graphics before zoom
|
||||
origWidth, // Number, canvas width
|
||||
origHeight, // Number, canvas height
|
||||
scaleX, // Number, horizontal zoom value of mind map graphics
|
||||
scaleY, // Number, vertical zoom value of mind map graphics
|
||||
}
|
||||
import MindMap from 'simple-mind-map'
|
||||
import MiniMap from 'simple-mind-map/src/MiniMap.js'
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.miniMap`.
|
||||
|
||||
## Methods
|
||||
|
||||
### calculationMiniMap(boxWidth, boxHeight)
|
||||
|
||||
"Calculate the rendering data for the small map, this function will call the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>MiniMap instance</h1>
|
||||
<h1>MiniMap plugin</h1>
|
||||
<blockquote>
|
||||
<p>v0.2.11+</p>
|
||||
</blockquote>
|
||||
@@ -9,21 +9,14 @@ parts, one is the current canvas content, and the other is the viewport frame.
|
||||
When zoomed, moved, or there are too many elements, the canvas may only display
|
||||
part of the mind map content. The viewport frame can be used to view the current
|
||||
viewport location, and can be quickly positioned by dragging on the small map.</p>
|
||||
<p>The <code>mindMap.miniMap</code> instance can be obtained through this.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>getMiniMap()</h3>
|
||||
<p>Obtain small map related data, this function is generally not used directly, the
|
||||
function returns:</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>
|
||||
svgHTML, <span class="hljs-comment">// String, svg string, i.e. html string, can be directly rendered to the small map container you prepared</span>
|
||||
<span class="hljs-attr">rect</span>: <span class="hljs-comment">// Object, position, size, etc. of mind map graphics before zoom</span>
|
||||
origWidth, <span class="hljs-comment">// Number, canvas width</span>
|
||||
origHeight, <span class="hljs-comment">// Number, canvas height</span>
|
||||
scaleX, <span class="hljs-comment">// Number, horizontal zoom value of mind map graphics</span>
|
||||
scaleY, <span class="hljs-comment">// Number, vertical zoom value of mind map graphics</span>
|
||||
}
|
||||
<h2>Register</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> MiniMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/MiniMap.js'</span>
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.miniMap</code>.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>calculationMiniMap(boxWidth, boxHeight)</h3>
|
||||
<p>"Calculate the rendering data for the small map, this function will call the
|
||||
<code>getMiniMap()</code> method, so using this function is sufficient.</p>
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
# Select instance
|
||||
# Select plugin
|
||||
|
||||
The `select` instance is responsible for the mouse right-click multi-selection
|
||||
of nodes, and can be obtained through `mindMap.select`
|
||||
The `Select` plugin provides the function of right-clicking to select multiple nodes.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Select from 'simple-mind-map/src/Select.js'
|
||||
|
||||
MindMap.usePlugin(Select)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.select`.
|
||||
|
||||
## Method
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Select instance</h1>
|
||||
<p>The <code>select</code> instance is responsible for the mouse right-click multi-selection
|
||||
of nodes, and can be obtained through <code>mindMap.select</code></p>
|
||||
<h1>Select plugin</h1>
|
||||
<p>The <code>Select</code> plugin provides the function of right-clicking to select multiple nodes.</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">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Select <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Select.js'</span>
|
||||
|
||||
MindMap.usePlugin(Select)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.select</code>.</p>
|
||||
<h2>Method</h2>
|
||||
<h3>toPos(x, y)</h3>
|
||||
<p>Convert mouse position to position relative to the container <code>el</code></p>
|
||||
|
||||
@@ -40,6 +40,13 @@ Environments that support the `module` field will use `index.js` as the entry
|
||||
point, otherwise the packed `simpleMindMap.umd.min.js` will be used as the entry
|
||||
point.
|
||||
|
||||
### Compile the doc
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm run buildDoc
|
||||
```
|
||||
|
||||
### Packaging the Demo
|
||||
|
||||
```bash
|
||||
@@ -92,6 +99,16 @@ const mindMap = new MindMap({
|
||||
});
|
||||
```
|
||||
|
||||
The non-packaged 'ES' module is introduced by default, and only contains core functions, not unregistered plugin content, which can effectively reduce the size. However, you need to configure the `babel` compilation `simple mind-map` in your project to prevent some newer `js` syntax some browsers not supporting it.
|
||||
|
||||
If you need a file in the format of `umd` module, such as `CDN` in the browser, you can import it in the following way:
|
||||
|
||||
```js
|
||||
import MindMap from "simple-mind-map/dist/simpleMindMap.umd.min.js";
|
||||
```
|
||||
|
||||
The disadvantage of this method is that it will contain all the content, including the plugins you have not registered, so the overall volume will be relatively large.
|
||||
|
||||
## Problems
|
||||
|
||||
### Error when using in Vite, indicating xml-js dependency error
|
||||
|
||||
@@ -29,6 +29,10 @@ fields:</p>
|
||||
<p>Environments that support the <code>module</code> field will use <code>index.js</code> as the entry
|
||||
point, otherwise the packed <code>simpleMindMap.umd.min.js</code> will be used as the entry
|
||||
point.</p>
|
||||
<h3>Compile the doc</h3>
|
||||
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
|
||||
npm run buildDoc
|
||||
</code></pre>
|
||||
<h3>Packaging the Demo</h3>
|
||||
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
|
||||
npm run build
|
||||
@@ -67,6 +71,11 @@ compile this dependency:</p>
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
<p>The non-packaged 'ES' module is introduced by default, and only contains core functions, not unregistered plugin content, which can effectively reduce the size. However, you need to configure the <code>babel</code> compilation <code>simple mind-map</code> in your project to prevent some newer <code>js</code> syntax some browsers not supporting it.</p>
|
||||
<p>If you need a file in the format of <code>umd</code> module, such as <code>CDN</code> in the browser, you can import it in the following way:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">"simple-mind-map/dist/simpleMindMap.umd.min.js"</span>;
|
||||
</code></pre>
|
||||
<p>The disadvantage of this method is that it will contain all the content, including the plugins you have not registered, so the overall volume will be relatively large.</p>
|
||||
<h2>Problems</h2>
|
||||
<h3>Error when using in Vite, indicating xml-js dependency error</h3>
|
||||
<p>Solution: use the following import method:</p>
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
# Utility Methods
|
||||
|
||||
## Base utility Methods
|
||||
|
||||
Reference:
|
||||
|
||||
```js
|
||||
import {walk, ...} from 'simple-mind-map/src/utils'
|
||||
```
|
||||
|
||||
## Methods
|
||||
### Methods
|
||||
|
||||
### walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)
|
||||
#### walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)
|
||||
|
||||
Depth-first traversal of a tree
|
||||
|
||||
@@ -34,11 +36,11 @@ Example:
|
||||
walk(tree, null, () => {}, () => {}, false, 0, 0);
|
||||
```
|
||||
|
||||
### bfsWalk(root, callback)
|
||||
#### bfsWalk(root, callback)
|
||||
|
||||
Breadth-first traversal of a tree
|
||||
|
||||
### resizeImgSize(width, height, maxWidth, maxHeight)
|
||||
#### resizeImgSize(width, height, maxWidth, maxHeight)
|
||||
|
||||
Resize image size
|
||||
|
||||
@@ -52,17 +54,17 @@ Resize image size
|
||||
|
||||
`maxWidth` and `maxHeight` can both be passed, or only one of them can be passed
|
||||
|
||||
### resizeImg(imgUrl, maxWidth, maxHeight)
|
||||
#### resizeImg(imgUrl, maxWidth, maxHeight)
|
||||
|
||||
Resize image, internally loads the image first, then calls the `resizeImgSize`
|
||||
method, and returns a `promise`
|
||||
|
||||
### simpleDeepClone(data)
|
||||
#### simpleDeepClone(data)
|
||||
|
||||
Extremely simple deep copy method, can only be used for objects that are all
|
||||
basic data, otherwise it will throw an error
|
||||
|
||||
### copyRenderTree(tree, root)
|
||||
#### copyRenderTree(tree, root)
|
||||
|
||||
Copy render tree data, example:
|
||||
|
||||
@@ -70,7 +72,7 @@ Copy render tree data, example:
|
||||
copyRenderTree({}, this.mindMap.renderer.renderTree);
|
||||
```
|
||||
|
||||
### copyNodeTree(tree, root)
|
||||
#### copyNodeTree(tree, root)
|
||||
|
||||
Copy node tree data, mainly eliminating the reference `node` instance `_node`
|
||||
and copying the `data` of the data object, example:
|
||||
@@ -79,30 +81,76 @@ and copying the `data` of the data object, example:
|
||||
copyNodeTree({}, node);
|
||||
```
|
||||
|
||||
### imgToDataUrl(src)
|
||||
#### imgToDataUrl(src)
|
||||
|
||||
Convert image to dataURL
|
||||
|
||||
### downloadFile(file, fileName)
|
||||
#### downloadFile(file, fileName)
|
||||
|
||||
Download file
|
||||
|
||||
### throttle(fn, time = 300, ctx)
|
||||
#### throttle(fn, time = 300, ctx)
|
||||
|
||||
Throttle function
|
||||
|
||||
### asyncRun(taskList, callback = () => {})
|
||||
#### asyncRun(taskList, callback = () => {})
|
||||
|
||||
Run tasks in task list asynchronously, tasks are run synchronously without order
|
||||
|
||||
### degToRad(deg)
|
||||
#### degToRad(deg)
|
||||
|
||||
> v0.2.24+
|
||||
|
||||
Angle to radian
|
||||
|
||||
### camelCaseToHyphen(str)
|
||||
#### camelCaseToHyphen(str)
|
||||
|
||||
> v0.2.24+
|
||||
|
||||
CamelCase to hyphen
|
||||
CamelCase to hyphen
|
||||
|
||||
#### joinFontStr({ italic, bold, fontSize, fontFamily })
|
||||
|
||||
> v0.3.4+
|
||||
|
||||
Join the `font` attribute value of the `css` font
|
||||
|
||||
#### measureText(text, { italic, bold, fontSize, fontFamily })
|
||||
|
||||
> v0.3.4+
|
||||
|
||||
Measure the width and height of the text, return value:
|
||||
|
||||
```js
|
||||
{ width, height }
|
||||
```
|
||||
|
||||
## Simulate CSS background in Canvas
|
||||
|
||||
Import:
|
||||
|
||||
```js
|
||||
import drawBackgroundImageToCanvas from 'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```js
|
||||
let width = 500
|
||||
let height = 500
|
||||
let img = '/1.jpg'
|
||||
let canvas = document.createElement('canvas')
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
drawBackgroundImageToCanvas(ctx, width, height, img, {
|
||||
backgroundRepeat: 'repeat-y',
|
||||
backgroundSize: '60%',
|
||||
backgroundPosition: 'center center'
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
// fail
|
||||
} else {
|
||||
// success
|
||||
}
|
||||
})
|
||||
```
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Utility Methods</h1>
|
||||
<h2>Base utility Methods</h2>
|
||||
<p>Reference:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> {walk, ...} <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/utils'</span>
|
||||
</code></pre>
|
||||
<h2>Methods</h2>
|
||||
<h3>walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)</h3>
|
||||
<h3>Methods</h3>
|
||||
<h4>walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)</h4>
|
||||
<p>Depth-first traversal of a tree</p>
|
||||
<p><code>root</code>: the root node of the tree to be traversed</p>
|
||||
<p><code>parent</code>: parent node</p>
|
||||
@@ -19,48 +20,83 @@ root, parent, isRoot, layerIndex, index</p>
|
||||
<p>Example:</p>
|
||||
<pre class="hljs"><code>walk(tree, <span class="hljs-literal">null</span>, <span class="hljs-function">() =></span> {}, <span class="hljs-function">() =></span> {}, <span class="hljs-literal">false</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
|
||||
</code></pre>
|
||||
<h3>bfsWalk(root, callback)</h3>
|
||||
<h4>bfsWalk(root, callback)</h4>
|
||||
<p>Breadth-first traversal of a tree</p>
|
||||
<h3>resizeImgSize(width, height, maxWidth, maxHeight)</h3>
|
||||
<h4>resizeImgSize(width, height, maxWidth, maxHeight)</h4>
|
||||
<p>Resize image size</p>
|
||||
<p><code>width</code>: original width of the image</p>
|
||||
<p><code>height</code>: original height of the image</p>
|
||||
<p><code>maxWidth</code>: the width to resize to</p>
|
||||
<p><code>maxHeight</code>: the height to resize to</p>
|
||||
<p><code>maxWidth</code> and <code>maxHeight</code> can both be passed, or only one of them can be passed</p>
|
||||
<h3>resizeImg(imgUrl, maxWidth, maxHeight)</h3>
|
||||
<h4>resizeImg(imgUrl, maxWidth, maxHeight)</h4>
|
||||
<p>Resize image, internally loads the image first, then calls the <code>resizeImgSize</code>
|
||||
method, and returns a <code>promise</code></p>
|
||||
<h3>simpleDeepClone(data)</h3>
|
||||
<h4>simpleDeepClone(data)</h4>
|
||||
<p>Extremely simple deep copy method, can only be used for objects that are all
|
||||
basic data, otherwise it will throw an error</p>
|
||||
<h3>copyRenderTree(tree, root)</h3>
|
||||
<h4>copyRenderTree(tree, root)</h4>
|
||||
<p>Copy render tree data, example:</p>
|
||||
<pre class="hljs"><code>copyRenderTree({}, <span class="hljs-built_in">this</span>.mindMap.renderer.renderTree);
|
||||
</code></pre>
|
||||
<h3>copyNodeTree(tree, root)</h3>
|
||||
<h4>copyNodeTree(tree, root)</h4>
|
||||
<p>Copy node tree data, mainly eliminating the reference <code>node</code> instance <code>_node</code>
|
||||
and copying the <code>data</code> of the data object, example:</p>
|
||||
<pre class="hljs"><code>copyNodeTree({}, node);
|
||||
</code></pre>
|
||||
<h3>imgToDataUrl(src)</h3>
|
||||
<h4>imgToDataUrl(src)</h4>
|
||||
<p>Convert image to dataURL</p>
|
||||
<h3>downloadFile(file, fileName)</h3>
|
||||
<h4>downloadFile(file, fileName)</h4>
|
||||
<p>Download file</p>
|
||||
<h3>throttle(fn, time = 300, ctx)</h3>
|
||||
<h4>throttle(fn, time = 300, ctx)</h4>
|
||||
<p>Throttle function</p>
|
||||
<h3>asyncRun(taskList, callback = () => {})</h3>
|
||||
<h4>asyncRun(taskList, callback = () => {})</h4>
|
||||
<p>Run tasks in task list asynchronously, tasks are run synchronously without order</p>
|
||||
<h3>degToRad(deg)</h3>
|
||||
<h4>degToRad(deg)</h4>
|
||||
<blockquote>
|
||||
<p>v0.2.24+</p>
|
||||
</blockquote>
|
||||
<p>Angle to radian</p>
|
||||
<h3>camelCaseToHyphen(str)</h3>
|
||||
<h4>camelCaseToHyphen(str)</h4>
|
||||
<blockquote>
|
||||
<p>v0.2.24+</p>
|
||||
</blockquote>
|
||||
<p>CamelCase to hyphen</p>
|
||||
<h4>joinFontStr({ italic, bold, fontSize, fontFamily })</h4>
|
||||
<blockquote>
|
||||
<p>v0.3.4+</p>
|
||||
</blockquote>
|
||||
<p>Join the <code>font</code> attribute value of the <code>css</code> font</p>
|
||||
<h4>measureText(text, { italic, bold, fontSize, fontFamily })</h4>
|
||||
<blockquote>
|
||||
<p>v0.3.4+</p>
|
||||
</blockquote>
|
||||
<p>Measure the width and height of the text, return value:</p>
|
||||
<pre class="hljs"><code>{ width, height }
|
||||
</code></pre>
|
||||
<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">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
</code></pre>
|
||||
<p>Usage:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">let</span> width = <span class="hljs-number">500</span>
|
||||
<span class="hljs-keyword">let</span> height = <span class="hljs-number">500</span>
|
||||
<span class="hljs-keyword">let</span> img = <span class="hljs-string">'/1.jpg'</span>
|
||||
<span class="hljs-keyword">let</span> canvas = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'canvas'</span>)
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
drawBackgroundImageToCanvas(ctx, width, height, img, {
|
||||
<span class="hljs-attr">backgroundRepeat</span>: <span class="hljs-string">'repeat-y'</span>,
|
||||
<span class="hljs-attr">backgroundSize</span>: <span class="hljs-string">'60%'</span>,
|
||||
<span class="hljs-attr">backgroundPosition</span>: <span class="hljs-string">'center center'</span>
|
||||
}, <span class="hljs-function">(<span class="hljs-params">err</span>) =></span> {
|
||||
<span class="hljs-keyword">if</span> (err) {
|
||||
<span class="hljs-comment">// fail</span>
|
||||
} <span class="hljs-keyword">else</span> {
|
||||
<span class="hljs-comment">// success</span>
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
# Watermark instance
|
||||
# Watermark plugin
|
||||
|
||||
> 0.2.24+
|
||||
|
||||
`Watermark` instance is responsible for displaying the watermark, and can be obtained
|
||||
through `mindMap.watermark`.
|
||||
`Watermark` instance is responsible for displaying the watermark.
|
||||
|
||||
Please refer to the [Instantiation Options](/mind-map/#/doc/zh/constructor) of the `MindMap` class for configuration.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Watermark from 'simple-mind-map/src/Watermark.js'
|
||||
|
||||
MindMap.usePlugin(Watermark)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.watermark`.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -29,4 +41,10 @@ mindMap.watermark.updateWatermark({
|
||||
fontSize: 20
|
||||
}
|
||||
})
|
||||
```
|
||||
```
|
||||
|
||||
### hasWatermark()
|
||||
|
||||
> v0.3.2+
|
||||
|
||||
Gets whether the watermark exists.
|
||||
@@ -1,11 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Watermark instance</h1>
|
||||
<h1>Watermark plugin</h1>
|
||||
<blockquote>
|
||||
<p>0.2.24+</p>
|
||||
</blockquote>
|
||||
<p><code>Watermark</code> instance is responsible for displaying the watermark, and can be obtained
|
||||
through <code>mindMap.watermark</code>.</p>
|
||||
<p><code>Watermark</code> instance is responsible for displaying the watermark.</p>
|
||||
<p>Please refer to the <a href="/mind-map/#/doc/zh/constructor">Instantiation Options</a> of the <code>MindMap</code> class for configuration.</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">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Watermark <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Watermark.js'</span>
|
||||
|
||||
MindMap.usePlugin(Watermark)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.watermark</code>.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>draw()</h3>
|
||||
<p>Redraw the watermark.</p>
|
||||
@@ -24,6 +31,11 @@ through <code>mindMap.watermark</code>.</p>
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
<h3>hasWatermark()</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.2+</p>
|
||||
</blockquote>
|
||||
<p>Gets whether the watermark exists.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
51
web/src/pages/Doc/en/xmind/index.md
Normal file
51
web/src/pages/Doc/en/xmind/index.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# XMind parse
|
||||
|
||||
> v0.2.7+
|
||||
|
||||
Provides methods for importing `XMind` files.
|
||||
|
||||
## Import
|
||||
|
||||
```js
|
||||
import xmind from 'simple-mind-map/src/parse/xmind.js'
|
||||
```
|
||||
|
||||
If you are using the file in the format of `umd`, you can obtain it in the following way:
|
||||
|
||||
```js
|
||||
import MindMap from "simple-mind-map/dist/simpleMindMap.umd.min"
|
||||
|
||||
MindMap.xmind
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
### xmind.parseXmindFile(file)
|
||||
|
||||
Parsing the `.xmind` file and returning the parsed data. Note that this is
|
||||
complete data, including the node tree, theme, and structure. You can use
|
||||
`mindMap.setFullData(data)` to render the returned data to the canvas.
|
||||
|
||||
`file`: `File` object
|
||||
|
||||
### xmind.transformXmind(content)
|
||||
|
||||
Convert `xmind` data. The `.xmind` file is essentially a `zip` file that can be
|
||||
decompressed by changing the suffix to zip. Inside, there is a `content.json`
|
||||
file. If you have parsed this file yourself, you can pass the contents of this
|
||||
file to this method for conversion. The converted data is the complete data,
|
||||
including the node tree, theme, structure, etc. You can use
|
||||
`mindMap.setFullData(data)` to render the returned data to the canvas.
|
||||
|
||||
`content`: the contents of the `content.json` file within the `.xmind` zip
|
||||
package
|
||||
|
||||
### xmind.transformOldXmind(content)
|
||||
|
||||
> v0.2.8+
|
||||
|
||||
For data parsing of the `xmind8` version, because the `.xmind` file in this
|
||||
version does not have a `content.json`, it corresponds to `content.xml`.
|
||||
|
||||
`content`: the contents of the `content.xml` file within the `.xmind` zip
|
||||
package
|
||||
51
web/src/pages/Doc/en/xmind/index.vue
Normal file
51
web/src/pages/Doc/en/xmind/index.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>XMind parse</h1>
|
||||
<blockquote>
|
||||
<p>v0.2.7+</p>
|
||||
</blockquote>
|
||||
<p>Provides methods for importing <code>XMind</code> files.</p>
|
||||
<h2>Import</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> xmind <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/parse/xmind.js'</span>
|
||||
</code></pre>
|
||||
<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-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">"simple-mind-map/dist/simpleMindMap.umd.min"</span>
|
||||
|
||||
MindMap.xmind
|
||||
</code></pre>
|
||||
<h2>Methods</h2>
|
||||
<h3>xmind.parseXmindFile(file)</h3>
|
||||
<p>Parsing the <code>.xmind</code> file and returning the parsed data. Note that this is
|
||||
complete data, including the node tree, theme, and structure. You can use
|
||||
<code>mindMap.setFullData(data)</code> to render the returned data to the canvas.</p>
|
||||
<p><code>file</code>: <code>File</code> object</p>
|
||||
<h3>xmind.transformXmind(content)</h3>
|
||||
<p>Convert <code>xmind</code> data. The <code>.xmind</code> file is essentially a <code>zip</code> file that can be
|
||||
decompressed by changing the suffix to zip. Inside, there is a <code>content.json</code>
|
||||
file. If you have parsed this file yourself, you can pass the contents of this
|
||||
file to this method for conversion. The converted data is the complete data,
|
||||
including the node tree, theme, structure, etc. You can use
|
||||
<code>mindMap.setFullData(data)</code> to render the returned data to the canvas.</p>
|
||||
<p><code>content</code>: the contents of the <code>content.json</code> file within the <code>.xmind</code> zip
|
||||
package</p>
|
||||
<h3>xmind.transformOldXmind(content)</h3>
|
||||
<blockquote>
|
||||
<p>v0.2.8+</p>
|
||||
</blockquote>
|
||||
<p>For data parsing of the <code>xmind8</code> version, because the <code>.xmind</code> file in this
|
||||
version does not have a <code>content.json</code>, it corresponds to <code>content.xml</code>.</p>
|
||||
<p><code>content</code>: the contents of the <code>content.xml</code> file within the <code>.xmind</code> zip
|
||||
package</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
export default [{"lang":"zh","children":[{"path":"batchExecution","title":"BatchExecution实例"},{"path":"changelog","title":"Changelog"},{"path":"command","title":"Command实例"},{"path":"constructor","title":"构造函数"},{"path":"doExport","title":"DoExport实例"},{"path":"introduction","title":"简介"},{"path":"keyboardNavigation","title":"KeyboardNavigation实例"},{"path":"keyCommand","title":"KeyCommand实例"},{"path":"miniMap","title":"MiniMap实例"},{"path":"node","title":"Node实例"},{"path":"render","title":"Render实例"},{"path":"select","title":"Select实例"},{"path":"start","title":"开始"},{"path":"translate","title":"参与翻译"},{"path":"utils","title":"内置工具方法"},{"path":"view","title":"View实例"},{"path":"watermark","title":"Watermark实例"}]},{"lang":"en","children":[{"path":"batchExecution","title":"batchExecution instance"},{"path":"changelog","title":"Changelog"},{"path":"command","title":"command instance"},{"path":"constructor","title":"Constructor"},{"path":"doExport","title":"DoExport instance"},{"path":"introduction","title":"Introduction"},{"path":"keyboardNavigation","title":"KeyboardNavigation instance"},{"path":"keyCommand","title":"KeyCommand instance"},{"path":"miniMap","title":"MiniMap instance"},{"path":"node","title":"Node instance"},{"path":"render","title":"Render instance"},{"path":"select","title":"Select instance"},{"path":"start","title":"Start"},{"path":"translate","title":"Participate in translation"},{"path":"utils","title":"Utility Methods"},{"path":"view","title":"View instance"},{"path":"watermark","title":"Watermark instance"}]}]
|
||||
export default [{"lang":"zh","children":[{"path":"batchExecution","title":"BatchExecution实例"},{"path":"changelog","title":"Changelog"},{"path":"command","title":"Command实例"},{"path":"constructor","title":"构造函数"},{"path":"doExport","title":"Export 插件"},{"path":"drag","title":"Drag插件"},{"path":"introduction","title":"简介"},{"path":"keyboardNavigation","title":"KeyboardNavigation插件"},{"path":"keyCommand","title":"KeyCommand实例"},{"path":"miniMap","title":"MiniMap插件"},{"path":"node","title":"Node实例"},{"path":"render","title":"Render实例"},{"path":"select","title":"Select 插件 "},{"path":"start","title":"开始"},{"path":"translate","title":"参与翻译"},{"path":"utils","title":"内置工具方法"},{"path":"view","title":"View实例"},{"path":"watermark","title":"Watermark插件"},{"path":"xmind","title":"XMind解析"}]},{"lang":"en","children":[{"path":"batchExecution","title":"batchExecution instance"},{"path":"changelog","title":"Changelog"},{"path":"command","title":"command instance"},{"path":"constructor","title":"Constructor"},{"path":"doExport","title":"Export plugin"},{"path":"drag","title":"Drag plugin"},{"path":"introduction","title":"Introduction"},{"path":"keyboardNavigation","title":"KeyboardNavigation plugin"},{"path":"keyCommand","title":"KeyCommand instance"},{"path":"miniMap","title":"MiniMap plugin"},{"path":"node","title":"Node instance"},{"path":"render","title":"Render instance"},{"path":"select","title":"Select plugin"},{"path":"start","title":"Start"},{"path":"translate","title":"Participate in translation"},{"path":"utils","title":"Utility Methods"},{"path":"view","title":"View instance"},{"path":"watermark","title":"Watermark plugin"},{"path":"xmind","title":"XMind parse"}]}]
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
## 0.3.4
|
||||
|
||||
New:节点文本增加自动换行功能。
|
||||
|
||||
Fix:1.修复批量删除的节点中如果存在根节点会出现删除异常的问题。2.修复底边风格的情况下,节点高度过高会和其他节点重叠的问题。
|
||||
|
||||
## 0.3.3
|
||||
|
||||
修复:根节点文字无法换行的问题。
|
||||
|
||||
## 0.3.2
|
||||
|
||||
修复:1.修复二级节点拖拽到其他节点或其他节点拖拽到二级节点时节点样式没有更新的问题;2.修复当思维导图实际内容大于屏幕宽高时,导出的时候超出的部分没有绘制水印的问题。
|
||||
|
||||
## 0.3.1
|
||||
|
||||
修复:1.删除背景图片不生效的问题;2.节点拖拽到根节点时连接线跑到根节点上方的问题。
|
||||
|
||||
新增:背景图片展示增加位置和大小设置。导出的图片也同步支持该设置。
|
||||
|
||||
## 0.3.0
|
||||
|
||||
升级为插件化架构,将一些非核心功能抽离出来作为插件,按需注册,减小整体体积。
|
||||
|
||||
## 0.2.24
|
||||
|
||||
新增:节点自由拖拽改为可配置,默认为`false`不开启;支持添加水印。
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.3.4</h2>
|
||||
<p>New:节点文本增加自动换行功能。</p>
|
||||
<p>Fix:1.修复批量删除的节点中如果存在根节点会出现删除异常的问题。2.修复底边风格的情况下,节点高度过高会和其他节点重叠的问题。</p>
|
||||
<h2>0.3.3</h2>
|
||||
<p>修复:根节点文字无法换行的问题。</p>
|
||||
<h2>0.3.2</h2>
|
||||
<p>修复:1.修复二级节点拖拽到其他节点或其他节点拖拽到二级节点时节点样式没有更新的问题;2.修复当思维导图实际内容大于屏幕宽高时,导出的时候超出的部分没有绘制水印的问题。</p>
|
||||
<h2>0.3.1</h2>
|
||||
<p>修复:1.删除背景图片不生效的问题;2.节点拖拽到根节点时连接线跑到根节点上方的问题。</p>
|
||||
<p>新增:背景图片展示增加位置和大小设置。导出的图片也同步支持该设置。</p>
|
||||
<h2>0.3.0</h2>
|
||||
<p>升级为插件化架构,将一些非核心功能抽离出来作为插件,按需注册,减小整体体积。</p>
|
||||
<h2>0.2.24</h2>
|
||||
<p>新增:节点自由拖拽改为可配置,默认为<code>false</code>不开启;支持添加水印。</p>
|
||||
<h2>0.2.23</h2>
|
||||
|
||||
@@ -20,40 +20,6 @@ const mindMap = new MindMap({
|
||||
});
|
||||
```
|
||||
|
||||
## Xmind解析方法
|
||||
|
||||
> v0.2.7+
|
||||
|
||||
可以通过如下方法获取解析`Xmind`文件的方法:
|
||||
|
||||
```js
|
||||
import MindMap from "simple-mind-map";
|
||||
|
||||
console.log(MindMap.xmind)
|
||||
```
|
||||
|
||||
`MindMap.xmind`对象上挂载了两个方法:
|
||||
|
||||
### parseXmindFile(file)
|
||||
|
||||
解析`.xmind`文件,返回解析后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用`mindMap.setFullData(data)`来将返回的数据渲染到画布上
|
||||
|
||||
`file`:`File`对象
|
||||
|
||||
### transformXmind(content)
|
||||
|
||||
转换`xmind`数据,`.xmind`文件本质上是一个压缩包,改成`zip`后缀可以解压缩,里面存在一个`content.json`文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用`mindMap.setFullData(data)`来将返回的数据渲染到画布上
|
||||
|
||||
`content`:`.xmind`压缩包内的`content.json`文件内容
|
||||
|
||||
### transformOldXmind(content)
|
||||
|
||||
> v0.2.8+
|
||||
|
||||
针对`xmind8`版本的数据解析,因为该版本的`.xmind`文件内没有`content.json`,对应的是`content.xml`。
|
||||
|
||||
`content`:`.xmind`压缩包内的`content.xml`文件内容
|
||||
|
||||
## 实例化选项
|
||||
|
||||
| 字段名称 | 类型 | 默认值 | 描述 | 是否必填 |
|
||||
@@ -74,6 +40,7 @@ console.log(MindMap.xmind)
|
||||
| readonly(v0.1.7+) | Boolean | false | 是否是只读模式 | |
|
||||
| enableFreeDrag(v0.2.4+) | Boolean | false | 是否开启节点自由拖拽 | |
|
||||
| watermarkConfig(v0.2.4+) | Object | | 水印配置,详细配置请参考下方表格【水印配置】 | |
|
||||
| textAutoWrapWidth(v0.3.4+) | Number | 500 | 节点内每行文本达到该宽度后自动换行 | |
|
||||
|
||||
### 水印配置
|
||||
|
||||
@@ -117,15 +84,51 @@ mindMap.setTheme('主题名称')
|
||||
|
||||
主题的所有配置可以参考[默认主题](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js)。`defineTheme`方法会把你传入的配置和默认配置做合并。大部分主题其实需要自定义的部分不是很多,一个典型的自定义主题配置可以参考[blueSky](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/blueSky.js)。
|
||||
|
||||
### usePlugin(plugin)
|
||||
|
||||
> v0.3.0+
|
||||
|
||||
注册插件,如果需要使用非核心的一些功能,比如小地图、水印等,可以通过该方法进行注册。可链式调用。
|
||||
|
||||
注意:插件需要在实例化`MindMap`前注册。
|
||||
|
||||
## 静态属性
|
||||
|
||||
### pluginList
|
||||
|
||||
> v0.3.0+
|
||||
|
||||
当前注册的所有插件列表。
|
||||
|
||||
## 实例方法
|
||||
|
||||
### render()
|
||||
### getSvgData()
|
||||
|
||||
> v0.3.0+
|
||||
|
||||
获取`svg`数据,返回一个对象,详细结构如下:
|
||||
|
||||
```js
|
||||
{
|
||||
svg, // Element,思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)
|
||||
svgHTML, // String,svg字符串,即html字符串,可以直接渲染到你准备的小地图容器内
|
||||
rect: // Object,思维导图图形未缩放时的位置尺寸等信息
|
||||
origWidth, // Number,画布宽度
|
||||
origHeight, // Number,画布高度
|
||||
scaleX, // Number,思维导图图形的水平缩放值
|
||||
scaleY, // Number,思维导图图形的垂直缩放值
|
||||
}
|
||||
```
|
||||
|
||||
### render(callback)
|
||||
|
||||
- `callback`:`v0.3.2+`,`Function`,当重新渲染完成时调用
|
||||
|
||||
触发整体渲染,会进行节点复用,性能较`reRender`会更好一点,如果只是节点位置变化了可以调用该方法进行渲染
|
||||
|
||||
### reRender()
|
||||
### reRender(callback)
|
||||
|
||||
- `callback`:`v0.3.2+`,`Function`,当重新渲染完成时调用
|
||||
|
||||
整体重新渲染,会清空画布,节点也会重新创建,性能不好,慎重使用
|
||||
|
||||
@@ -295,6 +298,8 @@ mindMap.updateConfig({
|
||||
|
||||
### export(type, isDownload, fileName)
|
||||
|
||||
> 需要先注册`Export`插件
|
||||
|
||||
导出
|
||||
|
||||
`type`:要导出的类型,可选值:png、svg、json、pdf(v0.2.1+)、smm(本质也是json)
|
||||
|
||||
@@ -16,28 +16,6 @@
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
<h2>Xmind解析方法</h2>
|
||||
<blockquote>
|
||||
<p>v0.2.7+</p>
|
||||
</blockquote>
|
||||
<p>可以通过如下方法获取解析<code>Xmind</code>文件的方法:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">"simple-mind-map"</span>;
|
||||
|
||||
<span class="hljs-built_in">console</span>.log(MindMap.xmind)
|
||||
</code></pre>
|
||||
<p><code>MindMap.xmind</code>对象上挂载了两个方法:</p>
|
||||
<h3>parseXmindFile(file)</h3>
|
||||
<p>解析<code>.xmind</code>文件,返回解析后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用<code>mindMap.setFullData(data)</code>来将返回的数据渲染到画布上</p>
|
||||
<p><code>file</code>:<code>File</code>对象</p>
|
||||
<h3>transformXmind(content)</h3>
|
||||
<p>转换<code>xmind</code>数据,<code>.xmind</code>文件本质上是一个压缩包,改成<code>zip</code>后缀可以解压缩,里面存在一个<code>content.json</code>文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用<code>mindMap.setFullData(data)</code>来将返回的数据渲染到画布上</p>
|
||||
<p><code>content</code>:<code>.xmind</code>压缩包内的<code>content.json</code>文件内容</p>
|
||||
<h3>transformOldXmind(content)</h3>
|
||||
<blockquote>
|
||||
<p>v0.2.8+</p>
|
||||
</blockquote>
|
||||
<p>针对<code>xmind8</code>版本的数据解析,因为该版本的<code>.xmind</code>文件内没有<code>content.json</code>,对应的是<code>content.xml</code>。</p>
|
||||
<p><code>content</code>:<code>.xmind</code>压缩包内的<code>content.xml</code>文件内容</p>
|
||||
<h2>实例化选项</h2>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -162,6 +140,13 @@
|
||||
<td>水印配置,详细配置请参考下方表格【水印配置】</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>textAutoWrapWidth(v0.3.4+)</td>
|
||||
<td>Number</td>
|
||||
<td>500</td>
|
||||
<td>节点内每行文本达到该宽度后自动换行</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>水印配置</h3>
|
||||
@@ -229,10 +214,43 @@ MindMap.defineTheme(<span class="hljs-string">'主题名称'</span>, {
|
||||
mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
</code></pre>
|
||||
<p>主题的所有配置可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/default.js">默认主题</a>。<code>defineTheme</code>方法会把你传入的配置和默认配置做合并。大部分主题其实需要自定义的部分不是很多,一个典型的自定义主题配置可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/themes/blueSky.js">blueSky</a>。</p>
|
||||
<h3>usePlugin(plugin)</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.0+</p>
|
||||
</blockquote>
|
||||
<p>注册插件,如果需要使用非核心的一些功能,比如小地图、水印等,可以通过该方法进行注册。可链式调用。</p>
|
||||
<p>注意:插件需要在实例化<code>MindMap</code>前注册。</p>
|
||||
<h2>静态属性</h2>
|
||||
<h3>pluginList</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.0+</p>
|
||||
</blockquote>
|
||||
<p>当前注册的所有插件列表。</p>
|
||||
<h2>实例方法</h2>
|
||||
<h3>render()</h3>
|
||||
<h3>getSvgData()</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.0+</p>
|
||||
</blockquote>
|
||||
<p>获取<code>svg</code>数据,返回一个对象,详细结构如下:</p>
|
||||
<pre class="hljs"><code>{
|
||||
svg, <span class="hljs-comment">// Element,思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)</span>
|
||||
svgHTML, <span class="hljs-comment">// String,svg字符串,即html字符串,可以直接渲染到你准备的小地图容器内</span>
|
||||
<span class="hljs-attr">rect</span>: <span class="hljs-comment">// Object,思维导图图形未缩放时的位置尺寸等信息</span>
|
||||
origWidth, <span class="hljs-comment">// Number,画布宽度</span>
|
||||
origHeight, <span class="hljs-comment">// Number,画布高度</span>
|
||||
scaleX, <span class="hljs-comment">// Number,思维导图图形的水平缩放值</span>
|
||||
scaleY, <span class="hljs-comment">// Number,思维导图图形的垂直缩放值</span>
|
||||
}
|
||||
</code></pre>
|
||||
<h3>render(callback)</h3>
|
||||
<ul>
|
||||
<li><code>callback</code>:<code>v0.3.2+</code>,<code>Function</code>,当重新渲染完成时调用</li>
|
||||
</ul>
|
||||
<p>触发整体渲染,会进行节点复用,性能较<code>reRender</code>会更好一点,如果只是节点位置变化了可以调用该方法进行渲染</p>
|
||||
<h3>reRender()</h3>
|
||||
<h3>reRender(callback)</h3>
|
||||
<ul>
|
||||
<li><code>callback</code>:<code>v0.3.2+</code>,<code>Function</code>,当重新渲染完成时调用</li>
|
||||
</ul>
|
||||
<p>整体重新渲染,会清空画布,节点也会重新创建,性能不好,慎重使用</p>
|
||||
<h3>resize()</h3>
|
||||
<p>容器尺寸变化后,需要调用该方法进行适应</p>
|
||||
@@ -599,6 +617,9 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<p>获取思维导图数据</p>
|
||||
<p><code>withConfig</code>:<code>Boolean</code>,默认为<code>false</code>,即获取的数据只包括节点树,如果传<code>true</code>则会包含主题、布局、视图等数据</p>
|
||||
<h3>export(type, isDownload, fileName)</h3>
|
||||
<blockquote>
|
||||
<p>需要先注册<code>Export</code>插件</p>
|
||||
</blockquote>
|
||||
<p>导出</p>
|
||||
<p><code>type</code>:要导出的类型,可选值:png、svg、json、pdf(v0.2.1+)、smm(本质也是json)</p>
|
||||
<p><code>isDownload</code>:是否需要直接触发下载,布尔值,默认为<code>false</code></p>
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
# DoExport实例
|
||||
# Export 插件
|
||||
|
||||
`doExport`实例负责导出,可通过`mindMap.doExport`获取到该实例
|
||||
`Export`插件提供导出的功能。
|
||||
|
||||
## 注册
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Export from 'simple-mind-map/src/Export.js'
|
||||
|
||||
MindMap.usePlugin(Export)
|
||||
```
|
||||
|
||||
注册完且实例化`MindMap`后可通过`mindMap.doExport`获取到该实例。
|
||||
|
||||
## 方法
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>DoExport实例</h1>
|
||||
<p><code>doExport</code>实例负责导出,可通过<code>mindMap.doExport</code>获取到该实例</p>
|
||||
<h1>Export 插件</h1>
|
||||
<p><code>Export</code>插件提供导出的功能。</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Export <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Export.js'</span>
|
||||
|
||||
MindMap.usePlugin(Export)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.doExport</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>png()</h3>
|
||||
<p>导出为<code>png</code>,异步方法,返回图片数据,<code>data:url</code>数据,可以自行下载或显示</p>
|
||||
|
||||
21
web/src/pages/Doc/zh/drag/index.md
Normal file
21
web/src/pages/Doc/zh/drag/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Drag插件
|
||||
|
||||
`Drag`插件提供节点拖拽的功能,包括:
|
||||
|
||||
1.拖拽节点进行移动,改变节点在节点树中的位置,即作为其他节点的子节点、兄弟节点等等
|
||||
|
||||
2.拖拽节点到自定义的画布位置
|
||||
|
||||
配置请参考`MindMap`类的[实例化选项](/mind-map/#/doc/zh/constructor)。
|
||||
|
||||
## 注册
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Drag from 'simple-mind-map/src/Drag.js'
|
||||
|
||||
MindMap.usePlugin(Drag)
|
||||
```
|
||||
|
||||
注册完且实例化`MindMap`后可通过`mindMap.drag`获取到该实例。
|
||||
|
||||
27
web/src/pages/Doc/zh/drag/index.vue
Normal file
27
web/src/pages/Doc/zh/drag/index.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Drag插件</h1>
|
||||
<p><code>Drag</code>插件提供节点拖拽的功能,包括:</p>
|
||||
<p>1.拖拽节点进行移动,改变节点在节点树中的位置,即作为其他节点的子节点、兄弟节点等等</p>
|
||||
<p>2.拖拽节点到自定义的画布位置</p>
|
||||
<p>配置请参考<code>MindMap</code>类的<a href="/mind-map/#/doc/zh/constructor">实例化选项</a>。</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Drag <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Drag.js'</span>
|
||||
|
||||
MindMap.usePlugin(Drag)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.drag</code>获取到该实例。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
## 特性
|
||||
|
||||
- [x] 插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小整体体积
|
||||
- [x] 支持逻辑结构图、思维导图、组织结构图、目录组织图四种结构
|
||||
- [x] 内置多种主题,允许高度自定义样式,支持注册新主题
|
||||
- [x] 支持快捷键
|
||||
@@ -14,7 +15,7 @@
|
||||
- [x] 支持节点自由拖拽、拖拽调整
|
||||
- [x] 支持多种节点形状
|
||||
- [x] 支持导出为`json`、`png`、`svg`、`pdf`,支持从`json`、`xmind`导入
|
||||
- [x] 支持小地图
|
||||
- [x] 支持小地图、支持水印
|
||||
|
||||
## 目录介绍
|
||||
|
||||
@@ -27,15 +28,13 @@
|
||||
使用`simple-mind-map`工具库,基于`vue2.x`、`ElementUI`搭建的在线思维导图。特性:
|
||||
|
||||
- [x] 工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要
|
||||
|
||||
- [x] 侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板
|
||||
|
||||
- [x] 导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件
|
||||
|
||||
- [x] 右键菜单,支持展开、收起、整理布局等操作
|
||||
|
||||
- [x] 底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图
|
||||
|
||||
提供文档页面服务。
|
||||
|
||||
3.`dist`
|
||||
|
||||
打包`web`后的资源文件夹。
|
||||
@@ -50,9 +49,11 @@
|
||||
|
||||
[只需百来行代码,为你的Web页面增加本地文件操作能力,确定不试试吗?](https://juejin.cn/post/7157681502506090510)
|
||||
|
||||
[当你按下方向键,电视是如何寻找下一个焦点的](https://juejin.cn/post/7199666255883927612)
|
||||
|
||||
## 特别说明
|
||||
|
||||
本项目较粗糙,未进行完整测试,功能尚不是很完善,性能也存在一些问题,仅用于学习和参考,请勿用于实际项目。
|
||||
本项目较粗糙,未进行完整测试,功能尚不是很完善,性能也存在一些问题,尤其当节点数量比较庞大的时候,仅用于学习和参考,请谨慎用于实际项目。
|
||||
|
||||
项目内置的主题和图标来自于:
|
||||
|
||||
|
||||
@@ -4,17 +4,18 @@
|
||||
<p><code>simple-mind-map</code>是一个简单&强大的Web思维导图库,不依赖任何特定框架。</p>
|
||||
<h2>特性</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox0" checked="true"><label for="checkbox0">支持逻辑结构图、思维导图、组织结构图、目录组织图四种结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox1" checked="true"><label for="checkbox1">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox2" checked="true"><label for="checkbox2">支持快捷键</label></li>
|
||||
<li><input type="checkbox" id="checkbox3" checked="true"><label for="checkbox3">节点内容支持图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox4" checked="true"><label for="checkbox4">支持前进后退</label></li>
|
||||
<li><input type="checkbox" id="checkbox5" checked="true"><label for="checkbox5">支持拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox6" checked="true"><label for="checkbox6">支持右键和Ctrl+左键两种多选方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox7" checked="true"><label for="checkbox7">支持节点自由拖拽、拖拽调整</label></li>
|
||||
<li><input type="checkbox" id="checkbox8" checked="true"><label for="checkbox8">支持多种节点形状</label></li>
|
||||
<li><input type="checkbox" id="checkbox9" checked="true"><label for="checkbox9">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>,支持从<code>json</code>、<code>xmind</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox10" checked="true"><label for="checkbox10">支持小地图</label></li>
|
||||
<li><input type="checkbox" id="checkbox0" checked="true"><label for="checkbox0">插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小整体体积</label></li>
|
||||
<li><input type="checkbox" id="checkbox1" checked="true"><label for="checkbox1">支持逻辑结构图、思维导图、组织结构图、目录组织图四种结构</label></li>
|
||||
<li><input type="checkbox" id="checkbox2" checked="true"><label for="checkbox2">内置多种主题,允许高度自定义样式,支持注册新主题</label></li>
|
||||
<li><input type="checkbox" id="checkbox3" checked="true"><label for="checkbox3">支持快捷键</label></li>
|
||||
<li><input type="checkbox" id="checkbox4" checked="true"><label for="checkbox4">节点内容支持图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox5" checked="true"><label for="checkbox5">支持前进后退</label></li>
|
||||
<li><input type="checkbox" id="checkbox6" checked="true"><label for="checkbox6">支持拖动、缩放</label></li>
|
||||
<li><input type="checkbox" id="checkbox7" checked="true"><label for="checkbox7">支持右键和Ctrl+左键两种多选方式</label></li>
|
||||
<li><input type="checkbox" id="checkbox8" checked="true"><label for="checkbox8">支持节点自由拖拽、拖拽调整</label></li>
|
||||
<li><input type="checkbox" id="checkbox9" checked="true"><label for="checkbox9">支持多种节点形状</label></li>
|
||||
<li><input type="checkbox" id="checkbox10" checked="true"><label for="checkbox10">支持导出为</label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>,支持从<code>json</code>、<code>xmind</code>导入</li>
|
||||
<li><input type="checkbox" id="checkbox11" checked="true"><label for="checkbox11">支持小地图、支持水印</label></li>
|
||||
</ul>
|
||||
<h2>目录介绍</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
@@ -22,22 +23,13 @@
|
||||
<p>2.<code>web</code></p>
|
||||
<p>使用<code>simple-mind-map</code>工具库,基于<code>vue2.x</code>、<code>ElementUI</code>搭建的在线思维导图。特性:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox11" checked="true"><label for="checkbox11">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox12" checked="true"><label for="checkbox12">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox13" checked="true"><label for="checkbox13">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox14" checked="true"><label for="checkbox14">右键菜单,支持展开、收起、整理布局等操作</label></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><input type="checkbox" id="checkbox15" checked="true"><label for="checkbox15">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></p>
|
||||
</li>
|
||||
<li><input type="checkbox" id="checkbox12" checked="true"><label for="checkbox12">工具栏,支持插入节点、删除节点;编辑节点图片、图标、超链接、备注、标签、概要</label></li>
|
||||
<li><input type="checkbox" id="checkbox13" checked="true"><label for="checkbox13">侧边栏,基础样式设置面板、节点样式设置面板、大纲面板、主题选择面板、结构选择面板</label></li>
|
||||
<li><input type="checkbox" id="checkbox14" checked="true"><label for="checkbox14">导入导出功能;数据默认保存在浏览器本地存储,也支持直接创建、打开、编辑电脑本地文件</label></li>
|
||||
<li><input type="checkbox" id="checkbox15" checked="true"><label for="checkbox15">右键菜单,支持展开、收起、整理布局等操作</label></li>
|
||||
<li><input type="checkbox" id="checkbox16" checked="true"><label for="checkbox16">底部栏,支持节点数量、字数统计;支持切换编辑和只读模式;支持放大缩小;支持全屏切换;支持小地图</label></li>
|
||||
</ul>
|
||||
<p>提供文档页面服务。</p>
|
||||
<p>3.<code>dist</code></p>
|
||||
<p>打包<code>web</code>后的资源文件夹。</p>
|
||||
<p>4.<code>docs</code></p>
|
||||
@@ -45,8 +37,9 @@
|
||||
<h2>相关文章</h2>
|
||||
<p><a href="https://juejin.cn/post/6987711560521089061">Web思维导图实现的技术点分析</a></p>
|
||||
<p><a href="https://juejin.cn/post/7157681502506090510">只需百来行代码,为你的Web页面增加本地文件操作能力,确定不试试吗?</a></p>
|
||||
<p><a href="https://juejin.cn/post/7199666255883927612">当你按下方向键,电视是如何寻找下一个焦点的</a></p>
|
||||
<h2>特别说明</h2>
|
||||
<p>本项目较粗糙,未进行完整测试,功能尚不是很完善,性能也存在一些问题,仅用于学习和参考,请勿用于实际项目。</p>
|
||||
<p>本项目较粗糙,未进行完整测试,功能尚不是很完善,性能也存在一些问题,尤其当节点数量比较庞大的时候,仅用于学习和参考,请谨慎用于实际项目。</p>
|
||||
<p>项目内置的主题和图标来自于:</p>
|
||||
<p><a href="https://naotu.baidu.com/">百度脑图</a></p>
|
||||
<p><a href="https://www.zhixi.com/">知犀思维导图</a></p>
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
# KeyboardNavigation实例
|
||||
# KeyboardNavigation插件
|
||||
|
||||
> v0.2.17+
|
||||
|
||||
`KeyboardNavigation`实例负责处理键盘导航,也就是当你按下方向键时会自动寻找下一个节点并激活,可通过`mindMap.keyboardNavigation`获取到该实例
|
||||
`KeyboardNavigation`插件提供键盘导航的功能,也就是当你按下方向键时会自动寻找下一个节点并激活
|
||||
|
||||
## 注册
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import KeyboardNavigation from 'simple-mind-map/src/KeyboardNavigation.js'
|
||||
|
||||
MindMap.usePlugin(KeyboardNavigation)
|
||||
```
|
||||
|
||||
注册完且实例化`MindMap`后可通过`mindMap.keyboardNavigation`获取到该实例。
|
||||
|
||||
## 方法
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>KeyboardNavigation实例</h1>
|
||||
<h1>KeyboardNavigation插件</h1>
|
||||
<blockquote>
|
||||
<p>v0.2.17+</p>
|
||||
</blockquote>
|
||||
<p><code>KeyboardNavigation</code>实例负责处理键盘导航,也就是当你按下方向键时会自动寻找下一个节点并激活,可通过<code>mindMap.keyboardNavigation</code>获取到该实例</p>
|
||||
<p><code>KeyboardNavigation</code>插件提供键盘导航的功能,也就是当你按下方向键时会自动寻找下一个节点并激活</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> KeyboardNavigation <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/KeyboardNavigation.js'</span>
|
||||
|
||||
MindMap.usePlugin(KeyboardNavigation)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.keyboardNavigation</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>focus(dir)</h3>
|
||||
<p><code>dir</code>:要寻找哪个方向的下一个节点,可选值:<code>Left</code>、 <code>Up</code>、 <code>Right</code>、 <code>Down</code></p>
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
# MiniMap实例
|
||||
# MiniMap插件
|
||||
|
||||
> v0.2.11+
|
||||
|
||||
用于帮助快速开发小地图功能,小地图由两部分组成,一个是当前的画布内容,一个是视口框,当缩放、移动、元素过多时画布上可能只显示了思维导图的部分内容,可以通过视口框来查看当前视口所在位置,以及可以通过在小地图上拖动来快速定位。
|
||||
|
||||
可通过`mindMap.miniMap`获取到该实例。
|
||||
|
||||
## 方法
|
||||
|
||||
### getMiniMap()
|
||||
|
||||
获取小地图相关数据,这个函数一般不会直接使用,函数返回的内容:
|
||||
## 注册
|
||||
|
||||
```js
|
||||
{
|
||||
svg, // Element,思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)
|
||||
svgHTML, // String,svg字符串,即html字符串,可以直接渲染到你准备的小地图容器内
|
||||
rect: // Object,思维导图图形未缩放时的位置尺寸等信息
|
||||
origWidth, // Number,画布宽度
|
||||
origHeight, // Number,画布高度
|
||||
scaleX, // Number,思维导图图形的水平缩放值
|
||||
scaleY, // Number,思维导图图形的垂直缩放值
|
||||
}
|
||||
import MindMap from 'simple-mind-map'
|
||||
import MiniMap from 'simple-mind-map/src/MiniMap.js'
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
```
|
||||
|
||||
注册完且实例化`MindMap`后可通过`mindMap.miniMap`获取到该实例。
|
||||
|
||||
## 方法
|
||||
|
||||
### calculationMiniMap(boxWidth, boxHeight)
|
||||
|
||||
计算小地图的渲染数据,该函数内会调用`getMiniMap()`方法,所以一般使用该函数即可。
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>MiniMap实例</h1>
|
||||
<h1>MiniMap插件</h1>
|
||||
<blockquote>
|
||||
<p>v0.2.11+</p>
|
||||
</blockquote>
|
||||
<p>用于帮助快速开发小地图功能,小地图由两部分组成,一个是当前的画布内容,一个是视口框,当缩放、移动、元素过多时画布上可能只显示了思维导图的部分内容,可以通过视口框来查看当前视口所在位置,以及可以通过在小地图上拖动来快速定位。</p>
|
||||
<p>可通过<code>mindMap.miniMap</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>getMiniMap()</h3>
|
||||
<p>获取小地图相关数据,这个函数一般不会直接使用,函数返回的内容:</p>
|
||||
<pre class="hljs"><code>{
|
||||
svg, <span class="hljs-comment">// Element,思维导图图形的整体svg元素,包括:svg(画布容器)、g(实际的思维导图组)</span>
|
||||
svgHTML, <span class="hljs-comment">// String,svg字符串,即html字符串,可以直接渲染到你准备的小地图容器内</span>
|
||||
<span class="hljs-attr">rect</span>: <span class="hljs-comment">// Object,思维导图图形未缩放时的位置尺寸等信息</span>
|
||||
origWidth, <span class="hljs-comment">// Number,画布宽度</span>
|
||||
origHeight, <span class="hljs-comment">// Number,画布高度</span>
|
||||
scaleX, <span class="hljs-comment">// Number,思维导图图形的水平缩放值</span>
|
||||
scaleY, <span class="hljs-comment">// Number,思维导图图形的垂直缩放值</span>
|
||||
}
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> MiniMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/MiniMap.js'</span>
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.miniMap</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>calculationMiniMap(boxWidth, boxHeight)</h3>
|
||||
<p>计算小地图的渲染数据,该函数内会调用<code>getMiniMap()</code>方法,所以一般使用该函数即可。</p>
|
||||
<p><code>boxWidth</code>:小地图容器的宽度</p>
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
# Select实例
|
||||
# Select 插件
|
||||
|
||||
`select`实例负责鼠标右键多选节点操作,可通过`mindMap.select`获取到该实例
|
||||
`Select`插件提供鼠标右键多选节点的功能。
|
||||
|
||||
## 注册
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Select from 'simple-mind-map/src/Select.js'
|
||||
|
||||
MindMap.usePlugin(Select)
|
||||
```
|
||||
|
||||
注册完且实例化`MindMap`后可通过`mindMap.select`获取到该实例。
|
||||
|
||||
## 方法
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Select实例</h1>
|
||||
<p><code>select</code>实例负责鼠标右键多选节点操作,可通过<code>mindMap.select</code>获取到该实例</p>
|
||||
<h1>Select 插件</h1>
|
||||
<p><code>Select</code>插件提供鼠标右键多选节点的功能。</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Select <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Select.js'</span>
|
||||
|
||||
MindMap.usePlugin(Select)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.select</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>toPos(x, y)</h3>
|
||||
<p>转换鼠标位置为相对于容器<code>el</code>的位置</p>
|
||||
|
||||
@@ -36,6 +36,13 @@ npm run buildLibrary
|
||||
|
||||
支持`module`字段的环境会以`index.js`为入口,否则会以打包后的`simpleMindMap.umd.min.js`为入口。
|
||||
|
||||
### 编译文档
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npm run buildDoc
|
||||
```
|
||||
|
||||
### 打包demo
|
||||
|
||||
```bash
|
||||
@@ -83,6 +90,16 @@ const mindMap = new MindMap({
|
||||
});
|
||||
```
|
||||
|
||||
默认引入的是未打包的`ES`模块,且只包含核心功能,不包含未注册的插件内容,能有效减小体积,不过你需要在你的项目中配置`babel`编译`simple-mind-map`,防止一些较新的`js`语法部分浏览器不支持。
|
||||
|
||||
如果你需要`umd`模块格式的文件,比如以`CDN`的方式在浏览器上使用,那么你可以使用如下方式引入:
|
||||
|
||||
```js
|
||||
import MindMap from "simple-mind-map/dist/simpleMindMap.umd.min.js";
|
||||
```
|
||||
|
||||
这种方式的缺点是会包含所有的内容,包括你没有注册的插件,所以整体体积会比较大。
|
||||
|
||||
## 问题
|
||||
|
||||
### 1.在Vite中使用报错,提示xml-js依赖出错
|
||||
|
||||
@@ -25,6 +25,10 @@ npm run buildLibrary
|
||||
}
|
||||
</code></pre>
|
||||
<p>支持<code>module</code>字段的环境会以<code>index.js</code>为入口,否则会以打包后的<code>simpleMindMap.umd.min.js</code>为入口。</p>
|
||||
<h3>编译文档</h3>
|
||||
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
|
||||
npm run buildDoc
|
||||
</code></pre>
|
||||
<h3>打包demo</h3>
|
||||
<pre class="hljs"><code><span class="hljs-built_in">cd</span> web
|
||||
npm run build
|
||||
@@ -57,6 +61,11 @@ npm run build
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
<p>默认引入的是未打包的<code>ES</code>模块,且只包含核心功能,不包含未注册的插件内容,能有效减小体积,不过你需要在你的项目中配置<code>babel</code>编译<code>simple-mind-map</code>,防止一些较新的<code>js</code>语法部分浏览器不支持。</p>
|
||||
<p>如果你需要<code>umd</code>模块格式的文件,比如以<code>CDN</code>的方式在浏览器上使用,那么你可以使用如下方式引入:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">"simple-mind-map/dist/simpleMindMap.umd.min.js"</span>;
|
||||
</code></pre>
|
||||
<p>这种方式的缺点是会包含所有的内容,包括你没有注册的插件,所以整体体积会比较大。</p>
|
||||
<h2>问题</h2>
|
||||
<h3>1.在Vite中使用报错,提示xml-js依赖出错</h3>
|
||||
<p>解决方法:使用如下引入方式:</p>
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
# 内置工具方法
|
||||
|
||||
## 基础工具方法
|
||||
|
||||
引用:
|
||||
|
||||
```js
|
||||
import {walk, ...} from 'simple-mind-map/src/utils'
|
||||
```
|
||||
|
||||
## 方法
|
||||
### 方法
|
||||
|
||||
### walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)
|
||||
#### walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)
|
||||
|
||||
深度优先遍历树
|
||||
|
||||
@@ -32,11 +34,11 @@ import {walk, ...} from 'simple-mind-map/src/utils'
|
||||
walk(tree, null, () => {}, () => {}, false, 0, 0)
|
||||
```
|
||||
|
||||
### bfsWalk(root, callback)
|
||||
#### bfsWalk(root, callback)
|
||||
|
||||
广度优先遍历树
|
||||
|
||||
### resizeImgSize(width, height, maxWidth, maxHeight)
|
||||
#### resizeImgSize(width, height, maxWidth, maxHeight)
|
||||
|
||||
缩放图片的尺寸
|
||||
|
||||
@@ -50,15 +52,15 @@ walk(tree, null, () => {}, () => {}, false, 0, 0)
|
||||
|
||||
`maxWidth`和`maxHeight`可以同时都传,也可以只传一个
|
||||
|
||||
### resizeImg(imgUrl, maxWidth, maxHeight)
|
||||
#### resizeImg(imgUrl, maxWidth, maxHeight)
|
||||
|
||||
缩放图片,内部先加载图片,然后调用`resizeImgSize`方法,返回一个`promise`
|
||||
|
||||
### simpleDeepClone(data)
|
||||
#### simpleDeepClone(data)
|
||||
|
||||
极简的深拷贝方法,只能针对全是基本数据的对象,否则会报错
|
||||
|
||||
### copyRenderTree(tree, root)
|
||||
#### copyRenderTree(tree, root)
|
||||
|
||||
复制渲染树数据,示例:
|
||||
|
||||
@@ -66,7 +68,7 @@ walk(tree, null, () => {}, () => {}, false, 0, 0)
|
||||
copyRenderTree({}, this.mindMap.renderer.renderTree)
|
||||
```
|
||||
|
||||
### copyNodeTree(tree, root)
|
||||
#### copyNodeTree(tree, root)
|
||||
|
||||
复制节点树数据,主要是剔除其中的引用`node`实例的`_node`,然后复制`data`对象的数据,示例:
|
||||
|
||||
@@ -74,30 +76,76 @@ copyRenderTree({}, this.mindMap.renderer.renderTree)
|
||||
copyNodeTree({}, node)
|
||||
```
|
||||
|
||||
### imgToDataUrl(src)
|
||||
#### imgToDataUrl(src)
|
||||
|
||||
图片转成dataURL
|
||||
|
||||
### downloadFile(file, fileName)
|
||||
#### downloadFile(file, fileName)
|
||||
|
||||
下载文件
|
||||
|
||||
### throttle(fn, time = 300, ctx)
|
||||
#### throttle(fn, time = 300, ctx)
|
||||
|
||||
节流函数
|
||||
|
||||
### asyncRun(taskList, callback = () => {})
|
||||
#### asyncRun(taskList, callback = () => {})
|
||||
|
||||
异步执行任务队列,多个任务是同步执行的,没有先后顺序
|
||||
|
||||
### degToRad(deg)
|
||||
#### degToRad(deg)
|
||||
|
||||
> v0.2.24+
|
||||
|
||||
角度转弧度
|
||||
|
||||
### camelCaseToHyphen(str)
|
||||
#### camelCaseToHyphen(str)
|
||||
|
||||
> v0.2.24+
|
||||
|
||||
驼峰转连字符
|
||||
驼峰转连字符
|
||||
|
||||
#### joinFontStr({ italic, bold, fontSize, fontFamily })
|
||||
|
||||
> v0.3.4+
|
||||
|
||||
拼接`css`字体的`font`属性值
|
||||
|
||||
#### measureText(text, { italic, bold, fontSize, fontFamily })
|
||||
|
||||
> v0.3.4+
|
||||
|
||||
测量文本的宽高,返回值:
|
||||
|
||||
```js
|
||||
{ width, height }
|
||||
```
|
||||
|
||||
## 在canvas中模拟css的背景属性
|
||||
|
||||
引入:
|
||||
|
||||
```js
|
||||
import drawBackgroundImageToCanvas from 'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'
|
||||
```
|
||||
|
||||
使用:
|
||||
|
||||
```js
|
||||
let width = 500
|
||||
let height = 500
|
||||
let img = '/1.jpg'
|
||||
let canvas = document.createElement('canvas')
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
drawBackgroundImageToCanvas(ctx, width, height, img, {
|
||||
backgroundRepeat: 'repeat-y',
|
||||
backgroundSize: '60%',
|
||||
backgroundPosition: 'center center'
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
// 失败
|
||||
} else {
|
||||
// 成功
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>内置工具方法</h1>
|
||||
<h2>基础工具方法</h2>
|
||||
<p>引用:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> {walk, ...} <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/utils'</span>
|
||||
</code></pre>
|
||||
<h2>方法</h2>
|
||||
<h3>walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)</h3>
|
||||
<h3>方法</h3>
|
||||
<h4>walk(root, parent, beforeCallback, afterCallback, isRoot, layerIndex = 0, index = 0)</h4>
|
||||
<p>深度优先遍历树</p>
|
||||
<p><code>root</code>:要遍历的树的根节点</p>
|
||||
<p><code>parent</code>:父节点</p>
|
||||
@@ -17,45 +18,80 @@
|
||||
<p>示例:</p>
|
||||
<pre class="hljs"><code>walk(tree, <span class="hljs-literal">null</span>, <span class="hljs-function">() =></span> {}, <span class="hljs-function">() =></span> {}, <span class="hljs-literal">false</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>)
|
||||
</code></pre>
|
||||
<h3>bfsWalk(root, callback)</h3>
|
||||
<h4>bfsWalk(root, callback)</h4>
|
||||
<p>广度优先遍历树</p>
|
||||
<h3>resizeImgSize(width, height, maxWidth, maxHeight)</h3>
|
||||
<h4>resizeImgSize(width, height, maxWidth, maxHeight)</h4>
|
||||
<p>缩放图片的尺寸</p>
|
||||
<p><code>width</code>:图片原本的宽</p>
|
||||
<p><code>height</code>:图片原本的高</p>
|
||||
<p><code>maxWidth</code>:要缩放到的宽</p>
|
||||
<p><code>maxHeight</code>:要缩放到的高</p>
|
||||
<p><code>maxWidth</code>和<code>maxHeight</code>可以同时都传,也可以只传一个</p>
|
||||
<h3>resizeImg(imgUrl, maxWidth, maxHeight)</h3>
|
||||
<h4>resizeImg(imgUrl, maxWidth, maxHeight)</h4>
|
||||
<p>缩放图片,内部先加载图片,然后调用<code>resizeImgSize</code>方法,返回一个<code>promise</code></p>
|
||||
<h3>simpleDeepClone(data)</h3>
|
||||
<h4>simpleDeepClone(data)</h4>
|
||||
<p>极简的深拷贝方法,只能针对全是基本数据的对象,否则会报错</p>
|
||||
<h3>copyRenderTree(tree, root)</h3>
|
||||
<h4>copyRenderTree(tree, root)</h4>
|
||||
<p>复制渲染树数据,示例:</p>
|
||||
<pre class="hljs"><code>copyRenderTree({}, <span class="hljs-built_in">this</span>.mindMap.renderer.renderTree)
|
||||
</code></pre>
|
||||
<h3>copyNodeTree(tree, root)</h3>
|
||||
<h4>copyNodeTree(tree, root)</h4>
|
||||
<p>复制节点树数据,主要是剔除其中的引用<code>node</code>实例的<code>_node</code>,然后复制<code>data</code>对象的数据,示例:</p>
|
||||
<pre class="hljs"><code>copyNodeTree({}, node)
|
||||
</code></pre>
|
||||
<h3>imgToDataUrl(src)</h3>
|
||||
<h4>imgToDataUrl(src)</h4>
|
||||
<p>图片转成dataURL</p>
|
||||
<h3>downloadFile(file, fileName)</h3>
|
||||
<h4>downloadFile(file, fileName)</h4>
|
||||
<p>下载文件</p>
|
||||
<h3>throttle(fn, time = 300, ctx)</h3>
|
||||
<h4>throttle(fn, time = 300, ctx)</h4>
|
||||
<p>节流函数</p>
|
||||
<h3>asyncRun(taskList, callback = () => {})</h3>
|
||||
<h4>asyncRun(taskList, callback = () => {})</h4>
|
||||
<p>异步执行任务队列,多个任务是同步执行的,没有先后顺序</p>
|
||||
<h3>degToRad(deg)</h3>
|
||||
<h4>degToRad(deg)</h4>
|
||||
<blockquote>
|
||||
<p>v0.2.24+</p>
|
||||
</blockquote>
|
||||
<p>角度转弧度</p>
|
||||
<h3>camelCaseToHyphen(str)</h3>
|
||||
<h4>camelCaseToHyphen(str)</h4>
|
||||
<blockquote>
|
||||
<p>v0.2.24+</p>
|
||||
</blockquote>
|
||||
<p>驼峰转连字符</p>
|
||||
<h4>joinFontStr({ italic, bold, fontSize, fontFamily })</h4>
|
||||
<blockquote>
|
||||
<p>v0.3.4+</p>
|
||||
</blockquote>
|
||||
<p>拼接<code>css</code>字体的<code>font</code>属性值</p>
|
||||
<h4>measureText(text, { italic, bold, fontSize, fontFamily })</h4>
|
||||
<blockquote>
|
||||
<p>v0.3.4+</p>
|
||||
</blockquote>
|
||||
<p>测量文本的宽高,返回值:</p>
|
||||
<pre class="hljs"><code>{ width, height }
|
||||
</code></pre>
|
||||
<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">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
</code></pre>
|
||||
<p>使用:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">let</span> width = <span class="hljs-number">500</span>
|
||||
<span class="hljs-keyword">let</span> height = <span class="hljs-number">500</span>
|
||||
<span class="hljs-keyword">let</span> img = <span class="hljs-string">'/1.jpg'</span>
|
||||
<span class="hljs-keyword">let</span> canvas = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'canvas'</span>)
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
drawBackgroundImageToCanvas(ctx, width, height, img, {
|
||||
<span class="hljs-attr">backgroundRepeat</span>: <span class="hljs-string">'repeat-y'</span>,
|
||||
<span class="hljs-attr">backgroundSize</span>: <span class="hljs-string">'60%'</span>,
|
||||
<span class="hljs-attr">backgroundPosition</span>: <span class="hljs-string">'center center'</span>
|
||||
}, <span class="hljs-function">(<span class="hljs-params">err</span>) =></span> {
|
||||
<span class="hljs-keyword">if</span> (err) {
|
||||
<span class="hljs-comment">// 失败</span>
|
||||
} <span class="hljs-keyword">else</span> {
|
||||
<span class="hljs-comment">// 成功</span>
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
# Watermark实例
|
||||
# Watermark插件
|
||||
|
||||
> 0.2.24+
|
||||
|
||||
`Watermark`实例负责显示水印,可通过`mindMap.watermark`获取到该实例。
|
||||
`Watermark`插件负责显示水印。
|
||||
|
||||
配置请参考`MindMap`类的[实例化选项](/mind-map/#/doc/zh/constructor)。
|
||||
|
||||
## 注册
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Watermark from 'simple-mind-map/src/Watermark.js'
|
||||
|
||||
MindMap.usePlugin(Watermark)
|
||||
```
|
||||
|
||||
注册完且实例化`MindMap`后可通过`mindMap.watermark`获取到该实例。
|
||||
|
||||
## 方法
|
||||
|
||||
@@ -28,4 +41,10 @@ mindMap.watermark.updateWatermark({
|
||||
fontSize: 20
|
||||
}
|
||||
})
|
||||
```
|
||||
```
|
||||
|
||||
### hasWatermark()
|
||||
|
||||
> v0.3.2+
|
||||
|
||||
获取是否存在水印。
|
||||
@@ -1,10 +1,18 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Watermark实例</h1>
|
||||
<h1>Watermark插件</h1>
|
||||
<blockquote>
|
||||
<p>0.2.24+</p>
|
||||
</blockquote>
|
||||
<p><code>Watermark</code>实例负责显示水印,可通过<code>mindMap.watermark</code>获取到该实例。</p>
|
||||
<p><code>Watermark</code>插件负责显示水印。</p>
|
||||
<p>配置请参考<code>MindMap</code>类的<a href="/mind-map/#/doc/zh/constructor">实例化选项</a>。</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> Watermark <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/Watermark.js'</span>
|
||||
|
||||
MindMap.usePlugin(Watermark)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.watermark</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>draw()</h3>
|
||||
<p>重新绘制水印。</p>
|
||||
@@ -23,6 +31,11 @@
|
||||
}
|
||||
})
|
||||
</code></pre>
|
||||
<h3>hasWatermark()</h3>
|
||||
<blockquote>
|
||||
<p>v0.3.2+</p>
|
||||
</blockquote>
|
||||
<p>获取是否存在水印。</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
41
web/src/pages/Doc/zh/xmind/index.md
Normal file
41
web/src/pages/Doc/zh/xmind/index.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# XMind解析
|
||||
|
||||
> v0.2.7+
|
||||
|
||||
提供导入`XMind`文件的方法。
|
||||
|
||||
## 引入
|
||||
|
||||
```js
|
||||
import xmind from 'simple-mind-map/src/parse/xmind.js'
|
||||
```
|
||||
|
||||
如果使用的是`umd`格式的文件,那么可以通过如下方式获取:
|
||||
|
||||
```js
|
||||
import MindMap from "simple-mind-map/dist/simpleMindMap.umd.min"
|
||||
|
||||
MindMap.xmind
|
||||
```
|
||||
|
||||
## 方法
|
||||
|
||||
### xmind.parseXmindFile(file)
|
||||
|
||||
解析`.xmind`文件,返回解析后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用`mindMap.setFullData(data)`来将返回的数据渲染到画布上
|
||||
|
||||
`file`:`File`对象
|
||||
|
||||
### xmind.transformXmind(content)
|
||||
|
||||
转换`xmind`数据,`.xmind`文件本质上是一个压缩包,改成`zip`后缀可以解压缩,里面存在一个`content.json`文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用`mindMap.setFullData(data)`来将返回的数据渲染到画布上
|
||||
|
||||
`content`:`.xmind`压缩包内的`content.json`文件内容
|
||||
|
||||
### xmind.transformOldXmind(content)
|
||||
|
||||
> v0.2.8+
|
||||
|
||||
针对`xmind8`版本的数据解析,因为该版本的`.xmind`文件内没有`content.json`,对应的是`content.xml`。
|
||||
|
||||
`content`:`.xmind`压缩包内的`content.xml`文件内容
|
||||
41
web/src/pages/Doc/zh/xmind/index.vue
Normal file
41
web/src/pages/Doc/zh/xmind/index.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>XMind解析</h1>
|
||||
<blockquote>
|
||||
<p>v0.2.7+</p>
|
||||
</blockquote>
|
||||
<p>提供导入<code>XMind</code>文件的方法。</p>
|
||||
<h2>引入</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> xmind <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/parse/xmind.js'</span>
|
||||
</code></pre>
|
||||
<p>如果使用的是<code>umd</code>格式的文件,那么可以通过如下方式获取:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">"simple-mind-map/dist/simpleMindMap.umd.min"</span>
|
||||
|
||||
MindMap.xmind
|
||||
</code></pre>
|
||||
<h2>方法</h2>
|
||||
<h3>xmind.parseXmindFile(file)</h3>
|
||||
<p>解析<code>.xmind</code>文件,返回解析后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用<code>mindMap.setFullData(data)</code>来将返回的数据渲染到画布上</p>
|
||||
<p><code>file</code>:<code>File</code>对象</p>
|
||||
<h3>xmind.transformXmind(content)</h3>
|
||||
<p>转换<code>xmind</code>数据,<code>.xmind</code>文件本质上是一个压缩包,改成<code>zip</code>后缀可以解压缩,里面存在一个<code>content.json</code>文件,如果你自己解析出了这个文件,那么可以把这个文件内容传递给这个方法进行转换,转换后的数据,注意是完整的数据,包含节点树、主题、结构等,可以使用<code>mindMap.setFullData(data)</code>来将返回的数据渲染到画布上</p>
|
||||
<p><code>content</code>:<code>.xmind</code>压缩包内的<code>content.json</code>文件内容</p>
|
||||
<h3>xmind.transformOldXmind(content)</h3>
|
||||
<blockquote>
|
||||
<p>v0.2.8+</p>
|
||||
</blockquote>
|
||||
<p>针对<code>xmind8</code>版本的数据解析,因为该版本的<code>.xmind</code>文件内没有<code>content.json</code>,对应的是<code>content.xml</code>。</p>
|
||||
<p><code>content</code>:<code>.xmind</code>压缩包内的<code>content.xml</code>文件内容</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -25,6 +25,7 @@
|
||||
}
|
||||
"
|
||||
></ImgUpload>
|
||||
<!-- 图片重复方式 -->
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.imageRepeat') }}</span>
|
||||
<el-select
|
||||
@@ -47,6 +48,52 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- 图片位置 -->
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.imagePosition') }}</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 120px"
|
||||
v-model="style.backgroundPosition"
|
||||
placeholder=""
|
||||
@change="
|
||||
value => {
|
||||
update('backgroundPosition', value)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in backgroundPositionList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<!-- 图片大小 -->
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('baseStyle.imageSize') }}</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 120px"
|
||||
v-model="style.backgroundSize"
|
||||
placeholder=""
|
||||
@change="
|
||||
value => {
|
||||
update('backgroundSize', value)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in backgroundSizeList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
@@ -389,7 +436,7 @@
|
||||
<script>
|
||||
import Sidebar from './Sidebar'
|
||||
import Color from './Color'
|
||||
import { lineWidthList, lineStyleList, backgroundRepeatList } from '@/config'
|
||||
import { lineWidthList, lineStyleList, backgroundRepeatList, backgroundPositionList, backgroundSizeList } from '@/config'
|
||||
import ImgUpload from '@/components/ImgUpload'
|
||||
import { storeConfig } from '@/api'
|
||||
import { mapState } from 'vuex'
|
||||
@@ -434,6 +481,8 @@ export default {
|
||||
iconSize: 0,
|
||||
backgroundImage: '',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: '',
|
||||
backgroundSize: '',
|
||||
marginX: 0,
|
||||
marginY: 0,
|
||||
nodeUseLineStyle: false
|
||||
@@ -464,7 +513,13 @@ export default {
|
||||
},
|
||||
backgroundRepeatList() {
|
||||
return backgroundRepeatList[this.$i18n.locale] || backgroundRepeatList.zh
|
||||
}
|
||||
},
|
||||
backgroundPositionList() {
|
||||
return backgroundPositionList[this.$i18n.locale] || backgroundPositionList.zh
|
||||
},
|
||||
backgroundSizeList() {
|
||||
return backgroundSizeList[this.$i18n.locale] || backgroundSizeList.zh
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
activeSidebar(val) {
|
||||
@@ -499,6 +554,8 @@ export default {
|
||||
'iconSize',
|
||||
'backgroundImage',
|
||||
'backgroundRepeat',
|
||||
'backgroundPosition',
|
||||
'backgroundSize',
|
||||
'nodeUseLineStyle'
|
||||
].forEach(key => {
|
||||
this.style[key] = this.mindMap.getThemeConfig(key)
|
||||
@@ -580,6 +637,7 @@ export default {
|
||||
this.mindMap.watermark.updateWatermark({
|
||||
...config
|
||||
})
|
||||
this.data.config = this.data.config || {}
|
||||
this.data.config.watermarkConfig = this.mindMap.getConfig('watermarkConfig')
|
||||
storeConfig({
|
||||
config: this.data.config
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
|
||||
<script>
|
||||
import MindMap from 'simple-mind-map'
|
||||
import MiniMap from 'simple-mind-map/src/MiniMap.js'
|
||||
import Watermark from 'simple-mind-map/src/Watermark.js'
|
||||
import KeyboardNavigation from 'simple-mind-map/src/KeyboardNavigation.js'
|
||||
import Export from 'simple-mind-map/src/Export.js'
|
||||
import Drag from 'simple-mind-map/src/Drag.js'
|
||||
import Select from 'simple-mind-map/src/Select.js'
|
||||
import Outline from './Outline'
|
||||
import Style from './Style'
|
||||
import BaseStyle from './BaseStyle'
|
||||
@@ -39,6 +45,15 @@ import SidebarTrigger from './SidebarTrigger.vue'
|
||||
import { mapState } from 'vuex'
|
||||
import customThemeList from '@/customThemes'
|
||||
|
||||
// 注册插件
|
||||
MindMap
|
||||
.usePlugin(MiniMap)
|
||||
.usePlugin(Watermark)
|
||||
.usePlugin(Drag)
|
||||
.usePlugin(KeyboardNavigation)
|
||||
.usePlugin(Export)
|
||||
.usePlugin(Select)
|
||||
|
||||
// 注册自定义主题
|
||||
customThemeList.forEach((item) => {
|
||||
MindMap.defineTheme(item.value, item.theme)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MindMap from 'simple-mind-map'
|
||||
import xmind from 'simple-mind-map/src/parse/xmind.js'
|
||||
import { fileToBuffer } from '@/utils'
|
||||
import { read, utils } from 'xlsx'
|
||||
|
||||
@@ -146,7 +146,7 @@ export default {
|
||||
*/
|
||||
async handleXmind(file) {
|
||||
try {
|
||||
let data = await MindMap.xmind.parseXmindFile(file.raw)
|
||||
let data = await xmind.parseXmindFile(file.raw)
|
||||
this.$bus.$emit('setData', data)
|
||||
this.$message.success('导入成功')
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user