mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 22:08:25 +08:00
Compare commits
59 Commits
0.7.1-fix.
...
0.7.3-fix.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
745531f20f | ||
|
|
3acd425c09 | ||
|
|
8dcc7c985d | ||
|
|
253ded33bf | ||
|
|
2c6b8294f4 | ||
|
|
83a5ef8e2e | ||
|
|
b959e90723 | ||
|
|
89ebc9a1fa | ||
|
|
56d2e34fbd | ||
|
|
0f2aed7e8a | ||
|
|
288ceafa92 | ||
|
|
99dc443142 | ||
|
|
b6440eba1a | ||
|
|
545e46babc | ||
|
|
b95b6af1b1 | ||
|
|
ccef5fc581 | ||
|
|
ed82fe5a61 | ||
|
|
1550f032d9 | ||
|
|
7d2758a21c | ||
|
|
e4fab73017 | ||
|
|
1beb03eaa6 | ||
|
|
20f67efd58 | ||
|
|
8c3d66eb3c | ||
|
|
a4f6006efd | ||
|
|
1d297350cc | ||
|
|
07650f8978 | ||
|
|
b26e5625ce | ||
|
|
1e38731ecb | ||
|
|
ef9b9804cb | ||
|
|
9fe321a127 | ||
|
|
464e57d019 | ||
|
|
50f125471e | ||
|
|
6bbee4a5cc | ||
|
|
5052c0427a | ||
|
|
9528631ed1 | ||
|
|
2a816f62fa | ||
|
|
8596e3356d | ||
|
|
7422af7f3b | ||
|
|
0f047da78b | ||
|
|
f866abb34c | ||
|
|
01d7e36990 | ||
|
|
a9493b9c16 | ||
|
|
a59a283d74 | ||
|
|
aafcba8bb7 | ||
|
|
11ea7d452c | ||
|
|
47d21d85fb | ||
|
|
518b7642a0 | ||
|
|
a9ea4b8e33 | ||
|
|
443465eb86 | ||
|
|
e1172c8d0d | ||
|
|
7a2605fdad | ||
|
|
a97d549d69 | ||
|
|
fcf48ca3dc | ||
|
|
c0ad18cff8 | ||
|
|
73e7855575 | ||
|
|
69ef7faf49 | ||
|
|
036f845968 | ||
|
|
740e2e3410 | ||
|
|
ba44f69f9f |
27
README.md
27
README.md
@@ -25,18 +25,21 @@ Github:[releases](https://github.com/wanglin2/mind-map/releases)。
|
||||
|
||||
百度云盘:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
|
||||
|
||||
> 客户端版本会落后于在线版本,尝试最新功能请优先使用在线版。
|
||||
|
||||
# 特性
|
||||
|
||||
- [x] 插件化架构,除核心功能外,其他功能作为插件提供,按需使用,减小打包体积
|
||||
- [x] 支持逻辑结构图、思维导图、组织结构图、目录组织图、时间轴(横向、竖向)、鱼骨图等结构
|
||||
- [x] 内置多种主题,允许高度自定义样式,支持注册新主题
|
||||
- [x] 节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要
|
||||
- [x] 节点内容支持文本(普通文本、富文本)、图片、图标、超链接、备注、标签、概要、数学公式
|
||||
- [x] 节点支持拖拽(拖拽移动、自由调整)、多种节点形状,支持使用 DDM 完全自定义节点内容
|
||||
- [x] 支持画布拖动、缩放
|
||||
- [x] 支持鼠标按键拖动选择和Ctrl+左键两种多选节点方式
|
||||
- [x] 支持导出为`json`、`png`、`svg`、`pdf`、`markdown`、`xmind`,支持从`json`、`xmind`、`markdown`导入
|
||||
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印
|
||||
- [x] 支持快捷键、前进后退、关联线、搜索替换、小地图、水印、滚动条
|
||||
- [x] 提供丰富的配置,满足各种场景各种使用习惯
|
||||
- [x] 支持协同编辑
|
||||
|
||||
# 安装
|
||||
|
||||
@@ -91,11 +94,11 @@ const mindMap = new MindMap({
|
||||
|
||||
# 请作者喝杯咖啡
|
||||
|
||||
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡哟~
|
||||
开源不易,如果本项目有帮助到你的话,可以考虑请作者喝杯咖啡~
|
||||
|
||||
> 厚椰乳一盒 + 纯牛奶半盒 + 冰块 + 咖啡液 = 生椰拿铁 yyds
|
||||
|
||||
> 推荐使用支付宝,微信获取不到头像。转账请备注【思维导图】。你的头像和名字将会出现在下面和[文档页面](https://wanglin2.github.io/mind-map/#/doc/zh/introduction/%E8%AF%B7%E4%BD%9C%E8%80%85%E5%96%9D%E6%9D%AF%E5%92%96%E5%95%A1)
|
||||
> 推荐使用支付宝,微信获取不到头像。转账请备注【思维导图】。
|
||||
|
||||
<p>
|
||||
<img src="./web/src/assets/img/alipay.jpg" style="width: 300px" />
|
||||
@@ -183,4 +186,20 @@ const mindMap = new MindMap({
|
||||
<img src="./web/src/assets/avatar/敏.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>敏</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>沐风牧草</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/有希.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>有希</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/樊笼.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>樊笼</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/达仁科技.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>达仁科技</span>
|
||||
</span>
|
||||
</p>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!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,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel="icon" href="dist/logo.ico"><title>思绪思维导图</title><script>// 自定义静态资源的路径
|
||||
window.externalPublicPath = './dist/'
|
||||
// 接管应用
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?3d449dfd2d4c7693c086" rel="stylesheet"><link href="dist/css/app.css?3d449dfd2d4c7693c086" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
window.takeOverApp = false</script><link href="dist/css/chunk-vendors.css?ceeef97326ffc3ea9cba" rel="stylesheet"><link href="dist/css/app.css?ceeef97326ffc3ea9cba" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
@@ -66,4 +66,4 @@
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
// 实例化页面
|
||||
window.initApp()
|
||||
}</script><script src="dist/js/chunk-vendors.js?3d449dfd2d4c7693c086"></script><script src="dist/js/app.js?3d449dfd2d4c7693c086"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?ceeef97326ffc3ea9cba"></script><script src="dist/js/app.js?ceeef97326ffc3ea9cba"></script></body></html>
|
||||
152
simple-mind-map/bin/wsServer.mjs
Normal file
152
simple-mind-map/bin/wsServer.mjs
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import ws from 'ws'
|
||||
import http from 'http'
|
||||
import * as map from 'lib0/map'
|
||||
|
||||
const wsReadyStateConnecting = 0
|
||||
const wsReadyStateOpen = 1
|
||||
const wsReadyStateClosing = 2 // eslint-disable-line
|
||||
const wsReadyStateClosed = 3 // eslint-disable-line
|
||||
|
||||
const pingTimeout = 30000
|
||||
|
||||
const port = process.env.PORT || 4444
|
||||
// @ts-ignore
|
||||
const wss = new ws.Server({ noServer: true })
|
||||
|
||||
const server = http.createServer((request, response) => {
|
||||
response.writeHead(200, { 'Content-Type': 'text/plain' })
|
||||
response.end('okay')
|
||||
})
|
||||
|
||||
/**
|
||||
* Map froms topic-name to set of subscribed clients.
|
||||
* @type {Map<string, Set<any>>}
|
||||
*/
|
||||
const topics = new Map()
|
||||
|
||||
/**
|
||||
* @param {any} conn
|
||||
* @param {object} message
|
||||
*/
|
||||
const send = (conn, message) => {
|
||||
if (
|
||||
conn.readyState !== wsReadyStateConnecting &&
|
||||
conn.readyState !== wsReadyStateOpen
|
||||
) {
|
||||
conn.close()
|
||||
}
|
||||
try {
|
||||
conn.send(JSON.stringify(message))
|
||||
} catch (e) {
|
||||
conn.close()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a new client
|
||||
* @param {any} conn
|
||||
*/
|
||||
const onconnection = conn => {
|
||||
/**
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
const subscribedTopics = new Set()
|
||||
let closed = false
|
||||
// Check if connection is still alive
|
||||
let pongReceived = true
|
||||
const pingInterval = setInterval(() => {
|
||||
if (!pongReceived) {
|
||||
conn.close()
|
||||
clearInterval(pingInterval)
|
||||
} else {
|
||||
pongReceived = false
|
||||
try {
|
||||
conn.ping()
|
||||
} catch (e) {
|
||||
conn.close()
|
||||
}
|
||||
}
|
||||
}, pingTimeout)
|
||||
conn.on('pong', () => {
|
||||
pongReceived = true
|
||||
})
|
||||
conn.on('close', () => {
|
||||
subscribedTopics.forEach(topicName => {
|
||||
const subs = topics.get(topicName) || new Set()
|
||||
subs.delete(conn)
|
||||
if (subs.size === 0) {
|
||||
topics.delete(topicName)
|
||||
}
|
||||
})
|
||||
subscribedTopics.clear()
|
||||
closed = true
|
||||
})
|
||||
conn.on(
|
||||
'message',
|
||||
/** @param {object} message */ message => {
|
||||
if (typeof message === 'string') {
|
||||
message = JSON.parse(message)
|
||||
}
|
||||
if (message && message.type && !closed) {
|
||||
switch (message.type) {
|
||||
case 'subscribe':
|
||||
/** @type {Array<string>} */ ;(message.topics || []).forEach(
|
||||
topicName => {
|
||||
if (typeof topicName === 'string') {
|
||||
// add conn to topic
|
||||
const topic = map.setIfUndefined(
|
||||
topics,
|
||||
topicName,
|
||||
() => new Set()
|
||||
)
|
||||
topic.add(conn)
|
||||
// add topic to conn
|
||||
subscribedTopics.add(topicName)
|
||||
}
|
||||
}
|
||||
)
|
||||
break
|
||||
case 'unsubscribe':
|
||||
/** @type {Array<string>} */ ;(message.topics || []).forEach(
|
||||
topicName => {
|
||||
const subs = topics.get(topicName)
|
||||
if (subs) {
|
||||
subs.delete(conn)
|
||||
}
|
||||
}
|
||||
)
|
||||
break
|
||||
case 'publish':
|
||||
if (message.topic) {
|
||||
const receivers = topics.get(message.topic)
|
||||
if (receivers) {
|
||||
message.clients = receivers.size
|
||||
receivers.forEach(receiver => send(receiver, message))
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'ping':
|
||||
send(conn, { type: 'pong' })
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
wss.on('connection', onconnection)
|
||||
|
||||
server.on('upgrade', (request, socket, head) => {
|
||||
// You may check auth of request here..
|
||||
/**
|
||||
* @param {any} ws
|
||||
*/
|
||||
const handleAuth = ws => {
|
||||
wss.emit('connection', ws, request)
|
||||
}
|
||||
wss.handleUpgrade(request, socket, head, handleAuth)
|
||||
})
|
||||
|
||||
server.listen(port)
|
||||
|
||||
console.log('Signaling server running on localhost:', port)
|
||||
@@ -14,6 +14,7 @@ import TouchEvent from './src/plugins/TouchEvent.js'
|
||||
import Search from './src/plugins/Search.js'
|
||||
import Painter from './src/plugins/Painter.js'
|
||||
import Scrollbar from './src/plugins/Scrollbar.js'
|
||||
import Formula from './src/plugins/Formula.js'
|
||||
import xmind from './src/parse/xmind.js'
|
||||
import markdown from './src/parse/markdown.js'
|
||||
import icons from './src/svg/icons.js'
|
||||
@@ -43,5 +44,6 @@ MindMap.usePlugin(MiniMap)
|
||||
.usePlugin(Search)
|
||||
.usePlugin(Painter)
|
||||
.usePlugin(Scrollbar)
|
||||
.usePlugin(Formula)
|
||||
|
||||
export default MindMap
|
||||
|
||||
@@ -258,15 +258,13 @@ class MindMap {
|
||||
|
||||
// 动态设置思维导图数据,纯节点数据
|
||||
setData(data) {
|
||||
data = simpleDeepClone(data || {})
|
||||
this.execCommand('CLEAR_ACTIVE_NODE')
|
||||
this.command.clearHistory()
|
||||
this.command.addHistory()
|
||||
if (this.richText) {
|
||||
this.renderer.renderTree = this.richText.handleSetData(data)
|
||||
} else {
|
||||
this.renderer.renderTree = data
|
||||
}
|
||||
this.renderer.setData(data)
|
||||
this.reRender(() => {}, CONSTANTS.SET_DATA)
|
||||
this.emit('set_data', data)
|
||||
}
|
||||
|
||||
// 动态设置思维导图数据,包括节点数据、布局、主题、视图
|
||||
|
||||
646
simple-mind-map/package-lock.json
generated
646
simple-mind-map/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.7.1-fix.2",
|
||||
"version": "0.7.3-fix.1",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
@@ -13,6 +13,7 @@
|
||||
}
|
||||
],
|
||||
"types": "./types/index.d.ts",
|
||||
"typings": "./types/index.d.ts",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -21,7 +22,8 @@
|
||||
"scripts": {
|
||||
"lint": "eslint src/",
|
||||
"format": "prettier --write .",
|
||||
"types": "npx -p typescript tsc index.js --declaration --allowJs --emitDeclarationOnly --outDir types --target es2017"
|
||||
"types": "npx -p typescript tsc index.js --declaration --allowJs --emitDeclarationOnly --outDir types --target es2017",
|
||||
"wsServe": "node ./bin/wsServer.mjs"
|
||||
},
|
||||
"module": "index.js",
|
||||
"main": "./dist/simpleMindMap.umd.min.js",
|
||||
@@ -31,11 +33,14 @@
|
||||
"eventemitter3": "^4.0.7",
|
||||
"jspdf": "^2.5.1",
|
||||
"jszip": "^3.10.1",
|
||||
"katex": "^0.16.8",
|
||||
"mdast-util-from-markdown": "^1.3.0",
|
||||
"quill": "^1.3.6",
|
||||
"tern": "^0.24.3",
|
||||
"uuid": "^9.0.0",
|
||||
"xml-js": "^1.6.11"
|
||||
"xml-js": "^1.6.11",
|
||||
"y-webrtc": "^10.2.5",
|
||||
"yjs": "^13.6.8"
|
||||
},
|
||||
"keywords": [
|
||||
"javascript",
|
||||
|
||||
@@ -1,27 +1,3 @@
|
||||
// 标签颜色列表
|
||||
export const tagColorList = [
|
||||
{
|
||||
color: 'rgb(77, 65, 0)',
|
||||
background: 'rgb(255, 244, 179)'
|
||||
},
|
||||
{
|
||||
color: 'rgb(0, 50, 77)',
|
||||
background: 'rgb(179, 229, 255)'
|
||||
},
|
||||
{
|
||||
color: 'rgb(77, 0, 73)',
|
||||
background: 'rgb(255, 179, 251)'
|
||||
},
|
||||
{
|
||||
color: 'rgb(57, 77, 0)',
|
||||
background: 'rgb(236, 255, 179)'
|
||||
},
|
||||
{
|
||||
color: 'rgb(0, 77, 47)',
|
||||
background: 'rgb(179, 255, 226)'
|
||||
}
|
||||
]
|
||||
|
||||
// 主题列表
|
||||
export const themeList = [
|
||||
{
|
||||
@@ -365,7 +341,7 @@ export const cssContent = `
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.smm-node:hover .smm-hover-node{
|
||||
.smm-node:not(.smm-node-dragging):hover .smm-hover-node{
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@@ -188,5 +188,26 @@ export const defaultOpt = {
|
||||
// 拖拽节点时鼠标移动到画布边缘是否开启画布自动移动
|
||||
autoMoveWhenMouseInEdgeOnDrag: true,
|
||||
// 是否首次加载fit view
|
||||
fit: false
|
||||
fit: false,
|
||||
// 拖拽多个节点时随鼠标移动的示意矩形的样式配置
|
||||
dragMultiNodeRectConfig: {
|
||||
width: 40,
|
||||
height: 20,
|
||||
fill: '' // 填充颜色,如果不传默认使用连线的颜色
|
||||
},
|
||||
// 节点拖拽时新位置的示意矩形的填充颜色,如果不传默认使用连线的颜色
|
||||
dragPlaceholderRectFill: '',
|
||||
// 节点拖拽时的透明度配置
|
||||
dragOpacityConfig: {
|
||||
cloneNodeOpacity: 0.5, // 跟随鼠标移动的克隆节点或矩形的透明度
|
||||
beingDragNodeOpacity: 0.3 // 被拖拽节点的透明度
|
||||
},
|
||||
// 自定义标签的颜色
|
||||
// {pass: 'green, unpass: 'red'}
|
||||
tagsColorMap: {},
|
||||
// 节点协作样式配置
|
||||
cooperateStyle: {
|
||||
avatarSize: 22,// 头像大小
|
||||
fontSize: 12,// 如果是文字头像,那么文字的大小
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,13 @@ import {
|
||||
walk,
|
||||
bfsWalk,
|
||||
loadImage,
|
||||
isUndef
|
||||
isUndef,
|
||||
getTopAncestorsFomNodeList,
|
||||
addDataToAppointNodes,
|
||||
createUidForAppointNodes,
|
||||
formatDataToArray,
|
||||
getNodeIndex,
|
||||
createUid
|
||||
} from '../../utils'
|
||||
import { shapeList } from './node/Shape'
|
||||
import { lineStyleProps } from '../../themes/default'
|
||||
@@ -40,7 +46,6 @@ const layouts = {
|
||||
}
|
||||
|
||||
// 渲染
|
||||
|
||||
class Render {
|
||||
// 构造函数
|
||||
constructor(opt = {}) {
|
||||
@@ -92,6 +97,15 @@ class Render {
|
||||
)(this, this.mindMap.opt.layout)
|
||||
}
|
||||
|
||||
// 重新设置思维导图数据
|
||||
setData(data) {
|
||||
if (this.mindMap.richText) {
|
||||
this.renderTree = this.mindMap.richText.handleSetData(data)
|
||||
} else {
|
||||
this.renderTree = data
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定事件
|
||||
bindEvent() {
|
||||
// 点击事件
|
||||
@@ -132,9 +146,18 @@ class Render {
|
||||
// 插入同级节点
|
||||
this.insertNode = this.insertNode.bind(this)
|
||||
this.mindMap.command.add('INSERT_NODE', this.insertNode)
|
||||
// 插入多个同级节点
|
||||
this.insertMultiNode = this.insertMultiNode.bind(this)
|
||||
this.mindMap.command.add('INSERT_MULTI_NODE', this.insertMultiNode)
|
||||
// 插入子节点
|
||||
this.insertChildNode = this.insertChildNode.bind(this)
|
||||
this.mindMap.command.add('INSERT_CHILD_NODE', this.insertChildNode)
|
||||
// 插入多个子节点
|
||||
this.insertMultiChildNode = this.insertMultiChildNode.bind(this)
|
||||
this.mindMap.command.add(
|
||||
'INSERT_MULTI_CHILD_NODE',
|
||||
this.insertMultiChildNode
|
||||
)
|
||||
// 上移节点
|
||||
this.upNode = this.upNode.bind(this)
|
||||
this.mindMap.command.add('UP_NODE', this.upNode)
|
||||
@@ -202,6 +225,9 @@ class Render {
|
||||
// 设置节点标签
|
||||
this.setNodeTag = this.setNodeTag.bind(this)
|
||||
this.mindMap.command.add('SET_NODE_TAG', this.setNodeTag)
|
||||
// 设置节点公式
|
||||
this.insertFormula = this.insertFormula.bind(this)
|
||||
this.mindMap.command.add('INSERT_FORMULA', this.insertFormula)
|
||||
// 添加节点概要
|
||||
this.addGeneralization = this.addGeneralization.bind(this)
|
||||
this.mindMap.command.add('ADD_GENERALIZATION', this.addGeneralization)
|
||||
@@ -386,15 +412,6 @@ class Render {
|
||||
})
|
||||
}
|
||||
|
||||
// 获取节点在同级里的索引位置
|
||||
getNodeIndex(node) {
|
||||
return node.parent
|
||||
? node.parent.children.findIndex(item => {
|
||||
return item.uid === node.uid
|
||||
})
|
||||
: 0
|
||||
}
|
||||
|
||||
// 全选
|
||||
selectAll() {
|
||||
walk(
|
||||
@@ -439,58 +456,120 @@ class Render {
|
||||
}
|
||||
}
|
||||
|
||||
// 规范指定节点数据
|
||||
formatAppointNodes(appointNodes) {
|
||||
if (!appointNodes) return []
|
||||
return Array.isArray(appointNodes) ? appointNodes : [appointNodes]
|
||||
}
|
||||
|
||||
// 插入同级节点,多个节点只会操作第一个节点
|
||||
// 插入同级节点
|
||||
insertNode(
|
||||
openEdit = true,
|
||||
appointNodes = [],
|
||||
appointData = null,
|
||||
appointChildren = []
|
||||
) {
|
||||
appointNodes = this.formatAppointNodes(appointNodes)
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.textEdit.hideEditTextBox()
|
||||
let {
|
||||
const {
|
||||
defaultInsertSecondLevelNodeText,
|
||||
defaultInsertBelowSecondLevelNodeText
|
||||
} = this.mindMap.opt
|
||||
let list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
let first = list[0]
|
||||
if (first.isGeneralization) {
|
||||
return
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const handleMultiNodes = list.length > 1
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
|
||||
}
|
||||
if (first.isRoot) {
|
||||
this.insertChildNode(openEdit, appointNodes, appointData)
|
||||
} else {
|
||||
let text =
|
||||
first.layerIndex === 1
|
||||
? defaultInsertSecondLevelNodeText
|
||||
: defaultInsertBelowSecondLevelNodeText
|
||||
if (first.layerIndex === 1) {
|
||||
first.parent.destroy()
|
||||
// 动态指定的子节点数据也需要添加相关属性
|
||||
appointChildren = addDataToAppointNodes(appointChildren, {
|
||||
...params
|
||||
})
|
||||
const needDestroyNodeList = {}
|
||||
list.forEach(node => {
|
||||
if (node.isGeneralization || node.isRoot) {
|
||||
return
|
||||
}
|
||||
let index = this.getNodeIndex(first)
|
||||
let isRichText = !!this.mindMap.richText
|
||||
first.parent.nodeData.children.splice(index + 1, 0, {
|
||||
inserting: openEdit,
|
||||
const parent = node.parent
|
||||
const isOneLayer = node.layerIndex === 1
|
||||
// 插入二级节点时根节点需要重新渲染
|
||||
if (isOneLayer && !needDestroyNodeList[parent.uid]) {
|
||||
needDestroyNodeList[parent.uid] = parent
|
||||
}
|
||||
// 新插入节点的默认文本
|
||||
const text = isOneLayer
|
||||
? defaultInsertSecondLevelNodeText
|
||||
: defaultInsertBelowSecondLevelNodeText
|
||||
// 计算插入位置
|
||||
const index = parent.nodeData.children.findIndex(item => {
|
||||
return item.data.uid === node.uid
|
||||
})
|
||||
const newNodeData = {
|
||||
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式,
|
||||
data: {
|
||||
text: text,
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
...params,
|
||||
uid: createUid(),
|
||||
...(appointData || {})
|
||||
},
|
||||
children: [...appointChildren]
|
||||
})
|
||||
this.mindMap.render()
|
||||
children: [...createUidForAppointNodes(appointChildren, true)]
|
||||
}
|
||||
parent.nodeData.children.splice(index + 1, 0, newNodeData)
|
||||
})
|
||||
Object.keys(needDestroyNodeList).forEach(key => {
|
||||
needDestroyNodeList[key].destroy()
|
||||
})
|
||||
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
|
||||
if (handleMultiNodes || !openEdit) {
|
||||
this.clearActive()
|
||||
}
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
// 插入多个同级节点
|
||||
insertMultiNode(appointNodes, nodeList) {
|
||||
if (!nodeList || nodeList.length <= 0) return
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.textEdit.hideEditTextBox()
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: true
|
||||
}
|
||||
nodeList = addDataToAppointNodes(nodeList, params)
|
||||
const needDestroyNodeList = {}
|
||||
list.forEach(node => {
|
||||
if (node.isGeneralization || node.isRoot) {
|
||||
return
|
||||
}
|
||||
const parent = node.parent
|
||||
const isOneLayer = node.layerIndex === 1
|
||||
// 插入二级节点时根节点需要重新渲染
|
||||
if (isOneLayer && !needDestroyNodeList[parent.uid]) {
|
||||
needDestroyNodeList[parent.uid] = parent
|
||||
}
|
||||
// 计算插入位置
|
||||
const index = parent.nodeData.children.findIndex(item => {
|
||||
return item.data.uid === node.uid
|
||||
})
|
||||
const newNodeList = createUidForAppointNodes(simpleDeepClone(nodeList), true)
|
||||
parent.nodeData.children.splice(
|
||||
index + 1,
|
||||
0,
|
||||
...newNodeList
|
||||
)
|
||||
})
|
||||
Object.keys(needDestroyNodeList).forEach(key => {
|
||||
needDestroyNodeList[key].destroy()
|
||||
})
|
||||
this.clearActive()
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
// 插入子节点
|
||||
@@ -500,16 +579,28 @@ class Render {
|
||||
appointData = null,
|
||||
appointChildren = []
|
||||
) {
|
||||
appointNodes = this.formatAppointNodes(appointNodes)
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.textEdit.hideEditTextBox()
|
||||
let {
|
||||
const {
|
||||
defaultInsertSecondLevelNodeText,
|
||||
defaultInsertBelowSecondLevelNodeText
|
||||
} = this.mindMap.opt
|
||||
let list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const handleMultiNodes = list.length > 1
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: handleMultiNodes || !openEdit // 如果同时对多个节点插入子节点,那么需要把新增的节点设为激活状态。如果不进入编辑状态,那么也需要手动设为激活状态
|
||||
}
|
||||
// 动态指定的子节点数据也需要添加相关属性
|
||||
appointChildren = addDataToAppointNodes(appointChildren, {
|
||||
...params
|
||||
})
|
||||
list.forEach(node => {
|
||||
if (node.isGeneralization) {
|
||||
return
|
||||
@@ -517,27 +608,66 @@ class Render {
|
||||
if (!node.nodeData.children) {
|
||||
node.nodeData.children = []
|
||||
}
|
||||
let text = node.isRoot
|
||||
const text = node.isRoot
|
||||
? defaultInsertSecondLevelNodeText
|
||||
: defaultInsertBelowSecondLevelNodeText
|
||||
let isRichText = !!this.mindMap.richText
|
||||
node.nodeData.children.push({
|
||||
inserting: openEdit,
|
||||
const newNode = {
|
||||
inserting: handleMultiNodes ? false : openEdit, // 如果同时对多个节点插入子节点,那么无需进入编辑模式
|
||||
data: {
|
||||
text: text,
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
uid: createUid(),
|
||||
...params,
|
||||
...(appointData || {})
|
||||
},
|
||||
children: [...appointChildren]
|
||||
})
|
||||
children: [...createUidForAppointNodes(appointChildren, true)]
|
||||
}
|
||||
node.nodeData.children.push(newNode)
|
||||
// 插入子节点时自动展开子节点
|
||||
node.nodeData.data.expand = true
|
||||
if (node.isRoot) {
|
||||
node.destroy()
|
||||
}
|
||||
})
|
||||
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
|
||||
if (handleMultiNodes || !openEdit) {
|
||||
this.clearActive()
|
||||
}
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
// 插入多个子节点
|
||||
insertMultiChildNode(appointNodes, childList) {
|
||||
if (!childList || childList.length <= 0) return
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.textEdit.hideEditTextBox()
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
const isRichText = !!this.mindMap.richText
|
||||
const params = {
|
||||
expand: true,
|
||||
richText: isRichText,
|
||||
resetRichText: isRichText,
|
||||
isActive: true
|
||||
}
|
||||
childList = addDataToAppointNodes(childList, params)
|
||||
list.forEach(node => {
|
||||
if (node.isGeneralization) {
|
||||
return
|
||||
}
|
||||
if (!node.nodeData.children) {
|
||||
node.nodeData.children = []
|
||||
}
|
||||
childList = createUidForAppointNodes(childList, true)
|
||||
node.nodeData.children.push(...childList)
|
||||
// 插入子节点时自动展开子节点
|
||||
node.nodeData.data.expand = true
|
||||
if (node.isRoot) {
|
||||
node.destroy()
|
||||
}
|
||||
})
|
||||
this.clearActive()
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
@@ -598,19 +728,19 @@ class Render {
|
||||
// 复制节点
|
||||
copy() {
|
||||
this.beingCopyData = this.copyNode()
|
||||
this.setCoptyDataToClipboard(this.beingCopyData)
|
||||
this.setCopyDataToClipboard(this.beingCopyData)
|
||||
}
|
||||
|
||||
// 剪切节点
|
||||
cut() {
|
||||
this.mindMap.execCommand('CUT_NODE', copyData => {
|
||||
this.beingCopyData = copyData
|
||||
this.setCoptyDataToClipboard(copyData)
|
||||
this.setCopyDataToClipboard(copyData)
|
||||
})
|
||||
}
|
||||
|
||||
// 将粘贴或剪切的数据设置到用户剪切板中
|
||||
setCoptyDataToClipboard(data) {
|
||||
setCopyDataToClipboard(data) {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(
|
||||
JSON.stringify({
|
||||
@@ -701,13 +831,9 @@ class Render {
|
||||
}
|
||||
if (smmData) {
|
||||
this.mindMap.execCommand(
|
||||
'INSERT_CHILD_NODE',
|
||||
false,
|
||||
'INSERT_MULTI_CHILD_NODE',
|
||||
[],
|
||||
{
|
||||
...smmData.data
|
||||
},
|
||||
[...smmData.children]
|
||||
Array.isArray(smmData) ? smmData : [smmData]
|
||||
)
|
||||
} else {
|
||||
this.mindMap.execCommand('INSERT_CHILD_NODE', false, [], {
|
||||
@@ -741,86 +867,70 @@ class Render {
|
||||
|
||||
// 将节点移动到另一个节点的前面
|
||||
insertBefore(node, exist) {
|
||||
if (node.isRoot) {
|
||||
return
|
||||
}
|
||||
// 如果是二级节点变成了下级节点,或是下级节点变成了二级节点,节点样式需要更新
|
||||
let nodeLayerChanged =
|
||||
(node.layerIndex === 1 && exist.layerIndex !== 1) ||
|
||||
(node.layerIndex !== 1 && exist.layerIndex === 1)
|
||||
// 移动节点
|
||||
let nodeParent = node.parent
|
||||
let nodeBorthers = nodeParent.children
|
||||
let nodeIndex = nodeBorthers.findIndex(item => {
|
||||
return item.uid === node.uid
|
||||
})
|
||||
if (nodeIndex === -1) {
|
||||
return
|
||||
}
|
||||
nodeBorthers.splice(nodeIndex, 1)
|
||||
nodeParent.nodeData.children.splice(nodeIndex, 1)
|
||||
|
||||
// 目标节点
|
||||
let existParent = exist.parent
|
||||
let existBorthers = existParent.children
|
||||
let existIndex = existBorthers.findIndex(item => {
|
||||
return item.uid === exist.uid
|
||||
})
|
||||
if (existIndex === -1) {
|
||||
return
|
||||
}
|
||||
existBorthers.splice(existIndex, 0, node)
|
||||
existParent.nodeData.children.splice(existIndex, 0, node.nodeData)
|
||||
this.mindMap.render(() => {
|
||||
if (nodeLayerChanged) {
|
||||
node.reRender()
|
||||
}
|
||||
})
|
||||
this.insertTo(node, exist, 'before')
|
||||
}
|
||||
|
||||
// 将节点移动到另一个节点的后面
|
||||
insertAfter(node, exist) {
|
||||
if (node.isRoot) {
|
||||
return
|
||||
}
|
||||
// 如果是二级节点变成了下级节点,或是下级节点变成了二级节点,节点样式需要更新
|
||||
let nodeLayerChanged =
|
||||
(node.layerIndex === 1 && exist.layerIndex !== 1) ||
|
||||
(node.layerIndex !== 1 && exist.layerIndex === 1)
|
||||
// 移动节点
|
||||
let nodeParent = node.parent
|
||||
let nodeBorthers = nodeParent.children
|
||||
let nodeIndex = nodeBorthers.findIndex(item => {
|
||||
return item.uid === node.uid
|
||||
})
|
||||
if (nodeIndex === -1) {
|
||||
return
|
||||
}
|
||||
nodeBorthers.splice(nodeIndex, 1)
|
||||
nodeParent.nodeData.children.splice(nodeIndex, 1)
|
||||
this.insertTo(node, exist, 'after')
|
||||
}
|
||||
|
||||
// 目标节点
|
||||
let existParent = exist.parent
|
||||
let existBorthers = existParent.children
|
||||
let existIndex = existBorthers.findIndex(item => {
|
||||
return item.uid === exist.uid
|
||||
// 将节点移动到另一个节点的前面或后面
|
||||
insertTo(node, exist, dir = 'before') {
|
||||
let nodeList = formatDataToArray(node)
|
||||
nodeList = nodeList.filter(item => {
|
||||
return !item.isRoot
|
||||
})
|
||||
if (existIndex === -1) {
|
||||
return
|
||||
if (dir === 'after') {
|
||||
nodeList.reverse()
|
||||
}
|
||||
existIndex++
|
||||
existBorthers.splice(existIndex, 0, node)
|
||||
existParent.nodeData.children.splice(existIndex, 0, node.nodeData)
|
||||
this.mindMap.render(() => {
|
||||
if (nodeLayerChanged) {
|
||||
node.reRender()
|
||||
nodeList.forEach(item => {
|
||||
this.checkNodeLayerChange(item, exist)
|
||||
// 移动节点
|
||||
let nodeParent = item.parent
|
||||
let nodeBorthers = nodeParent.children
|
||||
let nodeIndex = nodeBorthers.findIndex(item2 => {
|
||||
return item.uid === item2.uid
|
||||
})
|
||||
if (nodeIndex === -1) {
|
||||
return
|
||||
}
|
||||
nodeBorthers.splice(nodeIndex, 1)
|
||||
nodeParent.nodeData.children.splice(nodeIndex, 1)
|
||||
|
||||
// 目标节点
|
||||
let existParent = exist.parent
|
||||
let existBorthers = existParent.children
|
||||
let existIndex = existBorthers.findIndex(item2 => {
|
||||
return item2.uid === exist.uid
|
||||
})
|
||||
if (existIndex === -1) {
|
||||
return
|
||||
}
|
||||
if (dir === 'after') {
|
||||
existIndex++
|
||||
}
|
||||
existBorthers.splice(existIndex, 0, item)
|
||||
existParent.nodeData.children.splice(existIndex, 0, item.nodeData)
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
// 如果是富文本模式,那么某些层级变化需要更新样式
|
||||
checkNodeLayerChange(node, toNode) {
|
||||
if (this.mindMap.richText) {
|
||||
let nodeLayerChanged =
|
||||
(node.layerIndex === 1 && toNode.layerIndex !== 1) ||
|
||||
(node.layerIndex !== 1 && toNode.layerIndex === 1)
|
||||
if (nodeLayerChanged) {
|
||||
node.nodeData.data.resetRichText = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移除节点
|
||||
removeNode(appointNodes = []) {
|
||||
appointNodes = this.formatAppointNodes(appointNodes)
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
if (this.activeNodeList.length <= 0 && appointNodes.length <= 0) {
|
||||
return
|
||||
}
|
||||
@@ -892,32 +1002,40 @@ class Render {
|
||||
|
||||
// 移除某个指定节点
|
||||
removeOneNode(node) {
|
||||
let index = this.getNodeIndex(node)
|
||||
let index = getNodeIndex(node)
|
||||
node.remove()
|
||||
node.parent.children.splice(index, 1)
|
||||
node.parent.nodeData.children.splice(index, 1)
|
||||
}
|
||||
|
||||
// 复制节点,多个节点只会操作第一个节点
|
||||
// 复制节点
|
||||
copyNode() {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
return copyNodeTree({}, this.activeNodeList[0], true)
|
||||
const nodeList = getTopAncestorsFomNodeList(this.activeNodeList)
|
||||
return nodeList.map(node => {
|
||||
return copyNodeTree({}, node, true)
|
||||
})
|
||||
}
|
||||
|
||||
// 剪切节点,多个节点只会操作第一个节点
|
||||
// 剪切节点
|
||||
cutNode(callback) {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
return
|
||||
}
|
||||
let node = this.activeNodeList[0]
|
||||
if (node.isRoot) {
|
||||
return null
|
||||
}
|
||||
let copyData = copyNodeTree({}, node, true)
|
||||
this.removeActiveNode(node)
|
||||
this.removeOneNode(node)
|
||||
const nodeList = getTopAncestorsFomNodeList(this.activeNodeList).filter(
|
||||
node => {
|
||||
return !node.isRoot
|
||||
}
|
||||
)
|
||||
const copyData = nodeList.map(node => {
|
||||
return copyNodeTree({}, node, true)
|
||||
})
|
||||
nodeList.forEach(node => {
|
||||
this.removeActiveNode(node)
|
||||
this.removeOneNode(node)
|
||||
})
|
||||
this.mindMap.emit('node_active', null, [...this.activeNodeList])
|
||||
this.mindMap.render()
|
||||
if (callback && typeof callback === 'function') {
|
||||
@@ -925,16 +1043,19 @@ class Render {
|
||||
}
|
||||
}
|
||||
|
||||
// 移动一个节点作为另一个节点的子节点
|
||||
// 移动节点作为另一个节点的子节点
|
||||
moveNodeTo(node, toNode) {
|
||||
if (node.isRoot) {
|
||||
return
|
||||
}
|
||||
// let copyData = copyNodeTree({}, node, false, true)
|
||||
this.removeActiveNode(node)
|
||||
this.removeOneNode(node)
|
||||
let nodeList = formatDataToArray(node)
|
||||
nodeList = nodeList.filter(item => {
|
||||
return !item.isRoot
|
||||
})
|
||||
nodeList.forEach(item => {
|
||||
this.checkNodeLayerChange(item, toNode)
|
||||
this.removeActiveNode(item)
|
||||
this.removeOneNode(item)
|
||||
toNode.nodeData.children.push(item.nodeData)
|
||||
})
|
||||
this.mindMap.emit('node_active', null, [...this.activeNodeList])
|
||||
toNode.nodeData.children.push(node.nodeData)
|
||||
this.mindMap.render()
|
||||
if (toNode.isRoot) {
|
||||
toNode.destroy()
|
||||
@@ -943,11 +1064,18 @@ class Render {
|
||||
|
||||
// 粘贴节点到节点
|
||||
pasteNode(data) {
|
||||
if (this.activeNodeList.length <= 0 || !data) {
|
||||
data = formatDataToArray(data)
|
||||
if (this.activeNodeList.length <= 0 || data.length <= 0) {
|
||||
return
|
||||
}
|
||||
this.activeNodeList.forEach(item => {
|
||||
item.nodeData.children.push(simpleDeepClone(data))
|
||||
this.activeNodeList.forEach(node => {
|
||||
node.nodeData.children.push(
|
||||
...data.map(item => {
|
||||
const newData = simpleDeepClone(item)
|
||||
createUidForAppointNodes([newData], true)
|
||||
return newData
|
||||
})
|
||||
)
|
||||
})
|
||||
this.mindMap.render()
|
||||
}
|
||||
@@ -1171,6 +1299,17 @@ class Render {
|
||||
})
|
||||
}
|
||||
|
||||
// 设置节点公式
|
||||
insertFormula(formula, appointNodes = []) {
|
||||
// 只在富文本模式下可用,并且需要注册Formula插件
|
||||
if (!this.mindMap.richText || !this.mindMap.formula) return
|
||||
appointNodes = formatDataToArray(appointNodes)
|
||||
const list = appointNodes.length > 0 ? appointNodes : this.activeNodeList
|
||||
list.forEach(node => {
|
||||
this.mindMap.formula.insertFormulaToNode(node, formula)
|
||||
})
|
||||
}
|
||||
|
||||
// 添加节点概要
|
||||
addGeneralization(data) {
|
||||
if (this.activeNodeList.length <= 0) {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { getStrWithBrFromHtml, checkNodeOuter } from '../../utils'
|
||||
import {
|
||||
getStrWithBrFromHtml,
|
||||
checkNodeOuter,
|
||||
focusInput,
|
||||
selectAllInput,
|
||||
htmlEscape
|
||||
} from '../../utils'
|
||||
import { ERROR_TYPES } from '../../constants/constant'
|
||||
|
||||
// 节点文字编辑类
|
||||
@@ -167,9 +173,11 @@ export default class TextEdit {
|
||||
let scale = this.mindMap.view.scale
|
||||
let lineHeight = node.style.merge('lineHeight')
|
||||
let fontSize = node.style.merge('fontSize')
|
||||
let textLines = (this.cacheEditingText || node.nodeData.data.text).split(
|
||||
/\n/gim
|
||||
)
|
||||
let textLines = (this.cacheEditingText || node.nodeData.data.text)
|
||||
.split(/\n/gim)
|
||||
.map(item => {
|
||||
return htmlEscape(item)
|
||||
})
|
||||
let isMultiLine = node._textData.node.attr('data-ismultiLine') === 'true'
|
||||
node.style.domText(this.textEditNode, scale, isMultiLine)
|
||||
this.textEditNode.style.zIndex = nodeTextEditZIndex
|
||||
@@ -188,35 +196,16 @@ export default class TextEdit {
|
||||
this.showTextEdit = true
|
||||
// 选中文本
|
||||
// if (!this.cacheEditingText) {
|
||||
// this.selectNodeText()
|
||||
// selectAllInput(this.textEditNode)
|
||||
// }
|
||||
if (isInserting || (selectTextOnEnterEditText && !isFromKeyDown)) {
|
||||
this.selectNodeText()
|
||||
selectAllInput(this.textEditNode)
|
||||
} else {
|
||||
this.focus()
|
||||
focusInput(this.textEditNode)
|
||||
}
|
||||
this.cacheEditingText = ''
|
||||
}
|
||||
|
||||
// 聚焦
|
||||
focus() {
|
||||
let selection = window.getSelection()
|
||||
let range = document.createRange()
|
||||
range.selectNodeContents(this.textEditNode)
|
||||
range.collapse()
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
}
|
||||
|
||||
// 选中文本
|
||||
selectNodeText() {
|
||||
let selection = window.getSelection()
|
||||
let range = document.createRange()
|
||||
range.selectNodeContents(this.textEditNode)
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
}
|
||||
|
||||
// 获取当前正在编辑的内容
|
||||
getEditText() {
|
||||
return getStrWithBrFromHtml(this.textEditNode.innerHTML)
|
||||
|
||||
@@ -6,6 +6,7 @@ import nodeExpandBtnMethods from './nodeExpandBtn'
|
||||
import nodeCommandWrapsMethods from './nodeCommandWraps'
|
||||
import nodeCreateContentsMethods from './nodeCreateContents'
|
||||
import nodeExpandBtnPlaceholderRectMethods from './nodeExpandBtnPlaceholderRect'
|
||||
import nodeCooperateMethods from './nodeCooperate'
|
||||
import { CONSTANTS } from '../../../constants/constant'
|
||||
|
||||
// 节点类
|
||||
@@ -14,7 +15,7 @@ class Node {
|
||||
constructor(opt = {}) {
|
||||
// 节点数据
|
||||
this.nodeData = this.handleData(opt.data || {})
|
||||
// id
|
||||
// uid
|
||||
this.uid = opt.uid
|
||||
// 控制实例
|
||||
this.mindMap = opt.mindMap
|
||||
@@ -55,6 +56,8 @@ class Node {
|
||||
this.parent = opt.parent || null
|
||||
// 子节点
|
||||
this.children = opt.children || []
|
||||
// 当前同时操作该节点的用户列表
|
||||
this.userList = []
|
||||
// 节点内容的容器
|
||||
this.group = null
|
||||
this.shapeNode = null // 节点形状节点
|
||||
@@ -74,6 +77,7 @@ class Node {
|
||||
this._openExpandNode = null
|
||||
this._closeExpandNode = null
|
||||
this._fillExpandNode = null
|
||||
this._userListGroup = null
|
||||
this._lines = []
|
||||
this._generalizationLine = null
|
||||
this._generalizationNode = null
|
||||
@@ -121,6 +125,12 @@ class Node {
|
||||
Object.keys(nodeCreateContentsMethods).forEach(item => {
|
||||
this[item] = nodeCreateContentsMethods[item].bind(this)
|
||||
})
|
||||
// 协同相关
|
||||
if (this.mindMap.cooperate) {
|
||||
Object.keys(nodeCooperateMethods).forEach((item) => {
|
||||
this[item] = nodeCooperateMethods[item].bind(this)
|
||||
})
|
||||
}
|
||||
// 初始化
|
||||
this.getSize()
|
||||
}
|
||||
@@ -283,6 +293,8 @@ class Node {
|
||||
this.group.add(this.shapeNode)
|
||||
// 渲染一个隐藏的矩形区域,用来触发展开收起按钮的显示
|
||||
this.renderExpandBtnPlaceholderRect()
|
||||
// 创建协同头像节点
|
||||
if (this.createUserListNode) this.createUserListNode()
|
||||
// 概要节点添加一个带所属节点id的类名
|
||||
if (this.isGeneralization && this.generalizationBelongNode) {
|
||||
this.group.addClass('generalization_' + this.generalizationBelongNode.uid)
|
||||
@@ -440,12 +452,14 @@ class Node {
|
||||
this.mindMap.emit('node_mouseup', this, e)
|
||||
})
|
||||
this.group.on('mouseenter', e => {
|
||||
if (this.isDrag) return
|
||||
this._isMouseenter = true
|
||||
// 显示展开收起按钮
|
||||
this.showExpandBtn()
|
||||
this.mindMap.emit('node_mouseenter', this, e)
|
||||
})
|
||||
this.group.on('mouseleave', e => {
|
||||
if (!this._isMouseenter) return
|
||||
this._isMouseenter = false
|
||||
this.hideExpandBtn()
|
||||
this.mindMap.emit('node_mouseleave', this, e)
|
||||
@@ -525,6 +539,8 @@ class Node {
|
||||
}
|
||||
// 更新概要
|
||||
this.renderGeneralization()
|
||||
// 更新协同头像
|
||||
if (this.updateUserListNode) this.updateUserListNode()
|
||||
// 更新节点位置
|
||||
let t = this.group.transform()
|
||||
// // 如果上次不在可视区内,且本次也不在,那么直接返回
|
||||
@@ -701,6 +717,61 @@ class Node {
|
||||
}
|
||||
}
|
||||
|
||||
// 设置节点透明度
|
||||
// 包括连接线和下级节点
|
||||
setOpacity(val) {
|
||||
// 自身及连线
|
||||
this.group.opacity(val)
|
||||
this._lines.forEach(line => {
|
||||
line.opacity(val)
|
||||
})
|
||||
// 子节点
|
||||
this.children.forEach(item => {
|
||||
item.setOpacity(val)
|
||||
})
|
||||
// 概要节点
|
||||
if (this._generalizationNode) {
|
||||
this._generalizationLine.opacity(val)
|
||||
this._generalizationNode.group.opacity(val)
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏子节点
|
||||
hideChildren() {
|
||||
this._lines.forEach(item => {
|
||||
item.hide()
|
||||
})
|
||||
if (this.children && this.children.length) {
|
||||
this.children.forEach(item => {
|
||||
item.hide()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 显示子节点
|
||||
showChildren() {
|
||||
this._lines.forEach(item => {
|
||||
item.show()
|
||||
})
|
||||
if (this.children && this.children.length) {
|
||||
this.children.forEach(item => {
|
||||
item.show()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 被拖拽中
|
||||
startDrag() {
|
||||
this.isDrag = true
|
||||
this.group.addClass('smm-node-dragging')
|
||||
}
|
||||
|
||||
// 拖拽结束
|
||||
endDrag() {
|
||||
this.isDrag = false
|
||||
this.group.removeClass('smm-node-dragging')
|
||||
}
|
||||
|
||||
// 连线
|
||||
renderLine(deep = false) {
|
||||
if (this.nodeData.data.expand === false) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { tagColorList } from '../../../constants/constant'
|
||||
import { checkIsNodeStyleDataKey } from '../../../utils/index'
|
||||
import {
|
||||
checkIsNodeStyleDataKey,
|
||||
generateColorByContent
|
||||
} from '../../../utils/index'
|
||||
|
||||
const rootProp = ['paddingX', 'paddingY']
|
||||
const backgroundStyleProps = [
|
||||
@@ -163,10 +165,10 @@ class Style {
|
||||
}
|
||||
|
||||
// 标签文字
|
||||
tagText(node, index) {
|
||||
tagText(node) {
|
||||
node
|
||||
.fill({
|
||||
color: tagColorList[index].color
|
||||
color: '#fff'
|
||||
})
|
||||
.css({
|
||||
'font-size': '12px'
|
||||
@@ -174,9 +176,9 @@ class Style {
|
||||
}
|
||||
|
||||
// 标签矩形
|
||||
tagRect(node, index) {
|
||||
tagRect(node, text, color) {
|
||||
node.fill({
|
||||
color: tagColorList[index].background
|
||||
color: color || generateColorByContent(text.node.textContent)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
104
simple-mind-map/src/core/render/node/nodeCooperate.js
Normal file
104
simple-mind-map/src/core/render/node/nodeCooperate.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import { Circle, G, Text, Image } from '@svgdotjs/svg.js'
|
||||
import { generateColorByContent } from '../../../utils/index'
|
||||
|
||||
// 协同相关功能
|
||||
|
||||
// 创建容器
|
||||
function createUserListNode() {
|
||||
// 如果没有注册协作插件,那么需要创建
|
||||
if (!this.mindMap.cooperate) return
|
||||
this._userListGroup = new G()
|
||||
this.group.add(this._userListGroup)
|
||||
}
|
||||
|
||||
// 创建文本头像
|
||||
function createTextAvatar(item) {
|
||||
const { avatarSize, fontSize } = this.mindMap.opt.cooperateStyle
|
||||
const g = new G()
|
||||
const str = item.isMore ? item.name : String(item.name)[0]
|
||||
// 圆
|
||||
const circle = new Circle().size(avatarSize, avatarSize)
|
||||
circle.fill({
|
||||
color: item.color || generateColorByContent(str)
|
||||
})
|
||||
// 文本
|
||||
const text = new Text()
|
||||
.text(str)
|
||||
.fill({
|
||||
color: '#fff'
|
||||
})
|
||||
.css({
|
||||
'font-size': fontSize
|
||||
})
|
||||
.dx(-fontSize / 2)
|
||||
.dy((avatarSize - fontSize) / 2)
|
||||
g.add(circle).add(text)
|
||||
return g
|
||||
}
|
||||
|
||||
// 创建图片头像
|
||||
function createImageAvatar(item) {
|
||||
const { avatarSize } = this.mindMap.opt.cooperateStyle
|
||||
return new Image().load(item.avatar).size(avatarSize, avatarSize)
|
||||
}
|
||||
|
||||
// 更新渲染
|
||||
function updateUserListNode() {
|
||||
if (!this._userListGroup) return
|
||||
const { avatarSize } = this.mindMap.opt.cooperateStyle
|
||||
this._userListGroup.clear()
|
||||
// 根据当前节点长度计算最多能显示几个
|
||||
const length = this.userList.length
|
||||
const maxShowCount = Math.floor(this.width / avatarSize)
|
||||
const list = []
|
||||
if (length > maxShowCount) {
|
||||
// 如果当前用户数量比最多能显示的多,最后需要显示一个提示信息
|
||||
list.push(...this.userList.slice(0, maxShowCount - 1), {
|
||||
isMore: true,
|
||||
name: '+' + (length - maxShowCount + 1)
|
||||
})
|
||||
} else {
|
||||
list.push(...this.userList)
|
||||
}
|
||||
list.forEach((item, index) => {
|
||||
let node = null
|
||||
if (item.avatar) {
|
||||
node = this.createImageAvatar(item)
|
||||
} else {
|
||||
node = this.createTextAvatar(item)
|
||||
}
|
||||
node.x(index * avatarSize).cy(-avatarSize / 2)
|
||||
this._userListGroup.add(node)
|
||||
})
|
||||
}
|
||||
|
||||
// 添加用户
|
||||
function addUser(userInfo) {
|
||||
if (
|
||||
this.userList.find(item => {
|
||||
return item.id == userInfo.id
|
||||
})
|
||||
)
|
||||
return
|
||||
this.userList.push(userInfo)
|
||||
this.updateUserListNode()
|
||||
}
|
||||
|
||||
// 移除用户
|
||||
function removeUser(userInfo) {
|
||||
const index = this.userList.findIndex(item => {
|
||||
return item.id == userInfo.id
|
||||
})
|
||||
if (index === -1) return
|
||||
this.userList.splice(index, 1)
|
||||
this.updateUserListNode()
|
||||
}
|
||||
|
||||
export default {
|
||||
createUserListNode,
|
||||
updateUserListNode,
|
||||
createTextAvatar,
|
||||
createImageAvatar,
|
||||
addUser,
|
||||
removeUser
|
||||
}
|
||||
@@ -3,7 +3,8 @@ import {
|
||||
resizeImgSize,
|
||||
removeHtmlStyle,
|
||||
addHtmlStyle,
|
||||
checkIsRichText
|
||||
checkIsRichText,
|
||||
isUndef
|
||||
} from '../../../utils'
|
||||
import { Image, SVG, A, G, Rect, Text, ForeignObject } from '@svgdotjs/svg.js'
|
||||
import iconsSvg from '../../../svg/icons'
|
||||
@@ -164,7 +165,10 @@ function createTextNode() {
|
||||
let lineHeight = this.getStyle('lineHeight', false)
|
||||
// 文本超长自动换行
|
||||
let textStyle = this.style.getTextFontStyle()
|
||||
let textArr = this.nodeData.data.text.split(/\n/gim)
|
||||
let textArr = []
|
||||
if (!isUndef(this.nodeData.data.text)) {
|
||||
textArr = String(this.nodeData.data.text).split(/\n/gim)
|
||||
}
|
||||
let maxWidth = this.mindMap.opt.textAutoWrapWidth
|
||||
let isMultiLine = false
|
||||
textArr.forEach((item, index) => {
|
||||
@@ -249,12 +253,15 @@ function createTagNode() {
|
||||
tagData.slice(0, this.mindMap.opt.maxTag).forEach((item, index) => {
|
||||
let tag = new G()
|
||||
// 标签文本
|
||||
let text = new Text().text(item).x(8).cy(10)
|
||||
let text = new Text().text(item).x(8).cy(8)
|
||||
this.style.tagText(text, index)
|
||||
let { width } = text.bbox()
|
||||
// 标签矩形
|
||||
let rect = new Rect().size(width + 16, 20)
|
||||
this.style.tagRect(rect, index)
|
||||
// 先从自定义的颜色中获取颜色,没有的话就按照内容生成
|
||||
const tagsColorList = this.mindMap.opt.tagsColorMap || {}
|
||||
const color = tagsColorList[text.node.textContent]
|
||||
this.style.tagRect(rect, text, color)
|
||||
tag.add(rect).add(text)
|
||||
nodes.push({
|
||||
node: tag,
|
||||
|
||||
@@ -136,6 +136,7 @@ function renderExpandBtn() {
|
||||
this._expandBtn.on('dblclick', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
this._expandBtn.addClass('smm-expand-btn')
|
||||
this.group.add(this._expandBtn)
|
||||
}
|
||||
this._showExpandBtn = true
|
||||
|
||||
@@ -129,6 +129,10 @@ class Base {
|
||||
this.renderer.addActiveNode(newNode)
|
||||
}
|
||||
}
|
||||
// 如果当前节点在激活节点列表里,那么添加上激活的状态
|
||||
if (this.mindMap.renderer.findActiveNodeIndex(newNode) !== -1) {
|
||||
newNode.nodeData.data.isActive = true
|
||||
}
|
||||
// 根节点
|
||||
if (isRoot) {
|
||||
newNode.isRoot = true
|
||||
|
||||
@@ -149,8 +149,8 @@ class AssociativeLine {
|
||||
) {
|
||||
nodeToIds.set(cur, data.associativeLineTargets)
|
||||
}
|
||||
if (data.id) {
|
||||
idToNode.set(data.id, cur)
|
||||
if (data.uid) {
|
||||
idToNode.set(data.uid, cur)
|
||||
}
|
||||
},
|
||||
() => {},
|
||||
@@ -158,8 +158,8 @@ class AssociativeLine {
|
||||
0
|
||||
)
|
||||
nodeToIds.forEach((ids, node) => {
|
||||
ids.forEach((id, index) => {
|
||||
let toNode = idToNode.get(id)
|
||||
ids.forEach((uid, index) => {
|
||||
let toNode = idToNode.get(uid)
|
||||
if (!node || !toNode) return
|
||||
const associativeLinePoint = (node.nodeData.data.associativeLinePoint ||
|
||||
[])[index]
|
||||
@@ -234,6 +234,11 @@ class AssociativeLine {
|
||||
controlPoints
|
||||
})
|
||||
})
|
||||
// 双击进入关联线文本编辑状态
|
||||
clickPath.dblclick(() => {
|
||||
if (!this.activeLine) return
|
||||
this.showEditTextBox(text)
|
||||
})
|
||||
// 渲染关联线文字
|
||||
this.renderText(this.getText(node, toNode), path, text)
|
||||
this.lineList.push([path, clickPath, text, node, toNode])
|
||||
@@ -252,28 +257,25 @@ class AssociativeLine {
|
||||
}) {
|
||||
let { associativeLineActiveColor } = this.mindMap.themeConfig
|
||||
// 如果当前存在激活节点,那么取消激活节点
|
||||
if (this.mindMap.renderer.activeNodeList.length > 0) {
|
||||
this.clearActiveNodes()
|
||||
} else {
|
||||
// 否则清除当前的关联线的激活状态,如果有的话
|
||||
this.clearActiveLine()
|
||||
// 保存当前激活的关联线信息
|
||||
this.activeLine = [path, clickPath, text, node, toNode]
|
||||
// 让不可见的点击线显示
|
||||
clickPath.stroke({ color: associativeLineActiveColor })
|
||||
// 如果没有输入过关联线文字,那么显示默认文字
|
||||
if (!this.getText(node, toNode)) {
|
||||
this.renderText(this.mindMap.opt.defaultAssociativeLineText, path, text)
|
||||
}
|
||||
// 渲染控制点和连线
|
||||
this.renderControls(
|
||||
startPoint,
|
||||
endPoint,
|
||||
controlPoints[0],
|
||||
controlPoints[1]
|
||||
)
|
||||
this.mindMap.emit('associative_line_click', path, clickPath, node, toNode)
|
||||
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
|
||||
// 否则清除当前的关联线的激活状态,如果有的话
|
||||
this.clearActiveLine()
|
||||
// 保存当前激活的关联线信息
|
||||
this.activeLine = [path, clickPath, text, node, toNode]
|
||||
// 让不可见的点击线显示
|
||||
clickPath.stroke({ color: associativeLineActiveColor })
|
||||
// 如果没有输入过关联线文字,那么显示默认文字
|
||||
if (!this.getText(node, toNode)) {
|
||||
this.renderText(this.mindMap.opt.defaultAssociativeLineText, path, text)
|
||||
}
|
||||
// 渲染控制点和连线
|
||||
this.renderControls(
|
||||
startPoint,
|
||||
endPoint,
|
||||
controlPoints[0],
|
||||
controlPoints[1]
|
||||
)
|
||||
this.mindMap.emit('associative_line_click', path, clickPath, node, toNode)
|
||||
}
|
||||
|
||||
// 移除所有连接线
|
||||
@@ -395,21 +397,21 @@ class AssociativeLine {
|
||||
addLine(fromNode, toNode) {
|
||||
if (!fromNode || !toNode) return
|
||||
// 目标节点如果没有id,则生成一个id
|
||||
let id = toNode.nodeData.data.id
|
||||
if (!id) {
|
||||
id = uuid()
|
||||
let uid = toNode.nodeData.data.uid
|
||||
if (!uid) {
|
||||
uid = uuid()
|
||||
this.mindMap.execCommand('SET_NODE_DATA', toNode, {
|
||||
id
|
||||
uid
|
||||
})
|
||||
}
|
||||
// 将目标节点id保存起来
|
||||
let list = fromNode.nodeData.data.associativeLineTargets || []
|
||||
// 连线节点是否存在相同的id,存在则阻止添加关联线
|
||||
const sameLine = list.some(item => item === id)
|
||||
const sameLine = list.some(item => item === uid)
|
||||
if (sameLine) {
|
||||
return
|
||||
}
|
||||
list.push(id)
|
||||
list.push(uid)
|
||||
// 保存控制点
|
||||
let [startPoint, endPoint] = computeNodePoints(fromNode, toNode)
|
||||
let controlPoints = computeCubicBezierPathPoints(
|
||||
@@ -458,7 +460,7 @@ class AssociativeLine {
|
||||
let newAssociativeLineText = {}
|
||||
if (associativeLineText) {
|
||||
Object.keys(associativeLineText).forEach(item => {
|
||||
if (item !== toNode.nodeData.data.id) {
|
||||
if (item !== toNode.nodeData.data.uid) {
|
||||
newAssociativeLineText[item] = associativeLineText[item]
|
||||
}
|
||||
})
|
||||
@@ -483,13 +485,6 @@ class AssociativeLine {
|
||||
})
|
||||
}
|
||||
|
||||
// 清除当前激活的节点
|
||||
clearActiveNodes() {
|
||||
if (this.mindMap.renderer.activeNodeList.length > 0) {
|
||||
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
|
||||
}
|
||||
}
|
||||
|
||||
// 清除激活的线
|
||||
clearActiveLine() {
|
||||
if (this.activeLine) {
|
||||
|
||||
322
simple-mind-map/src/plugins/Cooperate.js
Normal file
322
simple-mind-map/src/plugins/Cooperate.js
Normal file
@@ -0,0 +1,322 @@
|
||||
import * as Y from 'yjs'
|
||||
import { WebrtcProvider } from 'y-webrtc'
|
||||
import { isSameObject, simpleDeepClone, getType, isUndef } from '../utils/index'
|
||||
|
||||
// 协同插件
|
||||
class Cooperate {
|
||||
constructor(opt) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
// yjs文档
|
||||
this.ydoc = new Y.Doc()
|
||||
// 共享数据
|
||||
this.ymap = null
|
||||
// 连接提供者
|
||||
this.provider = null
|
||||
// 感知数据
|
||||
this.awareness = null
|
||||
this.currentAwarenessData = []
|
||||
// 当前的平级对象类型的思维导图数据
|
||||
this.currentData = null
|
||||
// 用户信息
|
||||
this.userInfo = null
|
||||
// 绑定事件
|
||||
this.bindEvent()
|
||||
// 处理实例化时传入的思维导图数据
|
||||
if (this.mindMap.opt.data) {
|
||||
this.initData(this.mindMap.opt.data)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
initData(data) {
|
||||
data = simpleDeepClone(data)
|
||||
// 解绑原来的数据
|
||||
if (this.ymap) {
|
||||
this.ymap.unobserve(this.onObserve)
|
||||
}
|
||||
// 创建共享数据
|
||||
this.ymap = this.ydoc.getMap()
|
||||
// 思维导图树结构转平级对象结构
|
||||
this.currentData = this.transformTreeDataToObject(data)
|
||||
// 将思维导图数据添加到共享数据中
|
||||
Object.keys(this.currentData).forEach(uid => {
|
||||
this.ymap.set(uid, this.currentData[uid])
|
||||
})
|
||||
// 监听数据同步
|
||||
this.onObserve = this.onObserve.bind(this)
|
||||
this.ymap.observe(this.onObserve)
|
||||
}
|
||||
|
||||
// 获取yjs doc实例
|
||||
getDoc() {
|
||||
return this.ydoc
|
||||
}
|
||||
|
||||
// 设置连接提供者
|
||||
setProvider(provider, webrtcProviderConfig = {}) {
|
||||
const { roomName, signalingList, ...otherConfig } = webrtcProviderConfig
|
||||
this.provider =
|
||||
provider ||
|
||||
new WebrtcProvider(roomName, this.ydoc, {
|
||||
signaling: signalingList,
|
||||
...otherConfig
|
||||
})
|
||||
this.awareness = this.provider.awareness
|
||||
|
||||
// 监听状态同步事件
|
||||
this.onAwareness = this.onAwareness.bind(this)
|
||||
this.awareness.on('change', this.onAwareness)
|
||||
}
|
||||
|
||||
// 绑定事件
|
||||
bindEvent() {
|
||||
// 监听思维导图改变
|
||||
this.onDataChange = this.onDataChange.bind(this)
|
||||
this.mindMap.on('data_change', this.onDataChange)
|
||||
|
||||
// 监听思维导图节点激活事件
|
||||
this.onNodeActive = this.onNodeActive.bind(this)
|
||||
this.mindMap.on('node_active', this.onNodeActive)
|
||||
|
||||
// 监听设置思维导图数据事件
|
||||
this.initData = this.initData.bind(this)
|
||||
this.mindMap.on('set_data', this.initData)
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
unBindEvent() {
|
||||
if (this.ymap) {
|
||||
this.ymap.unobserve(this.onObserve)
|
||||
}
|
||||
this.mindMap.off('data_change', this.onDataChange)
|
||||
this.mindMap.off('node_active', this.onNodeActive)
|
||||
this.mindMap.off('set_data', this.initData)
|
||||
this.ydoc.destroy()
|
||||
}
|
||||
|
||||
// 数据同步时的处理,更新当前思维导图
|
||||
onObserve(event) {
|
||||
const data = event.target.toJSON()
|
||||
// 如果数据没有改变直接返回
|
||||
if (isSameObject(data, this.currentData)) return
|
||||
this.currentData = data
|
||||
// 平级对象转树结构
|
||||
const res = this.transformObjectToTreeData(data)
|
||||
if (!res) return
|
||||
// 更新思维导图画布
|
||||
this.mindMap.renderer.setData(res)
|
||||
this.mindMap.render()
|
||||
this.mindMap.command.addHistory()
|
||||
}
|
||||
|
||||
// 当前思维导图改变后的处理,触发同步
|
||||
onDataChange(data) {
|
||||
const res = this.transformTreeDataToObject(data)
|
||||
this.updateChanges(res)
|
||||
}
|
||||
|
||||
// 找出更新点
|
||||
updateChanges(data) {
|
||||
const oldData = this.currentData
|
||||
this.currentData = data
|
||||
this.ydoc.transact(() => {
|
||||
// 找出新增的或修改的
|
||||
Object.keys(data).forEach(uid => {
|
||||
// 新增的或已经存在的,如果数据发生了改变
|
||||
if (!oldData[uid] || !isSameObject(oldData[uid], data[uid])) {
|
||||
this.ymap.set(uid, data[uid])
|
||||
}
|
||||
})
|
||||
// 找出删除的
|
||||
Object.keys(oldData).forEach(uid => {
|
||||
if (!data[uid]) {
|
||||
this.ymap.delete(uid)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 节点激活状态改变后触发感知数据同步
|
||||
onNodeActive(node, nodeList) {
|
||||
if (this.userInfo) {
|
||||
this.awareness.setLocalStateField(this.userInfo.name, {
|
||||
// 用户信息
|
||||
userInfo: {
|
||||
...this.userInfo
|
||||
},
|
||||
// 当前激活的节点id列表
|
||||
nodeIdList: nodeList.map(item => {
|
||||
return item.uid
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 设置用户信息
|
||||
/**
|
||||
* {
|
||||
* id: '', // 必传,用户唯一的id
|
||||
* name: '', // 用户名称。name和avatar两个只传一个即可,如果都传了,会显示avatar
|
||||
* avatar: '', // 用户头像
|
||||
* color: '' // 如果没有传头像,那么会以一个圆形来显示名称的第一个字,文字的颜色为白色,圆的颜色可以通过该字段设置
|
||||
* }
|
||||
**/
|
||||
setUserInfo(userInfo) {
|
||||
if (
|
||||
getType(userInfo) !== 'Object' ||
|
||||
isUndef(userInfo.id) ||
|
||||
(isUndef(userInfo.name) && isUndef(userInfo.avatar))
|
||||
)
|
||||
return
|
||||
this.userInfo = userInfo || null
|
||||
}
|
||||
|
||||
// 监听感知数据同步事件
|
||||
onAwareness() {
|
||||
const walk = (list, callback) => {
|
||||
list.forEach(value => {
|
||||
const userName = Object.keys(value)[0]
|
||||
if (!userName) return
|
||||
const data = value[userName]
|
||||
const userInfo = data.userInfo
|
||||
const nodeIdList = data.nodeIdList
|
||||
nodeIdList.forEach(uid => {
|
||||
const node = this.mindMap.renderer.findNodeByUid(uid)
|
||||
if (node) {
|
||||
callback(node, userInfo)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 清除之前的数据
|
||||
walk(this.currentAwarenessData, (node, userInfo) => {
|
||||
node.removeUser(userInfo)
|
||||
})
|
||||
// 设置当前数据
|
||||
const data = Array.from(this.awareness.getStates().values())
|
||||
this.currentAwarenessData = data
|
||||
walk(data, (node, userInfo) => {
|
||||
// 不显示自己
|
||||
if (userInfo.id === this.userInfo.id) return
|
||||
node.addUser(userInfo)
|
||||
})
|
||||
}
|
||||
|
||||
// 将树结构转平级对象
|
||||
/*
|
||||
{
|
||||
data: {
|
||||
uid: 'xxx'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
data: {
|
||||
uid: 'xxx'
|
||||
},
|
||||
children: []
|
||||
}
|
||||
]
|
||||
}
|
||||
转为:
|
||||
{
|
||||
uid: {
|
||||
children: [uid1, uid2],
|
||||
data: {}
|
||||
}
|
||||
}
|
||||
*/
|
||||
transformTreeDataToObject(data) {
|
||||
const res = {}
|
||||
const walk = (root, parent) => {
|
||||
const uid = root.data.uid
|
||||
if (parent) {
|
||||
parent.children.push(uid)
|
||||
}
|
||||
res[uid] = {
|
||||
isRoot: !parent,
|
||||
data: {
|
||||
...root.data
|
||||
},
|
||||
children: []
|
||||
}
|
||||
if (root.children && root.children.length > 0) {
|
||||
root.children.forEach(item => {
|
||||
walk(item, res[uid])
|
||||
})
|
||||
}
|
||||
}
|
||||
walk(data, null)
|
||||
return res
|
||||
}
|
||||
|
||||
// 找到父节点的uid
|
||||
findParentUid(data, targetUid) {
|
||||
const uids = Object.keys(data)
|
||||
let res = ''
|
||||
uids.forEach(uid => {
|
||||
const children = data[uid].children
|
||||
const isParent =
|
||||
children.findIndex(childUid => {
|
||||
return childUid === targetUid
|
||||
}) !== -1
|
||||
if (isParent) {
|
||||
res = uid
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// 将平级对象转树结构
|
||||
transformObjectToTreeData(data) {
|
||||
const uids = Object.keys(data)
|
||||
if (uids.length <= 0) return null
|
||||
const rootKey = uids.find(uid => {
|
||||
return data[uid].isRoot
|
||||
})
|
||||
if (!rootKey || !data[rootKey]) return null
|
||||
// 根节点
|
||||
const res = {
|
||||
data: simpleDeepClone(data[rootKey].data),
|
||||
children: []
|
||||
}
|
||||
const map = {}
|
||||
map[rootKey] = res
|
||||
uids.forEach(uid => {
|
||||
const parentUid = this.findParentUid(data, uid)
|
||||
const cur = data[uid]
|
||||
const node = map[uid] || {
|
||||
data: simpleDeepClone(cur.data),
|
||||
children: []
|
||||
}
|
||||
if (!map[uid]) {
|
||||
map[uid] = node
|
||||
}
|
||||
if (parentUid) {
|
||||
if (map[parentUid]) {
|
||||
map[parentUid].children.push(node)
|
||||
} else {
|
||||
map[parentUid] = {
|
||||
data: simpleDeepClone(data[parentUid].data),
|
||||
children: [node]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.unBindEvent()
|
||||
}
|
||||
}
|
||||
|
||||
Cooperate.instanceName = 'cooperate'
|
||||
|
||||
export default Cooperate
|
||||
@@ -1,4 +1,4 @@
|
||||
import { bfsWalk, throttle } from '../utils'
|
||||
import { bfsWalk, throttle, getTopAncestorsFomNodeList } from '../utils'
|
||||
import Base from '../layouts/Base'
|
||||
|
||||
// 节点拖动插件
|
||||
@@ -13,10 +13,14 @@ class Drag extends Base {
|
||||
|
||||
// 复位
|
||||
reset() {
|
||||
// 是否正在跳转中
|
||||
this.isDragging = false
|
||||
// 鼠标按下的节点
|
||||
this.mousedownNode = null
|
||||
// 被拖拽中的节点列表
|
||||
this.beingDragNodeList = []
|
||||
// 当前画布节点列表
|
||||
this.nodeList = []
|
||||
// 当前拖拽节点
|
||||
this.node = null
|
||||
// 当前重叠节点
|
||||
this.overlapNode = null
|
||||
// 当前上一个同级节点
|
||||
@@ -27,16 +31,11 @@ class Drag extends Base {
|
||||
this.drawTransform = null
|
||||
// 克隆节点
|
||||
this.clone = null
|
||||
// 连接线
|
||||
this.line = null
|
||||
// 同级位置占位符
|
||||
this.placeholder = null
|
||||
// 鼠标按下位置和节点左上角的偏移量
|
||||
this.offsetX = 0
|
||||
this.offsetY = 0
|
||||
// 克隆节点左上角的坐标
|
||||
this.cloneNodeLeft = 0
|
||||
this.cloneNodeTop = 0
|
||||
// 当前鼠标是否按下
|
||||
this.isMousedown = false
|
||||
// 拖拽的鼠标位置变量
|
||||
@@ -53,45 +52,42 @@ class Drag extends Base {
|
||||
bindEvent() {
|
||||
this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this)
|
||||
this.mindMap.on('node_mousedown', (node, e) => {
|
||||
if (this.mindMap.opt.readonly || node.isGeneralization) {
|
||||
return
|
||||
}
|
||||
if (e.which !== 1 || node.isRoot) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
// 计算鼠标按下的位置距离节点左上角的距离
|
||||
this.drawTransform = this.mindMap.draw.transform()
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.offsetX = x - (node.left * scaleX + translateX)
|
||||
this.offsetY = y - (node.top * scaleY + translateY)
|
||||
this.node = node
|
||||
this.isMousedown = true
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
this.nodeTreeToList()
|
||||
})
|
||||
this.mindMap.on('mousemove', e => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
this.mindMap.emit('node_dragging', this.node)
|
||||
e.preventDefault()
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseMoveX = x
|
||||
this.mouseMoveY = y
|
||||
// 只读模式、不是鼠标左键按下、按下的是概要节点或根节点直接返回
|
||||
if (
|
||||
Math.abs(x - this.mouseDownX) <= this.checkDragOffset &&
|
||||
Math.abs(y - this.mouseDownY) <= this.checkDragOffset &&
|
||||
!this.node.isDrag
|
||||
this.mindMap.opt.readonly ||
|
||||
e.which !== 1 ||
|
||||
node.isGeneralization ||
|
||||
node.isRoot
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.mindMap.renderer.clearAllActive()
|
||||
e.preventDefault()
|
||||
this.isMousedown = true
|
||||
// 记录鼠标按下时的节点
|
||||
this.mousedownNode = node
|
||||
// 记录鼠标按下的坐标
|
||||
const { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
})
|
||||
this.mindMap.on('mousemove', e => {
|
||||
if (this.mindMap.opt.readonly || !this.isMousedown) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
const { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseMoveX = x
|
||||
this.mouseMoveY = y
|
||||
// 还没开始移动时鼠标位移过小不认为是拖拽
|
||||
if (
|
||||
!this.isDragging &&
|
||||
Math.abs(x - this.mouseDownX) <= this.checkDragOffset &&
|
||||
Math.abs(y - this.mouseDownY) <= this.checkDragOffset
|
||||
) {
|
||||
return
|
||||
}
|
||||
this.mindMap.emit('node_dragging')
|
||||
this.handleStartMove()
|
||||
this.onMove(x, y, e)
|
||||
})
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
@@ -105,9 +101,12 @@ class Drag extends Base {
|
||||
return
|
||||
}
|
||||
this.isMousedown = false
|
||||
let _nodeIsDrag = this.node.isDrag
|
||||
this.node.isDrag = false
|
||||
this.node.show()
|
||||
// 恢复被拖拽节点的临时设置
|
||||
this.beingDragNodeList.forEach(node => {
|
||||
node.setOpacity(1)
|
||||
node.showChildren()
|
||||
node.endDrag()
|
||||
})
|
||||
this.removeCloneNode()
|
||||
let overlapNodeUid = this.overlapNode
|
||||
? this.overlapNode.nodeData.data.uid
|
||||
@@ -117,17 +116,33 @@ class Drag extends Base {
|
||||
// 存在重叠子节点,则移动作为其子节点
|
||||
if (this.overlapNode) {
|
||||
this.mindMap.renderer.setNodeActive(this.overlapNode, false)
|
||||
this.mindMap.execCommand('MOVE_NODE_TO', this.node, this.overlapNode)
|
||||
this.mindMap.execCommand(
|
||||
'MOVE_NODE_TO',
|
||||
this.beingDragNodeList,
|
||||
this.overlapNode
|
||||
)
|
||||
} else if (this.prevNode) {
|
||||
// 存在前一个相邻节点,作为其下一个兄弟节点
|
||||
this.mindMap.renderer.setNodeActive(this.prevNode, false)
|
||||
this.mindMap.execCommand('INSERT_AFTER', this.node, this.prevNode)
|
||||
this.mindMap.execCommand(
|
||||
'INSERT_AFTER',
|
||||
this.beingDragNodeList,
|
||||
this.prevNode
|
||||
)
|
||||
} else if (this.nextNode) {
|
||||
// 存在下一个相邻节点,作为其前一个兄弟节点
|
||||
this.mindMap.renderer.setNodeActive(this.nextNode, false)
|
||||
this.mindMap.execCommand('INSERT_BEFORE', this.node, this.nextNode)
|
||||
} else if (_nodeIsDrag && this.mindMap.opt.enableFreeDrag) {
|
||||
// 自定义位置
|
||||
this.mindMap.execCommand(
|
||||
'INSERT_BEFORE',
|
||||
this.beingDragNodeList,
|
||||
this.nextNode
|
||||
)
|
||||
} else if (
|
||||
this.clone &&
|
||||
this.mindMap.opt.enableFreeDrag &&
|
||||
this.beingDragNodeList.length === 1
|
||||
) {
|
||||
// 如果只拖拽了一个节点,那么设置自定义位置
|
||||
let { x, y } = this.mindMap.toPos(
|
||||
e.clientX - this.offsetX,
|
||||
e.clientY - this.offsetY
|
||||
@@ -135,11 +150,16 @@ class Drag extends Base {
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
x = (x - translateX) / scaleX
|
||||
y = (y - translateY) / scaleY
|
||||
this.node.left = x
|
||||
this.node.top = y
|
||||
this.node.customLeft = x
|
||||
this.node.customTop = y
|
||||
this.mindMap.execCommand('SET_NODE_CUSTOM_POSITION', this.node, x, y)
|
||||
this.mousedownNode.left = x
|
||||
this.mousedownNode.top = y
|
||||
this.mousedownNode.customLeft = x
|
||||
this.mousedownNode.customTop = y
|
||||
this.mindMap.execCommand(
|
||||
'SET_NODE_CUSTOM_POSITION',
|
||||
this.mousedownNode,
|
||||
x,
|
||||
y
|
||||
)
|
||||
this.mindMap.render()
|
||||
}
|
||||
this.reset()
|
||||
@@ -150,24 +170,131 @@ class Drag extends Base {
|
||||
})
|
||||
}
|
||||
|
||||
// 拖动中
|
||||
onMove(x, y, e) {
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
// 更新克隆节点的位置
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
let cloneNodeLeft = x - this.offsetX
|
||||
let cloneNodeTop = y - this.offsetY
|
||||
x = (cloneNodeLeft - translateX) / scaleX
|
||||
y = (cloneNodeTop - translateY) / scaleY
|
||||
let t = this.clone.transform()
|
||||
this.clone.translate(x - t.translateX, y - t.translateY)
|
||||
// 检测新位置
|
||||
this.checkOverlapNode()
|
||||
// 如果注册了多选节点插件,那么复用它的边缘自动移动画布功能
|
||||
if (this.mindMap.opt.autoMoveWhenMouseInEdgeOnDrag && this.mindMap.select) {
|
||||
this.drawTransform = this.mindMap.draw.transform()
|
||||
this.mindMap.select.clearAutoMoveTimer()
|
||||
this.mindMap.select.onMove(e.clientX, e.clientY)
|
||||
}
|
||||
}
|
||||
|
||||
// 开始拖拽时初始化一些数据
|
||||
handleStartMove() {
|
||||
if (!this.isDragging) {
|
||||
this.isDragging = true
|
||||
// 鼠标按下的节点
|
||||
let node = this.mousedownNode
|
||||
// 计算鼠标按下的位置距离节点左上角的距离
|
||||
this.drawTransform = this.mindMap.draw.transform()
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
this.offsetX = this.mouseDownX - (node.left * scaleX + translateX)
|
||||
this.offsetY = this.mouseDownY - (node.top * scaleY + translateY)
|
||||
// 如果鼠标按下的节点是激活节点,那么保存当前所有激活的节点
|
||||
if (node.nodeData.data.isActive) {
|
||||
// 找出这些激活节点中的最顶层节点
|
||||
this.beingDragNodeList = getTopAncestorsFomNodeList(
|
||||
// 过滤掉根节点和概要节点
|
||||
this.mindMap.renderer.activeNodeList.filter(item => {
|
||||
return !item.isRoot && !item.isGeneralization
|
||||
})
|
||||
)
|
||||
} else {
|
||||
// 否则只拖拽按下的节点
|
||||
this.beingDragNodeList = [node]
|
||||
}
|
||||
// 将节点树转为节点数组
|
||||
this.nodeTreeToList()
|
||||
// 创建克隆节点
|
||||
this.createCloneNode()
|
||||
// 清除当前所有激活的节点
|
||||
this.mindMap.renderer.clearAllActive()
|
||||
}
|
||||
}
|
||||
|
||||
// 节点由树转换成数组,从子节点到根节点
|
||||
nodeTreeToList() {
|
||||
const list = []
|
||||
bfsWalk(this.mindMap.renderer.root, node => {
|
||||
// 过滤掉当前被拖拽的节点
|
||||
if (this.checkIsInBeingDragNodeList(node)) {
|
||||
return
|
||||
}
|
||||
if (!list[node.layerIndex]) {
|
||||
list[node.layerIndex] = []
|
||||
}
|
||||
list[node.layerIndex].push(node)
|
||||
})
|
||||
this.nodeList = list.reduceRight((res, cur) => {
|
||||
return [...res, ...cur]
|
||||
}, [])
|
||||
}
|
||||
|
||||
// 创建克隆节点
|
||||
createCloneNode() {
|
||||
if (!this.clone) {
|
||||
// 节点
|
||||
this.clone = this.node.group.clone()
|
||||
this.clone.opacity(0.5)
|
||||
const {
|
||||
dragMultiNodeRectConfig,
|
||||
dragPlaceholderRectFill,
|
||||
dragOpacityConfig
|
||||
} = this.mindMap.opt
|
||||
const {
|
||||
width: rectWidth,
|
||||
height: rectHeight,
|
||||
fill: rectFill
|
||||
} = dragMultiNodeRectConfig
|
||||
const node = this.beingDragNodeList[0]
|
||||
const lineColor = node.style.merge('lineColor', true)
|
||||
// 如果当前被拖拽的节点数量大于1,那么创建一个矩形示意
|
||||
if (this.beingDragNodeList.length > 1) {
|
||||
this.clone = this.draw
|
||||
.rect()
|
||||
.size(rectWidth, rectHeight)
|
||||
.radius(rectHeight / 2)
|
||||
.fill({
|
||||
color: rectFill || lineColor
|
||||
})
|
||||
this.offsetX = rectWidth / 2
|
||||
this.offsetY = rectHeight / 2
|
||||
} else {
|
||||
// 否则克隆当前的节点
|
||||
this.clone = node.group.clone()
|
||||
// 删除展开收起按钮元素
|
||||
const expandEl = this.clone.findOne('.smm-expand-btn')
|
||||
if (expandEl) {
|
||||
expandEl.remove()
|
||||
}
|
||||
this.mindMap.draw.add(this.clone)
|
||||
}
|
||||
this.clone.opacity(dragOpacityConfig.cloneNodeOpacity)
|
||||
this.clone.css('z-index', 99999)
|
||||
this.node.isDrag = true
|
||||
this.node.hide()
|
||||
// 连接线
|
||||
this.line = this.draw.path()
|
||||
this.line.opacity(0.5)
|
||||
this.node.styleLine(this.line, this.node)
|
||||
// 同级位置占位符
|
||||
// 同级位置提示元素
|
||||
this.placeholder = this.draw.rect().fill({
|
||||
color: this.node.style.merge('lineColor', true)
|
||||
color: dragPlaceholderRectFill || lineColor
|
||||
})
|
||||
// 当前被拖拽的节点的临时设置
|
||||
this.beingDragNodeList.forEach(node => {
|
||||
// 降低透明度
|
||||
node.setOpacity(dragOpacityConfig.beingDragNodeOpacity)
|
||||
// 隐藏连线及下级节点
|
||||
node.hideChildren()
|
||||
// 设置拖拽状态
|
||||
node.startDrag()
|
||||
})
|
||||
this.mindMap.draw.add(this.clone)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,42 +304,9 @@ class Drag extends Base {
|
||||
return
|
||||
}
|
||||
this.clone.remove()
|
||||
this.line.remove()
|
||||
this.placeholder.remove()
|
||||
}
|
||||
|
||||
// 拖动中
|
||||
onMove(x, y, e) {
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
this.createCloneNode()
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
this.cloneNodeLeft = x - this.offsetX
|
||||
this.cloneNodeTop = y - this.offsetY
|
||||
x = (this.cloneNodeLeft - translateX) / scaleX
|
||||
y = (this.cloneNodeTop - translateY) / scaleY
|
||||
let t = this.clone.transform()
|
||||
this.clone.translate(x - t.translateX, y - t.translateY)
|
||||
// 连接线
|
||||
let parent = this.node.parent
|
||||
this.line.plot(
|
||||
this.quadraticCurvePath(
|
||||
parent.left + parent.width / 2,
|
||||
parent.top + parent.height / 2,
|
||||
x + this.node.width / 2,
|
||||
y + this.node.height / 2
|
||||
)
|
||||
)
|
||||
this.checkOverlapNode()
|
||||
// 如果注册了多选节点插件,那么复用它的边缘自动移动画布功能
|
||||
if (this.mindMap.opt.autoMoveWhenMouseInEdgeOnDrag && this.mindMap.select) {
|
||||
this.drawTransform = this.mindMap.draw.transform()
|
||||
this.mindMap.select.clearAutoMoveTimer()
|
||||
this.mindMap.select.onMove(e.clientX, e.clientY)
|
||||
}
|
||||
}
|
||||
|
||||
// 检测重叠节点
|
||||
checkOverlapNode() {
|
||||
if (!this.drawTransform || !this.placeholder) {
|
||||
@@ -226,9 +320,6 @@ class Drag extends Base {
|
||||
if (node.nodeData.data.isActive) {
|
||||
this.mindMap.renderer.setNodeActive(node, false)
|
||||
}
|
||||
if (node.uid === this.node.uid || this.node.isParent(node)) {
|
||||
return
|
||||
}
|
||||
if (this.overlapNode || (this.prevNode && this.nextNode)) {
|
||||
return
|
||||
}
|
||||
@@ -484,7 +575,7 @@ class Drag extends Base {
|
||||
if (node.layerIndex === 1) {
|
||||
sameDir = item.dir === node.dir
|
||||
}
|
||||
return item !== this.node && sameDir
|
||||
return sameDir && !this.checkIsInBeingDragNodeList(item)
|
||||
})
|
||||
: []
|
||||
this.handleVerticalCheck(node, checkList)
|
||||
@@ -535,7 +626,7 @@ class Drag extends Base {
|
||||
handleFishbone(node) {
|
||||
let checkList = node.parent
|
||||
? node.parent.children.filter(item => {
|
||||
return item !== this.node && item.layerIndex > 1
|
||||
return item.layerIndex > 1 && !this.checkIsInBeingDragNodeList(item)
|
||||
})
|
||||
: []
|
||||
if (node.layerIndex === 1) {
|
||||
@@ -553,8 +644,8 @@ class Drag extends Base {
|
||||
// 获取节点的兄弟节点列表通用方法
|
||||
commonGetNodeCheckList(node) {
|
||||
return node.parent
|
||||
? node.parent.children.filter(item => {
|
||||
return item !== this.node
|
||||
? [...node.parent.children].filter(item => {
|
||||
return !this.checkIsInBeingDragNodeList(item)
|
||||
})
|
||||
: []
|
||||
}
|
||||
@@ -585,18 +676,11 @@ class Drag extends Base {
|
||||
}
|
||||
}
|
||||
|
||||
// 节点由树转换成数组,从子节点到根节点
|
||||
nodeTreeToList() {
|
||||
const list = []
|
||||
bfsWalk(this.mindMap.renderer.root, node => {
|
||||
if (!list[node.layerIndex]) {
|
||||
list[node.layerIndex] = []
|
||||
}
|
||||
list[node.layerIndex].push(node)
|
||||
// 检查某个节点是否在被拖拽节点内
|
||||
checkIsInBeingDragNodeList(node) {
|
||||
return !!this.beingDragNodeList.find(item => {
|
||||
return item.uid === node.uid || item.isParent(node)
|
||||
})
|
||||
this.nodeList = list.reduceRight((res, cur) => {
|
||||
return [...res, ...cur]
|
||||
}, [])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class Export {
|
||||
let task = imageList.map(async item => {
|
||||
let imgUlr = item.attr('href') || item.attr('xlink:href')
|
||||
// 已经是data:URL形式不用转换
|
||||
if (/^data:/.test(imgUlr)) {
|
||||
if (/^data:/.test(imgUlr) || imgUlr === 'none') {
|
||||
return
|
||||
}
|
||||
let imgData = await imgToDataUrl(imgUlr)
|
||||
|
||||
53
simple-mind-map/src/plugins/Formula.js
Normal file
53
simple-mind-map/src/plugins/Formula.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import katex from 'katex'
|
||||
import Quill from 'quill'
|
||||
|
||||
// 数学公式支持插件
|
||||
// 该插件在富文本模式下可用
|
||||
class Formula {
|
||||
// 构造函数
|
||||
constructor(opt) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
window.katex = katex
|
||||
this.extendQuill()
|
||||
}
|
||||
|
||||
// 修改formula格式工具
|
||||
extendQuill() {
|
||||
const QuillFormula = Quill.import('formats/formula')
|
||||
|
||||
class CustomFormulaBlot extends QuillFormula {
|
||||
static create(value) {
|
||||
let node = super.create(value)
|
||||
if (typeof value === 'string') {
|
||||
katex.render(value, node, {
|
||||
throwOnError: false,
|
||||
errorColor: '#f00',
|
||||
output: 'mathml' // 增加该配置,默认只输出公式
|
||||
})
|
||||
node.setAttribute('data-value', value)
|
||||
}
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
Quill.register('formats/formula', CustomFormulaBlot, true)
|
||||
}
|
||||
|
||||
// 给指定的节点插入指定公式
|
||||
insertFormulaToNode(node, formula) {
|
||||
let richTextPlugin = this.mindMap.richText
|
||||
richTextPlugin.showEditText(node)
|
||||
richTextPlugin.quill.insertEmbed(
|
||||
richTextPlugin.quill.getLength() - 1,
|
||||
'formula',
|
||||
formula
|
||||
)
|
||||
richTextPlugin.setTextStyleIfNotRichText(richTextPlugin.node)
|
||||
richTextPlugin.hideEditText([node])
|
||||
}
|
||||
}
|
||||
|
||||
Formula.instanceName = 'formula'
|
||||
|
||||
export default Formula
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
walk,
|
||||
getTextFromHtml,
|
||||
isWhite,
|
||||
getVisibleColorFromTheme
|
||||
getVisibleColorFromTheme,
|
||||
isUndef
|
||||
} from '../utils'
|
||||
import { CONSTANTS } from '../constants/constant'
|
||||
|
||||
@@ -237,7 +238,10 @@ class RichText {
|
||||
}
|
||||
if (!node.nodeData.data.richText) {
|
||||
// 还不是富文本的情况
|
||||
let text = node.nodeData.data.text.split(/\n/gim).join('<br>')
|
||||
let text = ''
|
||||
if (!isUndef(node.nodeData.data.text)) {
|
||||
text = String(node.nodeData.data.text).split(/\n/gim).join('<br>')
|
||||
}
|
||||
let html = `<p>${text}</p>`
|
||||
this.textEditNode.innerHTML = this.cacheEditingText || html
|
||||
} else {
|
||||
@@ -616,7 +620,7 @@ class RichText {
|
||||
// 处理导入数据
|
||||
handleSetData(data) {
|
||||
let walk = root => {
|
||||
if (!root.data.richText) {
|
||||
if (root.data && !root.data.richText) {
|
||||
root.data.richText = true
|
||||
root.data.resetRichText = true
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { bfsWalk, throttle } from '../utils'
|
||||
import { bfsWalk, throttle, checkTwoRectIsOverlap } from '../utils'
|
||||
|
||||
// 节点选择插件
|
||||
class Select {
|
||||
@@ -89,23 +89,28 @@ class Select {
|
||||
}
|
||||
)
|
||||
})
|
||||
this.mindMap.on('mouseup', () => {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
this.checkTriggerNodeActiveEvent()
|
||||
clearTimeout(this.autoMoveTimer)
|
||||
this.isMousedown = false
|
||||
this.cacheActiveList = []
|
||||
if (this.rect) this.rect.remove()
|
||||
this.rect = null
|
||||
setTimeout(() => {
|
||||
this.isSelecting = false
|
||||
}, 0)
|
||||
})
|
||||
this.onMouseup = this.onMouseup.bind(this)
|
||||
this.mindMap.on('mouseup', this.onMouseup)
|
||||
this.mindMap.on('node_mouseup', this.onMouseup)
|
||||
}
|
||||
|
||||
// 结束框选
|
||||
onMouseup() {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
return
|
||||
}
|
||||
if (!this.isMousedown) {
|
||||
return
|
||||
}
|
||||
this.checkTriggerNodeActiveEvent()
|
||||
clearTimeout(this.autoMoveTimer)
|
||||
this.isMousedown = false
|
||||
this.cacheActiveList = []
|
||||
if (this.rect) this.rect.remove()
|
||||
this.rect = null
|
||||
setTimeout(() => {
|
||||
this.isSelecting = false
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// 如果激活节点改变了,那么触发事件
|
||||
@@ -184,6 +189,7 @@ class Select {
|
||||
|
||||
// 创建矩形
|
||||
createRect(x, y) {
|
||||
if (this.rect) this.rect.remove()
|
||||
this.rect = this.mindMap.svg
|
||||
.polygon()
|
||||
.stroke({
|
||||
@@ -210,24 +216,19 @@ class Select {
|
||||
left = left * scaleX + translateX
|
||||
top = top * scaleY + translateY
|
||||
if (
|
||||
((left >= minx && left <= maxx) || (right >= minx && right <= maxx)) &&
|
||||
((top >= miny && top <= maxy) || (bottom >= miny && bottom <= maxy))
|
||||
checkTwoRectIsOverlap(minx, maxx, miny, maxy, left, right, top, bottom)
|
||||
) {
|
||||
// this.mindMap.batchExecution.push('activeNode' + node.uid, () => {
|
||||
if (node.nodeData.data.isActive) {
|
||||
return
|
||||
}
|
||||
this.mindMap.renderer.setNodeActive(node, true)
|
||||
this.mindMap.renderer.addActiveNode(node)
|
||||
// })
|
||||
} else if (node.nodeData.data.isActive) {
|
||||
// this.mindMap.batchExecution.push('activeNode' + node.uid, () => {
|
||||
if (!node.nodeData.data.isActive) {
|
||||
return
|
||||
}
|
||||
this.mindMap.renderer.setNodeActive(node, false)
|
||||
this.mindMap.renderer.removeActiveNode(node)
|
||||
// })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { Text } from '@svgdotjs/svg.js'
|
||||
import { getStrWithBrFromHtml } from '../../utils/index'
|
||||
import {
|
||||
getStrWithBrFromHtml,
|
||||
focusInput,
|
||||
selectAllInput
|
||||
} from '../../utils/index'
|
||||
|
||||
// 创建文字节点
|
||||
function createText(data) {
|
||||
@@ -36,7 +40,7 @@ function showEditTextBox(g) {
|
||||
this.mindMap.keyCommand.addShortcut('Enter', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
|
||||
// 输入框元素没有创建过,则先创建
|
||||
if (!this.textEditNode) {
|
||||
this.textEditNode = document.createElement('div')
|
||||
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
|
||||
@@ -55,20 +59,27 @@ function showEditTextBox(g) {
|
||||
associativeLineTextFontFamily,
|
||||
associativeLineTextLineHeight
|
||||
} = this.mindMap.themeConfig
|
||||
let { defaultAssociativeLineText, nodeTextEditZIndex } = this.mindMap.opt
|
||||
let scale = this.mindMap.view.scale
|
||||
let [, , , node, toNode] = this.activeLine
|
||||
let textLines = (
|
||||
this.getText(node, toNode) || this.mindMap.opt.defaultAssociativeLineText
|
||||
).split(/\n/gim)
|
||||
let text = this.getText(node, toNode)
|
||||
let textLines = (text || defaultAssociativeLineText).split(/\n/gim)
|
||||
this.textEditNode.style.fontFamily = associativeLineTextFontFamily
|
||||
this.textEditNode.style.fontSize = associativeLineTextFontSize * scale + 'px'
|
||||
this.textEditNode.style.lineHeight =
|
||||
textLines.length > 1 ? associativeLineTextLineHeight : 'normal'
|
||||
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
|
||||
this.textEditNode.style.zIndex = nodeTextEditZIndex
|
||||
this.textEditNode.innerHTML = textLines.join('<br>')
|
||||
this.textEditNode.style.display = 'block'
|
||||
this.updateTextEditBoxPos(g)
|
||||
this.showTextEdit = true
|
||||
// 如果是默认文本要全选输入框
|
||||
if (text === '' || text === defaultAssociativeLineText) {
|
||||
selectAllInput(this.textEditNode)
|
||||
} else {
|
||||
// 否则聚焦即可
|
||||
focusInput(this.textEditNode)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理画布缩放
|
||||
@@ -94,10 +105,13 @@ function hideEditTextBox() {
|
||||
}
|
||||
let [path, , text, node, toNode] = this.activeLine
|
||||
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
|
||||
// 如果是默认文本,那么不保存
|
||||
let isDefaultText = str === this.mindMap.opt.defaultAssociativeLineText
|
||||
str = isDefaultText ? '' : str
|
||||
this.mindMap.execCommand('SET_NODE_DATA', node, {
|
||||
associativeLineText: {
|
||||
...(node.nodeData.data.associativeLineText || {}),
|
||||
[toNode.nodeData.data.id]: str
|
||||
[toNode.nodeData.data.uid]: str
|
||||
}
|
||||
})
|
||||
this.textEditNode.style.display = 'none'
|
||||
@@ -113,7 +127,7 @@ function getText(node, toNode) {
|
||||
if (!obj) {
|
||||
return ''
|
||||
}
|
||||
return obj[toNode.nodeData.data.id] || ''
|
||||
return obj[toNode.nodeData.data.uid] || ''
|
||||
}
|
||||
|
||||
// 渲染关联线文字
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 获取目标节点在起始节点的目标数组中的索引
|
||||
export const getAssociativeLineTargetIndex = (node, toNode) => {
|
||||
return node.nodeData.data.associativeLineTargets.findIndex(item => {
|
||||
return item === toNode.nodeData.data.id
|
||||
return item === toNode.nodeData.data.uid
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { mergerIconList } from '../utils'
|
||||
|
||||
// 超链接图标
|
||||
const hyperlink =
|
||||
'<svg t="1624174958075" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7982" ><path d="M435.484444 251.733333v68.892445L295.822222 320.682667a168.504889 168.504889 0 0 0-2.844444 336.952889h142.506666v68.892444H295.822222a237.397333 237.397333 0 0 1 0-474.794667h139.662222z m248.945778 0a237.397333 237.397333 0 0 1 0 474.851556H544.654222v-69.006222l139.776 0.056889a168.504889 168.504889 0 0 0 2.844445-336.952889H544.597333V251.676444h139.776z m-25.827555 203.946667a34.474667 34.474667 0 0 1 0 68.892444H321.649778a34.474667 34.474667 0 0 1 0-68.892444h336.952889z" p-id="7983"></path></svg>'
|
||||
@@ -281,12 +283,21 @@ export const nodeIconList = [
|
||||
// 获取nodeIconList icon内容
|
||||
const getNodeIconListIcon = (name, extendIconList = []) => {
|
||||
let arr = name.split('_')
|
||||
let typeData = [...nodeIconList, ...extendIconList].find(item => {
|
||||
const iconList = mergerIconList([...nodeIconList, ...extendIconList])
|
||||
let typeData = iconList.find(item => {
|
||||
return item.type === arr[0]
|
||||
})
|
||||
return typeData.list.find(item => {
|
||||
return item.name === arr[1]
|
||||
}).icon
|
||||
if (typeData) {
|
||||
let typeName = typeData.list.find(item => {
|
||||
return item.name === arr[1]
|
||||
})
|
||||
if (typeName) {
|
||||
return typeName.icon
|
||||
}
|
||||
return ''
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { nodeDataNoStylePropList } from '../constants/constant'
|
||||
|
||||
import MersenneTwister from './mersenneTwister'
|
||||
// 深度优先遍历树
|
||||
export const walk = (
|
||||
root,
|
||||
@@ -167,19 +167,22 @@ export const copyNodeTree = (
|
||||
tree,
|
||||
root,
|
||||
removeActiveState = false,
|
||||
keepId = false
|
||||
removeId = true
|
||||
) => {
|
||||
tree.data = simpleDeepClone(root.nodeData ? root.nodeData.data : root.data)
|
||||
// 去除节点id,因为节点id不能重复
|
||||
if (tree.data.id && !keepId) delete tree.data.id
|
||||
if (tree.data.uid) delete tree.data.uid
|
||||
// 移除节点uid
|
||||
if (removeId) {
|
||||
delete tree.data.uid
|
||||
} else if (!tree.data.uid) {// 否则保留或生成
|
||||
tree.data.uid = createUid()
|
||||
}
|
||||
if (removeActiveState) {
|
||||
tree.data.isActive = false
|
||||
}
|
||||
tree.children = []
|
||||
if (root.children && root.children.length > 0) {
|
||||
root.children.forEach((item, index) => {
|
||||
tree.children[index] = copyNodeTree({}, item, removeActiveState, keepId)
|
||||
tree.children[index] = copyNodeTree({}, item, removeActiveState, removeId)
|
||||
})
|
||||
} else if (
|
||||
root.nodeData &&
|
||||
@@ -187,7 +190,7 @@ export const copyNodeTree = (
|
||||
root.nodeData.children.length > 0
|
||||
) {
|
||||
root.nodeData.children.forEach((item, index) => {
|
||||
tree.children[index] = copyNodeTree({}, item, removeActiveState, keepId)
|
||||
tree.children[index] = copyNodeTree({}, item, removeActiveState, removeId)
|
||||
})
|
||||
}
|
||||
return tree
|
||||
@@ -465,7 +468,7 @@ export const removeHTMLEntities = str => {
|
||||
|
||||
// 获取一个数据的类型
|
||||
export const getType = data => {
|
||||
return Object.prototype.toString.call(data).slice(7, -1)
|
||||
return Object.prototype.toString.call(data).slice(8, -1)
|
||||
}
|
||||
|
||||
// 判断一个数据是否是null和undefined和空字符串
|
||||
@@ -669,3 +672,205 @@ export const checkIsNodeStyleDataKey = key => {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 合并图标数组
|
||||
// const data = [
|
||||
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },
|
||||
// { type: 'priority', name: '优先级图标', list: [{ name: '2', icon: 'c' }, { name: 3, icon: 'd' }] },
|
||||
// ];
|
||||
|
||||
// mergerIconList(data) 结果
|
||||
|
||||
// [
|
||||
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'c' }, { name: 3, icon: 'd' }] },
|
||||
// ]
|
||||
export const mergerIconList = list => {
|
||||
return list.reduce((result, item) => {
|
||||
const existingItem = result.find(x => x.type === item.type)
|
||||
if (existingItem) {
|
||||
item.list.forEach(newObj => {
|
||||
const existingObj = existingItem.list.find(x => x.name === newObj.name)
|
||||
if (existingObj) {
|
||||
existingObj.icon = newObj.icon
|
||||
} else {
|
||||
existingItem.list.push(newObj)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
result.push({ ...item })
|
||||
}
|
||||
return result
|
||||
}, [])
|
||||
}
|
||||
|
||||
// 从节点实例列表里找出顶层的节点
|
||||
export const getTopAncestorsFomNodeList = list => {
|
||||
let res = []
|
||||
list.forEach(node => {
|
||||
if (
|
||||
!list.find(item => {
|
||||
return item.uid !== node.uid && item.isParent(node)
|
||||
})
|
||||
) {
|
||||
res.push(node)
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// 判断两个矩形是否重叠
|
||||
export const checkTwoRectIsOverlap = (
|
||||
minx1,
|
||||
maxx1,
|
||||
miny1,
|
||||
maxy1,
|
||||
minx2,
|
||||
maxx2,
|
||||
miny2,
|
||||
maxy2
|
||||
) => {
|
||||
return maxx1 > minx2 && maxx2 > minx1 && maxy1 > miny2 && maxy2 > miny1
|
||||
}
|
||||
|
||||
// 聚焦指定输入框
|
||||
export const focusInput = el => {
|
||||
let selection = window.getSelection()
|
||||
let range = document.createRange()
|
||||
range.selectNodeContents(el)
|
||||
range.collapse()
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
}
|
||||
|
||||
// 聚焦全选指定输入框
|
||||
export const selectAllInput = el => {
|
||||
let selection = window.getSelection()
|
||||
let range = document.createRange()
|
||||
range.selectNodeContents(el)
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
}
|
||||
|
||||
// 给指定的节点列表树数据添加附加数据,会修改原数据
|
||||
export const addDataToAppointNodes = (appointNodes, data = {}) => {
|
||||
const walk = list => {
|
||||
list.forEach(node => {
|
||||
node.data = {
|
||||
...node.data,
|
||||
...data
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
walk(node.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
walk(appointNodes)
|
||||
return appointNodes
|
||||
}
|
||||
|
||||
// 给指定的节点列表树数据添加uid,会修改原数据
|
||||
// createNewId默认为false,即如果节点不存在uid的话,会创建新的uid。如果传true,那么无论节点数据原来是否存在uid,都会创建新的uid
|
||||
export const createUidForAppointNodes = (appointNodes, createNewId = false) => {
|
||||
const walk = list => {
|
||||
list.forEach(node => {
|
||||
if (!node.data) {
|
||||
node.data = {}
|
||||
}
|
||||
if (createNewId || isUndef(node.data.uid)) {
|
||||
node.data.uid = createUid()
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
walk(node.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
walk(appointNodes)
|
||||
return appointNodes
|
||||
}
|
||||
|
||||
// 传入一个数据,如果该数据是数组,那么返回该数组,否则返回一个以该数据为成员的数组
|
||||
export const formatDataToArray = data => {
|
||||
if (!data) return []
|
||||
return Array.isArray(data) ? data : [data]
|
||||
}
|
||||
|
||||
// 获取节点在同级里的位置索引
|
||||
export const getNodeIndex = node => {
|
||||
return node.parent
|
||||
? node.parent.children.findIndex(item => {
|
||||
return item.uid === node.uid
|
||||
})
|
||||
: 0
|
||||
}
|
||||
|
||||
// 根据内容生成颜色
|
||||
export const generateColorByContent = str => {
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||
}
|
||||
// 这里使用伪随机数的原因是因为
|
||||
// 1. 如果字符串的内容差不多,根据hash生产的颜色就比较相近,不好区分,比如v1.1 v1.2,所以需要加入随机数来使得颜色能够区分开
|
||||
// 2. 普通的随机数每次数值不一样,就会导致每次新增标签原来的标签颜色就会发生改变,所以加入了这个方法,使得内容不变随机数也不变
|
||||
const rng = new MersenneTwister(hash)
|
||||
const h = rng.genrand_int32() % 360
|
||||
return 'hsla(' + h + ', 50%, 50%, 1)'
|
||||
}
|
||||
|
||||
// html转义
|
||||
export const htmlEscape = str => {
|
||||
;[
|
||||
['&', '&'],
|
||||
['<', '<'],
|
||||
['>', '>']
|
||||
].forEach(item => {
|
||||
str = str.replace(new RegExp(item[0], 'g'), item[1])
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
// 判断两个对象是否相同,只处理对象或数组
|
||||
export const isSameObject = (a, b) => {
|
||||
const type = getType(a)
|
||||
// a、b类型不一致,那么肯定不相同
|
||||
if (type !== getType(b)) return false
|
||||
// 如果都是对象
|
||||
if (type === 'Object') {
|
||||
const keysa = Object.keys(a)
|
||||
const keysb = Object.keys(b)
|
||||
// 对象字段数量不一样,肯定不相同
|
||||
if (keysa.length !== keysb.length) return false
|
||||
// 字段数量一样,那么需要遍历字段进行判断
|
||||
for (let i = 0; i < keysa.length; i++) {
|
||||
const key = keysa[i]
|
||||
// b没有a的一个字段,那么肯定不相同
|
||||
if (!keysb.includes(key)) return false
|
||||
// 字段名称一样,那么需要递归判断它们的值
|
||||
const isSame = isSameObject(a[key], b[key])
|
||||
if (!isSame) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
} else if (type === 'Array') {
|
||||
// 如果都是数组
|
||||
// 数组长度不一样,肯定不相同
|
||||
if (a.length !== b.length) return false
|
||||
// 长度一样,那么需要遍历进行判断
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
const itema = a[i]
|
||||
const itemb = b[i]
|
||||
const typea = getType(itema)
|
||||
const typeb = getType(itemb)
|
||||
if (typea !== typeb) return false
|
||||
const isSame = isSameObject(itema, itemb)
|
||||
if (!isSame) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
// 其他类型,直接全等判断
|
||||
return a === b
|
||||
}
|
||||
}
|
||||
|
||||
65
simple-mind-map/src/utils/mersenneTwister.js
Normal file
65
simple-mind-map/src/utils/mersenneTwister.js
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @description 为了保证相同的内容每次生成的随机数都是一样的,我们可以使用一个伪随机数生成器(PRNG),并使用内容的哈希值作为种子。以下是一个使用Mersenne Twister算法的PRNG的实现:
|
||||
*
|
||||
* @param {*} seed
|
||||
*/
|
||||
|
||||
export default function MersenneTwister(seed) {
|
||||
this.N = 624
|
||||
this.M = 397
|
||||
this.MATRIX_A = 0x9908b0df
|
||||
this.UPPER_MASK = 0x80000000
|
||||
this.LOWER_MASK = 0x7fffffff
|
||||
|
||||
this.mt = new Array(this.N)
|
||||
this.mti = this.N + 1
|
||||
|
||||
this.init_genrand(seed)
|
||||
}
|
||||
|
||||
MersenneTwister.prototype.init_genrand = function (s) {
|
||||
this.mt[0] = s >>> 0
|
||||
for (this.mti = 1; this.mti < this.N; this.mti++) {
|
||||
s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30)
|
||||
this.mt[this.mti] =
|
||||
((((s & 0xffff0000) >>> 16) * 1812433253) << 16) +
|
||||
(s & 0x0000ffff) * 1812433253 +
|
||||
this.mti
|
||||
this.mt[this.mti] >>>= 0
|
||||
}
|
||||
}
|
||||
|
||||
MersenneTwister.prototype.genrand_int32 = function () {
|
||||
var y
|
||||
var mag01 = new Array(0x0, this.MATRIX_A)
|
||||
|
||||
if (this.mti >= this.N) {
|
||||
var kk
|
||||
|
||||
if (this.mti == this.N + 1) this.init_genrand(5489)
|
||||
|
||||
for (kk = 0; kk < this.N - this.M; kk++) {
|
||||
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK)
|
||||
this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]
|
||||
}
|
||||
|
||||
for (; kk < this.N - 1; kk++) {
|
||||
y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK)
|
||||
this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]
|
||||
}
|
||||
|
||||
y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK)
|
||||
this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]
|
||||
|
||||
this.mti = 0
|
||||
}
|
||||
|
||||
y = this.mt[this.mti++]
|
||||
|
||||
y ^= y >>> 11
|
||||
y ^= (y << 7) & 0x9d2c5680
|
||||
y ^= (y << 15) & 0xefc60000
|
||||
y ^= y >>> 18
|
||||
|
||||
return y >>> 0
|
||||
}
|
||||
334
simple-mind-map/types/index.d.ts
vendored
334
simple-mind-map/types/index.d.ts
vendored
@@ -1,166 +1,176 @@
|
||||
export default MindMap
|
||||
export default MindMap;
|
||||
declare class MindMap {
|
||||
/**
|
||||
*
|
||||
* @param {defaultOpt} opt
|
||||
*/
|
||||
constructor(opt?: {
|
||||
readonly: boolean
|
||||
layout: string
|
||||
fishboneDeg: number
|
||||
theme: string
|
||||
themeConfig: {}
|
||||
scaleRatio: number
|
||||
mouseScaleCenterUseMousePosition: boolean
|
||||
maxTag: number
|
||||
expandBtnSize: number
|
||||
imgTextMargin: number
|
||||
textContentMargin: number
|
||||
selectTranslateStep: number
|
||||
selectTranslateLimit: number
|
||||
customNoteContentShow: any
|
||||
enableFreeDrag: boolean
|
||||
watermarkConfig: {
|
||||
text: string
|
||||
lineSpacing: number
|
||||
textSpacing: number
|
||||
angle: number
|
||||
textStyle: {
|
||||
color: string
|
||||
opacity: number
|
||||
fontSize: number
|
||||
}
|
||||
}
|
||||
textAutoWrapWidth: number
|
||||
customHandleMousewheel: any
|
||||
mousewheelAction: string
|
||||
mousewheelMoveStep: number
|
||||
mousewheelZoomActionReverse: boolean
|
||||
defaultInsertSecondLevelNodeText: string
|
||||
defaultInsertBelowSecondLevelNodeText: string
|
||||
expandBtnStyle: {
|
||||
color: string
|
||||
fill: string
|
||||
fontSize: number
|
||||
strokeColor: string
|
||||
}
|
||||
expandBtnIcon: {
|
||||
open: string
|
||||
close: string
|
||||
}
|
||||
expandBtnNumHandler: (num: any) => any
|
||||
isShowExpandNum: boolean
|
||||
enableShortcutOnlyWhenMouseInSvg: boolean
|
||||
initRootNodePosition: any
|
||||
exportPaddingX: number
|
||||
exportPaddingY: number
|
||||
nodeTextEditZIndex: number
|
||||
nodeNoteTooltipZIndex: number
|
||||
isEndNodeTextEditOnClickOuter: boolean
|
||||
maxHistoryCount: number
|
||||
alwaysShowExpandBtn: boolean
|
||||
iconList: any[]
|
||||
maxNodeCacheCount: number
|
||||
defaultAssociativeLineText: string
|
||||
fitPadding: number
|
||||
enableCtrlKeyNodeSelection: boolean
|
||||
useLeftKeySelectionRightKeyDrag: boolean
|
||||
beforeTextEdit: any
|
||||
isUseCustomNodeContent: boolean
|
||||
customCreateNodeContent: any
|
||||
customInnerElsAppendTo: any
|
||||
nodeDragPlaceholderMaxSize: number
|
||||
enableAutoEnterTextEditWhenKeydown: boolean
|
||||
richTextEditFakeInPlace: boolean
|
||||
customHandleClipboardText: any
|
||||
disableMouseWheelZoom: boolean
|
||||
errorHandler: (code: any, error: any) => void
|
||||
resetCss: string
|
||||
enableDblclickReset: boolean
|
||||
minExportImgCanvasScale: number
|
||||
hoverRectColor: string
|
||||
hoverRectPadding: number
|
||||
selectTextOnEnterEditText: boolean
|
||||
deleteNodeActive: boolean
|
||||
autoMoveWhenMouseInEdgeOnDrag: boolean
|
||||
})
|
||||
opt: any
|
||||
el: any
|
||||
elRect: any
|
||||
width: any
|
||||
height: any
|
||||
cssEl: HTMLStyleElement
|
||||
svg: any
|
||||
draw: any
|
||||
event: Event
|
||||
keyCommand: KeyCommand
|
||||
command: Command
|
||||
renderer: Render
|
||||
view: View
|
||||
batchExecution: BatchExecution
|
||||
handleOpt(opt: any): any
|
||||
addCss(): void
|
||||
removeCss(): void
|
||||
render(callback: any, source?: string): void
|
||||
reRender(callback: any, source?: string): void
|
||||
resize(): void
|
||||
on(event: any, fn: any): void
|
||||
emit(event: any, ...args: any[]): void
|
||||
off(event: any, fn: any): void
|
||||
initCache(): void
|
||||
initTheme(): void
|
||||
themeConfig: any
|
||||
setTheme(theme: any): void
|
||||
getTheme(): any
|
||||
setThemeConfig(config: any): void
|
||||
getCustomThemeConfig(): any
|
||||
getThemeConfig(prop: any): any
|
||||
getConfig(prop: any): any
|
||||
updateConfig(opt?: {}): void
|
||||
getLayout(): any
|
||||
setLayout(layout: any): void
|
||||
execCommand(...args: any[]): void
|
||||
setData(data: any): void
|
||||
setFullData(data: any): void
|
||||
getData(withConfig: any): any
|
||||
export(...args: any[]): Promise<any>
|
||||
toPos(
|
||||
x: any,
|
||||
y: any
|
||||
): {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
setMode(mode: any): void
|
||||
getSvgData({
|
||||
paddingX,
|
||||
paddingY
|
||||
}?: {
|
||||
paddingX?: number
|
||||
paddingY?: number
|
||||
}): {
|
||||
svg: any
|
||||
svgHTML: any
|
||||
rect: any
|
||||
origWidth: any
|
||||
origHeight: any
|
||||
scaleX: any
|
||||
scaleY: any
|
||||
}
|
||||
addPlugin(plugin: any, opt: any): void
|
||||
removePlugin(plugin: any): void
|
||||
initPlugin(plugin: any): void
|
||||
destroy(): void
|
||||
/**
|
||||
*
|
||||
* @param {defaultOpt} opt
|
||||
*/
|
||||
constructor(opt?: {
|
||||
readonly: boolean;
|
||||
layout: string;
|
||||
fishboneDeg: number;
|
||||
theme: string;
|
||||
themeConfig: {};
|
||||
scaleRatio: number;
|
||||
mouseScaleCenterUseMousePosition: boolean;
|
||||
maxTag: number;
|
||||
expandBtnSize: number;
|
||||
imgTextMargin: number;
|
||||
textContentMargin: number;
|
||||
selectTranslateStep: number;
|
||||
selectTranslateLimit: number;
|
||||
customNoteContentShow: any;
|
||||
enableFreeDrag: boolean;
|
||||
watermarkConfig: {
|
||||
text: string;
|
||||
lineSpacing: number;
|
||||
textSpacing: number;
|
||||
angle: number;
|
||||
textStyle: {
|
||||
color: string;
|
||||
opacity: number;
|
||||
fontSize: number;
|
||||
};
|
||||
};
|
||||
textAutoWrapWidth: number;
|
||||
customHandleMousewheel: any;
|
||||
mousewheelAction: string;
|
||||
mousewheelMoveStep: number;
|
||||
mousewheelZoomActionReverse: boolean;
|
||||
defaultInsertSecondLevelNodeText: string;
|
||||
defaultInsertBelowSecondLevelNodeText: string;
|
||||
expandBtnStyle: {
|
||||
color: string;
|
||||
fill: string;
|
||||
fontSize: number;
|
||||
strokeColor: string;
|
||||
};
|
||||
expandBtnIcon: {
|
||||
open: string;
|
||||
close: string;
|
||||
};
|
||||
expandBtnNumHandler: (num: any) => any;
|
||||
isShowExpandNum: boolean;
|
||||
enableShortcutOnlyWhenMouseInSvg: boolean;
|
||||
initRootNodePosition: any;
|
||||
exportPaddingX: number;
|
||||
exportPaddingY: number;
|
||||
nodeTextEditZIndex: number;
|
||||
nodeNoteTooltipZIndex: number;
|
||||
isEndNodeTextEditOnClickOuter: boolean;
|
||||
maxHistoryCount: number;
|
||||
alwaysShowExpandBtn: boolean;
|
||||
iconList: any[];
|
||||
maxNodeCacheCount: number;
|
||||
defaultAssociativeLineText: string;
|
||||
fitPadding: number;
|
||||
enableCtrlKeyNodeSelection: boolean;
|
||||
useLeftKeySelectionRightKeyDrag: boolean;
|
||||
beforeTextEdit: any;
|
||||
isUseCustomNodeContent: boolean;
|
||||
customCreateNodeContent: any;
|
||||
customInnerElsAppendTo: any;
|
||||
nodeDragPlaceholderMaxSize: number;
|
||||
enableAutoEnterTextEditWhenKeydown: boolean;
|
||||
richTextEditFakeInPlace: boolean;
|
||||
customHandleClipboardText: any;
|
||||
disableMouseWheelZoom: boolean;
|
||||
errorHandler: (code: any, error: any) => void;
|
||||
resetCss: string;
|
||||
enableDblclickReset: boolean;
|
||||
minExportImgCanvasScale: number;
|
||||
hoverRectColor: string;
|
||||
hoverRectPadding: number;
|
||||
selectTextOnEnterEditText: boolean;
|
||||
deleteNodeActive: boolean;
|
||||
autoMoveWhenMouseInEdgeOnDrag: boolean;
|
||||
fit: boolean;
|
||||
dragMultiNodeRectConfig: {
|
||||
width: number;
|
||||
height: number;
|
||||
fill: string;
|
||||
};
|
||||
dragPlaceholderRectFill: string;
|
||||
dragOpacityConfig: {
|
||||
cloneNodeOpacity: number;
|
||||
beingDragNodeOpacity: number;
|
||||
};
|
||||
tagsColorMap: {};
|
||||
cooperateStyle: {
|
||||
avatarSize: number;
|
||||
fontSize: number;
|
||||
};
|
||||
});
|
||||
opt: any;
|
||||
el: any;
|
||||
elRect: any;
|
||||
width: any;
|
||||
height: any;
|
||||
cssEl: HTMLStyleElement;
|
||||
svg: any;
|
||||
draw: any;
|
||||
event: Event;
|
||||
keyCommand: KeyCommand;
|
||||
command: Command;
|
||||
renderer: Render;
|
||||
view: View;
|
||||
batchExecution: BatchExecution;
|
||||
handleOpt(opt: any): any;
|
||||
addCss(): void;
|
||||
removeCss(): void;
|
||||
render(callback: any, source?: string): void;
|
||||
reRender(callback: any, source?: string): void;
|
||||
resize(): void;
|
||||
on(event: any, fn: any): void;
|
||||
emit(event: any, ...args: any[]): void;
|
||||
off(event: any, fn: any): void;
|
||||
initCache(): void;
|
||||
initTheme(): void;
|
||||
themeConfig: any;
|
||||
setTheme(theme: any): void;
|
||||
getTheme(): any;
|
||||
setThemeConfig(config: any): void;
|
||||
getCustomThemeConfig(): any;
|
||||
getThemeConfig(prop: any): any;
|
||||
getConfig(prop: any): any;
|
||||
updateConfig(opt?: {}): void;
|
||||
getLayout(): any;
|
||||
setLayout(layout: any): void;
|
||||
execCommand(...args: any[]): void;
|
||||
setData(data: any): void;
|
||||
setFullData(data: any): void;
|
||||
getData(withConfig: any): any;
|
||||
export(...args: any[]): Promise<any>;
|
||||
toPos(x: any, y: any): {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
setMode(mode: any): void;
|
||||
getSvgData({ paddingX, paddingY }?: {
|
||||
paddingX?: number;
|
||||
paddingY?: number;
|
||||
}): {
|
||||
svg: any;
|
||||
svgHTML: any;
|
||||
rect: any;
|
||||
origWidth: any;
|
||||
origHeight: any;
|
||||
scaleX: any;
|
||||
scaleY: any;
|
||||
};
|
||||
addPlugin(plugin: any, opt: any): void;
|
||||
removePlugin(plugin: any): void;
|
||||
initPlugin(plugin: any): void;
|
||||
destroy(): void;
|
||||
}
|
||||
declare namespace MindMap {
|
||||
let pluginList: any[]
|
||||
function usePlugin(plugin: any, opt?: {}): typeof MindMap
|
||||
function hasPlugin(plugin: any): number
|
||||
function defineTheme(name: any, config?: {}): Error
|
||||
const pluginList: any[];
|
||||
function usePlugin(plugin: any, opt?: {}): typeof MindMap;
|
||||
function hasPlugin(plugin: any): number;
|
||||
function defineTheme(name: any, config?: {}): Error;
|
||||
}
|
||||
import Event from './src/core/event/Event'
|
||||
import KeyCommand from './src/core/command/KeyCommand'
|
||||
import Command from './src/core/command/Command'
|
||||
import Render from './src/core/render/Render'
|
||||
import View from './src/core/view/View'
|
||||
import BatchExecution from './src/utils/BatchExecution'
|
||||
import Event from "./src/core/event/Event";
|
||||
import KeyCommand from "./src/core/command/KeyCommand";
|
||||
import Command from "./src/core/command/Command";
|
||||
import Render from "./src/core/render/Render";
|
||||
import View from "./src/core/view/View";
|
||||
import BatchExecution from "./src/utils/BatchExecution";
|
||||
|
||||
200
simple-mind-map/types/src/constants/constant.d.ts
vendored
200
simple-mind-map/types/src/constants/constant.d.ts
vendored
@@ -1,113 +1,109 @@
|
||||
export const tagColorList: {
|
||||
color: string
|
||||
background: string
|
||||
}[]
|
||||
export const themeList: {
|
||||
name: string
|
||||
value: string
|
||||
dark: boolean
|
||||
}[]
|
||||
name: string;
|
||||
value: string;
|
||||
dark: boolean;
|
||||
}[];
|
||||
export namespace CONSTANTS {
|
||||
let CHANGE_THEME: string
|
||||
let CHANGE_LAYOUT: string
|
||||
let SET_DATA: string
|
||||
let TRANSFORM_TO_NORMAL_NODE: string
|
||||
namespace MODE {
|
||||
let READONLY: string
|
||||
let EDIT: string
|
||||
}
|
||||
namespace LAYOUT {
|
||||
let LOGICAL_STRUCTURE: string
|
||||
let MIND_MAP: string
|
||||
let ORGANIZATION_STRUCTURE: string
|
||||
let CATALOG_ORGANIZATION: string
|
||||
let TIMELINE: string
|
||||
let TIMELINE2: string
|
||||
let FISHBONE: string
|
||||
let VERTICAL_TIMELINE: string
|
||||
}
|
||||
namespace DIR {
|
||||
let UP: string
|
||||
let LEFT: string
|
||||
let DOWN: string
|
||||
let RIGHT: string
|
||||
}
|
||||
namespace KEY_DIR {
|
||||
let LEFT_1: string
|
||||
export { LEFT_1 as LEFT }
|
||||
let UP_1: string
|
||||
export { UP_1 as UP }
|
||||
let RIGHT_1: string
|
||||
export { RIGHT_1 as RIGHT }
|
||||
let DOWN_1: string
|
||||
export { DOWN_1 as DOWN }
|
||||
}
|
||||
namespace SHAPE {
|
||||
let RECTANGLE: string
|
||||
let DIAMOND: string
|
||||
let PARALLELOGRAM: string
|
||||
let ROUNDED_RECTANGLE: string
|
||||
let OCTAGONAL_RECTANGLE: string
|
||||
let OUTER_TRIANGULAR_RECTANGLE: string
|
||||
let INNER_TRIANGULAR_RECTANGLE: string
|
||||
let ELLIPSE: string
|
||||
let CIRCLE: string
|
||||
}
|
||||
namespace MOUSE_WHEEL_ACTION {
|
||||
let ZOOM: string
|
||||
let MOVE: string
|
||||
}
|
||||
namespace INIT_ROOT_NODE_POSITION {
|
||||
let LEFT_2: string
|
||||
export { LEFT_2 as LEFT }
|
||||
export let TOP: string
|
||||
let RIGHT_2: string
|
||||
export { RIGHT_2 as RIGHT }
|
||||
export let BOTTOM: string
|
||||
export let CENTER: string
|
||||
}
|
||||
namespace LAYOUT_GROW_DIR {
|
||||
let LEFT_3: string
|
||||
export { LEFT_3 as LEFT }
|
||||
let TOP_1: string
|
||||
export { TOP_1 as TOP }
|
||||
let RIGHT_3: string
|
||||
export { RIGHT_3 as RIGHT }
|
||||
let BOTTOM_1: string
|
||||
export { BOTTOM_1 as BOTTOM }
|
||||
}
|
||||
namespace PASTE_TYPE {
|
||||
let CLIP_BOARD: string
|
||||
let CANVAS: string
|
||||
}
|
||||
namespace SCROLL_BAR_DIR {
|
||||
let VERTICAL: string
|
||||
let HORIZONTAL: string
|
||||
}
|
||||
const CHANGE_THEME: string;
|
||||
const CHANGE_LAYOUT: string;
|
||||
const SET_DATA: string;
|
||||
const TRANSFORM_TO_NORMAL_NODE: string;
|
||||
namespace MODE {
|
||||
const READONLY: string;
|
||||
const EDIT: string;
|
||||
}
|
||||
namespace LAYOUT {
|
||||
const LOGICAL_STRUCTURE: string;
|
||||
const MIND_MAP: string;
|
||||
const ORGANIZATION_STRUCTURE: string;
|
||||
const CATALOG_ORGANIZATION: string;
|
||||
const TIMELINE: string;
|
||||
const TIMELINE2: string;
|
||||
const FISHBONE: string;
|
||||
const VERTICAL_TIMELINE: string;
|
||||
}
|
||||
namespace DIR {
|
||||
const UP: string;
|
||||
const LEFT: string;
|
||||
const DOWN: string;
|
||||
const RIGHT: string;
|
||||
}
|
||||
namespace KEY_DIR {
|
||||
const LEFT_1: string;
|
||||
export { LEFT_1 as LEFT };
|
||||
const UP_1: string;
|
||||
export { UP_1 as UP };
|
||||
const RIGHT_1: string;
|
||||
export { RIGHT_1 as RIGHT };
|
||||
const DOWN_1: string;
|
||||
export { DOWN_1 as DOWN };
|
||||
}
|
||||
namespace SHAPE {
|
||||
const RECTANGLE: string;
|
||||
const DIAMOND: string;
|
||||
const PARALLELOGRAM: string;
|
||||
const ROUNDED_RECTANGLE: string;
|
||||
const OCTAGONAL_RECTANGLE: string;
|
||||
const OUTER_TRIANGULAR_RECTANGLE: string;
|
||||
const INNER_TRIANGULAR_RECTANGLE: string;
|
||||
const ELLIPSE: string;
|
||||
const CIRCLE: string;
|
||||
}
|
||||
namespace MOUSE_WHEEL_ACTION {
|
||||
const ZOOM: string;
|
||||
const MOVE: string;
|
||||
}
|
||||
namespace INIT_ROOT_NODE_POSITION {
|
||||
const LEFT_2: string;
|
||||
export { LEFT_2 as LEFT };
|
||||
export const TOP: string;
|
||||
const RIGHT_2: string;
|
||||
export { RIGHT_2 as RIGHT };
|
||||
export const BOTTOM: string;
|
||||
export const CENTER: string;
|
||||
}
|
||||
namespace LAYOUT_GROW_DIR {
|
||||
const LEFT_3: string;
|
||||
export { LEFT_3 as LEFT };
|
||||
const TOP_1: string;
|
||||
export { TOP_1 as TOP };
|
||||
const RIGHT_3: string;
|
||||
export { RIGHT_3 as RIGHT };
|
||||
const BOTTOM_1: string;
|
||||
export { BOTTOM_1 as BOTTOM };
|
||||
}
|
||||
namespace PASTE_TYPE {
|
||||
const CLIP_BOARD: string;
|
||||
const CANVAS: string;
|
||||
}
|
||||
namespace SCROLL_BAR_DIR {
|
||||
const VERTICAL: string;
|
||||
const HORIZONTAL: string;
|
||||
}
|
||||
}
|
||||
export const initRootNodePositionMap: {
|
||||
[x: string]: number
|
||||
}
|
||||
[x: string]: number;
|
||||
};
|
||||
export const layoutList: {
|
||||
name: string
|
||||
value: string
|
||||
}[]
|
||||
export const layoutValueList: string[]
|
||||
export const nodeDataNoStylePropList: string[]
|
||||
name: string;
|
||||
value: string;
|
||||
}[];
|
||||
export const layoutValueList: string[];
|
||||
export const nodeDataNoStylePropList: string[];
|
||||
export namespace commonCaches {
|
||||
let measureCustomNodeContentSizeEl: any
|
||||
let measureRichtextNodeTextSizeEl: any
|
||||
const measureCustomNodeContentSizeEl: any;
|
||||
const measureRichtextNodeTextSizeEl: any;
|
||||
}
|
||||
export namespace ERROR_TYPES {
|
||||
let READ_CLIPBOARD_ERROR: string
|
||||
let PARSE_PASTE_DATA_ERROR: string
|
||||
let CUSTOM_HANDLE_CLIPBOARD_TEXT_ERROR: string
|
||||
let LOAD_CLIPBOARD_IMAGE_ERROR: string
|
||||
let BEFORE_TEXT_EDIT_ERROR: string
|
||||
let EXPORT_ERROR: string
|
||||
const READ_CLIPBOARD_ERROR: string;
|
||||
const PARSE_PASTE_DATA_ERROR: string;
|
||||
const CUSTOM_HANDLE_CLIPBOARD_TEXT_ERROR: string;
|
||||
const LOAD_CLIPBOARD_IMAGE_ERROR: string;
|
||||
const BEFORE_TEXT_EDIT_ERROR: string;
|
||||
const EXPORT_ERROR: string;
|
||||
}
|
||||
export namespace a4Size {
|
||||
let width: number
|
||||
let height: number
|
||||
const width: number;
|
||||
const height: number;
|
||||
}
|
||||
export const cssContent: '\n /* 鼠标hover和激活时渲染的矩形 */\n .smm-hover-node{\n display: none;\n opacity: 0.6;\n stroke-width: 1;\n }\n\n .smm-node:hover .smm-hover-node{\n display: block;\n }\n\n .smm-node.active .smm-hover-node{\n display: block;\n opacity: 1;\n stroke-width: 2;\n }\n'
|
||||
export const cssContent: "\n /* 鼠标hover和激活时渲染的矩形 */\n .smm-hover-node{\n display: none;\n opacity: 0.6;\n stroke-width: 1;\n }\n\n .smm-node:not(.smm-node-dragging):hover .smm-hover-node{\n display: block;\n }\n\n .smm-node.active .smm-hover-node{\n display: block;\n opacity: 1;\n stroke-width: 2;\n }\n";
|
||||
|
||||
@@ -1,82 +1,100 @@
|
||||
export namespace defaultOpt {
|
||||
let readonly: boolean
|
||||
let layout: string
|
||||
let fishboneDeg: number
|
||||
let theme: string
|
||||
let themeConfig: {}
|
||||
let scaleRatio: number
|
||||
let mouseScaleCenterUseMousePosition: boolean
|
||||
let maxTag: number
|
||||
let expandBtnSize: number
|
||||
let imgTextMargin: number
|
||||
let textContentMargin: number
|
||||
let selectTranslateStep: number
|
||||
let selectTranslateLimit: number
|
||||
let customNoteContentShow: any
|
||||
let enableFreeDrag: boolean
|
||||
namespace watermarkConfig {
|
||||
let text: string
|
||||
let lineSpacing: number
|
||||
let textSpacing: number
|
||||
let angle: number
|
||||
namespace textStyle {
|
||||
let color: string
|
||||
let opacity: number
|
||||
let fontSize: number
|
||||
const readonly: boolean;
|
||||
const layout: string;
|
||||
const fishboneDeg: number;
|
||||
const theme: string;
|
||||
const themeConfig: {};
|
||||
const scaleRatio: number;
|
||||
const mouseScaleCenterUseMousePosition: boolean;
|
||||
const maxTag: number;
|
||||
const expandBtnSize: number;
|
||||
const imgTextMargin: number;
|
||||
const textContentMargin: number;
|
||||
const selectTranslateStep: number;
|
||||
const selectTranslateLimit: number;
|
||||
const customNoteContentShow: any;
|
||||
const enableFreeDrag: boolean;
|
||||
namespace watermarkConfig {
|
||||
const text: string;
|
||||
const lineSpacing: number;
|
||||
const textSpacing: number;
|
||||
const angle: number;
|
||||
namespace textStyle {
|
||||
const color: string;
|
||||
const opacity: number;
|
||||
const fontSize: number;
|
||||
}
|
||||
}
|
||||
const textAutoWrapWidth: number;
|
||||
const customHandleMousewheel: any;
|
||||
const mousewheelAction: string;
|
||||
const mousewheelMoveStep: number;
|
||||
const mousewheelZoomActionReverse: boolean;
|
||||
const defaultInsertSecondLevelNodeText: string;
|
||||
const defaultInsertBelowSecondLevelNodeText: string;
|
||||
namespace expandBtnStyle {
|
||||
const color_1: string;
|
||||
export { color_1 as color };
|
||||
export const fill: string;
|
||||
const fontSize_1: number;
|
||||
export { fontSize_1 as fontSize };
|
||||
export const strokeColor: string;
|
||||
}
|
||||
namespace expandBtnIcon {
|
||||
const open: string;
|
||||
const close: string;
|
||||
}
|
||||
function expandBtnNumHandler(num: any): any;
|
||||
const isShowExpandNum: boolean;
|
||||
const enableShortcutOnlyWhenMouseInSvg: boolean;
|
||||
const initRootNodePosition: any;
|
||||
const exportPaddingX: number;
|
||||
const exportPaddingY: number;
|
||||
const nodeTextEditZIndex: number;
|
||||
const nodeNoteTooltipZIndex: number;
|
||||
const isEndNodeTextEditOnClickOuter: boolean;
|
||||
const maxHistoryCount: number;
|
||||
const alwaysShowExpandBtn: boolean;
|
||||
const iconList: any[];
|
||||
const maxNodeCacheCount: number;
|
||||
const defaultAssociativeLineText: string;
|
||||
const fitPadding: number;
|
||||
const enableCtrlKeyNodeSelection: boolean;
|
||||
const useLeftKeySelectionRightKeyDrag: boolean;
|
||||
const beforeTextEdit: any;
|
||||
const isUseCustomNodeContent: boolean;
|
||||
const customCreateNodeContent: any;
|
||||
const customInnerElsAppendTo: any;
|
||||
const nodeDragPlaceholderMaxSize: number;
|
||||
const enableAutoEnterTextEditWhenKeydown: boolean;
|
||||
const richTextEditFakeInPlace: boolean;
|
||||
const customHandleClipboardText: any;
|
||||
const disableMouseWheelZoom: boolean;
|
||||
function errorHandler(code: any, error: any): void;
|
||||
const resetCss: string;
|
||||
const enableDblclickReset: boolean;
|
||||
const minExportImgCanvasScale: number;
|
||||
const hoverRectColor: string;
|
||||
const hoverRectPadding: number;
|
||||
const selectTextOnEnterEditText: boolean;
|
||||
const deleteNodeActive: boolean;
|
||||
const autoMoveWhenMouseInEdgeOnDrag: boolean;
|
||||
const fit: boolean;
|
||||
namespace dragMultiNodeRectConfig {
|
||||
export const width: number;
|
||||
export const height: number;
|
||||
const fill_1: string;
|
||||
export { fill_1 as fill };
|
||||
}
|
||||
const dragPlaceholderRectFill: string;
|
||||
namespace dragOpacityConfig {
|
||||
const cloneNodeOpacity: number;
|
||||
const beingDragNodeOpacity: number;
|
||||
}
|
||||
const tagsColorMap: {};
|
||||
namespace cooperateStyle {
|
||||
export const avatarSize: number;
|
||||
const fontSize_2: number;
|
||||
export { fontSize_2 as fontSize };
|
||||
}
|
||||
}
|
||||
let textAutoWrapWidth: number
|
||||
let customHandleMousewheel: any
|
||||
let mousewheelAction: string
|
||||
let mousewheelMoveStep: number
|
||||
let mousewheelZoomActionReverse: boolean
|
||||
let defaultInsertSecondLevelNodeText: string
|
||||
let defaultInsertBelowSecondLevelNodeText: string
|
||||
namespace expandBtnStyle {
|
||||
let color_1: string
|
||||
export { color_1 as color }
|
||||
export let fill: string
|
||||
let fontSize_1: number
|
||||
export { fontSize_1 as fontSize }
|
||||
export let strokeColor: string
|
||||
}
|
||||
namespace expandBtnIcon {
|
||||
let open: string
|
||||
let close: string
|
||||
}
|
||||
function expandBtnNumHandler(num: any): any
|
||||
let isShowExpandNum: boolean
|
||||
let enableShortcutOnlyWhenMouseInSvg: boolean
|
||||
let initRootNodePosition: any
|
||||
let exportPaddingX: number
|
||||
let exportPaddingY: number
|
||||
let nodeTextEditZIndex: number
|
||||
let nodeNoteTooltipZIndex: number
|
||||
let isEndNodeTextEditOnClickOuter: boolean
|
||||
let maxHistoryCount: number
|
||||
let alwaysShowExpandBtn: boolean
|
||||
let iconList: any[]
|
||||
let maxNodeCacheCount: number
|
||||
let defaultAssociativeLineText: string
|
||||
let fitPadding: number
|
||||
let enableCtrlKeyNodeSelection: boolean
|
||||
let useLeftKeySelectionRightKeyDrag: boolean
|
||||
let beforeTextEdit: any
|
||||
let isUseCustomNodeContent: boolean
|
||||
let customCreateNodeContent: any
|
||||
let customInnerElsAppendTo: any
|
||||
let nodeDragPlaceholderMaxSize: number
|
||||
let enableAutoEnterTextEditWhenKeydown: boolean
|
||||
let richTextEditFakeInPlace: boolean
|
||||
let customHandleClipboardText: any
|
||||
let disableMouseWheelZoom: boolean
|
||||
function errorHandler(code: any, error: any): void
|
||||
let resetCss: string
|
||||
let enableDblclickReset: boolean
|
||||
let minExportImgCanvasScale: number
|
||||
let hoverRectColor: string
|
||||
let hoverRectPadding: number
|
||||
let selectTextOnEnterEditText: boolean
|
||||
let deleteNodeActive: boolean
|
||||
let autoMoveWhenMouseInEdgeOnDrag: boolean
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
export default Command
|
||||
export default Command;
|
||||
declare class Command {
|
||||
constructor(opt?: {})
|
||||
opt: {}
|
||||
mindMap: any
|
||||
commands: {}
|
||||
history: any[]
|
||||
activeHistoryIndex: number
|
||||
addHistory(): void
|
||||
clearHistory(): void
|
||||
registerShortcutKeys(): void
|
||||
exec(name: any, ...args: any[]): void
|
||||
add(name: any, fn: any): void
|
||||
remove(name: any, fn: any): void
|
||||
back(step?: number): any
|
||||
forward(step?: number): any
|
||||
getCopyData(): any
|
||||
removeDataUid(data: any): any
|
||||
constructor(opt?: {});
|
||||
opt: {};
|
||||
mindMap: any;
|
||||
commands: {};
|
||||
history: any[];
|
||||
activeHistoryIndex: number;
|
||||
addHistory(): void;
|
||||
clearHistory(): void;
|
||||
registerShortcutKeys(): void;
|
||||
exec(name: any, ...args: any[]): void;
|
||||
add(name: any, fn: any): void;
|
||||
remove(name: any, fn: any): void;
|
||||
back(step?: number): any;
|
||||
forward(step?: number): any;
|
||||
getCopyData(): any;
|
||||
removeDataUid(data: any): any;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
export default class KeyCommand {
|
||||
constructor(opt: any)
|
||||
opt: any
|
||||
mindMap: any
|
||||
shortcutMap: {}
|
||||
shortcutMapCache: {}
|
||||
isPause: boolean
|
||||
isInSvg: boolean
|
||||
pause(): void
|
||||
recovery(): void
|
||||
save(): void
|
||||
restore(): void
|
||||
bindEvent(): void
|
||||
checkKey(e: any, key: any): boolean
|
||||
getOriginEventCodeArr(e: any): any[]
|
||||
hasCombinationKey(e: any): any
|
||||
getKeyCodeArr(key: any): any[]
|
||||
/**
|
||||
* Enter
|
||||
* Tab | Insert
|
||||
* Shift + a
|
||||
*/
|
||||
addShortcut(key: any, fn: any): void
|
||||
removeShortcut(key: any, fn: any): void
|
||||
getShortcutFn(key: any): any[]
|
||||
constructor(opt: any);
|
||||
opt: any;
|
||||
mindMap: any;
|
||||
shortcutMap: {};
|
||||
shortcutMapCache: {};
|
||||
isPause: boolean;
|
||||
isInSvg: boolean;
|
||||
pause(): void;
|
||||
recovery(): void;
|
||||
save(): void;
|
||||
restore(): void;
|
||||
bindEvent(): void;
|
||||
checkKey(e: any, key: any): boolean;
|
||||
getOriginEventCodeArr(e: any): any[];
|
||||
hasCombinationKey(e: any): any;
|
||||
getKeyCodeArr(key: any): any[];
|
||||
/**
|
||||
* Enter
|
||||
* Tab | Insert
|
||||
* Shift + a
|
||||
*/
|
||||
addShortcut(key: any, fn: any): void;
|
||||
removeShortcut(key: any, fn: any): void;
|
||||
getShortcutFn(key: any): any[];
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
export const keyMap: {
|
||||
Backspace: number
|
||||
Tab: number
|
||||
Enter: number
|
||||
Shift: number
|
||||
Control: number
|
||||
Alt: number
|
||||
CapsLock: number
|
||||
Esc: number
|
||||
Spacebar: number
|
||||
PageUp: number
|
||||
PageDown: number
|
||||
End: number
|
||||
Home: number
|
||||
Insert: number
|
||||
Left: number
|
||||
Up: number
|
||||
Right: number
|
||||
Down: number
|
||||
Del: number
|
||||
NumLock: number
|
||||
Cmd: number
|
||||
CmdFF: number
|
||||
F1: number
|
||||
F2: number
|
||||
F3: number
|
||||
F4: number
|
||||
F5: number
|
||||
F6: number
|
||||
F7: number
|
||||
F8: number
|
||||
F9: number
|
||||
F10: number
|
||||
F11: number
|
||||
F12: number
|
||||
'`': number
|
||||
'=': number
|
||||
'-': number
|
||||
'/': number
|
||||
'.': number
|
||||
}
|
||||
export function isKey(e: any, key: any): boolean
|
||||
Backspace: number;
|
||||
Tab: number;
|
||||
Enter: number;
|
||||
Shift: number;
|
||||
Control: number;
|
||||
Alt: number;
|
||||
CapsLock: number;
|
||||
Esc: number;
|
||||
Spacebar: number;
|
||||
PageUp: number;
|
||||
PageDown: number;
|
||||
End: number;
|
||||
Home: number;
|
||||
Insert: number;
|
||||
Left: number;
|
||||
Up: number;
|
||||
Right: number;
|
||||
Down: number;
|
||||
Del: number;
|
||||
NumLock: number;
|
||||
Cmd: number;
|
||||
CmdFF: number;
|
||||
F1: number;
|
||||
F2: number;
|
||||
F3: number;
|
||||
F4: number;
|
||||
F5: number;
|
||||
F6: number;
|
||||
F7: number;
|
||||
F8: number;
|
||||
F9: number;
|
||||
F10: number;
|
||||
F11: number;
|
||||
F12: number;
|
||||
'`': number;
|
||||
'=': number;
|
||||
'-': number;
|
||||
'/': number;
|
||||
'.': number;
|
||||
};
|
||||
export function isKey(e: any, key: any): boolean;
|
||||
|
||||
66
simple-mind-map/types/src/core/event/Event.d.ts
vendored
66
simple-mind-map/types/src/core/event/Event.d.ts
vendored
@@ -1,35 +1,35 @@
|
||||
export default Event
|
||||
export default Event;
|
||||
declare class Event {
|
||||
constructor(opt?: {})
|
||||
opt: {}
|
||||
mindMap: any
|
||||
isLeftMousedown: boolean
|
||||
isRightMousedown: boolean
|
||||
isMiddleMousedown: boolean
|
||||
mousedownPos: {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
mousemovePos: {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
mousemoveOffset: {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
bindFn(): void
|
||||
onBodyClick(e: any): void
|
||||
onDrawClick(e: any): void
|
||||
onMousedown(e: any): void
|
||||
onMousemove(e: any): void
|
||||
onMouseup(e: any): void
|
||||
onMousewheel(e: any): void
|
||||
onContextmenu(e: any): void
|
||||
onSvgMousedown(e: any): void
|
||||
onKeyup(e: any): void
|
||||
onMouseenter(e: any): void
|
||||
onMouseleave(e: any): void
|
||||
bind(): void
|
||||
unbind(): void
|
||||
constructor(opt?: {});
|
||||
opt: {};
|
||||
mindMap: any;
|
||||
isLeftMousedown: boolean;
|
||||
isRightMousedown: boolean;
|
||||
isMiddleMousedown: boolean;
|
||||
mousedownPos: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
mousemovePos: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
mousemoveOffset: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
bindFn(): void;
|
||||
onBodyClick(e: any): void;
|
||||
onDrawClick(e: any): void;
|
||||
onMousedown(e: any): void;
|
||||
onMousemove(e: any): void;
|
||||
onMouseup(e: any): void;
|
||||
onMousewheel(e: any): void;
|
||||
onContextmenu(e: any): void;
|
||||
onSvgMousedown(e: any): void;
|
||||
onKeyup(e: any): void;
|
||||
onMouseenter(e: any): void;
|
||||
onMouseleave(e: any): void;
|
||||
bind(): void;
|
||||
unbind(): void;
|
||||
}
|
||||
|
||||
199
simple-mind-map/types/src/core/render/Render.d.ts
vendored
199
simple-mind-map/types/src/core/render/Render.d.ts
vendored
@@ -1,107 +1,96 @@
|
||||
export default Render
|
||||
export default Render;
|
||||
declare class Render {
|
||||
constructor(opt?: {})
|
||||
opt: {}
|
||||
mindMap: any
|
||||
themeConfig: any
|
||||
draw: any
|
||||
renderTree: any
|
||||
reRender: boolean
|
||||
isRendering: boolean
|
||||
hasWaitRendering: boolean
|
||||
nodeCache: {}
|
||||
lastNodeCache: {}
|
||||
renderSource: string
|
||||
activeNodeList: any[]
|
||||
root: any
|
||||
textEdit: TextEdit
|
||||
lastBeingCopyData: any
|
||||
beingCopyData: any
|
||||
beingPasteText: string
|
||||
beingPasteImgSize: number
|
||||
currentBeingPasteType: string
|
||||
setLayout(): void
|
||||
layout:
|
||||
| MindMap
|
||||
| CatalogOrganization
|
||||
| OrganizationStructure
|
||||
| Timeline
|
||||
| VerticalTimeline
|
||||
bindEvent(): void
|
||||
registerCommands(): void
|
||||
selectAll(): void
|
||||
back(step: any): void
|
||||
forward(step: any): void
|
||||
insertNode(
|
||||
openEdit?: boolean,
|
||||
appointNodes?: any[],
|
||||
appointData?: any,
|
||||
appointChildren?: any[]
|
||||
): void
|
||||
insertChildNode(
|
||||
openEdit?: boolean,
|
||||
appointNodes?: any[],
|
||||
appointData?: any,
|
||||
appointChildren?: any[]
|
||||
): void
|
||||
upNode(): void
|
||||
downNode(): void
|
||||
insertAfter(node: any, exist: any): void
|
||||
insertBefore(node: any, exist: any): void
|
||||
moveNodeTo(node: any, toNode: any): void
|
||||
removeNode(appointNodes?: any[]): void
|
||||
pasteNode(data: any): void
|
||||
cutNode(callback: any): any
|
||||
setNodeStyle(node: any, prop: any, value: any): void
|
||||
setNodeStyles(node: any, style: any): void
|
||||
setNodeActive(node: any, active: any): void
|
||||
clearAllActive(): void
|
||||
setNodeExpand(node: any, expand: any): void
|
||||
expandAllNode(): void
|
||||
unexpandAllNode(): void
|
||||
expandToLevel(level: any): void
|
||||
setNodeData(node: any, data: any): void
|
||||
setNodeText(node: any, text: any, richText: any, resetRichText: any): void
|
||||
setNodeImage(node: any, data: any): void
|
||||
setNodeIcon(node: any, icons: any): void
|
||||
setNodeHyperlink(node: any, link: any, title?: string): void
|
||||
setNodeNote(node: any, note: any): void
|
||||
setNodeTag(node: any, tag: any): void
|
||||
addGeneralization(data: any): void
|
||||
removeGeneralization(): void
|
||||
setNodeCustomPosition(node: any, left?: any, top?: any): void
|
||||
resetLayout(): void
|
||||
setNodeShape(node: any, shape: any): void
|
||||
goTargetNode(node: any, callback?: () => void): void
|
||||
registerShortcutKeys(): void
|
||||
insertNodeWrap: () => void
|
||||
toggleActiveExpand(): void
|
||||
removeNodeWrap: () => void
|
||||
copy(): void
|
||||
cut(): void
|
||||
startTextEdit(): void
|
||||
endTextEdit(): void
|
||||
render(callback: () => void, source: any): void
|
||||
clearActive(): void
|
||||
addActiveNode(node: any): void
|
||||
removeActiveNode(node: any): void
|
||||
findActiveNodeIndex(node: any): number
|
||||
getNodeIndex(node: any): any
|
||||
formatAppointNodes(appointNodes: any): any[]
|
||||
setCoptyDataToClipboard(data: any): void
|
||||
paste(): void
|
||||
onPaste(): Promise<void>
|
||||
removeOneNode(node: any): void
|
||||
copyNode(): any
|
||||
toggleNodeExpand(node: any): void
|
||||
setNodeDataRender(node: any, data: any, notRender?: boolean): void
|
||||
moveNodeToCenter(node: any): void
|
||||
expandToNodeUid(uid: any, callback?: () => void): void
|
||||
findNodeByUid(uid: any): any
|
||||
constructor(opt?: {});
|
||||
opt: {};
|
||||
mindMap: any;
|
||||
themeConfig: any;
|
||||
draw: any;
|
||||
renderTree: any;
|
||||
reRender: boolean;
|
||||
isRendering: boolean;
|
||||
hasWaitRendering: boolean;
|
||||
nodeCache: {};
|
||||
lastNodeCache: {};
|
||||
renderSource: string;
|
||||
activeNodeList: any[];
|
||||
root: any;
|
||||
textEdit: TextEdit;
|
||||
lastBeingCopyData: any;
|
||||
beingCopyData: any;
|
||||
beingPasteText: string;
|
||||
beingPasteImgSize: number;
|
||||
currentBeingPasteType: string;
|
||||
setLayout(): void;
|
||||
layout: MindMap | CatalogOrganization | OrganizationStructure | Timeline | VerticalTimeline;
|
||||
setData(data: any): void;
|
||||
bindEvent(): void;
|
||||
registerCommands(): void;
|
||||
selectAll(): void;
|
||||
back(step: any): void;
|
||||
forward(step: any): void;
|
||||
insertNode(openEdit?: boolean, appointNodes?: any[], appointData?: any, appointChildren?: any[]): void;
|
||||
insertMultiNode(appointNodes: any, nodeList: any): void;
|
||||
insertChildNode(openEdit?: boolean, appointNodes?: any[], appointData?: any, appointChildren?: any[]): void;
|
||||
insertMultiChildNode(appointNodes: any, childList: any): void;
|
||||
upNode(): void;
|
||||
downNode(): void;
|
||||
insertAfter(node: any, exist: any): void;
|
||||
insertBefore(node: any, exist: any): void;
|
||||
moveNodeTo(node: any, toNode: any): void;
|
||||
removeNode(appointNodes?: any[]): void;
|
||||
pasteNode(data: any): void;
|
||||
cutNode(callback: any): void;
|
||||
setNodeStyle(node: any, prop: any, value: any): void;
|
||||
setNodeStyles(node: any, style: any): void;
|
||||
setNodeActive(node: any, active: any): void;
|
||||
clearAllActive(): void;
|
||||
setNodeExpand(node: any, expand: any): void;
|
||||
expandAllNode(): void;
|
||||
unexpandAllNode(): void;
|
||||
expandToLevel(level: any): void;
|
||||
setNodeData(node: any, data: any): void;
|
||||
setNodeText(node: any, text: any, richText: any, resetRichText: any): void;
|
||||
setNodeImage(node: any, data: any): void;
|
||||
setNodeIcon(node: any, icons: any): void;
|
||||
setNodeHyperlink(node: any, link: any, title?: string): void;
|
||||
setNodeNote(node: any, note: any): void;
|
||||
setNodeTag(node: any, tag: any): void;
|
||||
insertFormula(formula: any, appointNodes?: any[]): void;
|
||||
addGeneralization(data: any): void;
|
||||
removeGeneralization(): void;
|
||||
setNodeCustomPosition(node: any, left?: any, top?: any): void;
|
||||
resetLayout(): void;
|
||||
setNodeShape(node: any, shape: any): void;
|
||||
goTargetNode(node: any, callback?: () => void): void;
|
||||
registerShortcutKeys(): void;
|
||||
insertNodeWrap: () => void;
|
||||
toggleActiveExpand(): void;
|
||||
removeNodeWrap: () => void;
|
||||
copy(): void;
|
||||
cut(): void;
|
||||
startTextEdit(): void;
|
||||
endTextEdit(): void;
|
||||
render(callback: () => void, source: any): void;
|
||||
clearActive(): void;
|
||||
addActiveNode(node: any): void;
|
||||
removeActiveNode(node: any): void;
|
||||
findActiveNodeIndex(node: any): number;
|
||||
setCopyDataToClipboard(data: any): void;
|
||||
paste(): void;
|
||||
onPaste(): Promise<void>;
|
||||
insertTo(node: any, exist: any, dir?: string): void;
|
||||
checkNodeLayerChange(node: any, toNode: any): void;
|
||||
removeOneNode(node: any): void;
|
||||
copyNode(): any;
|
||||
toggleNodeExpand(node: any): void;
|
||||
setNodeDataRender(node: any, data: any, notRender?: boolean): void;
|
||||
moveNodeToCenter(node: any): void;
|
||||
expandToNodeUid(uid: any, callback?: () => void): void;
|
||||
findNodeByUid(uid: any): any;
|
||||
}
|
||||
import TextEdit from './TextEdit'
|
||||
import MindMap from '../../layouts/MindMap'
|
||||
import CatalogOrganization from '../../layouts/CatalogOrganization'
|
||||
import OrganizationStructure from '../../layouts/OrganizationStructure'
|
||||
import Timeline from '../../layouts/Timeline'
|
||||
import VerticalTimeline from '../../layouts/VerticalTimeline'
|
||||
import TextEdit from "./TextEdit";
|
||||
import MindMap from "../../layouts/MindMap";
|
||||
import CatalogOrganization from "../../layouts/CatalogOrganization";
|
||||
import OrganizationStructure from "../../layouts/OrganizationStructure";
|
||||
import Timeline from "../../layouts/Timeline";
|
||||
import VerticalTimeline from "../../layouts/VerticalTimeline";
|
||||
|
||||
@@ -1,29 +1,17 @@
|
||||
export default class TextEdit {
|
||||
constructor(renderer: any)
|
||||
renderer: any
|
||||
mindMap: any
|
||||
currentNode: any
|
||||
textEditNode: HTMLDivElement
|
||||
showTextEdit: boolean
|
||||
cacheEditingText: string
|
||||
bindEvent(): void
|
||||
show(
|
||||
node: any,
|
||||
e: any,
|
||||
isInserting?: boolean,
|
||||
isFromKeyDown?: boolean
|
||||
): Promise<void>
|
||||
onScale(): void
|
||||
checkIsAutoEnterTextEditKey(e: any): boolean
|
||||
registerTmpShortcut(): void
|
||||
showEditTextBox(
|
||||
node: any,
|
||||
rect: any,
|
||||
isInserting: any,
|
||||
isFromKeyDown: any
|
||||
): void
|
||||
focus(): void
|
||||
selectNodeText(): void
|
||||
getEditText(): any
|
||||
hideEditTextBox(): any
|
||||
constructor(renderer: any);
|
||||
renderer: any;
|
||||
mindMap: any;
|
||||
currentNode: any;
|
||||
textEditNode: HTMLDivElement;
|
||||
showTextEdit: boolean;
|
||||
cacheEditingText: string;
|
||||
bindEvent(): void;
|
||||
show(node: any, e: any, isInserting?: boolean, isFromKeyDown?: boolean): Promise<void>;
|
||||
onScale(): void;
|
||||
checkIsAutoEnterTextEditKey(e: any): boolean;
|
||||
registerTmpShortcut(): void;
|
||||
showEditTextBox(node: any, rect: any, isInserting: any, isFromKeyDown: any): void;
|
||||
getEditText(): any;
|
||||
hideEditTextBox(): any;
|
||||
}
|
||||
|
||||
232
simple-mind-map/types/src/core/render/node/Node.d.ts
vendored
232
simple-mind-map/types/src/core/render/node/Node.d.ts
vendored
@@ -1,116 +1,120 @@
|
||||
export default Node
|
||||
export default Node;
|
||||
declare class Node {
|
||||
constructor(opt?: {})
|
||||
nodeData: any
|
||||
uid: any
|
||||
mindMap: any
|
||||
renderer: any
|
||||
draw: any
|
||||
style: Style
|
||||
shapeInstance: Shape
|
||||
shapePadding: {
|
||||
paddingX: number
|
||||
paddingY: number
|
||||
}
|
||||
isRoot: any
|
||||
isGeneralization: any
|
||||
generalizationBelongNode: any
|
||||
layerIndex: any
|
||||
width: any
|
||||
height: any
|
||||
_left: any
|
||||
_top: any
|
||||
customLeft: any
|
||||
customTop: any
|
||||
isDrag: boolean
|
||||
parent: any
|
||||
children: any
|
||||
group: any
|
||||
shapeNode: any
|
||||
hoverNode: any
|
||||
_customNodeContent: any
|
||||
_imgData: any
|
||||
_iconData: any
|
||||
_textData: any
|
||||
_hyperlinkData: any
|
||||
_tagData: any
|
||||
_noteData: any
|
||||
noteEl: any
|
||||
_expandBtn: any
|
||||
_lastExpandBtnType: any
|
||||
_showExpandBtn: boolean
|
||||
_openExpandNode: any
|
||||
_closeExpandNode: any
|
||||
_fillExpandNode: any
|
||||
_lines: any[]
|
||||
_generalizationLine: any
|
||||
_generalizationNode: any
|
||||
_unVisibleRectRegionNode: any
|
||||
_isMouseenter: boolean
|
||||
_rectInfo: {
|
||||
imgContentWidth: number
|
||||
imgContentHeight: number
|
||||
textContentWidth: number
|
||||
textContentHeight: number
|
||||
}
|
||||
_generalizationNodeWidth: number
|
||||
_generalizationNodeHeight: number
|
||||
textContentItemMargin: any
|
||||
blockContentMargin: any
|
||||
expandBtnSize: any
|
||||
isMultipleChoice: boolean
|
||||
needLayout: boolean
|
||||
isHide: boolean
|
||||
set left(arg: any)
|
||||
get left(): any
|
||||
set top(arg: any)
|
||||
get top(): any
|
||||
reset(): void
|
||||
handleData(data: any): any
|
||||
createNodeData(): void
|
||||
getSize(): boolean
|
||||
getNodeRect(): {
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
layout(): void
|
||||
bindGroupEvent(): void
|
||||
active(e: any): void
|
||||
update(): void
|
||||
getNodePosInClient(
|
||||
_left: any,
|
||||
_top: any
|
||||
): {
|
||||
left: any
|
||||
top: any
|
||||
}
|
||||
reRender(): boolean
|
||||
updateNodeActive(): void
|
||||
render(callback?: () => void): void
|
||||
remove(): void
|
||||
destroy(): void
|
||||
hide(): void
|
||||
show(): void
|
||||
renderLine(deep?: boolean): void
|
||||
getShape(): any
|
||||
hasCustomPosition(): boolean
|
||||
ancestorHasCustomPosition(): boolean
|
||||
addChildren(node: any): void
|
||||
styleLine(line: any, node: any): void
|
||||
removeLine(): void
|
||||
isParent(node: any): boolean
|
||||
isBrother(node: any): any
|
||||
getPaddingVale(): {
|
||||
paddingX: any
|
||||
paddingY: any
|
||||
}
|
||||
getStyle(prop: any, root: any): any
|
||||
getSelfStyle(prop: any): any
|
||||
getParentSelfStyle(prop: any): any
|
||||
getSelfInhertStyle(prop: any): any
|
||||
getBorderWidth(): any
|
||||
getData(key: any): any
|
||||
hasCustomStyle(): boolean
|
||||
constructor(opt?: {});
|
||||
nodeData: any;
|
||||
uid: any;
|
||||
mindMap: any;
|
||||
renderer: any;
|
||||
draw: any;
|
||||
style: Style;
|
||||
shapeInstance: Shape;
|
||||
shapePadding: {
|
||||
paddingX: number;
|
||||
paddingY: number;
|
||||
};
|
||||
isRoot: any;
|
||||
isGeneralization: any;
|
||||
generalizationBelongNode: any;
|
||||
layerIndex: any;
|
||||
width: any;
|
||||
height: any;
|
||||
_left: any;
|
||||
_top: any;
|
||||
customLeft: any;
|
||||
customTop: any;
|
||||
isDrag: boolean;
|
||||
parent: any;
|
||||
children: any;
|
||||
userList: any[];
|
||||
group: any;
|
||||
shapeNode: any;
|
||||
hoverNode: any;
|
||||
_customNodeContent: any;
|
||||
_imgData: any;
|
||||
_iconData: any;
|
||||
_textData: any;
|
||||
_hyperlinkData: any;
|
||||
_tagData: any;
|
||||
_noteData: any;
|
||||
noteEl: any;
|
||||
_expandBtn: any;
|
||||
_lastExpandBtnType: any;
|
||||
_showExpandBtn: boolean;
|
||||
_openExpandNode: any;
|
||||
_closeExpandNode: any;
|
||||
_fillExpandNode: any;
|
||||
_userListGroup: any;
|
||||
_lines: any[];
|
||||
_generalizationLine: any;
|
||||
_generalizationNode: any;
|
||||
_unVisibleRectRegionNode: any;
|
||||
_isMouseenter: boolean;
|
||||
_rectInfo: {
|
||||
imgContentWidth: number;
|
||||
imgContentHeight: number;
|
||||
textContentWidth: number;
|
||||
textContentHeight: number;
|
||||
};
|
||||
_generalizationNodeWidth: number;
|
||||
_generalizationNodeHeight: number;
|
||||
textContentItemMargin: any;
|
||||
blockContentMargin: any;
|
||||
expandBtnSize: any;
|
||||
isMultipleChoice: boolean;
|
||||
needLayout: boolean;
|
||||
isHide: boolean;
|
||||
set left(arg: any);
|
||||
get left(): any;
|
||||
set top(arg: any);
|
||||
get top(): any;
|
||||
reset(): void;
|
||||
handleData(data: any): any;
|
||||
createNodeData(): void;
|
||||
getSize(): boolean;
|
||||
getNodeRect(): {
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
layout(): void;
|
||||
bindGroupEvent(): void;
|
||||
active(e: any): void;
|
||||
update(): void;
|
||||
getNodePosInClient(_left: any, _top: any): {
|
||||
left: any;
|
||||
top: any;
|
||||
};
|
||||
reRender(): boolean;
|
||||
updateNodeActive(): void;
|
||||
render(callback?: () => void): void;
|
||||
remove(): void;
|
||||
destroy(): void;
|
||||
hide(): void;
|
||||
show(): void;
|
||||
setOpacity(val: any): void;
|
||||
hideChildren(): void;
|
||||
showChildren(): void;
|
||||
startDrag(): void;
|
||||
endDrag(): void;
|
||||
renderLine(deep?: boolean): void;
|
||||
getShape(): any;
|
||||
hasCustomPosition(): boolean;
|
||||
ancestorHasCustomPosition(): boolean;
|
||||
addChildren(node: any): void;
|
||||
styleLine(line: any, node: any): void;
|
||||
removeLine(): void;
|
||||
isParent(node: any): boolean;
|
||||
isBrother(node: any): any;
|
||||
getPaddingVale(): {
|
||||
paddingX: any;
|
||||
paddingY: any;
|
||||
};
|
||||
getStyle(prop: any, root: any): any;
|
||||
getSelfStyle(prop: any): any;
|
||||
getParentSelfStyle(prop: any): any;
|
||||
getSelfInhertStyle(prop: any): any;
|
||||
getBorderWidth(): any;
|
||||
getData(key: any): any;
|
||||
hasCustomStyle(): boolean;
|
||||
}
|
||||
import Style from './Style'
|
||||
import Shape from './Shape'
|
||||
import Style from "./Style";
|
||||
import Shape from "./Shape";
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
export default class Shape {
|
||||
constructor(node: any)
|
||||
node: any
|
||||
getShapePadding(
|
||||
width: any,
|
||||
height: any,
|
||||
paddingX: any,
|
||||
paddingY: any
|
||||
): {
|
||||
paddingX: number
|
||||
paddingY: number
|
||||
}
|
||||
createShape(): any
|
||||
getNodeSize(): {
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
createRect(): any
|
||||
createDiamond(): any
|
||||
createParallelogram(): any
|
||||
createRoundedRectangle(): any
|
||||
createOctagonalRectangle(): any
|
||||
createOuterTriangularRectangle(): any
|
||||
createInnerTriangularRectangle(): any
|
||||
createEllipse(): any
|
||||
createCircle(): any
|
||||
constructor(node: any);
|
||||
node: any;
|
||||
getShapePadding(width: any, height: any, paddingX: any, paddingY: any): {
|
||||
paddingX: number;
|
||||
paddingY: number;
|
||||
};
|
||||
createShape(): any;
|
||||
getNodeSize(): {
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
createRect(): any;
|
||||
createDiamond(): any;
|
||||
createParallelogram(): any;
|
||||
createRoundedRectangle(): any;
|
||||
createOctagonalRectangle(): any;
|
||||
createOuterTriangularRectangle(): any;
|
||||
createInnerTriangularRectangle(): any;
|
||||
createEllipse(): any;
|
||||
createCircle(): any;
|
||||
}
|
||||
export const shapeList: string[]
|
||||
export const shapeList: string[];
|
||||
|
||||
@@ -1,43 +1,36 @@
|
||||
export default Style
|
||||
export default Style;
|
||||
declare class Style {
|
||||
static setBackgroundStyle(el: any, themeConfig: any): void
|
||||
static removeBackgroundStyle(el: any): void
|
||||
constructor(ctx: any)
|
||||
ctx: any
|
||||
merge(prop: any, root: any): any
|
||||
getStyle(prop: any, root: any): any
|
||||
getSelfStyle(prop: any): any
|
||||
rect(node: any): void
|
||||
shape(node: any): void
|
||||
text(node: any): void
|
||||
createStyleText(): string
|
||||
getTextFontStyle(): {
|
||||
italic: boolean
|
||||
bold: any
|
||||
fontSize: any
|
||||
fontFamily: any
|
||||
}
|
||||
domText(node: any, fontSizeScale: number, isMultiLine: any): void
|
||||
tagText(node: any, index: any): void
|
||||
tagRect(node: any, index: any): void
|
||||
iconNode(node: any): void
|
||||
line(
|
||||
node: any,
|
||||
{
|
||||
width,
|
||||
color,
|
||||
dasharray
|
||||
}?: {
|
||||
width: any
|
||||
color: any
|
||||
dasharray: any
|
||||
}
|
||||
): void
|
||||
generalizationLine(node: any): void
|
||||
iconBtn(node: any, node2: any, fillNode: any): void
|
||||
hasCustomStyle(): boolean
|
||||
hoverNode(node: any): void
|
||||
static setBackgroundStyle(el: any, themeConfig: any): void;
|
||||
static removeBackgroundStyle(el: any): void;
|
||||
constructor(ctx: any);
|
||||
ctx: any;
|
||||
merge(prop: any, root: any): any;
|
||||
getStyle(prop: any, root: any): any;
|
||||
getSelfStyle(prop: any): any;
|
||||
rect(node: any): void;
|
||||
shape(node: any): void;
|
||||
text(node: any): void;
|
||||
createStyleText(): string;
|
||||
getTextFontStyle(): {
|
||||
italic: boolean;
|
||||
bold: any;
|
||||
fontSize: any;
|
||||
fontFamily: any;
|
||||
};
|
||||
domText(node: any, fontSizeScale: number, isMultiLine: any): void;
|
||||
tagText(node: any): void;
|
||||
tagRect(node: any, text: any, color: any): void;
|
||||
iconNode(node: any): void;
|
||||
line(node: any, { width, color, dasharray }?: {
|
||||
width: any;
|
||||
color: any;
|
||||
dasharray: any;
|
||||
}): void;
|
||||
generalizationLine(node: any): void;
|
||||
iconBtn(node: any, node2: any, fillNode: any): void;
|
||||
hasCustomStyle(): boolean;
|
||||
hoverNode(node: any): void;
|
||||
}
|
||||
declare namespace Style {
|
||||
let cacheStyle: any
|
||||
const cacheStyle: any;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
declare namespace _default {
|
||||
export { setData }
|
||||
export { setText }
|
||||
export { setImage }
|
||||
export { setIcon }
|
||||
export { setHyperlink }
|
||||
export { setNote }
|
||||
export { setTag }
|
||||
export { setShape }
|
||||
export { setStyle }
|
||||
export { setStyles }
|
||||
export { setData };
|
||||
export { setText };
|
||||
export { setImage };
|
||||
export { setIcon };
|
||||
export { setHyperlink };
|
||||
export { setNote };
|
||||
export { setTag };
|
||||
export { setShape };
|
||||
export { setStyle };
|
||||
export { setStyles };
|
||||
}
|
||||
export default _default
|
||||
declare function setData(data?: {}): void
|
||||
declare function setText(text: any, richText: any, resetRichText: any): void
|
||||
declare function setImage(imgData: any): void
|
||||
declare function setIcon(icons: any): void
|
||||
declare function setHyperlink(link: any, title: any): void
|
||||
declare function setNote(note: any): void
|
||||
declare function setTag(tag: any): void
|
||||
declare function setShape(shape: any): void
|
||||
declare function setStyle(prop: any, value: any): void
|
||||
declare function setStyles(style: any): void
|
||||
export default _default;
|
||||
declare function setData(data?: {}): void;
|
||||
declare function setText(text: any, richText: any, resetRichText: any): void;
|
||||
declare function setImage(imgData: any): void;
|
||||
declare function setIcon(icons: any): void;
|
||||
declare function setHyperlink(link: any, title: any): void;
|
||||
declare function setNote(note: any): void;
|
||||
declare function setTag(tag: any): void;
|
||||
declare function setShape(shape: any): void;
|
||||
declare function setStyle(prop: any, value: any): void;
|
||||
declare function setStyles(style: any): void;
|
||||
|
||||
18
simple-mind-map/types/src/core/render/node/nodeCooperate.d.ts
vendored
Normal file
18
simple-mind-map/types/src/core/render/node/nodeCooperate.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
declare namespace _default {
|
||||
export { createUserListNode };
|
||||
export { updateUserListNode };
|
||||
export { createTextAvatar };
|
||||
export { createImageAvatar };
|
||||
export { addUser };
|
||||
export { removeUser };
|
||||
}
|
||||
export default _default;
|
||||
declare function createUserListNode(): void;
|
||||
declare class createUserListNode {
|
||||
_userListGroup: any;
|
||||
}
|
||||
declare function updateUserListNode(): void;
|
||||
declare function createTextAvatar(item: any): any;
|
||||
declare function createImageAvatar(item: any): any;
|
||||
declare function addUser(userInfo: any): void;
|
||||
declare function removeUser(userInfo: any): void;
|
||||
@@ -1,45 +1,45 @@
|
||||
declare namespace _default {
|
||||
export { createImgNode }
|
||||
export { getImgShowSize }
|
||||
export { createIconNode }
|
||||
export { createRichTextNode }
|
||||
export { createTextNode }
|
||||
export { createHyperlinkNode }
|
||||
export { createTagNode }
|
||||
export { createNoteNode }
|
||||
export { measureCustomNodeContentSize }
|
||||
export { isUseCustomNodeContent }
|
||||
export { createImgNode };
|
||||
export { getImgShowSize };
|
||||
export { createIconNode };
|
||||
export { createRichTextNode };
|
||||
export { createTextNode };
|
||||
export { createHyperlinkNode };
|
||||
export { createTagNode };
|
||||
export { createNoteNode };
|
||||
export { measureCustomNodeContentSize };
|
||||
export { isUseCustomNodeContent };
|
||||
}
|
||||
export default _default
|
||||
export default _default;
|
||||
declare function createImgNode(): {
|
||||
node: any
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
declare function getImgShowSize(): any
|
||||
declare function createIconNode(): any
|
||||
node: any;
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
declare function getImgShowSize(): any;
|
||||
declare function createIconNode(): any;
|
||||
declare function createRichTextNode(): {
|
||||
node: any
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
declare function createTextNode(): any
|
||||
node: any;
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
declare function createTextNode(): any;
|
||||
declare function createHyperlinkNode(): {
|
||||
node: any
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
declare function createTagNode(): any[]
|
||||
node: any;
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
declare function createTagNode(): any[];
|
||||
declare function createNoteNode(): {
|
||||
node: any
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
node: any;
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
declare class createNoteNode {
|
||||
noteEl: HTMLDivElement
|
||||
noteEl: HTMLDivElement;
|
||||
}
|
||||
declare function measureCustomNodeContentSize(content: any): {
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
declare function isUseCustomNodeContent(): boolean
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
declare function isUseCustomNodeContent(): boolean;
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
declare namespace _default {
|
||||
export { createExpandNodeContent }
|
||||
export { updateExpandBtnNode }
|
||||
export { updateExpandBtnPos }
|
||||
export { renderExpandBtn }
|
||||
export { removeExpandBtn }
|
||||
export { showExpandBtn }
|
||||
export { hideExpandBtn }
|
||||
export { sumNode }
|
||||
export { createExpandNodeContent };
|
||||
export { updateExpandBtnNode };
|
||||
export { updateExpandBtnPos };
|
||||
export { renderExpandBtn };
|
||||
export { removeExpandBtn };
|
||||
export { showExpandBtn };
|
||||
export { hideExpandBtn };
|
||||
export { sumNode };
|
||||
}
|
||||
export default _default
|
||||
declare function createExpandNodeContent(): void
|
||||
export default _default;
|
||||
declare function createExpandNodeContent(): void;
|
||||
declare class createExpandNodeContent {
|
||||
_openExpandNode: any
|
||||
_closeExpandNode: any
|
||||
_fillExpandNode: any
|
||||
_openExpandNode: any;
|
||||
_closeExpandNode: any;
|
||||
_fillExpandNode: any;
|
||||
}
|
||||
declare function updateExpandBtnNode(): void
|
||||
declare function updateExpandBtnNode(): void;
|
||||
declare class updateExpandBtnNode {
|
||||
_lastExpandBtnType: boolean
|
||||
_lastExpandBtnType: boolean;
|
||||
}
|
||||
declare function updateExpandBtnPos(): void
|
||||
declare function renderExpandBtn(): void
|
||||
declare function updateExpandBtnPos(): void;
|
||||
declare function renderExpandBtn(): void;
|
||||
declare class renderExpandBtn {
|
||||
_expandBtn: any
|
||||
_showExpandBtn: boolean
|
||||
_expandBtn: any;
|
||||
_showExpandBtn: boolean;
|
||||
}
|
||||
declare function removeExpandBtn(): void
|
||||
declare function removeExpandBtn(): void;
|
||||
declare class removeExpandBtn {
|
||||
_showExpandBtn: boolean
|
||||
_showExpandBtn: boolean;
|
||||
}
|
||||
declare function showExpandBtn(): void
|
||||
declare function hideExpandBtn(): void
|
||||
declare function sumNode(data?: any[]): any
|
||||
declare function showExpandBtn(): void;
|
||||
declare function hideExpandBtn(): void;
|
||||
declare function sumNode(data?: any[]): any;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
declare namespace _default {
|
||||
export { renderExpandBtnPlaceholderRect }
|
||||
export { clearExpandBtnPlaceholderRect }
|
||||
export { updateExpandBtnPlaceholderRect }
|
||||
export { renderExpandBtnPlaceholderRect };
|
||||
export { clearExpandBtnPlaceholderRect };
|
||||
export { updateExpandBtnPlaceholderRect };
|
||||
}
|
||||
export default _default
|
||||
declare function renderExpandBtnPlaceholderRect(): void
|
||||
export default _default;
|
||||
declare function renderExpandBtnPlaceholderRect(): void;
|
||||
declare class renderExpandBtnPlaceholderRect {
|
||||
_unVisibleRectRegionNode: any
|
||||
_unVisibleRectRegionNode: any;
|
||||
}
|
||||
declare function clearExpandBtnPlaceholderRect(): void
|
||||
declare function clearExpandBtnPlaceholderRect(): void;
|
||||
declare class clearExpandBtnPlaceholderRect {
|
||||
_unVisibleRectRegionNode: any
|
||||
_unVisibleRectRegionNode: any;
|
||||
}
|
||||
declare function updateExpandBtnPlaceholderRect(): void
|
||||
declare function updateExpandBtnPlaceholderRect(): void;
|
||||
declare class updateExpandBtnPlaceholderRect {
|
||||
needRerenderExpandBtnPlaceholderRect: boolean
|
||||
needRerenderExpandBtnPlaceholderRect: boolean;
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
declare namespace _default {
|
||||
export { checkHasGeneralization }
|
||||
export { createGeneralizationNode }
|
||||
export { updateGeneralization }
|
||||
export { renderGeneralization }
|
||||
export { removeGeneralization }
|
||||
export { hideGeneralization }
|
||||
export { showGeneralization }
|
||||
export { checkHasGeneralization };
|
||||
export { createGeneralizationNode };
|
||||
export { updateGeneralization };
|
||||
export { renderGeneralization };
|
||||
export { removeGeneralization };
|
||||
export { hideGeneralization };
|
||||
export { showGeneralization };
|
||||
}
|
||||
export default _default
|
||||
declare function checkHasGeneralization(): boolean
|
||||
declare function createGeneralizationNode(): void
|
||||
export default _default;
|
||||
declare function checkHasGeneralization(): boolean;
|
||||
declare function createGeneralizationNode(): void;
|
||||
declare class createGeneralizationNode {
|
||||
_generalizationLine: any
|
||||
_generalizationNode: Node
|
||||
_generalizationNodeWidth: any
|
||||
_generalizationNodeHeight: any
|
||||
_generalizationLine: any;
|
||||
_generalizationNode: Node;
|
||||
_generalizationNodeWidth: any;
|
||||
_generalizationNodeHeight: any;
|
||||
}
|
||||
declare function updateGeneralization(): void
|
||||
declare function renderGeneralization(): void
|
||||
declare function updateGeneralization(): void;
|
||||
declare function renderGeneralization(): void;
|
||||
declare class renderGeneralization {
|
||||
_generalizationNodeWidth: number
|
||||
_generalizationNodeHeight: number
|
||||
_generalizationNodeWidth: number;
|
||||
_generalizationNodeHeight: number;
|
||||
}
|
||||
declare function removeGeneralization(): void
|
||||
declare function removeGeneralization(): void;
|
||||
declare class removeGeneralization {
|
||||
_generalizationLine: any
|
||||
_generalizationNode: any
|
||||
_generalizationLine: any;
|
||||
_generalizationNode: any;
|
||||
}
|
||||
declare function hideGeneralization(): void
|
||||
declare function showGeneralization(): void
|
||||
import Node from './Node'
|
||||
declare function hideGeneralization(): void;
|
||||
declare function showGeneralization(): void;
|
||||
import Node from "./Node";
|
||||
|
||||
68
simple-mind-map/types/src/core/view/View.d.ts
vendored
68
simple-mind-map/types/src/core/view/View.d.ts
vendored
@@ -1,36 +1,36 @@
|
||||
export default View
|
||||
export default View;
|
||||
declare class View {
|
||||
constructor(opt?: {})
|
||||
opt: {}
|
||||
mindMap: any
|
||||
scale: number
|
||||
sx: number
|
||||
sy: number
|
||||
x: number
|
||||
y: number
|
||||
firstDrag: boolean
|
||||
bind(): void
|
||||
getTransformData(): {
|
||||
transform: any
|
||||
state: {
|
||||
scale: number
|
||||
x: number
|
||||
y: number
|
||||
sx: number
|
||||
sy: number
|
||||
}
|
||||
}
|
||||
setTransformData(viewData: any): void
|
||||
translateXY(x: any, y: any): void
|
||||
translateX(step: any): void
|
||||
translateXTo(x: any): void
|
||||
translateY(step: any): void
|
||||
translateYTo(y: any): void
|
||||
transform(): void
|
||||
reset(): void
|
||||
narrow(cx: any, cy: any, isTouchPad: any): void
|
||||
enlarge(cx: any, cy: any, isTouchPad: any): void
|
||||
scaleInCenter(scale: any, cx: any, cy: any): void
|
||||
setScale(scale: any, cx: any, cy: any): void
|
||||
fit(): void
|
||||
constructor(opt?: {});
|
||||
opt: {};
|
||||
mindMap: any;
|
||||
scale: number;
|
||||
sx: number;
|
||||
sy: number;
|
||||
x: number;
|
||||
y: number;
|
||||
firstDrag: boolean;
|
||||
bind(): void;
|
||||
getTransformData(): {
|
||||
transform: any;
|
||||
state: {
|
||||
scale: number;
|
||||
x: number;
|
||||
y: number;
|
||||
sx: number;
|
||||
sy: number;
|
||||
};
|
||||
};
|
||||
setTransformData(viewData: any): void;
|
||||
translateXY(x: any, y: any): void;
|
||||
translateX(step: any): void;
|
||||
translateXTo(x: any): void;
|
||||
translateY(step: any): void;
|
||||
translateYTo(y: any): void;
|
||||
transform(): void;
|
||||
reset(): void;
|
||||
narrow(cx: any, cy: any, isTouchPad: any): void;
|
||||
enlarge(cx: any, cy: any, isTouchPad: any): void;
|
||||
scaleInCenter(scale: any, cx: any, cy: any): void;
|
||||
setScale(scale: any, cx: any, cy: any): void;
|
||||
fit(): void;
|
||||
}
|
||||
|
||||
85
simple-mind-map/types/src/layouts/Base.d.ts
vendored
85
simple-mind-map/types/src/layouts/Base.d.ts
vendored
@@ -1,46 +1,43 @@
|
||||
export default Base
|
||||
export default Base;
|
||||
declare class Base {
|
||||
constructor(renderer: any)
|
||||
renderer: any
|
||||
mindMap: any
|
||||
draw: any
|
||||
root: any
|
||||
lru: Lru
|
||||
doLayout(): void
|
||||
renderLine(): void
|
||||
renderExpandBtn(): void
|
||||
renderGeneralization(): void
|
||||
cacheNode(uid: any, node: any): void
|
||||
checkIsNeedResizeSources(): boolean
|
||||
checkIsLayerTypeChange(oldIndex: any, newIndex: any): boolean
|
||||
checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(node: any): void
|
||||
createNode(data: any, parent: any, isRoot: any, layerIndex: any): any
|
||||
formatPosition(value: any, size: any, nodeSize: any): number
|
||||
setNodeCenter(node: any): void
|
||||
updateChildren(children: any, prop: any, offset: any): void
|
||||
updateChildrenPro(children: any, props: any): void
|
||||
getNodeAreaWidth(node: any, withGeneralization?: boolean): number
|
||||
quadraticCurvePath(x1: any, y1: any, x2: any, y2: any): string
|
||||
cubicBezierPath(x1: any, y1: any, x2: any, y2: any): string
|
||||
getMarginX(layerIndex: any): any
|
||||
getMarginY(layerIndex: any): any
|
||||
getNodeWidthWithGeneralization(node: any): number
|
||||
getNodeHeightWithGeneralization(node: any): number
|
||||
/**
|
||||
* dir:生长方向,h(水平)、v(垂直)
|
||||
* isLeft:是否向左生长
|
||||
*/
|
||||
getNodeBoundaries(
|
||||
node: any,
|
||||
dir: any
|
||||
): {
|
||||
left: any
|
||||
right: any
|
||||
top: any
|
||||
bottom: any
|
||||
generalizationLineMargin: any
|
||||
generalizationNodeMargin: any
|
||||
}
|
||||
getNodeActChildrenLength(node: any): any
|
||||
constructor(renderer: any);
|
||||
renderer: any;
|
||||
mindMap: any;
|
||||
draw: any;
|
||||
root: any;
|
||||
lru: Lru;
|
||||
doLayout(): void;
|
||||
renderLine(): void;
|
||||
renderExpandBtn(): void;
|
||||
renderGeneralization(): void;
|
||||
cacheNode(uid: any, node: any): void;
|
||||
checkIsNeedResizeSources(): boolean;
|
||||
checkIsLayerTypeChange(oldIndex: any, newIndex: any): boolean;
|
||||
checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(node: any): void;
|
||||
createNode(data: any, parent: any, isRoot: any, layerIndex: any): any;
|
||||
formatPosition(value: any, size: any, nodeSize: any): number;
|
||||
setNodeCenter(node: any): void;
|
||||
updateChildren(children: any, prop: any, offset: any): void;
|
||||
updateChildrenPro(children: any, props: any): void;
|
||||
getNodeAreaWidth(node: any, withGeneralization?: boolean): number;
|
||||
quadraticCurvePath(x1: any, y1: any, x2: any, y2: any): string;
|
||||
cubicBezierPath(x1: any, y1: any, x2: any, y2: any): string;
|
||||
getMarginX(layerIndex: any): any;
|
||||
getMarginY(layerIndex: any): any;
|
||||
getNodeWidthWithGeneralization(node: any): number;
|
||||
getNodeHeightWithGeneralization(node: any): number;
|
||||
/**
|
||||
* dir:生长方向,h(水平)、v(垂直)
|
||||
* isLeft:是否向左生长
|
||||
*/
|
||||
getNodeBoundaries(node: any, dir: any): {
|
||||
left: any;
|
||||
right: any;
|
||||
top: any;
|
||||
bottom: any;
|
||||
generalizationLineMargin: any;
|
||||
generalizationNodeMargin: any;
|
||||
};
|
||||
getNodeActChildrenLength(node: any): any;
|
||||
}
|
||||
import Lru from '../utils/Lru'
|
||||
import Lru from "../utils/Lru";
|
||||
|
||||
@@ -1,21 +1,11 @@
|
||||
export default CatalogOrganization
|
||||
export default CatalogOrganization;
|
||||
declare class CatalogOrganization extends Base {
|
||||
constructor(opt?: {})
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedLeftTopValue(): void
|
||||
adjustLeftTopValue(): void
|
||||
updateBrothersLeft(node: any, addWidth: any): void
|
||||
updateBrothersTop(node: any, addHeight: any): void
|
||||
renderLine(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt?: {});
|
||||
computedBaseValue(): void;
|
||||
computedLeftTopValue(): void;
|
||||
adjustLeftTopValue(): void;
|
||||
updateBrothersLeft(node: any, addWidth: any): void;
|
||||
updateBrothersTop(node: any, addHeight: any): void;
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
36
simple-mind-map/types/src/layouts/Fishbone.d.ts
vendored
36
simple-mind-map/types/src/layouts/Fishbone.d.ts
vendored
@@ -1,25 +1,15 @@
|
||||
export default Fishbone
|
||||
export default Fishbone;
|
||||
declare class Fishbone extends Base {
|
||||
constructor(opt?: {})
|
||||
indent: number
|
||||
childIndent: number
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedLeftTopValue(): void
|
||||
adjustLeftTopValue(): void
|
||||
getNodeAreaHeight(node: any): number
|
||||
updateBrothersLeft(node: any): void
|
||||
updateBrothersTop(node: any, addHeight: any): void
|
||||
checkIsTop(node: any): boolean
|
||||
renderLine(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt?: {});
|
||||
indent: number;
|
||||
childIndent: number;
|
||||
computedBaseValue(): void;
|
||||
computedLeftTopValue(): void;
|
||||
adjustLeftTopValue(): void;
|
||||
getNodeAreaHeight(node: any): number;
|
||||
updateBrothersLeft(node: any): void;
|
||||
updateBrothersTop(node: any, addHeight: any): void;
|
||||
checkIsTop(node: any): boolean;
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
export default LogicalStructure
|
||||
export default LogicalStructure;
|
||||
declare class LogicalStructure extends Base {
|
||||
constructor(opt?: {})
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedTopValue(): void
|
||||
adjustTopValue(): void
|
||||
updateBrothers(node: any, addHeight: any): void
|
||||
renderLine(node: any, lines: any, style: any, lineStyle: any): void
|
||||
renderLineStraight(node: any, lines: any, style: any): any[]
|
||||
renderLineDirect(node: any, lines: any, style: any): any[]
|
||||
renderLineCurve(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt?: {});
|
||||
computedBaseValue(): void;
|
||||
computedTopValue(): void;
|
||||
adjustTopValue(): void;
|
||||
updateBrothers(node: any, addHeight: any): void;
|
||||
renderLineStraight(node: any, lines: any, style: any): any[];
|
||||
renderLineDirect(node: any, lines: any, style: any): any[];
|
||||
renderLineCurve(node: any, lines: any, style: any): any[];
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
32
simple-mind-map/types/src/layouts/MindMap.d.ts
vendored
32
simple-mind-map/types/src/layouts/MindMap.d.ts
vendored
@@ -1,23 +1,13 @@
|
||||
export default MindMap
|
||||
export default MindMap;
|
||||
declare class MindMap extends Base {
|
||||
constructor(opt?: {})
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedTopValue(): void
|
||||
adjustTopValue(): void
|
||||
updateBrothers(node: any, leftAddHeight: any, rightAddHeight: any): void
|
||||
renderLine(node: any, lines: any, style: any, lineStyle: any): void
|
||||
renderLineStraight(node: any, lines: any, style: any): any[]
|
||||
renderLineDirect(node: any, lines: any, style: any): any[]
|
||||
renderLineCurve(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt?: {});
|
||||
computedBaseValue(): void;
|
||||
computedTopValue(): void;
|
||||
adjustTopValue(): void;
|
||||
updateBrothers(node: any, leftAddHeight: any, rightAddHeight: any): void;
|
||||
renderLineStraight(node: any, lines: any, style: any): any[];
|
||||
renderLineDirect(node: any, lines: any, style: any): any[];
|
||||
renderLineCurve(node: any, lines: any, style: any): any[];
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
export default OrganizationStructure
|
||||
export default OrganizationStructure;
|
||||
declare class OrganizationStructure extends Base {
|
||||
constructor(opt?: {})
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedLeftValue(): void
|
||||
adjustLeftValue(): void
|
||||
updateBrothers(node: any, addWidth: any): void
|
||||
renderLine(node: any, lines: any, style: any, lineStyle: any): void
|
||||
renderLineDirect(node: any, lines: any, style: any): any[]
|
||||
renderLineStraight(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt?: {});
|
||||
computedBaseValue(): void;
|
||||
computedLeftValue(): void;
|
||||
adjustLeftValue(): void;
|
||||
updateBrothers(node: any, addWidth: any): void;
|
||||
renderLineDirect(node: any, lines: any, style: any): any[];
|
||||
renderLineStraight(node: any, lines: any, style: any): any[];
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
32
simple-mind-map/types/src/layouts/Timeline.d.ts
vendored
32
simple-mind-map/types/src/layouts/Timeline.d.ts
vendored
@@ -1,23 +1,13 @@
|
||||
export default Timeline
|
||||
export default Timeline;
|
||||
declare class Timeline extends Base {
|
||||
constructor(opt: {}, layout: any)
|
||||
layout: any
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedLeftTopValue(): void
|
||||
adjustLeftTopValue(): void
|
||||
getNodeAreaHeight(node: any): number
|
||||
updateBrothersLeft(node: any): void
|
||||
updateBrothersTop(node: any, addHeight: any): void
|
||||
renderLine(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt: {}, layout: any);
|
||||
layout: any;
|
||||
computedBaseValue(): void;
|
||||
computedLeftTopValue(): void;
|
||||
adjustLeftTopValue(): void;
|
||||
getNodeAreaHeight(node: any): number;
|
||||
updateBrothersLeft(node: any): void;
|
||||
updateBrothersTop(node: any, addHeight: any): void;
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
export default VerticalTimeline
|
||||
export default VerticalTimeline;
|
||||
declare class VerticalTimeline extends Base {
|
||||
constructor(opt: {}, layout: any)
|
||||
layout: any
|
||||
doLayout(callback: any): void
|
||||
computedBaseValue(): void
|
||||
computedTopValue(): void
|
||||
adjustLeftTopValue(): void
|
||||
updateBrothers(node: any, addHeight: any): void
|
||||
updateBrothersTop(node: any, addHeight: any): void
|
||||
renderLine(node: any, lines: any, style: any, lineStyle: any): void
|
||||
renderLineStraight(node: any, lines: any, style: any): any[]
|
||||
renderLineDirect(node: any, lines: any, style: any): any[]
|
||||
renderLineCurve(node: any, lines: any, style: any): any[]
|
||||
renderExpandBtn(node: any, btn: any): void
|
||||
renderGeneralization(node: any, gLine: any, gNode: any): void
|
||||
renderExpandBtnRect(
|
||||
rect: any,
|
||||
expandBtnSize: any,
|
||||
width: any,
|
||||
height: any,
|
||||
node: any
|
||||
): void
|
||||
constructor(opt: {}, layout: any);
|
||||
layout: any;
|
||||
computedBaseValue(): void;
|
||||
computedTopValue(): void;
|
||||
adjustLeftTopValue(): void;
|
||||
updateBrothers(node: any, addHeight: any): void;
|
||||
updateBrothersTop(node: any, addHeight: any): void;
|
||||
renderLineStraight(node: any, lines: any, style: any): any[];
|
||||
renderLineDirect(node: any, lines: any, style: any): any[];
|
||||
renderLineCurve(node: any, lines: any, style: any): any[];
|
||||
renderExpandBtnRect(rect: any, expandBtnSize: any, width: any, height: any, node: any): void;
|
||||
}
|
||||
import Base from './Base'
|
||||
import Base from "./Base";
|
||||
|
||||
280
simple-mind-map/types/src/layouts/fishboneUtils.d.ts
vendored
280
simple-mind-map/types/src/layouts/fishboneUtils.d.ts
vendored
@@ -1,137 +1,147 @@
|
||||
declare namespace _default {
|
||||
namespace top {
|
||||
function renderExpandBtn({
|
||||
node,
|
||||
btn,
|
||||
expandBtnSize,
|
||||
translateX,
|
||||
translateY,
|
||||
width,
|
||||
height
|
||||
}: {
|
||||
node: any
|
||||
btn: any
|
||||
expandBtnSize: any
|
||||
translateX: any
|
||||
translateY: any
|
||||
width: any
|
||||
height: any
|
||||
}): void
|
||||
function renderLine({
|
||||
node,
|
||||
line,
|
||||
top,
|
||||
x,
|
||||
lineLength,
|
||||
height,
|
||||
expandBtnSize,
|
||||
maxy,
|
||||
ctx
|
||||
}: {
|
||||
node: any
|
||||
line: any
|
||||
top: any
|
||||
x: any
|
||||
lineLength: any
|
||||
height: any
|
||||
expandBtnSize: any
|
||||
maxy: any
|
||||
ctx: any
|
||||
}): void
|
||||
function computedLeftTopValue({
|
||||
layerIndex,
|
||||
node,
|
||||
ctx
|
||||
}: {
|
||||
layerIndex: any
|
||||
node: any
|
||||
ctx: any
|
||||
}): void
|
||||
function adjustLeftTopValueBefore({
|
||||
node,
|
||||
parent,
|
||||
ctx,
|
||||
layerIndex
|
||||
}: {
|
||||
node: any
|
||||
parent: any
|
||||
ctx: any
|
||||
layerIndex: any
|
||||
}): void
|
||||
function adjustLeftTopValueAfter({
|
||||
parent,
|
||||
node,
|
||||
ctx
|
||||
}: {
|
||||
parent: any
|
||||
node: any
|
||||
ctx: any
|
||||
}): void
|
||||
}
|
||||
namespace bottom {
|
||||
function renderExpandBtn({
|
||||
node,
|
||||
btn,
|
||||
expandBtnSize,
|
||||
translateX,
|
||||
translateY,
|
||||
width,
|
||||
height
|
||||
}: {
|
||||
node: any
|
||||
btn: any
|
||||
expandBtnSize: any
|
||||
translateX: any
|
||||
translateY: any
|
||||
width: any
|
||||
height: any
|
||||
}): void
|
||||
function renderLine({
|
||||
node,
|
||||
line,
|
||||
top,
|
||||
x,
|
||||
lineLength,
|
||||
height,
|
||||
miny,
|
||||
ctx
|
||||
}: {
|
||||
node: any
|
||||
line: any
|
||||
top: any
|
||||
x: any
|
||||
lineLength: any
|
||||
height: any
|
||||
miny: any
|
||||
ctx: any
|
||||
}): void
|
||||
function computedLeftTopValue({
|
||||
layerIndex,
|
||||
node,
|
||||
ctx
|
||||
}: {
|
||||
layerIndex: any
|
||||
node: any
|
||||
ctx: any
|
||||
}): void
|
||||
function adjustLeftTopValueBefore({
|
||||
node,
|
||||
ctx,
|
||||
layerIndex
|
||||
}: {
|
||||
node: any
|
||||
ctx: any
|
||||
layerIndex: any
|
||||
}): void
|
||||
function adjustLeftTopValueAfter({
|
||||
parent,
|
||||
node,
|
||||
ctx
|
||||
}: {
|
||||
parent: any
|
||||
node: any
|
||||
ctx: any
|
||||
}): void
|
||||
}
|
||||
namespace top {
|
||||
function renderExpandBtn({ node, btn, expandBtnSize, translateX, translateY, width, height }: {
|
||||
node: any;
|
||||
btn: any;
|
||||
expandBtnSize: any;
|
||||
translateX: any;
|
||||
translateY: any;
|
||||
width: any;
|
||||
height: any;
|
||||
}): void;
|
||||
function renderExpandBtn({ node, btn, expandBtnSize, translateX, translateY, width, height }: {
|
||||
node: any;
|
||||
btn: any;
|
||||
expandBtnSize: any;
|
||||
translateX: any;
|
||||
translateY: any;
|
||||
width: any;
|
||||
height: any;
|
||||
}): void;
|
||||
function renderLine({ node, line, top, x, lineLength, height, expandBtnSize, maxy, ctx }: {
|
||||
node: any;
|
||||
line: any;
|
||||
top: any;
|
||||
x: any;
|
||||
lineLength: any;
|
||||
height: any;
|
||||
expandBtnSize: any;
|
||||
maxy: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function renderLine({ node, line, top, x, lineLength, height, expandBtnSize, maxy, ctx }: {
|
||||
node: any;
|
||||
line: any;
|
||||
top: any;
|
||||
x: any;
|
||||
lineLength: any;
|
||||
height: any;
|
||||
expandBtnSize: any;
|
||||
maxy: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function computedLeftTopValue({ layerIndex, node, ctx }: {
|
||||
layerIndex: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function computedLeftTopValue({ layerIndex, node, ctx }: {
|
||||
layerIndex: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueBefore({ node, parent, ctx, layerIndex }: {
|
||||
node: any;
|
||||
parent: any;
|
||||
ctx: any;
|
||||
layerIndex: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueBefore({ node, parent, ctx, layerIndex }: {
|
||||
node: any;
|
||||
parent: any;
|
||||
ctx: any;
|
||||
layerIndex: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueAfter({ parent, node, ctx }: {
|
||||
parent: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueAfter({ parent, node, ctx }: {
|
||||
parent: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
}
|
||||
namespace bottom {
|
||||
function renderExpandBtn({ node, btn, expandBtnSize, translateX, translateY, width, height }: {
|
||||
node: any;
|
||||
btn: any;
|
||||
expandBtnSize: any;
|
||||
translateX: any;
|
||||
translateY: any;
|
||||
width: any;
|
||||
height: any;
|
||||
}): void;
|
||||
function renderExpandBtn({ node, btn, expandBtnSize, translateX, translateY, width, height }: {
|
||||
node: any;
|
||||
btn: any;
|
||||
expandBtnSize: any;
|
||||
translateX: any;
|
||||
translateY: any;
|
||||
width: any;
|
||||
height: any;
|
||||
}): void;
|
||||
function renderLine({ node, line, top, x, lineLength, height, miny, ctx }: {
|
||||
node: any;
|
||||
line: any;
|
||||
top: any;
|
||||
x: any;
|
||||
lineLength: any;
|
||||
height: any;
|
||||
miny: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function renderLine({ node, line, top, x, lineLength, height, miny, ctx }: {
|
||||
node: any;
|
||||
line: any;
|
||||
top: any;
|
||||
x: any;
|
||||
lineLength: any;
|
||||
height: any;
|
||||
miny: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function computedLeftTopValue({ layerIndex, node, ctx }: {
|
||||
layerIndex: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function computedLeftTopValue({ layerIndex, node, ctx }: {
|
||||
layerIndex: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueBefore({ node, ctx, layerIndex }: {
|
||||
node: any;
|
||||
ctx: any;
|
||||
layerIndex: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueBefore({ node, ctx, layerIndex }: {
|
||||
node: any;
|
||||
ctx: any;
|
||||
layerIndex: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueAfter({ parent, node, ctx }: {
|
||||
parent: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
function adjustLeftTopValueAfter({ parent, node, ctx }: {
|
||||
parent: any;
|
||||
node: any;
|
||||
ctx: any;
|
||||
}): void;
|
||||
}
|
||||
}
|
||||
export default _default
|
||||
export default _default;
|
||||
|
||||
18
simple-mind-map/types/src/svg/btns.d.ts
vendored
18
simple-mind-map/types/src/svg/btns.d.ts
vendored
@@ -1,11 +1,11 @@
|
||||
declare namespace _default {
|
||||
export { open }
|
||||
export { close }
|
||||
export { remove }
|
||||
export { imgAdjust }
|
||||
export { open };
|
||||
export { close };
|
||||
export { remove };
|
||||
export { imgAdjust };
|
||||
}
|
||||
export default _default
|
||||
declare const open: '<svg t="1618141562310" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13476" width="200" height="200"><path d="M475.136 327.168v147.968h-147.968v74.24h147.968v147.968h74.24v-147.968h147.968v-74.24h-147.968v-147.968h-74.24z m36.864-222.208c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13477"></path></svg>'
|
||||
declare const close: '<svg t="1618141589243" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13611" width="200" height="200"><path d="M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13612"></path><path d="M252.928 474.624h518.144v74.24h-518.144z" p-id="13613"></path></svg>'
|
||||
declare const remove: '<svg width="14px" height="14px" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13611" width="200" height="200"><path fill="#ffffff" d="M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z" p-id="13612"></path><path fill="#ffffff" d="M252.928 474.624h518.144v74.24h-518.144z" p-id="13613"></path></svg>'
|
||||
declare const imgAdjust: '<svg width="12px" height="12px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path fill="#ffffff" d="M1008.128 614.4a25.6 25.6 0 0 0-27.648 5.632l-142.848 142.848L259.072 186.88 401.92 43.52A25.6 25.6 0 0 0 384 0h-358.4a25.6 25.6 0 0 0-25.6 25.6v358.4a25.6 25.6 0 0 0 43.52 17.92l143.36-142.848 578.048 578.048-142.848 142.848a25.6 25.6 0 0 0 17.92 43.52h358.4a25.6 25.6 0 0 0 25.6-25.6v-358.4a25.6 25.6 0 0 0-15.872-25.088z" /></svg>'
|
||||
export default _default;
|
||||
declare const open: "<svg t=\"1618141562310\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13476\" width=\"200\" height=\"200\"><path d=\"M475.136 327.168v147.968h-147.968v74.24h147.968v147.968h74.24v-147.968h147.968v-74.24h-147.968v-147.968h-74.24z m36.864-222.208c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z\" p-id=\"13477\"></path></svg>";
|
||||
declare const close: "<svg t=\"1618141589243\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13611\" width=\"200\" height=\"200\"><path d=\"M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z\" p-id=\"13612\"></path><path d=\"M252.928 474.624h518.144v74.24h-518.144z\" p-id=\"13613\"></path></svg>";
|
||||
declare const remove: "<svg width=\"14px\" height=\"14px\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13611\" width=\"200\" height=\"200\"><path fill=\"#ffffff\" d=\"M512 105.472c225.28 0 407.04 181.76 407.04 407.04s-181.76 407.04-407.04 407.04-407.04-181.76-407.04-407.04 181.76-407.04 407.04-407.04z m0-74.24c-265.216 0-480.768 215.552-480.768 480.768s215.552 480.768 480.768 480.768 480.768-215.552 480.768-480.768-215.552-480.768-480.768-480.768z\" p-id=\"13612\"></path><path fill=\"#ffffff\" d=\"M252.928 474.624h518.144v74.24h-518.144z\" p-id=\"13613\"></path></svg>";
|
||||
declare const imgAdjust: "<svg width=\"12px\" height=\"12px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path fill=\"#ffffff\" d=\"M1008.128 614.4a25.6 25.6 0 0 0-27.648 5.632l-142.848 142.848L259.072 186.88 401.92 43.52A25.6 25.6 0 0 0 384 0h-358.4a25.6 25.6 0 0 0-25.6 25.6v358.4a25.6 25.6 0 0 0 43.52 17.92l143.36-142.848 578.048 578.048-142.848 142.848a25.6 25.6 0 0 0 17.92 43.52h358.4a25.6 25.6 0 0 0 25.6-25.6v-358.4a25.6 25.6 0 0 0-15.872-25.088z\" /></svg>";
|
||||
|
||||
30
simple-mind-map/types/src/svg/icons.d.ts
vendored
30
simple-mind-map/types/src/svg/icons.d.ts
vendored
@@ -1,18 +1,18 @@
|
||||
export const nodeIconList: {
|
||||
name: string
|
||||
type: string
|
||||
list: {
|
||||
name: string
|
||||
icon: string
|
||||
}[]
|
||||
}[]
|
||||
name: string;
|
||||
type: string;
|
||||
list: {
|
||||
name: string;
|
||||
icon: string;
|
||||
}[];
|
||||
}[];
|
||||
declare namespace _default {
|
||||
export { hyperlink }
|
||||
export { note }
|
||||
export { nodeIconList }
|
||||
export { getNodeIconListIcon }
|
||||
export { hyperlink };
|
||||
export { note };
|
||||
export { nodeIconList };
|
||||
export { getNodeIconListIcon };
|
||||
}
|
||||
export default _default
|
||||
declare const hyperlink: '<svg t="1624174958075" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7982" ><path d="M435.484444 251.733333v68.892445L295.822222 320.682667a168.504889 168.504889 0 0 0-2.844444 336.952889h142.506666v68.892444H295.822222a237.397333 237.397333 0 0 1 0-474.794667h139.662222z m248.945778 0a237.397333 237.397333 0 0 1 0 474.851556H544.654222v-69.006222l139.776 0.056889a168.504889 168.504889 0 0 0 2.844445-336.952889H544.597333V251.676444h139.776z m-25.827555 203.946667a34.474667 34.474667 0 0 1 0 68.892444H321.649778a34.474667 34.474667 0 0 1 0-68.892444h336.952889z" p-id="7983"></path></svg>'
|
||||
declare const note: '<svg t="1624195132675" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8792" ><path d="M152.768 985.984 152.768 49.856l434.56 0 66.816 0 234.048 267.392 0 66.816 0 601.92L152.768 985.984 152.768 985.984zM654.144 193.088l0 124.16 108.736 0L654.144 193.088 654.144 193.088zM821.312 384.064l-167.168 0L587.328 384.064 587.328 317.312 587.328 116.736 219.584 116.736 219.584 919.04l601.728 0L821.312 384.064 821.312 384.064zM386.688 517.888 319.808 517.888 319.808 450.944l66.816 0L386.624 517.888 386.688 517.888zM386.688 651.584 319.808 651.584 319.808 584.704l66.816 0L386.624 651.584 386.688 651.584zM386.688 785.344 319.808 785.344l0-66.88 66.816 0L386.624 785.344 386.688 785.344zM721.024 517.888 453.632 517.888 453.632 450.944l267.392 0L721.024 517.888 721.024 517.888zM654.144 651.584 453.632 651.584 453.632 584.704l200.512 0L654.144 651.584 654.144 651.584zM620.672 785.344l-167.04 0 0-66.88 167.04 0L620.672 785.344 620.672 785.344z" p-id="8793"></path></svg>'
|
||||
declare function getNodeIconListIcon(name: any, extendIconList?: any[]): any
|
||||
export default _default;
|
||||
declare const hyperlink: "<svg t=\"1624174958075\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"7982\" ><path d=\"M435.484444 251.733333v68.892445L295.822222 320.682667a168.504889 168.504889 0 0 0-2.844444 336.952889h142.506666v68.892444H295.822222a237.397333 237.397333 0 0 1 0-474.794667h139.662222z m248.945778 0a237.397333 237.397333 0 0 1 0 474.851556H544.654222v-69.006222l139.776 0.056889a168.504889 168.504889 0 0 0 2.844445-336.952889H544.597333V251.676444h139.776z m-25.827555 203.946667a34.474667 34.474667 0 0 1 0 68.892444H321.649778a34.474667 34.474667 0 0 1 0-68.892444h336.952889z\" p-id=\"7983\"></path></svg>";
|
||||
declare const note: "<svg t=\"1624195132675\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"8792\" ><path d=\"M152.768 985.984 152.768 49.856l434.56 0 66.816 0 234.048 267.392 0 66.816 0 601.92L152.768 985.984 152.768 985.984zM654.144 193.088l0 124.16 108.736 0L654.144 193.088 654.144 193.088zM821.312 384.064l-167.168 0L587.328 384.064 587.328 317.312 587.328 116.736 219.584 116.736 219.584 919.04l601.728 0L821.312 384.064 821.312 384.064zM386.688 517.888 319.808 517.888 319.808 450.944l66.816 0L386.624 517.888 386.688 517.888zM386.688 651.584 319.808 651.584 319.808 584.704l66.816 0L386.624 651.584 386.688 651.584zM386.688 785.344 319.808 785.344l0-66.88 66.816 0L386.624 785.344 386.688 785.344zM721.024 517.888 453.632 517.888 453.632 450.944l267.392 0L721.024 517.888 721.024 517.888zM654.144 651.584 453.632 651.584 453.632 584.704l200.512 0L654.144 651.584 654.144 651.584zM620.672 785.344l-167.04 0 0-66.88 167.04 0L620.672 785.344 620.672 785.344z\" p-id=\"8793\"></path></svg>";
|
||||
declare function getNodeIconListIcon(name: any, extendIconList?: any[]): any;
|
||||
|
||||
282
simple-mind-map/types/src/themes/default.d.ts
vendored
282
simple-mind-map/types/src/themes/default.d.ts
vendored
@@ -1,143 +1,143 @@
|
||||
declare namespace _default {
|
||||
let paddingX: number
|
||||
let paddingY: number
|
||||
let imgMaxWidth: number
|
||||
let imgMaxHeight: number
|
||||
let iconSize: number
|
||||
let lineWidth: number
|
||||
let lineColor: string
|
||||
let lineDasharray: string
|
||||
let lineStyle: string
|
||||
let rootLineKeepSameInCurve: boolean
|
||||
let generalizationLineWidth: number
|
||||
let generalizationLineColor: string
|
||||
let generalizationLineMargin: number
|
||||
let generalizationNodeMargin: number
|
||||
let associativeLineWidth: number
|
||||
let associativeLineColor: string
|
||||
let associativeLineActiveWidth: number
|
||||
let associativeLineActiveColor: string
|
||||
let associativeLineTextColor: string
|
||||
let associativeLineTextFontSize: number
|
||||
let associativeLineTextLineHeight: number
|
||||
let associativeLineTextFontFamily: string
|
||||
let backgroundColor: string
|
||||
let backgroundImage: string
|
||||
let backgroundRepeat: string
|
||||
let backgroundPosition: string
|
||||
let backgroundSize: string
|
||||
let nodeUseLineStyle: boolean
|
||||
namespace root {
|
||||
let shape: string
|
||||
let fillColor: string
|
||||
let fontFamily: string
|
||||
let color: string
|
||||
let fontSize: number
|
||||
let fontWeight: string
|
||||
let fontStyle: string
|
||||
let lineHeight: number
|
||||
let borderColor: string
|
||||
let borderWidth: number
|
||||
let borderDasharray: string
|
||||
let borderRadius: number
|
||||
let textDecoration: string
|
||||
}
|
||||
namespace second {
|
||||
let shape_1: string
|
||||
export { shape_1 as shape }
|
||||
export let marginX: number
|
||||
export let marginY: number
|
||||
let fillColor_1: string
|
||||
export { fillColor_1 as fillColor }
|
||||
let fontFamily_1: string
|
||||
export { fontFamily_1 as fontFamily }
|
||||
let color_1: string
|
||||
export { color_1 as color }
|
||||
let fontSize_1: number
|
||||
export { fontSize_1 as fontSize }
|
||||
let fontWeight_1: string
|
||||
export { fontWeight_1 as fontWeight }
|
||||
let fontStyle_1: string
|
||||
export { fontStyle_1 as fontStyle }
|
||||
let lineHeight_1: number
|
||||
export { lineHeight_1 as lineHeight }
|
||||
let borderColor_1: string
|
||||
export { borderColor_1 as borderColor }
|
||||
let borderWidth_1: number
|
||||
export { borderWidth_1 as borderWidth }
|
||||
let borderDasharray_1: string
|
||||
export { borderDasharray_1 as borderDasharray }
|
||||
let borderRadius_1: number
|
||||
export { borderRadius_1 as borderRadius }
|
||||
let textDecoration_1: string
|
||||
export { textDecoration_1 as textDecoration }
|
||||
}
|
||||
namespace node {
|
||||
let shape_2: string
|
||||
export { shape_2 as shape }
|
||||
let marginX_1: number
|
||||
export { marginX_1 as marginX }
|
||||
let marginY_1: number
|
||||
export { marginY_1 as marginY }
|
||||
let fillColor_2: string
|
||||
export { fillColor_2 as fillColor }
|
||||
let fontFamily_2: string
|
||||
export { fontFamily_2 as fontFamily }
|
||||
let color_2: string
|
||||
export { color_2 as color }
|
||||
let fontSize_2: number
|
||||
export { fontSize_2 as fontSize }
|
||||
let fontWeight_2: string
|
||||
export { fontWeight_2 as fontWeight }
|
||||
let fontStyle_2: string
|
||||
export { fontStyle_2 as fontStyle }
|
||||
let lineHeight_2: number
|
||||
export { lineHeight_2 as lineHeight }
|
||||
let borderColor_2: string
|
||||
export { borderColor_2 as borderColor }
|
||||
let borderWidth_2: number
|
||||
export { borderWidth_2 as borderWidth }
|
||||
let borderRadius_2: number
|
||||
export { borderRadius_2 as borderRadius }
|
||||
let borderDasharray_2: string
|
||||
export { borderDasharray_2 as borderDasharray }
|
||||
let textDecoration_2: string
|
||||
export { textDecoration_2 as textDecoration }
|
||||
}
|
||||
namespace generalization {
|
||||
let shape_3: string
|
||||
export { shape_3 as shape }
|
||||
let marginX_2: number
|
||||
export { marginX_2 as marginX }
|
||||
let marginY_2: number
|
||||
export { marginY_2 as marginY }
|
||||
let fillColor_3: string
|
||||
export { fillColor_3 as fillColor }
|
||||
let fontFamily_3: string
|
||||
export { fontFamily_3 as fontFamily }
|
||||
let color_3: string
|
||||
export { color_3 as color }
|
||||
let fontSize_3: number
|
||||
export { fontSize_3 as fontSize }
|
||||
let fontWeight_3: string
|
||||
export { fontWeight_3 as fontWeight }
|
||||
let fontStyle_3: string
|
||||
export { fontStyle_3 as fontStyle }
|
||||
let lineHeight_3: number
|
||||
export { lineHeight_3 as lineHeight }
|
||||
let borderColor_3: string
|
||||
export { borderColor_3 as borderColor }
|
||||
let borderWidth_3: number
|
||||
export { borderWidth_3 as borderWidth }
|
||||
let borderDasharray_3: string
|
||||
export { borderDasharray_3 as borderDasharray }
|
||||
let borderRadius_3: number
|
||||
export { borderRadius_3 as borderRadius }
|
||||
let textDecoration_3: string
|
||||
export { textDecoration_3 as textDecoration }
|
||||
}
|
||||
const paddingX: number;
|
||||
const paddingY: number;
|
||||
const imgMaxWidth: number;
|
||||
const imgMaxHeight: number;
|
||||
const iconSize: number;
|
||||
const lineWidth: number;
|
||||
const lineColor: string;
|
||||
const lineDasharray: string;
|
||||
const lineStyle: string;
|
||||
const rootLineKeepSameInCurve: boolean;
|
||||
const generalizationLineWidth: number;
|
||||
const generalizationLineColor: string;
|
||||
const generalizationLineMargin: number;
|
||||
const generalizationNodeMargin: number;
|
||||
const associativeLineWidth: number;
|
||||
const associativeLineColor: string;
|
||||
const associativeLineActiveWidth: number;
|
||||
const associativeLineActiveColor: string;
|
||||
const associativeLineTextColor: string;
|
||||
const associativeLineTextFontSize: number;
|
||||
const associativeLineTextLineHeight: number;
|
||||
const associativeLineTextFontFamily: string;
|
||||
const backgroundColor: string;
|
||||
const backgroundImage: string;
|
||||
const backgroundRepeat: string;
|
||||
const backgroundPosition: string;
|
||||
const backgroundSize: string;
|
||||
const nodeUseLineStyle: boolean;
|
||||
namespace root {
|
||||
const shape: string;
|
||||
const fillColor: string;
|
||||
const fontFamily: string;
|
||||
const color: string;
|
||||
const fontSize: number;
|
||||
const fontWeight: string;
|
||||
const fontStyle: string;
|
||||
const lineHeight: number;
|
||||
const borderColor: string;
|
||||
const borderWidth: number;
|
||||
const borderDasharray: string;
|
||||
const borderRadius: number;
|
||||
const textDecoration: string;
|
||||
}
|
||||
namespace second {
|
||||
const shape_1: string;
|
||||
export { shape_1 as shape };
|
||||
export const marginX: number;
|
||||
export const marginY: number;
|
||||
const fillColor_1: string;
|
||||
export { fillColor_1 as fillColor };
|
||||
const fontFamily_1: string;
|
||||
export { fontFamily_1 as fontFamily };
|
||||
const color_1: string;
|
||||
export { color_1 as color };
|
||||
const fontSize_1: number;
|
||||
export { fontSize_1 as fontSize };
|
||||
const fontWeight_1: string;
|
||||
export { fontWeight_1 as fontWeight };
|
||||
const fontStyle_1: string;
|
||||
export { fontStyle_1 as fontStyle };
|
||||
const lineHeight_1: number;
|
||||
export { lineHeight_1 as lineHeight };
|
||||
const borderColor_1: string;
|
||||
export { borderColor_1 as borderColor };
|
||||
const borderWidth_1: number;
|
||||
export { borderWidth_1 as borderWidth };
|
||||
const borderDasharray_1: string;
|
||||
export { borderDasharray_1 as borderDasharray };
|
||||
const borderRadius_1: number;
|
||||
export { borderRadius_1 as borderRadius };
|
||||
const textDecoration_1: string;
|
||||
export { textDecoration_1 as textDecoration };
|
||||
}
|
||||
namespace node {
|
||||
const shape_2: string;
|
||||
export { shape_2 as shape };
|
||||
const marginX_1: number;
|
||||
export { marginX_1 as marginX };
|
||||
const marginY_1: number;
|
||||
export { marginY_1 as marginY };
|
||||
const fillColor_2: string;
|
||||
export { fillColor_2 as fillColor };
|
||||
const fontFamily_2: string;
|
||||
export { fontFamily_2 as fontFamily };
|
||||
const color_2: string;
|
||||
export { color_2 as color };
|
||||
const fontSize_2: number;
|
||||
export { fontSize_2 as fontSize };
|
||||
const fontWeight_2: string;
|
||||
export { fontWeight_2 as fontWeight };
|
||||
const fontStyle_2: string;
|
||||
export { fontStyle_2 as fontStyle };
|
||||
const lineHeight_2: number;
|
||||
export { lineHeight_2 as lineHeight };
|
||||
const borderColor_2: string;
|
||||
export { borderColor_2 as borderColor };
|
||||
const borderWidth_2: number;
|
||||
export { borderWidth_2 as borderWidth };
|
||||
const borderRadius_2: number;
|
||||
export { borderRadius_2 as borderRadius };
|
||||
const borderDasharray_2: string;
|
||||
export { borderDasharray_2 as borderDasharray };
|
||||
const textDecoration_2: string;
|
||||
export { textDecoration_2 as textDecoration };
|
||||
}
|
||||
namespace generalization {
|
||||
const shape_3: string;
|
||||
export { shape_3 as shape };
|
||||
const marginX_2: number;
|
||||
export { marginX_2 as marginX };
|
||||
const marginY_2: number;
|
||||
export { marginY_2 as marginY };
|
||||
const fillColor_3: string;
|
||||
export { fillColor_3 as fillColor };
|
||||
const fontFamily_3: string;
|
||||
export { fontFamily_3 as fontFamily };
|
||||
const color_3: string;
|
||||
export { color_3 as color };
|
||||
const fontSize_3: number;
|
||||
export { fontSize_3 as fontSize };
|
||||
const fontWeight_3: string;
|
||||
export { fontWeight_3 as fontWeight };
|
||||
const fontStyle_3: string;
|
||||
export { fontStyle_3 as fontStyle };
|
||||
const lineHeight_3: number;
|
||||
export { lineHeight_3 as lineHeight };
|
||||
const borderColor_3: string;
|
||||
export { borderColor_3 as borderColor };
|
||||
const borderWidth_3: number;
|
||||
export { borderWidth_3 as borderWidth };
|
||||
const borderDasharray_3: string;
|
||||
export { borderDasharray_3 as borderDasharray };
|
||||
const borderRadius_3: number;
|
||||
export { borderRadius_3 as borderRadius };
|
||||
const textDecoration_3: string;
|
||||
export { textDecoration_3 as textDecoration };
|
||||
}
|
||||
}
|
||||
export default _default
|
||||
export const supportActiveStyle: string[]
|
||||
export function checkIsNodeSizeIndependenceConfig(config: any): boolean
|
||||
export const lineStyleProps: string[]
|
||||
export default _default;
|
||||
export const supportActiveStyle: string[];
|
||||
export function checkIsNodeSizeIndependenceConfig(config: any): boolean;
|
||||
export const lineStyleProps: string[];
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export default BatchExecution
|
||||
export default BatchExecution;
|
||||
declare class BatchExecution {
|
||||
has: {}
|
||||
queue: any[]
|
||||
nextTick: any
|
||||
push(name: any, fn: any): void
|
||||
flush(): void
|
||||
has: {};
|
||||
queue: any[];
|
||||
nextTick: any;
|
||||
push(name: any, fn: any): void;
|
||||
flush(): void;
|
||||
}
|
||||
|
||||
18
simple-mind-map/types/src/utils/Lru.d.ts
vendored
18
simple-mind-map/types/src/utils/Lru.d.ts
vendored
@@ -1,10 +1,10 @@
|
||||
export default class CRU {
|
||||
constructor(max: any)
|
||||
max: any
|
||||
size: number
|
||||
pool: Map<any, any>
|
||||
add(key: any, value: any): void
|
||||
delete(key: any): void
|
||||
has(key: any): boolean
|
||||
get(key: any): any
|
||||
export default class Lru {
|
||||
constructor(max: any);
|
||||
max: any;
|
||||
size: number;
|
||||
pool: Map<any, any>;
|
||||
add(key: any, value: any): void;
|
||||
delete(key: any): void;
|
||||
has(key: any): boolean;
|
||||
get(key: any): any;
|
||||
}
|
||||
|
||||
183
simple-mind-map/types/src/utils/index.d.ts
vendored
183
simple-mind-map/types/src/utils/index.d.ts
vendored
@@ -1,113 +1,70 @@
|
||||
export function walk(
|
||||
root: any,
|
||||
parent: any,
|
||||
beforeCallback: any,
|
||||
afterCallback: any,
|
||||
isRoot: any,
|
||||
layerIndex?: number,
|
||||
index?: number
|
||||
): void
|
||||
export function bfsWalk(root: any, callback: any): void
|
||||
export function resizeImgSizeByOriginRatio(
|
||||
width: any,
|
||||
height: any,
|
||||
newWidth: any,
|
||||
newHeight: any
|
||||
): any[]
|
||||
export function resizeImgSize(
|
||||
width: any,
|
||||
height: any,
|
||||
maxWidth: any,
|
||||
maxHeight: any
|
||||
): any[]
|
||||
export function resizeImg(
|
||||
imgUrl: any,
|
||||
maxWidth: any,
|
||||
maxHeight: any
|
||||
): Promise<any>
|
||||
export function getStrWithBrFromHtml(str: any): any
|
||||
export function simpleDeepClone(data: any): any
|
||||
export function copyRenderTree(
|
||||
tree: any,
|
||||
root: any,
|
||||
removeActiveState?: boolean
|
||||
): any
|
||||
export function copyNodeTree(
|
||||
tree: any,
|
||||
root: any,
|
||||
removeActiveState?: boolean,
|
||||
keepId?: boolean
|
||||
): any
|
||||
export function imgToDataUrl(src: any): Promise<any>
|
||||
export function parseDataUrl(data: any): any
|
||||
export function downloadFile(file: any, fileName: any): void
|
||||
export function throttle(
|
||||
fn: any,
|
||||
time: number,
|
||||
ctx: any
|
||||
): (...args: any[]) => void
|
||||
export function asyncRun(taskList: any, callback?: () => void): void
|
||||
export function degToRad(deg: any): number
|
||||
export function camelCaseToHyphen(str: any): any
|
||||
export function measureText(
|
||||
text: any,
|
||||
{
|
||||
italic,
|
||||
bold,
|
||||
fontSize,
|
||||
fontFamily
|
||||
}: {
|
||||
italic: any
|
||||
bold: any
|
||||
fontSize: any
|
||||
fontFamily: any
|
||||
}
|
||||
): {
|
||||
width: any
|
||||
height: any
|
||||
}
|
||||
export function joinFontStr({
|
||||
italic,
|
||||
bold,
|
||||
fontSize,
|
||||
fontFamily
|
||||
}: {
|
||||
italic: any
|
||||
bold: any
|
||||
fontSize: any
|
||||
fontFamily: any
|
||||
}): string
|
||||
export function nextTick(fn: any, ctx: any): () => void
|
||||
export function checkNodeOuter(
|
||||
mindMap: any,
|
||||
node: any
|
||||
): {
|
||||
isOuter: boolean
|
||||
offsetLeft: number
|
||||
offsetTop: number
|
||||
}
|
||||
export function getTextFromHtml(html: any): any
|
||||
export function readBlob(blob: any): Promise<any>
|
||||
export function nodeToHTML(node: any): any
|
||||
export function getImageSize(src: any): Promise<any>
|
||||
export function createUid(): any
|
||||
export function loadImage(imgFile: any): Promise<any>
|
||||
export function removeHTMLEntities(str: any): any
|
||||
export function getType(data: any): any
|
||||
export function isUndef(data: any): boolean
|
||||
export function removeHtmlStyle(html: any): any
|
||||
export function addHtmlStyle(html: any, tag: any, style: any): any
|
||||
export function checkIsRichText(str: any): boolean
|
||||
export function replaceHtmlText(
|
||||
html: any,
|
||||
searchText: any,
|
||||
replaceText: any
|
||||
): any
|
||||
export function isWhite(color: any): boolean
|
||||
export function isTransparent(color: any): boolean
|
||||
export function getVisibleColorFromTheme(themeConfig: any): any
|
||||
export function nodeRichTextToTextWithWrap(html: any): string
|
||||
export function textToNodeRichTextWithWrap(html: any): string
|
||||
export function isMobile(): boolean
|
||||
export function getObjectChangedProps(oldObject: any, newObject: any): {}
|
||||
export function checkIsNodeStyleDataKey(key: any): boolean
|
||||
export function walk(root: any, parent: any, beforeCallback: any, afterCallback: any, isRoot: any, layerIndex?: number, index?: number): void;
|
||||
export function bfsWalk(root: any, callback: any): void;
|
||||
export function resizeImgSizeByOriginRatio(width: any, height: any, newWidth: any, newHeight: any): any[];
|
||||
export function resizeImgSize(width: any, height: any, maxWidth: any, maxHeight: any): any[];
|
||||
export function resizeImg(imgUrl: any, maxWidth: any, maxHeight: any): Promise<any>;
|
||||
export function getStrWithBrFromHtml(str: any): any;
|
||||
export function simpleDeepClone(data: any): any;
|
||||
export function copyRenderTree(tree: any, root: any, removeActiveState?: boolean): any;
|
||||
export function copyNodeTree(tree: any, root: any, removeActiveState?: boolean, removeId?: boolean): any;
|
||||
export function imgToDataUrl(src: any): Promise<any>;
|
||||
export function parseDataUrl(data: any): any;
|
||||
export function downloadFile(file: any, fileName: any): void;
|
||||
export function throttle(fn: any, time: number, ctx: any): (...args: any[]) => void;
|
||||
export function asyncRun(taskList: any, callback?: () => void): void;
|
||||
export function degToRad(deg: any): number;
|
||||
export function camelCaseToHyphen(str: any): any;
|
||||
export function measureText(text: any, { italic, bold, fontSize, fontFamily }: {
|
||||
italic: any;
|
||||
bold: any;
|
||||
fontSize: any;
|
||||
fontFamily: any;
|
||||
}): {
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
export function joinFontStr({ italic, bold, fontSize, fontFamily }: {
|
||||
italic: any;
|
||||
bold: any;
|
||||
fontSize: any;
|
||||
fontFamily: any;
|
||||
}): string;
|
||||
export function nextTick(fn: any, ctx: any): () => void;
|
||||
export function checkNodeOuter(mindMap: any, node: any): {
|
||||
isOuter: boolean;
|
||||
offsetLeft: number;
|
||||
offsetTop: number;
|
||||
};
|
||||
export function getTextFromHtml(html: any): any;
|
||||
export function readBlob(blob: any): Promise<any>;
|
||||
export function nodeToHTML(node: any): any;
|
||||
export function getImageSize(src: any): Promise<any>;
|
||||
export function createUid(): any;
|
||||
export function loadImage(imgFile: any): Promise<any>;
|
||||
export function removeHTMLEntities(str: any): any;
|
||||
export function getType(data: any): any;
|
||||
export function isUndef(data: any): boolean;
|
||||
export function removeHtmlStyle(html: any): any;
|
||||
export function addHtmlStyle(html: any, tag: any, style: any): any;
|
||||
export function checkIsRichText(str: any): boolean;
|
||||
export function replaceHtmlText(html: any, searchText: any, replaceText: any): any;
|
||||
export function isWhite(color: any): boolean;
|
||||
export function isTransparent(color: any): boolean;
|
||||
export function getVisibleColorFromTheme(themeConfig: any): any;
|
||||
export function nodeRichTextToTextWithWrap(html: any): string;
|
||||
export function textToNodeRichTextWithWrap(html: any): string;
|
||||
export function isMobile(): boolean;
|
||||
export function getObjectChangedProps(oldObject: any, newObject: any): {};
|
||||
export function checkIsNodeStyleDataKey(key: any): boolean;
|
||||
export function mergerIconList(list: any): any;
|
||||
export function getTopAncestorsFomNodeList(list: any): any[];
|
||||
export function checkTwoRectIsOverlap(minx1: any, maxx1: any, miny1: any, maxy1: any, minx2: any, maxx2: any, miny2: any, maxy2: any): boolean;
|
||||
export function focusInput(el: any): void;
|
||||
export function selectAllInput(el: any): void;
|
||||
export function addDataToAppointNodes(appointNodes: any, data?: {}): any;
|
||||
export function createUidForAppointNodes(appointNodes: any, createNewId?: boolean): any;
|
||||
export function formatDataToArray(data: any): any[];
|
||||
export function getNodeIndex(node: any): any;
|
||||
export function generateColorByContent(str: any): string;
|
||||
export function htmlEscape(str: any): any;
|
||||
export function isSameObject(a: any, b: any): boolean;
|
||||
|
||||
23
simple-mind-map/types/src/utils/mersenneTwister.d.ts
vendored
Normal file
23
simple-mind-map/types/src/utils/mersenneTwister.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @description 为了保证相同的内容每次生成的随机数都是一样的,我们可以使用一个伪随机数生成器(PRNG),并使用内容的哈希值作为种子。以下是一个使用Mersenne Twister算法的PRNG的实现:
|
||||
*
|
||||
* @param {*} seed
|
||||
*/
|
||||
export default function MersenneTwister(seed: any): void;
|
||||
export default class MersenneTwister {
|
||||
/**
|
||||
* @description 为了保证相同的内容每次生成的随机数都是一样的,我们可以使用一个伪随机数生成器(PRNG),并使用内容的哈希值作为种子。以下是一个使用Mersenne Twister算法的PRNG的实现:
|
||||
*
|
||||
* @param {*} seed
|
||||
*/
|
||||
constructor(seed: any);
|
||||
N: number;
|
||||
M: number;
|
||||
MATRIX_A: number;
|
||||
UPPER_MASK: number;
|
||||
LOWER_MASK: number;
|
||||
mt: any[];
|
||||
mti: number;
|
||||
init_genrand(s: any): void;
|
||||
genrand_int32(): number;
|
||||
}
|
||||
2
web/package-lock.json
generated
2
web/package-lock.json
generated
@@ -18488,6 +18488,7 @@
|
||||
"integrity": "sha512-VCNRiAt2P/bLo09rYt3DLe6xXUMlhJwrvU18Ddd/lYJgC7s8+wvhgYs+MTx4OiAXdu58drGwSBO9SPx7C6J82Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/core": "^7.11.0",
|
||||
"@babel/helper-compilation-targets": "^7.9.6",
|
||||
"@babel/helper-module-imports": "^7.8.3",
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
@@ -18500,6 +18501,7 @@
|
||||
"@vue/babel-plugin-jsx": "^1.0.3",
|
||||
"@vue/babel-preset-jsx": "^1.2.4",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"core-js": "^3.6.5",
|
||||
"core-js-compat": "^3.6.5",
|
||||
"semver": "^6.1.0"
|
||||
}
|
||||
|
||||
BIN
web/src/assets/avatar/有希.jpg
Normal file
BIN
web/src/assets/avatar/有希.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
BIN
web/src/assets/avatar/樊笼.jpg
Normal file
BIN
web/src/assets/avatar/樊笼.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
BIN
web/src/assets/avatar/沐风牧草.jpg
Normal file
BIN
web/src/assets/avatar/沐风牧草.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
web/src/assets/avatar/达仁科技.jpg
Normal file
BIN
web/src/assets/avatar/达仁科技.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2479351 */
|
||||
src: url('iconfont.woff2?t=1691822758372') format('woff2'),
|
||||
url('iconfont.woff?t=1691822758372') format('woff'),
|
||||
url('iconfont.ttf?t=1691822758372') format('truetype');
|
||||
src: url('iconfont.woff2?t=1695365666344') format('woff2'),
|
||||
url('iconfont.woff?t=1695365666344') format('woff'),
|
||||
url('iconfont.ttf?t=1695365666344') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -13,6 +13,10 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icongongshi:before {
|
||||
content: "\e617";
|
||||
}
|
||||
|
||||
.icontouming:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,60 +1,83 @@
|
||||
// 布局结构图片映射
|
||||
export const layoutImgMap = {
|
||||
logicalStructure: require('../assets/img/structures/logicalStructure.png'),
|
||||
mindMap: require('../assets/img/structures/mindMap.png'),
|
||||
organizationStructure: require('../assets/img/structures/organizationStructure.png'),
|
||||
catalogOrganization: require('../assets/img/structures/catalogOrganization.png'),
|
||||
timeline: require('../assets/img/structures/timeline.png'),
|
||||
timeline2: require('../assets/img/structures/timeline2.png'),
|
||||
fishbone: require('../assets/img/structures/fishbone.png'),
|
||||
verticalTimeline: require('../assets/img/structures/verticalTimeline.png'),
|
||||
logicalStructure: require('../assets/img/structures/logicalStructure.png'),
|
||||
mindMap: require('../assets/img/structures/mindMap.png'),
|
||||
organizationStructure: require('../assets/img/structures/organizationStructure.png'),
|
||||
catalogOrganization: require('../assets/img/structures/catalogOrganization.png'),
|
||||
timeline: require('../assets/img/structures/timeline.png'),
|
||||
timeline2: require('../assets/img/structures/timeline2.png'),
|
||||
fishbone: require('../assets/img/structures/fishbone.png'),
|
||||
verticalTimeline: require('../assets/img/structures/verticalTimeline.png')
|
||||
}
|
||||
|
||||
// 主题图片映射
|
||||
export const themeMap = {
|
||||
default: require('../assets/img/themes/default.jpg'),
|
||||
classic: require('../assets/img/themes/classic.jpg'),
|
||||
minions: require('../assets/img/themes/minions.jpg'),
|
||||
pinkGrape: require('../assets/img/themes/pinkGrape.jpg'),
|
||||
mint: require('../assets/img/themes/mint.jpg'),
|
||||
gold: require('../assets/img/themes/gold.jpg'),
|
||||
vitalityOrange: require('../assets/img/themes/vitalityOrange.jpg'),
|
||||
greenLeaf: require('../assets/img/themes/greenLeaf.jpg'),
|
||||
dark2: require('../assets/img/themes/dark2.jpg'),
|
||||
skyGreen: require('../assets/img/themes/skyGreen.jpg'),
|
||||
classic2: require('../assets/img/themes/classic2.jpg'),
|
||||
classic3: require('../assets/img/themes/classic3.jpg'),
|
||||
classic4: require('../assets/img/themes/classic4.jpg'),
|
||||
classicGreen: require('../assets/img/themes/classicGreen.jpg'),
|
||||
classicBlue: require('../assets/img/themes/classicBlue.jpg'),
|
||||
blueSky: require('../assets/img/themes/blueSky.jpg'),
|
||||
brainImpairedPink: require('../assets/img/themes/brainImpairedPink.jpg'),
|
||||
dark: require('../assets/img/themes/dark.jpg'),
|
||||
earthYellow: require('../assets/img/themes/earthYellow.jpg'),
|
||||
freshGreen: require('../assets/img/themes/freshGreen.jpg'),
|
||||
freshRed: require('../assets/img/themes/freshRed.jpg'),
|
||||
romanticPurple: require('../assets/img/themes/romanticPurple.jpg'),
|
||||
simpleBlack: require('../assets/img/themes/simpleBlack.jpg'),
|
||||
courseGreen: require('../assets/img/themes/courseGreen.jpg'),
|
||||
coffee: require('../assets/img/themes/coffee.jpg'),
|
||||
redSpirit: require('../assets/img/themes/redSpirit.jpg'),
|
||||
blackHumour: require('../assets/img/themes/blackHumour.jpg'),
|
||||
lateNightOffice: require('../assets/img/themes/lateNightOffice.jpg'),
|
||||
blackGold: require('../assets/img/themes/blackGold.jpg'),
|
||||
autumn: require('../assets/img/themes/autumn.jpg'),
|
||||
avocado: require('../assets/img/themes/avocado.jpg'),
|
||||
orangeJuice: require('../assets/img/themes/orangeJuice.jpg'),
|
||||
oreo: require('../assets/img/themes/oreo.jpg'),
|
||||
shallowSea: require('../assets/img/themes/shallowSea.jpg'),
|
||||
lemonBubbles: require('../assets/img/themes/lemonBubbles.jpg'),
|
||||
rose: require('../assets/img/themes/rose.jpg'),
|
||||
seaBlueLine: require('../assets/img/themes/seaBlueLine.jpg'),
|
||||
neonLamp: require('../assets/img/themes/neonLamp.jpg'),
|
||||
darkNightLceBlade: require('../assets/img/themes/darkNightLceBlade.jpg'),
|
||||
morandi: require('../assets/img/themes/morandi.jpg'),
|
||||
classic5: require('../assets/img/themes/classic5.jpg'),
|
||||
dark3: require('../assets/img/themes/dark3.jpg'),
|
||||
dark4: require('../assets/img/themes/dark4.jpg'),
|
||||
cactus: require('../assets/img/themes/cactus.jpg'),
|
||||
default: require('../assets/img/themes/default.jpg'),
|
||||
classic: require('../assets/img/themes/classic.jpg'),
|
||||
minions: require('../assets/img/themes/minions.jpg'),
|
||||
pinkGrape: require('../assets/img/themes/pinkGrape.jpg'),
|
||||
mint: require('../assets/img/themes/mint.jpg'),
|
||||
gold: require('../assets/img/themes/gold.jpg'),
|
||||
vitalityOrange: require('../assets/img/themes/vitalityOrange.jpg'),
|
||||
greenLeaf: require('../assets/img/themes/greenLeaf.jpg'),
|
||||
dark2: require('../assets/img/themes/dark2.jpg'),
|
||||
skyGreen: require('../assets/img/themes/skyGreen.jpg'),
|
||||
classic2: require('../assets/img/themes/classic2.jpg'),
|
||||
classic3: require('../assets/img/themes/classic3.jpg'),
|
||||
classic4: require('../assets/img/themes/classic4.jpg'),
|
||||
classicGreen: require('../assets/img/themes/classicGreen.jpg'),
|
||||
classicBlue: require('../assets/img/themes/classicBlue.jpg'),
|
||||
blueSky: require('../assets/img/themes/blueSky.jpg'),
|
||||
brainImpairedPink: require('../assets/img/themes/brainImpairedPink.jpg'),
|
||||
dark: require('../assets/img/themes/dark.jpg'),
|
||||
earthYellow: require('../assets/img/themes/earthYellow.jpg'),
|
||||
freshGreen: require('../assets/img/themes/freshGreen.jpg'),
|
||||
freshRed: require('../assets/img/themes/freshRed.jpg'),
|
||||
romanticPurple: require('../assets/img/themes/romanticPurple.jpg'),
|
||||
simpleBlack: require('../assets/img/themes/simpleBlack.jpg'),
|
||||
courseGreen: require('../assets/img/themes/courseGreen.jpg'),
|
||||
coffee: require('../assets/img/themes/coffee.jpg'),
|
||||
redSpirit: require('../assets/img/themes/redSpirit.jpg'),
|
||||
blackHumour: require('../assets/img/themes/blackHumour.jpg'),
|
||||
lateNightOffice: require('../assets/img/themes/lateNightOffice.jpg'),
|
||||
blackGold: require('../assets/img/themes/blackGold.jpg'),
|
||||
autumn: require('../assets/img/themes/autumn.jpg'),
|
||||
avocado: require('../assets/img/themes/avocado.jpg'),
|
||||
orangeJuice: require('../assets/img/themes/orangeJuice.jpg'),
|
||||
oreo: require('../assets/img/themes/oreo.jpg'),
|
||||
shallowSea: require('../assets/img/themes/shallowSea.jpg'),
|
||||
lemonBubbles: require('../assets/img/themes/lemonBubbles.jpg'),
|
||||
rose: require('../assets/img/themes/rose.jpg'),
|
||||
seaBlueLine: require('../assets/img/themes/seaBlueLine.jpg'),
|
||||
neonLamp: require('../assets/img/themes/neonLamp.jpg'),
|
||||
darkNightLceBlade: require('../assets/img/themes/darkNightLceBlade.jpg'),
|
||||
morandi: require('../assets/img/themes/morandi.jpg'),
|
||||
classic5: require('../assets/img/themes/classic5.jpg'),
|
||||
dark3: require('../assets/img/themes/dark3.jpg'),
|
||||
dark4: require('../assets/img/themes/dark4.jpg'),
|
||||
cactus: require('../assets/img/themes/cactus.jpg')
|
||||
}
|
||||
|
||||
|
||||
// 公式列表
|
||||
export const formulaList = [
|
||||
'a^2',
|
||||
'a_2',
|
||||
'a^{2+2}',
|
||||
'a_{i,j}',
|
||||
'x_2^3',
|
||||
'\\overbrace{1+2+\\cdots+100}',
|
||||
'\\sum_{k=1}^N k^2',
|
||||
'\\lim_{n \\to \\infty}x_n',
|
||||
'\\int_{-N}^{N} e^x\\, dx',
|
||||
'\\sqrt{3}',
|
||||
'\\sqrt[n]{3}',
|
||||
'\\sin\\theta',
|
||||
'\\log X',
|
||||
'\\log_{10}',
|
||||
'\\log_\\alpha X',
|
||||
'\\lim_{t\\to n}T',
|
||||
'\\frac{1}{2}=0.5',
|
||||
'\\binom{n}{k}',
|
||||
'\\begin{matrix}x & y \\\\z & v\\end{matrix}',
|
||||
'\\begin{cases}3x + 5y + z \\\\7x - 2y + 4z \\\\-6x + 3y + 2z\\end{cases}'
|
||||
]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -103,11 +103,13 @@ export default {
|
||||
markdownFile: 'markdown file',
|
||||
tips: 'tips: .smm and .json file can be import',
|
||||
isTransparent: 'Background is transparent',
|
||||
pngTips: 'tips: Exporting pictures in rich text mode is time-consuming. It is recommended to export to svg format',
|
||||
pngTips:
|
||||
'tips: Exporting pictures in rich text mode is time-consuming. It is recommended to export to svg format',
|
||||
svgTips: 'tips: Exporting pictures in rich text mode is time-consuming',
|
||||
transformingDomToImages: 'Converting nodes: ',
|
||||
notifyTitle: 'Info',
|
||||
notifyMessage: 'If the download is not triggered, check whether it is blocked by the browser',
|
||||
notifyMessage:
|
||||
'If the download is not triggered, check whether it is blocked by the browser',
|
||||
paddingX: 'Padding x',
|
||||
paddingY: 'Padding y',
|
||||
useMultiPageExport: 'Export multi page'
|
||||
@@ -213,15 +215,19 @@ export default {
|
||||
export: 'Export',
|
||||
shortcutKey: 'Shortcut key',
|
||||
associativeLine: 'Associative line',
|
||||
painter: 'Painter'
|
||||
painter: 'Painter',
|
||||
formula: 'Formula'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: 'New feature reminder',
|
||||
newFeatureNoticeMessage: 'This update supports node rich text editing, But there are some defects, The most important impact is that the time to export the image is proportional to the number of nodes, Therefore, if you are more dependent on export requirements, you can use【Base style】-【Other config】-【Enable node rich text editing】Set to turn off rich text editing mode.'
|
||||
newFeatureNoticeMessage:
|
||||
'This update supports node rich text editing, But there are some defects, The most important impact is that the time to export the image is proportional to the number of nodes, Therefore, if you are more dependent on export requirements, you can use【Base style】-【Other config】-【Enable node rich text editing】Set to turn off rich text editing mode.'
|
||||
},
|
||||
mouseAction: {
|
||||
tip1: 'Current: Left click to drag the canvas, right click to box select nodes',
|
||||
tip2: 'Current: Left click to box select nodes, right click to drag the canvas',
|
||||
tip1:
|
||||
'Current: Left click to drag the canvas, right click to box select nodes',
|
||||
tip2:
|
||||
'Current: Left click to box select nodes, right click to drag the canvas'
|
||||
},
|
||||
search: {
|
||||
searchPlaceholder: 'Please enter the search content',
|
||||
@@ -229,5 +235,16 @@ export default {
|
||||
replace: 'Replace',
|
||||
replaceAll: 'Replace all',
|
||||
cancel: 'Cancel'
|
||||
},
|
||||
nodeIconSidebar: {
|
||||
title: 'Icon/Sticker',
|
||||
icon: 'Icon',
|
||||
sticker: 'Sticker'
|
||||
},
|
||||
formulaSidebar: {
|
||||
title: 'Formula',
|
||||
placeholder: 'Please enter LaText syntax',
|
||||
confirm: 'Confirm',
|
||||
common: 'Common formulas'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,15 +213,17 @@ export default {
|
||||
export: '导出',
|
||||
shortcutKey: '快捷键',
|
||||
associativeLine: '关联线',
|
||||
painter: '格式刷'
|
||||
painter: '格式刷',
|
||||
formula: '公式'
|
||||
},
|
||||
edit: {
|
||||
newFeatureNoticeTitle: '新特性提醒',
|
||||
newFeatureNoticeMessage: '本次更新支持了节点富文本编辑,但是存在一定缺陷,最主要的影响是导出为图片的时间和节点数量成正比,所以对导出需求比较依赖的话可以通过【基础样式】-【其他配置】-【是否开启节点富文本编辑】设置关掉富文本编辑模式。'
|
||||
newFeatureNoticeMessage:
|
||||
'本次更新支持了节点富文本编辑,但是存在一定缺陷,最主要的影响是导出为图片的时间和节点数量成正比,所以对导出需求比较依赖的话可以通过【基础样式】-【其他配置】-【是否开启节点富文本编辑】设置关掉富文本编辑模式。'
|
||||
},
|
||||
mouseAction: {
|
||||
tip1: '当前:左键拖动画布,右键框选节点',
|
||||
tip2: '当前:左键框选节点,右键拖动画布',
|
||||
tip2: '当前:左键框选节点,右键拖动画布'
|
||||
},
|
||||
search: {
|
||||
searchPlaceholder: '请输入查找内容',
|
||||
@@ -229,5 +231,16 @@ export default {
|
||||
replace: '替换',
|
||||
replaceAll: '全部替换',
|
||||
cancel: '取消'
|
||||
},
|
||||
nodeIconSidebar: {
|
||||
title: '图标/贴纸',
|
||||
icon: '图标',
|
||||
sticker: '贴纸'
|
||||
},
|
||||
formulaSidebar: {
|
||||
title: '公式',
|
||||
placeholder: '请输入 LaText 语法',
|
||||
confirm: '完成',
|
||||
common: '常用公式'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ let APIList = [
|
||||
'search',
|
||||
'painter',
|
||||
'scrollbar',
|
||||
'formula',
|
||||
'cooperate',
|
||||
'xmind',
|
||||
'markdown',
|
||||
'utils'
|
||||
|
||||
@@ -2,16 +2,24 @@
|
||||
<div class="headerContainer">
|
||||
<div class="left">
|
||||
<div class="title" @click="toIndex">
|
||||
<img src="../../../assets/img/logo2.png" alt="">
|
||||
<img src="../../../assets/img/logo2.png" alt="" />
|
||||
SimpleMindMap
|
||||
</div>
|
||||
</div>
|
||||
<div class="center">
|
||||
<div class="btn" @click="toIndex">{{ index }}</div>
|
||||
<div class="btn" @click="toDemo">{{ demoName }}</div>
|
||||
<div class="btn" @click="toHelp" :class="{ active: docType === 'help' }">
|
||||
{{ helpDoc }}
|
||||
</div>
|
||||
<div class="btn" @click="toDev" :class="{ active: docType === 'doc' }">
|
||||
{{ devDoc }}
|
||||
</div>
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
placement="bottom-start"
|
||||
@command="handleCommand"
|
||||
v-if="docType === 'doc'"
|
||||
>
|
||||
<span class="translateBtn">
|
||||
{{ currentLangName }}<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
@@ -41,6 +49,7 @@ import t from '../i18n'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
docType: '',
|
||||
lang: '',
|
||||
currentLangName: '',
|
||||
otherLangList: []
|
||||
@@ -49,7 +58,16 @@ export default {
|
||||
computed: {
|
||||
demoName() {
|
||||
return t('demo', this.lang)
|
||||
}
|
||||
},
|
||||
helpDoc() {
|
||||
return t('help', this.lang)
|
||||
},
|
||||
devDoc() {
|
||||
return t('dev', this.lang)
|
||||
},
|
||||
index() {
|
||||
return t('index', this.lang)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
@@ -61,6 +79,12 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 当前文档类型
|
||||
let docType = /^\/([^\/]+)\//.exec(this.$route.path)
|
||||
if (docType && docType[1]) {
|
||||
this.docType = docType[1]
|
||||
}
|
||||
// 当前文档语言
|
||||
let lang = /^\/doc\/([^\/]+)\//.exec(this.$route.path)
|
||||
if (lang && lang[1]) {
|
||||
this.lang = lang[1]
|
||||
@@ -87,6 +111,15 @@ export default {
|
||||
return `/doc/${path}/`
|
||||
})
|
||||
this.$router.push(url)
|
||||
},
|
||||
|
||||
toHelp() {
|
||||
this.lang = 'zh'
|
||||
this.$router.replace('/help/zh/')
|
||||
},
|
||||
|
||||
toDev() {
|
||||
this.$router.replace('/doc/zh/')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,6 +170,10 @@ export default {
|
||||
&:hover {
|
||||
color: #1ea59a;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #1ea59a;
|
||||
}
|
||||
}
|
||||
|
||||
.translateBtn {
|
||||
|
||||
@@ -1,5 +1,63 @@
|
||||
# Changelog
|
||||
|
||||
## 0.7.3-fix.1
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fixed some issues where the box selection area did not disappear when multiple nodes were selected.
|
||||
>
|
||||
> 2.Fixed an issue where the box selection area does not disappear when releasing the mouse over multiple selected nodes.
|
||||
>
|
||||
> 3.Fixed rendering anomalies caused by duplicate node uids when pasting nodes multiple times.
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.Add protocol selection function to the hyperlink input box.
|
||||
|
||||
## 0.7.3
|
||||
|
||||
New: 1.Add a Cooperate editing plugin.
|
||||
|
||||
Demo: 1.Fix the automatic closing of the sidebar caused by the formula sidebar component.
|
||||
|
||||
## 0.7.2
|
||||
|
||||
Fix:
|
||||
|
||||
> 1.Fixed the issue of nodes not being selected when the selection area does not include node boundaries when multiple nodes are selected.
|
||||
>
|
||||
> 2.Fix the issue of errors when node text is not a string.
|
||||
>
|
||||
> 3.Fix the issue of some text disappearing when edited again when there are<>&characters in the text in non rich text mode.
|
||||
|
||||
New:
|
||||
|
||||
> 1.Supports inserting mathematical formulas.
|
||||
>
|
||||
> 2.Supports dragging and moving multiple nodes simultaneously.
|
||||
>
|
||||
> 3.Supports copying and cutting multiple nodes simultaneously.
|
||||
>
|
||||
> 4.The node label color has been changed to be generated based on the label content, meaning that the same label content will generate the same color.
|
||||
>
|
||||
> 5.Optimize the insertion of child nodes: 1. When inserting child nodes into multiple nodes simultaneously, do not enter the editing state; 2. The newly inserted child node automatically enters the active state.
|
||||
>
|
||||
> 6.Optimize the insertion of sibling nodes: 1. Support the simultaneous insertion of sibling nodes into multiple nodes; 2. When calling the command to insert sibling nodes on the root node, no child nodes will be created.
|
||||
>
|
||||
> 7.Add a command to simultaneously insert multiple peers and multiple child nodes.
|
||||
>
|
||||
> 8.Changing the unique identifier of nodes from id to uid mainly affects the associated lines, which may not display properly in previous versions.
|
||||
>
|
||||
> 9.Optimize the logic of icon merging and support the expansion of icons under the internal classification of the library.
|
||||
>
|
||||
> 10.Associate line: 1. Double click the associate line to enter associate line text editing mode; If the associated line text is the default text, it will not be saved; 3. When there are active nodes, clicking on the associated line can directly activate the associated line.
|
||||
|
||||
Demo:
|
||||
|
||||
> 1.Fixed an issue where multiple nodes in the Zhixi mind map cannot be pasted when copying.
|
||||
>
|
||||
> 2.Add a sidebar for formula editing.
|
||||
|
||||
## 0.7.1-fix.2
|
||||
|
||||
Fix: 1.Fix the issue of plugin registration method chain call reporting errors.
|
||||
|
||||
@@ -1,6 +1,45 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.7.3-fix.1</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fixed some issues where the box selection area did not disappear when multiple nodes were selected.</p>
|
||||
<p>2.Fixed an issue where the box selection area does not disappear when releasing the mouse over multiple selected nodes.</p>
|
||||
<p>3.Fixed rendering anomalies caused by duplicate node uids when pasting nodes multiple times.</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.Add protocol selection function to the hyperlink input box.</p>
|
||||
</blockquote>
|
||||
<h2>0.7.3</h2>
|
||||
<p>New: 1.Add a Cooperate editing plugin.</p>
|
||||
<p>Demo: 1.Fix the automatic closing of the sidebar caused by the formula sidebar component.</p>
|
||||
<h2>0.7.2</h2>
|
||||
<p>Fix:</p>
|
||||
<blockquote>
|
||||
<p>1.Fixed the issue of nodes not being selected when the selection area does not include node boundaries when multiple nodes are selected.</p>
|
||||
<p>2.Fix the issue of errors when node text is not a string.</p>
|
||||
<p>3.Fix the issue of some text disappearing when edited again when there are<>&characters in the text in non rich text mode.</p>
|
||||
</blockquote>
|
||||
<p>New:</p>
|
||||
<blockquote>
|
||||
<p>1.Supports inserting mathematical formulas.</p>
|
||||
<p>2.Supports dragging and moving multiple nodes simultaneously.</p>
|
||||
<p>3.Supports copying and cutting multiple nodes simultaneously.</p>
|
||||
<p>4.The node label color has been changed to be generated based on the label content, meaning that the same label content will generate the same color.</p>
|
||||
<p>5.Optimize the insertion of child nodes: 1. When inserting child nodes into multiple nodes simultaneously, do not enter the editing state; 2. The newly inserted child node automatically enters the active state.</p>
|
||||
<p>6.Optimize the insertion of sibling nodes: 1. Support the simultaneous insertion of sibling nodes into multiple nodes; 2. When calling the command to insert sibling nodes on the root node, no child nodes will be created.</p>
|
||||
<p>7.Add a command to simultaneously insert multiple peers and multiple child nodes.</p>
|
||||
<p>8.Changing the unique identifier of nodes from id to uid mainly affects the associated lines, which may not display properly in previous versions.</p>
|
||||
<p>9.Optimize the logic of icon merging and support the expansion of icons under the internal classification of the library.</p>
|
||||
<p>10.Associate line: 1. Double click the associate line to enter associate line text editing mode; If the associated line text is the default text, it will not be saved; 3. When there are active nodes, clicking on the associated line can directly activate the associated line.</p>
|
||||
</blockquote>
|
||||
<p>Demo:</p>
|
||||
<blockquote>
|
||||
<p>1.Fixed an issue where multiple nodes in the Zhixi mind map cannot be pasted when copying.</p>
|
||||
<p>2.Add a sidebar for formula editing.</p>
|
||||
</blockquote>
|
||||
<h2>0.7.1-fix.2</h2>
|
||||
<p>Fix: 1.Fix the issue of plugin registration method chain call reporting errors.</p>
|
||||
<p>New:</p>
|
||||
|
||||
82
web/src/pages/Doc/en/client/index.md
Normal file
82
web/src/pages/Doc/en/client/index.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Client
|
||||
|
||||
This project also provides a client version using [Electron](https://www.electronjs.org/) Development. Supports 'Windows', 'Mac', and 'Linux'.
|
||||
|
||||
Currently, the function is relatively simple:
|
||||
|
||||
1. Support creating and opening files for editing;
|
||||
|
||||
2. Support viewing the list of recently edited files;
|
||||
|
||||
3. Support the copying, deletion, and renaming of files;
|
||||
|
||||
## Download
|
||||
|
||||
> The client version may lag behind the online version. To try new features, please prioritize using the online version.
|
||||
|
||||
You can directly download the corresponding client for installation and use, and two download addresses are provided:
|
||||
|
||||
Github:[releases](https://github.com/wanglin2/mind-map/releases)。
|
||||
|
||||
Baidu cloud disk:[地址](https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3)。
|
||||
|
||||
## Development
|
||||
|
||||
If necessary, you can also conduct secondary development.
|
||||
|
||||
### clone
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wanglin2/mind-map.git
|
||||
cd mind-map
|
||||
git checkout electron
|
||||
```
|
||||
|
||||
### Start serve
|
||||
|
||||
Execute in the project root directory:
|
||||
|
||||
```bash
|
||||
cd simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
cd ..
|
||||
cd web
|
||||
npm i
|
||||
npm link simple-mind-map
|
||||
npm run electron:serve
|
||||
```
|
||||
|
||||
### Packaging client
|
||||
|
||||
You need at least two computers, one 'Windows' and one 'Mac'.
|
||||
|
||||
Packaging 'Windows' application:
|
||||
|
||||
```bash
|
||||
npm run electron:build-win
|
||||
```
|
||||
|
||||
Packaging 'Mac' application:
|
||||
|
||||
```bash
|
||||
npm run electron:build-mac
|
||||
```
|
||||
|
||||
Packaging 'Linux' application:
|
||||
|
||||
```bash
|
||||
npm run electron:build-linux
|
||||
```
|
||||
|
||||
Packaging all applications:
|
||||
|
||||
```bash
|
||||
npm run electron:build-all
|
||||
```
|
||||
|
||||
Automatically pack according to your computer system:
|
||||
|
||||
```bash
|
||||
npm run electron:build
|
||||
```
|
||||
71
web/src/pages/Doc/en/client/index.vue
Normal file
71
web/src/pages/Doc/en/client/index.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Client</h1>
|
||||
<p>This project also provides a client version using <a href="https://www.electronjs.org/">Electron</a> Development. Supports 'Windows', 'Mac', and 'Linux'.</p>
|
||||
<p>Currently, the function is relatively simple:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Support creating and opening files for editing;</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Support viewing the list of recently edited files;</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Support the copying, deletion, and renaming of files;</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h2>Download</h2>
|
||||
<blockquote>
|
||||
<p>The client version may lag behind the online version. To try new features, please prioritize using the online version.</p>
|
||||
</blockquote>
|
||||
<p>You can directly download the corresponding client for installation and use, and two download addresses are provided:</p>
|
||||
<p>Github:<a href="https://github.com/wanglin2/mind-map/releases">releases</a>。</p>
|
||||
<p>Baidu cloud disk:<a href="https://pan.baidu.com/s/1huasEbKsGNH2Af68dvWiOg?pwd=3bp3">地址</a>。</p>
|
||||
<h2>Development</h2>
|
||||
<p>If necessary, you can also conduct secondary development.</p>
|
||||
<h3>clone</h3>
|
||||
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
|
||||
<span class="hljs-built_in">cd</span> mind-map
|
||||
git checkout electron
|
||||
</code></pre>
|
||||
<h3>Start serve</h3>
|
||||
<p>Execute in the project root directory:</p>
|
||||
<pre class="hljs"><code><span class="hljs-built_in">cd</span> simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
<span class="hljs-built_in">cd</span> ..
|
||||
<span class="hljs-built_in">cd</span> web
|
||||
npm i
|
||||
npm link simple-mind-map
|
||||
npm run electron:serve
|
||||
</code></pre>
|
||||
<h3>Packaging client</h3>
|
||||
<p>You need at least two computers, one 'Windows' and one 'Mac'.</p>
|
||||
<p>Packaging 'Windows' application:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-win
|
||||
</code></pre>
|
||||
<p>Packaging 'Mac' application:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-mac
|
||||
</code></pre>
|
||||
<p>Packaging 'Linux' application:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-linux
|
||||
</code></pre>
|
||||
<p>Packaging all applications:</p>
|
||||
<pre class="hljs"><code>npm run electron:build-all
|
||||
</code></pre>
|
||||
<p>Automatically pack according to your computer system:</p>
|
||||
<pre class="hljs"><code>npm run electron:build
|
||||
</code></pre>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -90,6 +90,11 @@ const mindMap = new MindMap({
|
||||
| deleteNodeActive(v0.7.1+) | Boolean | true | Enable the function of automatically activating adjacent nodes or parent nodes after deleting nodes | |
|
||||
| autoMoveWhenMouseInEdgeOnDrag(v0.7.1+) | Boolean | true | Whether to enable automatic canvas movement when the mouse moves to the edge of the canvas while dragging nodes | |
|
||||
| fit(v0.7.1-fix.2+) | Boolean | false | Is the first rendering scaled to fit the canvas size | |
|
||||
| dragMultiNodeRectConfig(v0.7.2+) | Object | { width: 40, height: 20, fill: '' } | The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle | |
|
||||
| dragPlaceholderRectFill(v0.7.2+) | String | | The filling color of the schematic rectangle for the new position when dragging nodes. If not transmitted, the default color for the connected line is used | |
|
||||
| dragOpacityConfig(v0.7.2+) | Object | { cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 } | The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node | |
|
||||
| tagsColorMap(v0.7.2+) | Object | {} | The color of a custom node label can be transferred to an object, where key is the label content to be assigned a color, and value is the color of the label content. If not transferred internally, a corresponding color will be generated based on the label content | |
|
||||
| cooperateStyle(v0.7.3+) | Object | { avatarSize: 22, fontSize: 12 } | The configuration of personnel avatar style during node collaboration editing, with field meanings as follows: avatar size, and if it is a text avatar, the size of the text | |
|
||||
|
||||
### Data structure
|
||||
|
||||
@@ -308,6 +313,7 @@ Listen to an event. Event list:
|
||||
| svg_mouseleave(v0.5.1+) | Triggered when the mouse moves out of the SVG canvas | e(event object) |
|
||||
| node_icon_click(v0.6.10+) | Triggered when clicking on an icon within a node | this(node instance)、item(Click on the icon name)、e(event object) |
|
||||
| view_theme_change(v0.6.12+) | Triggered after calling the setTheme method to set the theme | theme(theme name) |
|
||||
| set_data(v0.7.3+) | Triggered when the setData method is called to dynamically set mind map data | data(New Mind Map Data) |
|
||||
|
||||
### emit(event, ...args)
|
||||
|
||||
@@ -381,7 +387,7 @@ redo. All commands are as follows:
|
||||
| SELECT_ALL | Select all | |
|
||||
| BACK | Go back a specified number of steps | step (the number of steps to go back, default is 1) |
|
||||
| FORWARD | Go forward a specified number of steps | step (the number of steps to go forward, default is 1) |
|
||||
| INSERT_NODE | Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type) |
|
||||
| INSERT_NODE | Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective(v0.7.2+Supports simultaneous insertion of sibling nodes into multiple active nodes) | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type) |
|
||||
| INSERT_CHILD_NODE | Insert a child node, the active node or appoint node will be the operation node | openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is `true`)、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to [exampleData.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js) )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type) |
|
||||
| UP_NODE | Move node up, the active node will be the operation node. If there are multiple active nodes, only the first one will be effective. Using this command on the root node or the first node in the list will be invalid | |
|
||||
| DOWN_NODE | Move node down, the active node will be the operation node. If there are multiple active nodes, only the first one will be effective. Using this command on the root node or the last node in the list will be invalid | |
|
||||
@@ -402,15 +408,18 @@ redo. All commands are as follows:
|
||||
| SET_NODE_HYPERLINK | Set Node Hyperlink | node (node to set), link (hyperlink address), title (hyperlink name, optional) |
|
||||
| SET_NODE_NOTE | Set Node Note | node (node to set), note (note text) |
|
||||
| SET_NODE_TAG | Set Node Tag | node (node to set), tag (string array, built-in color information can be obtained in [constant.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/constants/constant.js)) |
|
||||
| INSERT_AFTER (v0.1.5+) | Move Node to After Another Node | node (node to move), exist (target node) |
|
||||
| INSERT_BEFORE (v0.1.5+) | Move Node to Before Another Node | node (node to move), exist (target node) |
|
||||
| MOVE_NODE_TO (v0.1.5+) | Move a node as a child of another node | node (the node to move), toNode (the target node) |
|
||||
| INSERT_AFTER (v0.1.5+) | Move Node to After Another Node | node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node) |
|
||||
| INSERT_BEFORE (v0.1.5+) | Move Node to Before Another Node | node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node) |
|
||||
| MOVE_NODE_TO (v0.1.5+) | Move a node as a child of another node | node (the node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), toNode (the target node) |
|
||||
| ADD_GENERALIZATION (v0.2.0+) | Add a node summary | data (the data for the summary, in object format, all numerical fields of the node are supported, default is `{text: 'summary'}`) |
|
||||
| REMOVE_GENERALIZATION (v0.2.0+) | Remove a node summary | |
|
||||
| SET_NODE_CUSTOM_POSITION (v0.2.0+) | Set a custom position for a node | node (the node to set), left (custom x coordinate, default is undefined), top (custom y coordinate, default is undefined) |
|
||||
| RESET_LAYOUT (v0.2.0+) | Arrange layout with one click | |
|
||||
| SET_NODE_SHAPE (v0.2.4+) | Set the shape of a node | node (the node to set), shape (the shape, all shapes: [Shape.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/core/render/node/Shape.js)) |
|
||||
| GO_TARGET_NODE(v0.6.7+) | Navigate to a node, and if the node is collapsed, it will automatically expand to that node | node(Node instance or node uid to locate)、callback(v0.6.9+, Callback function after positioning completion) |
|
||||
| INSERT_MULTI_NODE(v0.7.2+) | Insert multiple sibling nodes into the specified node at the same time, with the operating node being the currently active node or the specified node | appointNodes(Optional, specify nodes, specify multiple nodes to pass an array), nodeList(Data list of newly inserted nodes, array type) |
|
||||
| INSERT_MULTI_CHILD_NODE(v0.7.2+) | Insert multiple child nodes into the specified node simultaneously, with the operation node being the currently active node or the specified node | appointNodes(Optional, specify nodes, specify multiple nodes to pass an array), childList(Data list of newly inserted nodes, array type) |
|
||||
| INSERT_FORMULA(v0.7.2+) | Insert mathematical formulas into nodes, operate on the currently active node or specified node | formula(Mathematical formula to insert, LaText syntax), appointNodes(Optional, specify the node to insert the formula into. Multiple nodes can be passed as arrays, otherwise it defaults to the currently active node) |
|
||||
|
||||
### setData(data)
|
||||
|
||||
|
||||
@@ -490,6 +490,41 @@
|
||||
<td>Is the first rendering scaled to fit the canvas size</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragMultiNodeRectConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ width: 40, height: 20, fill: '' }</td>
|
||||
<td>The style configuration of the schematic rectangle that moves with the mouse when dragging multiple nodes, passing an object, and the field meanings are the width, height, and fill color of the rectangle</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragPlaceholderRectFill(v0.7.2+)</td>
|
||||
<td>String</td>
|
||||
<td></td>
|
||||
<td>The filling color of the schematic rectangle for the new position when dragging nodes. If not transmitted, the default color for the connected line is used</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>dragOpacityConfig(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ cloneNodeOpacity: 0.5, beingDragNodeOpacity: 0.3 }</td>
|
||||
<td>The transparency configuration during node dragging, passing an object, and the field meanings are: the transparency of the cloned node or rectangle that follows the mouse movement, and the transparency of the dragged node</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>tagsColorMap(v0.7.2+)</td>
|
||||
<td>Object</td>
|
||||
<td>{}</td>
|
||||
<td>The color of a custom node label can be transferred to an object, where key is the label content to be assigned a color, and value is the color of the label content. If not transferred internally, a corresponding color will be generated based on the label content</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cooperateStyle(v0.7.3+)</td>
|
||||
<td>Object</td>
|
||||
<td>{ avatarSize: 22, fontSize: 12 }</td>
|
||||
<td>The configuration of personnel avatar style during node collaboration editing, with field meanings as follows: avatar size, and if it is a text avatar, the size of the text</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Data structure</h3>
|
||||
@@ -893,6 +928,11 @@ poor performance and should be used sparingly.</p>
|
||||
<td>Triggered after calling the setTheme method to set the theme</td>
|
||||
<td>theme(theme name)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>set_data(v0.7.3+)</td>
|
||||
<td>Triggered when the setData method is called to dynamically set mind map data</td>
|
||||
<td>data(New Mind Map Data)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>emit(event, ...args)</h3>
|
||||
@@ -961,7 +1001,7 @@ redo. All commands are as follows:</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_NODE</td>
|
||||
<td>Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective</td>
|
||||
<td>Insert a sibling node, the active node or appoint node will be the operation node. If there are multiple active nodes, only the first one will be effective(v0.7.2+Supports simultaneous insertion of sibling nodes into multiple active nodes)</td>
|
||||
<td>openEdit(v0.4.6+, Whether to activate the newly inserted node and enter editing mode, default is <code>true</code>) 、 appointNodes(v0.4.7+, Optional, appoint node, Specifying multiple nodes can pass an array)、 appointData(Optional, Specify the data for the newly created node, Such as {text: 'xxx', ...}, Detailed structure can be referred to <a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/example/exampleData.js">exampleData.js</a> )、 appointChildren(v0.6.14+, Optional, Specify the child nodes of the newly created node, array type)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -1067,17 +1107,17 @@ redo. All commands are as follows:</p>
|
||||
<tr>
|
||||
<td>INSERT_AFTER (v0.1.5+)</td>
|
||||
<td>Move Node to After Another Node</td>
|
||||
<td>node (node to move), exist (target node)</td>
|
||||
<td>node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_BEFORE (v0.1.5+)</td>
|
||||
<td>Move Node to Before Another Node</td>
|
||||
<td>node (node to move), exist (target node)</td>
|
||||
<td>node (node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), exist (target node)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MOVE_NODE_TO (v0.1.5+)</td>
|
||||
<td>Move a node as a child of another node</td>
|
||||
<td>node (the node to move), toNode (the target node)</td>
|
||||
<td>node (the node to move, (v0.7.2+supports passing node arrays to move multiple nodes simultaneously)), toNode (the target node)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ADD_GENERALIZATION (v0.2.0+)</td>
|
||||
@@ -1109,6 +1149,21 @@ redo. All commands are as follows:</p>
|
||||
<td>Navigate to a node, and if the node is collapsed, it will automatically expand to that node</td>
|
||||
<td>node(Node instance or node uid to locate)、callback(v0.6.9+, Callback function after positioning completion)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_MULTI_NODE(v0.7.2+)</td>
|
||||
<td>Insert multiple sibling nodes into the specified node at the same time, with the operating node being the currently active node or the specified node</td>
|
||||
<td>appointNodes(Optional, specify nodes, specify multiple nodes to pass an array), nodeList(Data list of newly inserted nodes, array type)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_MULTI_CHILD_NODE(v0.7.2+)</td>
|
||||
<td>Insert multiple child nodes into the specified node simultaneously, with the operation node being the currently active node or the specified node</td>
|
||||
<td>appointNodes(Optional, specify nodes, specify multiple nodes to pass an array), childList(Data list of newly inserted nodes, array type)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>INSERT_FORMULA(v0.7.2+)</td>
|
||||
<td>Insert mathematical formulas into nodes, operate on the currently active node or specified node</td>
|
||||
<td>formula(Mathematical formula to insert, LaText syntax), appointNodes(Optional, specify the node to insert the formula into. Multiple nodes can be passed as arrays, otherwise it defaults to the currently active node)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>setData(data)</h3>
|
||||
|
||||
124
web/src/pages/Doc/en/cooperate/index.md
Normal file
124
web/src/pages/Doc/en/cooperate/index.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Cooperate plugin beta
|
||||
|
||||
> v0.7.3+
|
||||
|
||||
This plugin is used to achieve collaborative editing.
|
||||
|
||||
## Introduce
|
||||
|
||||
This plugin implements collaborative editing through [Yjs](https://github.com/yjs/yjs). The basic principle is to convert the tree data of the mind map into flat object data, and then collaborate through shared data of type [Y.Map](https://docs.yjs.dev/api/shared-types/y.map). That is, when certain operations are performed on the canvas, the 'y.map' object will be updated, and other collaborative clients will receive the updated data, convert it back to tree structure data, and update the canvas to achieve real-time updates.
|
||||
|
||||
To achieve collaboration, the backend is indispensable, and 'Yjs' provides some [Connection Providers](https://docs.yjs.dev/ecosystem/connection-provider). At the same time, it also provides examples of the backend, but it is only the simplest implementation. In actual projects, you should need to rewrite or improve it.
|
||||
|
||||
You can choose the 'Provider' that suits you, and the default is [y-webrtc](https://github.com/yjs/y-webrtc).
|
||||
|
||||
## demo
|
||||
|
||||
If you want to try it through demo, you can do the following steps:
|
||||
|
||||
1. Clone project and installation dependencies:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wanglin2/mind-map.git
|
||||
cd mind-map
|
||||
cd simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
cd ..
|
||||
cd web
|
||||
npm i
|
||||
npm link simple-mind-map
|
||||
```
|
||||
|
||||
2. Modify `web/src/pages/Edit/components/Edit.vue` file
|
||||
|
||||
To register Cooperate plugin, uncomment the line:
|
||||
|
||||
```js
|
||||
// .usePlugin(Cooperate)// Cooperate plugin
|
||||
```
|
||||
|
||||
Change the signaling server address to your local IP:
|
||||
|
||||
```js
|
||||
// cooperateTest function
|
||||
|
||||
signalingList: ['ws://【your ip】:4444']
|
||||
```
|
||||
|
||||
3. To register a collaborative plugin, uncomment the line:
|
||||
|
||||
```bash
|
||||
// Execute under web path
|
||||
npm run serve
|
||||
```
|
||||
|
||||
4. Start signaling server:
|
||||
|
||||
```bash
|
||||
// Execute under simple-mind-map path
|
||||
npm run wsServe
|
||||
```
|
||||
|
||||
The command executes the 'simple mind map/bin/wsServer.mjs' file, which is directly copied from the [y webrtc](https://github.com/yjs/y-webrtc) repository and may not be complete. Please be cautious when using it for actual projects.
|
||||
|
||||
5. Access the service address in two browsers:
|
||||
|
||||
```
|
||||
http://【your ip】:8080/#/?userName=userName
|
||||
```
|
||||
|
||||
You can set different userNames on different browsers. Then you can edit in one browser and see the automatic update in another browser.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Cooperate from 'simple-mind-map/src/plugins/Cooperate.js'
|
||||
MindMap.usePlugin(Cooperate)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.cooperate`.
|
||||
|
||||
## Methods
|
||||
|
||||
### getDoc()
|
||||
|
||||
Obtain Yjs doc instance.
|
||||
|
||||
### setProvider(provider, webrtcProviderConfig)
|
||||
|
||||
- `provider`: The connection provider for Yjs can refer to the [Connection Provider](https://docs.yjs.dev/ecosystem/connection-provider), default is `null`
|
||||
|
||||
- `webrtcProviderConfig`: the options of webrtc provider, An object needs to be passed in the following format:
|
||||
|
||||
```js
|
||||
{
|
||||
roomName: '', // Mandatory, room name
|
||||
signalingList: [''],// Mandatory, specify signaling server
|
||||
...// The other config of webrtc provider
|
||||
}
|
||||
```
|
||||
|
||||
For detailed configuration, please refer to [y-webrtc](https://github.com/yjs/y-webrtc)。
|
||||
|
||||
Set the connection provider for Yjs. If 'provider' is not transmitted, 'y webrtc' will be used by default. You can also use other 'providers'.
|
||||
|
||||
If the default 'y webrtc' is used, the necessary configuration needs to be passed in through the second parameter.
|
||||
|
||||
`simple-mind-map/bin/wsServer.mjs` file provides a simple signaling server code for testing and reference.
|
||||
|
||||
### setUserInfo(userInfo)
|
||||
|
||||
- `userInfo`: User information. The format is as follows:
|
||||
|
||||
```js
|
||||
{
|
||||
id: '', // Mandatory, user's unique ID
|
||||
name: '', // User name. Only one name and avatar can be transmitted. If both are transmitted, avatar will be displayed
|
||||
avatar: '', // User profile
|
||||
color: '' // If there is no avatar, the first character of the name will be displayed as a circle, and the color of the text will be white. The color of the circle can be set through this field
|
||||
}
|
||||
```
|
||||
|
||||
Set the current user's information for synchronization and display of perceptual data. If other collaborators activate a node, their avatar will be displayed above that node in your current canvas.
|
||||
109
web/src/pages/Doc/en/cooperate/index.vue
Normal file
109
web/src/pages/Doc/en/cooperate/index.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Cooperate plugin beta</h1>
|
||||
<blockquote>
|
||||
<p>v0.7.3+</p>
|
||||
</blockquote>
|
||||
<p>This plugin is used to achieve collaborative editing.</p>
|
||||
<h2>Introduce</h2>
|
||||
<p>This plugin implements collaborative editing through <a href="https://github.com/yjs/yjs">Yjs</a>. The basic principle is to convert the tree data of the mind map into flat object data, and then collaborate through shared data of type <a href="https://docs.yjs.dev/api/shared-types/y.map">Y.Map</a>. That is, when certain operations are performed on the canvas, the 'y.map' object will be updated, and other collaborative clients will receive the updated data, convert it back to tree structure data, and update the canvas to achieve real-time updates.</p>
|
||||
<p>To achieve collaboration, the backend is indispensable, and 'Yjs' provides some <a href="https://docs.yjs.dev/ecosystem/connection-provider">Connection Providers</a>. At the same time, it also provides examples of the backend, but it is only the simplest implementation. In actual projects, you should need to rewrite or improve it.</p>
|
||||
<p>You can choose the 'Provider' that suits you, and the default is <a href="https://github.com/yjs/y-webrtc">y-webrtc</a>.</p>
|
||||
<h2>demo</h2>
|
||||
<p>If you want to try it through demo, you can do the following steps:</p>
|
||||
<ol>
|
||||
<li>Clone project and installation dependencies:</li>
|
||||
</ol>
|
||||
<pre class="hljs"><code>git <span class="hljs-built_in">clone</span> https://github.com/wanglin2/mind-map.git
|
||||
<span class="hljs-built_in">cd</span> mind-map
|
||||
<span class="hljs-built_in">cd</span> simple-mind-map
|
||||
npm i
|
||||
npm link
|
||||
<span class="hljs-built_in">cd</span> ..
|
||||
<span class="hljs-built_in">cd</span> web
|
||||
npm i
|
||||
npm link simple-mind-map
|
||||
</code></pre>
|
||||
<ol start="2">
|
||||
<li>Modify <code>web/src/pages/Edit/components/Edit.vue</code> file</li>
|
||||
</ol>
|
||||
<p>To register Cooperate plugin, uncomment the line:</p>
|
||||
<pre class="hljs"><code><span class="hljs-comment">// .usePlugin(Cooperate)// Cooperate plugin</span>
|
||||
</code></pre>
|
||||
<p>Change the signaling server address to your local IP:</p>
|
||||
<pre class="hljs"><code><span class="hljs-comment">// cooperateTest function</span>
|
||||
|
||||
<span class="hljs-attr">signalingList</span>: [<span class="hljs-string">'ws://【your ip】:4444'</span>]
|
||||
</code></pre>
|
||||
<ol start="3">
|
||||
<li>To register a collaborative plugin, uncomment the line:</li>
|
||||
</ol>
|
||||
<pre class="hljs"><code>// Execute under web path
|
||||
npm run serve
|
||||
</code></pre>
|
||||
<ol start="4">
|
||||
<li>Start signaling server:</li>
|
||||
</ol>
|
||||
<pre class="hljs"><code>// Execute under simple-mind-map path
|
||||
npm run wsServe
|
||||
</code></pre>
|
||||
<p>The command executes the 'simple mind map/bin/wsServer.mjs' file, which is directly copied from the <a href="https://github.com/yjs/y-webrtc">y webrtc</a> repository and may not be complete. Please be cautious when using it for actual projects.</p>
|
||||
<ol start="5">
|
||||
<li>Access the service address in two browsers:</li>
|
||||
</ol>
|
||||
<pre class="hljs"><code>http://【your ip】:8080/#/?userName=userName
|
||||
</code></pre>
|
||||
<p>You can set different userNames on different browsers. Then you can edit in one browser and see the automatic update in another browser.</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> Cooperate <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/plugins/Cooperate.js'</span>
|
||||
MindMap.usePlugin(Cooperate)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.cooperate</code>.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>getDoc()</h3>
|
||||
<p>Obtain Yjs doc instance.</p>
|
||||
<h3>setProvider(provider, webrtcProviderConfig)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>provider</code>: The connection provider for Yjs can refer to the <a href="https://docs.yjs.dev/ecosystem/connection-provider">Connection Provider</a>, default is <code>null</code></p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>webrtcProviderConfig</code>: the options of webrtc provider, An object needs to be passed in the following format:</p>
|
||||
</li>
|
||||
</ul>
|
||||
<pre class="hljs"><code>{
|
||||
<span class="hljs-attr">roomName</span>: <span class="hljs-string">''</span>, <span class="hljs-comment">// Mandatory, room name</span>
|
||||
<span class="hljs-attr">signalingList</span>: [<span class="hljs-string">''</span>],<span class="hljs-comment">// Mandatory, specify signaling server</span>
|
||||
...<span class="hljs-comment">// The other config of webrtc provider</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>For detailed configuration, please refer to <a href="https://github.com/yjs/y-webrtc">y-webrtc</a>。</p>
|
||||
<p>Set the connection provider for Yjs. If 'provider' is not transmitted, 'y webrtc' will be used by default. You can also use other 'providers'.</p>
|
||||
<p>If the default 'y webrtc' is used, the necessary configuration needs to be passed in through the second parameter.</p>
|
||||
<p><code>simple-mind-map/bin/wsServer.mjs</code> file provides a simple signaling server code for testing and reference.</p>
|
||||
<h3>setUserInfo(userInfo)</h3>
|
||||
<ul>
|
||||
<li><code>userInfo</code>: User information. The format is as follows:</li>
|
||||
</ul>
|
||||
<pre class="hljs"><code>{
|
||||
<span class="hljs-attr">id</span>: <span class="hljs-string">''</span>, <span class="hljs-comment">// Mandatory, user's unique ID</span>
|
||||
<span class="hljs-attr">name</span>: <span class="hljs-string">''</span>, <span class="hljs-comment">// User name. Only one name and avatar can be transmitted. If both are transmitted, avatar will be displayed</span>
|
||||
<span class="hljs-attr">avatar</span>: <span class="hljs-string">''</span>, <span class="hljs-comment">// User profile</span>
|
||||
<span class="hljs-attr">color</span>: <span class="hljs-string">''</span> <span class="hljs-comment">// If there is no avatar, the first character of the name will be displayed as a circle, and the color of the text will be white. The color of the circle can be set through this field</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p>Set the current user's information for synchronization and display of perceptual data. If other collaborators activate a node, their avatar will be displayed above that node in your current canvas.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
36
web/src/pages/Doc/en/formula/index.md
Normal file
36
web/src/pages/Doc/en/formula/index.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Formula plugin
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
> This plugin is only supported in rich text mode, so it needs to be used after registering the RichText plugin
|
||||
|
||||
This plugin is used to support inserting formulas into nodes.
|
||||
|
||||
## Register
|
||||
|
||||
```js
|
||||
import MindMap from 'simple-mind-map'
|
||||
import Formula from 'simple-mind-map/src/plugins/Formula.js'
|
||||
|
||||
MindMap.usePlugin(Formula)
|
||||
```
|
||||
|
||||
After registration and instantiation of `MindMap`, the instance can be obtained through `mindMap.formula`.
|
||||
|
||||
## Usage
|
||||
|
||||
After registering the plugin, you can use the command 'INSERT_FORMULA' to insert the specified formula for the node:
|
||||
|
||||
```js
|
||||
mindMap.execCommand('INSERT_FORMULA', 'a^2')
|
||||
```
|
||||
|
||||
The above command will insert the 'a^2' formula into the currently active node.
|
||||
|
||||
If you want to assign a formula to a node or nodes, you can pass the second parameter:
|
||||
|
||||
```js
|
||||
mindMap.execCommand('INSERT_FORMULA', 'a^2', [Node])
|
||||
```
|
||||
|
||||
Pass in the specified node instance through the second parameter.
|
||||
39
web/src/pages/Doc/en/formula/index.vue
Normal file
39
web/src/pages/Doc/en/formula/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Formula plugin</h1>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>This plugin is only supported in rich text mode, so it needs to be used after registering the RichText plugin</p>
|
||||
</blockquote>
|
||||
<p>This plugin is used to support inserting formulas into 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> Formula <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/plugins/Formula.js'</span>
|
||||
|
||||
MindMap.usePlugin(Formula)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.formula</code>.</p>
|
||||
<h2>Usage</h2>
|
||||
<p>After registering the plugin, you can use the command 'INSERT_FORMULA' to insert the specified formula for the node:</p>
|
||||
<pre class="hljs"><code>mindMap.execCommand(<span class="hljs-string">'INSERT_FORMULA'</span>, <span class="hljs-string">'a^2'</span>)
|
||||
</code></pre>
|
||||
<p>The above command will insert the 'a^2' formula into the currently active node.</p>
|
||||
<p>If you want to assign a formula to a node or nodes, you can pass the second parameter:</p>
|
||||
<pre class="hljs"><code>mindMap.execCommand(<span class="hljs-string">'INSERT_FORMULA'</span>, <span class="hljs-string">'a^2'</span>, [Node])
|
||||
</code></pre>
|
||||
<p>Pass in the specified node instance through the second parameter.</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -11,13 +11,14 @@
|
||||
- [x] Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume
|
||||
- [x] Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures
|
||||
- [x] Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes
|
||||
- [x] Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, and summaries
|
||||
- [x] Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas
|
||||
- [x] Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM
|
||||
- [x] Support canvas dragging and scaling
|
||||
- [x] Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection
|
||||
- [x] Supoorts to export as `json`、`png`、`svg`、`pdf`、`markdown`、`xmind`, support import from `json`、`xmind`、`markdown`
|
||||
- [x] Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, and watermarks
|
||||
- [x] Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar
|
||||
- [x] Provide rich configurations to meet various scenarios and usage habits
|
||||
- [x] Support collaborative editing
|
||||
|
||||
## Repository Catalog Introduction
|
||||
|
||||
@@ -62,6 +63,8 @@ The folder containing the packaged resources for the `web` folder.
|
||||
|
||||
[My first Electron application](https://juejin.cn/post/7233012756314701884)
|
||||
|
||||
[Explore how to export HTML and SVG as images](https://juejin.cn/post/7276712861514170409)
|
||||
|
||||
## Special Note
|
||||
|
||||
This project can be used for learning and reference. Please deeply experience whether it can meet your needs when using it for actual projects.
|
||||
@@ -70,7 +73,7 @@ This project may not have fully tested every function point, so there may be bug
|
||||
|
||||
If you have suggestions or find bugs, you can submit [issues](https://github.com/wanglin2/mind-map/issues) here.
|
||||
|
||||
The built-in themes and icons in the project come from:
|
||||
The built-in themes and icons in the project part come from:
|
||||
|
||||
[Baidu Mind Map](https://naotu.baidu.com/)
|
||||
|
||||
@@ -90,7 +93,7 @@ There are many other online mind mapping products similar to Zhixi, such as [Git
|
||||
|
||||
`kityminder-core` is an open source brain mapping tool developed by Baidu. It has powerful functions and good performance, but it is no longer maintained. Therefore, the code is relatively old, and the interface beauty is relatively ordinary. In addition, bugs can only be fixed by yourself, and the functions can only be developed by yourself. It has high requirements for front-end development capabilities.
|
||||
|
||||
3.[jsmind](https://github.com/hizzgdev/jsmind)、[Mind-elixir](https://github.com/ssshooter/mind-elixir-core)、[my-mind](https://github.com/ondras/my-mind)、[blink-mind](https://github.com/awehook/blink-mind)、[remind](https://github.com/luvsic3/remind)、[vue3-mindmap](https://github.com/hellowuxin/vue3-mindmap)、[ZMindMap](https://github.com/zyascend/ZMindMap)...
|
||||
3.[jsmind](https://github.com/hizzgdev/jsmind)、[Mind-elixir](https://github.com/ssshooter/mind-elixir-core)、[my-mind](https://github.com/ondras/my-mind)、[blink-mind](https://github.com/awehook/blink-mind)、[remind](https://github.com/luvsic3/remind)、[vue3-mindmap](https://github.com/hellowuxin/vue3-mindmap)、[ZMindMap](https://github.com/zyascend/ZMindMap)、[mindmaptree](https://github.com/RockyRen/mindmaptree)...
|
||||
|
||||
These open-source mind maps are also good, each with its own characteristics, but they also have certain drawbacks, such as stopping updates, average interface aesthetics, less functionality, relying on a certain framework, and so on.
|
||||
|
||||
@@ -114,7 +117,7 @@ Unsupported: `IE` browser.
|
||||
|
||||
Open source is not easy. If this project is helpful to you, you can invite the author to have a cup of coffee~
|
||||
|
||||
> Please note the 【mind map】 for transfer. Your avatar and name will appear below.
|
||||
> Please note the 【mind map】 for transfer.
|
||||
|
||||
<img src="../../../../assets/img/alipay.jpg" style="width: 300px" />
|
||||
|
||||
@@ -204,4 +207,20 @@ Open source is not easy. If this project is helpful to you, you can invite the a
|
||||
<img src="../../../../assets/avatar/敏.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>敏</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>沐风牧草</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/有希.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>有希</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/樊笼.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>樊笼</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/达仁科技.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>达仁科技</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,16 +8,17 @@
|
||||
</blockquote>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox30" checked="true" /><label for="checkbox30">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox31" checked="true" /><label for="checkbox31">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
|
||||
<li><input type="checkbox" id="checkbox32" checked="true" /><label for="checkbox32">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox33" checked="true" /><label for="checkbox33">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, and summaries</label></li>
|
||||
<li><input type="checkbox" id="checkbox34" checked="true" /><label for="checkbox34">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox35" checked="true" /><label for="checkbox35">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox36" checked="true" /><label for="checkbox36">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox37" checked="true" /><label for="checkbox37">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox38" checked="true" /><label for="checkbox38">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, and watermarks</label></li>
|
||||
<li><input type="checkbox" id="checkbox39" checked="true" /><label for="checkbox39">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox48" checked="true" /><label for="checkbox48">Pluggable architecture, in addition to core functions, other functions are provided as plugins, which can be used as needed to reduce packaging volume</label></li>
|
||||
<li><input type="checkbox" id="checkbox49" checked="true" /><label for="checkbox49">Support logical structure chart, mind map, Organizational chart, directory organization chart, timeline (horizontal and vertical), fishbone chart and other structures</label></li>
|
||||
<li><input type="checkbox" id="checkbox50" checked="true" /><label for="checkbox50">Built-in multiple themes, allowing for highly customizable styles, and supporting registration of new themes</label></li>
|
||||
<li><input type="checkbox" id="checkbox51" checked="true" /><label for="checkbox51">Node content supports text (regular text, rich text), images, icons, hyperlinks, notes, labels, summaries, and math formulas</label></li>
|
||||
<li><input type="checkbox" id="checkbox52" checked="true" /><label for="checkbox52">Nodes support drag and drop (drag and move, freely adjust), multiple node shapes, and fully customize node content using DDM</label></li>
|
||||
<li><input type="checkbox" id="checkbox53" checked="true" /><label for="checkbox53">Support canvas dragging and scaling</label></li>
|
||||
<li><input type="checkbox" id="checkbox54" checked="true" /><label for="checkbox54">Supports two multi node selection methods: mouse button drag selection and Ctrl+left button selection</label></li>
|
||||
<li><input type="checkbox" id="checkbox55" checked="true" /><label for="checkbox55">Supoorts to export as </label><code>json</code>、<code>png</code>、<code>svg</code>、<code>pdf</code>、<code>markdown</code>、<code>xmind</code>, support import from <code>json</code>、<code>xmind</code>、<code>markdown</code></li>
|
||||
<li><input type="checkbox" id="checkbox56" checked="true" /><label for="checkbox56">Support shortcut keys, forward and backward, correlation lines, search and replacement, small maps, watermarks, and scrollbar</label></li>
|
||||
<li><input type="checkbox" id="checkbox57" checked="true" /><label for="checkbox57">Provide rich configurations to meet various scenarios and usage habits</label></li>
|
||||
<li><input type="checkbox" id="checkbox58" checked="true" /><label for="checkbox58">Support collaborative editing</label></li>
|
||||
</ul>
|
||||
<h2>Repository Catalog Introduction</h2>
|
||||
<p>1.<code>simple-mind-map</code></p>
|
||||
@@ -27,16 +28,16 @@ frameworks such as Vue and React, or without a framework.</p>
|
||||
<p>This is an online mind map built using the <code>simple-mind-map</code> library and based
|
||||
on <code>Vue2.x</code> and <code>ElementUI</code>. Features include:</p>
|
||||
<ul>
|
||||
<li><input type="checkbox" id="checkbox40" checked="true" /><label for="checkbox40">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
<li><input type="checkbox" id="checkbox59" checked="true" /><label for="checkbox59">Toolbar, which supports inserting and deleting nodes, and editing node</label>
|
||||
images, icons, hyperlinks, notes, tags, and summaries</li>
|
||||
<li><input type="checkbox" id="checkbox41" checked="true" /><label for="checkbox41">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
<li><input type="checkbox" id="checkbox60" checked="true" /><label for="checkbox60">Sidebar, with panels for basic style settings, node style settings,</label>
|
||||
outline, theme selection, and structure selection</li>
|
||||
<li><input type="checkbox" id="checkbox42" checked="true" /><label for="checkbox42">Import and export functionality; data is saved in the browser's local</label>
|
||||
<li><input type="checkbox" id="checkbox61" checked="true" /><label for="checkbox61">Import and export functionality; data is saved in the browser's local</label>
|
||||
storage by default, but it also supports creating, opening, and editing
|
||||
local files on the computer directly</li>
|
||||
<li><input type="checkbox" id="checkbox43" checked="true" /><label for="checkbox43">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
<li><input type="checkbox" id="checkbox62" checked="true" /><label for="checkbox62">Right-click menu, which supports operations such as expanding, collapsing,</label>
|
||||
and organizing layout</li>
|
||||
<li><input type="checkbox" id="checkbox44" checked="true" /><label for="checkbox44">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
<li><input type="checkbox" id="checkbox63" checked="true" /><label for="checkbox63">Bottom bar, which supports node and word count statistics, switching</label>
|
||||
between edit and read-only modes, zooming in and out, and switching to
|
||||
full screen, support mini map</li>
|
||||
</ul>
|
||||
@@ -49,11 +50,12 @@ full screen, support mini map</li>
|
||||
<p><a href="https://juejin.cn/post/7199666255883927612">When you press the direction key, how does the TV find the next focus</a></p>
|
||||
<p><a href="https://juejin.cn/post/7204854015463538744">How to simulate the background image style of css in canvas</a></p>
|
||||
<p><a href="https://juejin.cn/post/7233012756314701884">My first Electron application</a></p>
|
||||
<p><a href="https://juejin.cn/post/7276712861514170409">Explore how to export HTML and SVG as images</a></p>
|
||||
<h2>Special Note</h2>
|
||||
<p>This project can be used for learning and reference. Please deeply experience whether it can meet your needs when using it for actual projects.</p>
|
||||
<p>This project may not have fully tested every function point, so there may be bugs. In addition, when the number of nodes is very large, there may be some performance issues. Because everyone can accept different levels of congestion, you can test the maximum number of nodes yourself.</p>
|
||||
<p>If you have suggestions or find bugs, you can submit <a href="https://github.com/wanglin2/mind-map/issues">issues</a> here.</p>
|
||||
<p>The built-in themes and icons in the project come from:</p>
|
||||
<p>The built-in themes and icons in the project part 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>
|
||||
<p>Respect the copyright, and do not use the theme and icons directly for commercial projects.</p>
|
||||
@@ -63,7 +65,7 @@ full screen, support mini map</li>
|
||||
<p>There are many other online mind mapping products similar to Zhixi, such as <a href="https://gitmind.cn/">GitMind</a>、<a href="http://www.mindline.cn/">MindLine</a>、<a href="https://www.mindmeister.com/zh">MinMeister</a>、<a href="https://mubu.com/">Mubu</a> and so on, There are many searches on search engines, but these products either require fees or are developed by small companies, and their stability and sustainability cannot be guaranteed. Of course, the most crucial thing is that they are not open-source.</p>
|
||||
<p>2.<a href="https://github.com/fex-team/kityminder-core">kityminder-core</a></p>
|
||||
<p><code>kityminder-core</code> is an open source brain mapping tool developed by Baidu. It has powerful functions and good performance, but it is no longer maintained. Therefore, the code is relatively old, and the interface beauty is relatively ordinary. In addition, bugs can only be fixed by yourself, and the functions can only be developed by yourself. It has high requirements for front-end development capabilities.</p>
|
||||
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a>、<a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a>、<a href="https://github.com/ondras/my-mind">my-mind</a>、<a href="https://github.com/awehook/blink-mind">blink-mind</a>、<a href="https://github.com/luvsic3/remind">remind</a>、<a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a>、<a href="https://github.com/zyascend/ZMindMap">ZMindMap</a>...</p>
|
||||
<p>3.<a href="https://github.com/hizzgdev/jsmind">jsmind</a>、<a href="https://github.com/ssshooter/mind-elixir-core">Mind-elixir</a>、<a href="https://github.com/ondras/my-mind">my-mind</a>、<a href="https://github.com/awehook/blink-mind">blink-mind</a>、<a href="https://github.com/luvsic3/remind">remind</a>、<a href="https://github.com/hellowuxin/vue3-mindmap">vue3-mindmap</a>、<a href="https://github.com/zyascend/ZMindMap">ZMindMap</a>、<a href="https://github.com/RockyRen/mindmaptree">mindmaptree</a>...</p>
|
||||
<p>These open-source mind maps are also good, each with its own characteristics, but they also have certain drawbacks, such as stopping updates, average interface aesthetics, less functionality, relying on a certain framework, and so on.</p>
|
||||
<p>In summary, in open-source mind maps, it is difficult to find a better choice than <code>simple-mind-map</code>. Of course, <code>simple-mind-map</code> is far from being the best, and it also has many shortcomings, as you saw in the previous [special note]. However, <code>simple-mind-map</code> has always been in a fast iteration process, and we welcome you to join and improve it together.</p>
|
||||
<h2>Browser Compatibility</h2>
|
||||
@@ -76,7 +78,7 @@ full screen, support mini map</li>
|
||||
<h2>Invite the author to a cup of coffee</h2>
|
||||
<p>Open source is not easy. If this project is helpful to you, you can invite the author to have a cup of coffee~</p>
|
||||
<blockquote>
|
||||
<p>Please note the 【mind map】 for transfer. Your avatar and name will appear below.</p>
|
||||
<p>Please note the 【mind map】 for transfer.</p>
|
||||
</blockquote>
|
||||
<img src="../../../../assets/img/alipay.jpg" style="width: 300px" />
|
||||
<img src="../../../../assets/img/wechat.jpg" style="width: 300px" />
|
||||
@@ -163,6 +165,22 @@ full screen, support mini map</li>
|
||||
<img src="../../../../assets/avatar/敏.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>敏</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/沐风牧草.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>沐风牧草</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/有希.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>有希</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/樊笼.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>樊笼</p>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; width: fit-content; margin: 5px;">
|
||||
<img src="../../../../assets/avatar/达仁科技.jpg" style="width: 50px;height: 50px;object-fit: cover;border-radius: 50%;" />
|
||||
<p>达仁科技</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -56,6 +56,26 @@ Whether the node is currently being dragged
|
||||
|
||||
## Methods
|
||||
|
||||
### setOpacity(val)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `val`: Opacity value,0-1
|
||||
|
||||
Set node transparency, including connecting lines and child nodes.
|
||||
|
||||
### hideChildren()
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
Hide subordinate nodes.
|
||||
|
||||
### showChildren()
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
Display subordinate nodes.
|
||||
|
||||
### hasCustomStyle()
|
||||
|
||||
> v0.6.2+
|
||||
|
||||
@@ -31,6 +31,24 @@
|
||||
</blockquote>
|
||||
<p>Whether the node is currently being dragged</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>setOpacity(val)</h3>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>val</code>: Opacity value,0-1</li>
|
||||
</ul>
|
||||
<p>Set node transparency, including connecting lines and child nodes.</p>
|
||||
<h3>hideChildren()</h3>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<p>Hide subordinate nodes.</p>
|
||||
<h3>showChildren()</h3>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<p>Display subordinate nodes.</p>
|
||||
<h3>hasCustomStyle()</h3>
|
||||
<blockquote>
|
||||
<p>v0.6.2+</p>
|
||||
|
||||
@@ -15,6 +15,12 @@ Gets the root node of the node tree
|
||||
|
||||
## Methods
|
||||
|
||||
### setData(data)
|
||||
|
||||
> v0.7.3+
|
||||
|
||||
Dynamically set mind map data.
|
||||
|
||||
### clearActive()
|
||||
|
||||
Clears the currently active node
|
||||
|
||||
@@ -9,6 +9,11 @@ accessed through <code>mindMap.renderer</code>.</p>
|
||||
<h3>root</h3>
|
||||
<p>Gets the root node of the node tree</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>setData(data)</h3>
|
||||
<blockquote>
|
||||
<p>v0.7.3+</p>
|
||||
</blockquote>
|
||||
<p>Dynamically set mind map data.</p>
|
||||
<h3>clearActive()</h3>
|
||||
<p>Clears the currently active node</p>
|
||||
<h3>clearAllActive()</h3>
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
# Participate in translation
|
||||
# Contribute
|
||||
|
||||
## Participate in development
|
||||
|
||||
If you want to contribute code, you can 'fork' this project and switch to the 'feature' branch for development. After development and testing, you can submit the 'pr' to the 'feature' branch of this project. When submitting, please try to submit functional files as much as possible. Do not submit unnecessary files.
|
||||
|
||||
Before development, it is best to create a new 'issue' to describe the new features you want to add. We can have sufficient communication first, and when submitting a 'pr', please provide a detailed description of the features you are developing.
|
||||
|
||||
## Participate in translation
|
||||
|
||||
> Thanks for the first version English translation provided by [Emircan ERKUL](https://github.com/emircanerkul).
|
||||
>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Participate in translation</h1>
|
||||
<h1>Contribute</h1>
|
||||
<h2>Participate in development</h2>
|
||||
<p>If you want to contribute code, you can 'fork' this project and switch to the 'feature' branch for development. After development and testing, you can submit the 'pr' to the 'feature' branch of this project. When submitting, please try to submit functional files as much as possible. Do not submit unnecessary files.</p>
|
||||
<p>Before development, it is best to create a new 'issue' to describe the new features you want to add. We can have sufficient communication first, and when submitting a 'pr', please provide a detailed description of the features you are developing.</p>
|
||||
<h2>Participate in translation</h2>
|
||||
<blockquote>
|
||||
<p>Thanks for the first version English translation provided by <a href="https://github.com/emircanerkul">Emircan ERKUL</a>.</p>
|
||||
<p>Due to limited energy, most translations currently use machine translation, so accuracy is inevitably problematic.</p>
|
||||
|
||||
@@ -90,7 +90,9 @@ copyRenderTree({}, this.mindMap.renderer.renderTree);
|
||||
|
||||
- `removeActiveState`: `Boolean`, default is `false`, Whether to remove the active state of the node
|
||||
|
||||
- `keepId`: v0.4.6+, `Boolean`, default is `false`, Whether to retain the `id` of the replicated node will be deleted by default to prevent duplicate node `id`. However, for mobile node scenarios, the original `id` of the node needs to be retained
|
||||
- `removeId`:v0.7.3-fix.1+, Is remove the uid from the node data, default is `true`
|
||||
|
||||
> - `keepId`: (Original fourth parameter) v0.4.6+, `Boolean`, default is `false`, Whether to retain the `id` of the replicated node will be deleted by default to prevent duplicate node `id`. However, for mobile node scenarios, the original `id` of the node needs to be retained
|
||||
|
||||
Copy node tree data, mainly eliminating the reference `node` instance `_node`
|
||||
and copying the `data` of the data object, example:
|
||||
@@ -250,6 +252,117 @@ Convert the wrapped text of `<br>` into node rich text content in the form of `<
|
||||
|
||||
Determine if it is a mobile environment.
|
||||
|
||||
#### getTopAncestorsFomNodeList(list)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `list`: Arrray, Node instance list.
|
||||
|
||||
Find the top-level node list from the node instance list.
|
||||
|
||||
#### checkTwoRectIsOverlap(minx1, maxx1, miny1, maxy1, minx2, maxx2, miny2, maxy2)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
The parameter is the position of two rectangles.
|
||||
|
||||
Determine if two rectangles overlap.
|
||||
|
||||
#### focusInput(el)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `el`: DOM nodes, elements that can be focused, typically input box elements.
|
||||
|
||||
Focus on the specified input box.
|
||||
|
||||
#### selectAllInput(el)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `el`: DOM nodes, elements that can be focused, typically input box elements.
|
||||
|
||||
Focus and select all specified input boxes.
|
||||
|
||||
#### addDataToAppointNodes(appointNodes, data = {})
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `appointNodes`:Node instance list, array type.
|
||||
|
||||
- `data`:The data to be attached to all nodes in the specified node instance list tree.
|
||||
|
||||
Adding additional data to the specified node list tree data will modify the original data.
|
||||
|
||||
#### createUidForAppointNodes(appointNodes, createNewId)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `appointNodes`:Node instance list, array type.
|
||||
|
||||
- `createNewId`:v0.7.3-fix.1+, `Boolean`, default is `false`, If the node does not have a 'uid', a new 'uid' will be created. If 'true' is passed, a new 'uid' will be created regardless of whether the node data originally exists or not`
|
||||
|
||||
Adding a uid to the specified node list tree data (if the uid does not exist) will modify the original data.
|
||||
|
||||
#### getNodeIndex(node)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `node`:Node instance.
|
||||
|
||||
Gets the position index of a node within its peers.
|
||||
|
||||
#### mergerIconList(list)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `list`:The array of node icons to be merged into the library.
|
||||
|
||||
```js
|
||||
// const data = [
|
||||
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },
|
||||
// { type: 'priority', name: '优先级图标', list: [{ name: '2', icon: 'c' }, { name: 3, icon: 'd' }] },
|
||||
// ];
|
||||
|
||||
// mergerIconList(data) result:
|
||||
|
||||
// [
|
||||
// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'c' }, { name: 3, icon: 'd' }] },
|
||||
// ]
|
||||
```
|
||||
|
||||
Merge icon arrays.
|
||||
|
||||
#### htmlEscape(str)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `str`:String.
|
||||
|
||||
Escape the incoming string, currently escaping the following three characters:
|
||||
|
||||
```
|
||||
& -> &
|
||||
< -> <
|
||||
> -> >
|
||||
```
|
||||
|
||||
#### generateColorByContent(str)
|
||||
|
||||
> v0.7.2+
|
||||
|
||||
- `str`:String.
|
||||
|
||||
Generate colors based on incoming content, and the same content will generate the same color.
|
||||
|
||||
#### isSameObject(a, b)
|
||||
|
||||
> v0.7.3+
|
||||
|
||||
- `a`、`b`: Object | Array, Two objects to compare
|
||||
|
||||
Determine whether two objects are the same, only handling objects or arrays.
|
||||
|
||||
## Simulate CSS background in Canvas
|
||||
|
||||
Import:
|
||||
|
||||
@@ -54,9 +54,14 @@ basic data, otherwise it will throw an error</p>
|
||||
<p><code>removeActiveState</code>: <code>Boolean</code>, default is <code>false</code>, Whether to remove the active state of the node</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>keepId</code>: v0.4.6+, <code>Boolean</code>, default is <code>false</code>, Whether to retain the <code>id</code> of the replicated node will be deleted by default to prevent duplicate node <code>id</code>. However, for mobile node scenarios, the original <code>id</code> of the node needs to be retained</p>
|
||||
<p><code>removeId</code>:v0.7.3-fix.1+, Is remove the uid from the node data, default is <code>true</code></p>
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><code>keepId</code>: (Original fourth parameter) v0.4.6+, <code>Boolean</code>, default is <code>false</code>, Whether to retain the <code>id</code> of the replicated node will be deleted by default to prevent duplicate node <code>id</code>. However, for mobile node scenarios, the original <code>id</code> of the node needs to be retained</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<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);
|
||||
@@ -179,6 +184,117 @@ and copying the <code>data</code> of the data object, example:</p>
|
||||
<p>v0.6.13+</p>
|
||||
</blockquote>
|
||||
<p>Determine if it is a mobile environment.</p>
|
||||
<h4>getTopAncestorsFomNodeList(list)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>list</code>: Arrray, Node instance list.</li>
|
||||
</ul>
|
||||
<p>Find the top-level node list from the node instance list.</p>
|
||||
<h4>checkTwoRectIsOverlap(minx1, maxx1, miny1, maxy1, minx2, maxx2, miny2, maxy2)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<p>The parameter is the position of two rectangles.</p>
|
||||
<p>Determine if two rectangles overlap.</p>
|
||||
<h4>focusInput(el)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>el</code>: DOM nodes, elements that can be focused, typically input box elements.</li>
|
||||
</ul>
|
||||
<p>Focus on the specified input box.</p>
|
||||
<h4>selectAllInput(el)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>el</code>: DOM nodes, elements that can be focused, typically input box elements.</li>
|
||||
</ul>
|
||||
<p>Focus and select all specified input boxes.</p>
|
||||
<h4>addDataToAppointNodes(appointNodes, data = {})</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>appointNodes</code>:Node instance list, array type.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>data</code>:The data to be attached to all nodes in the specified node instance list tree.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Adding additional data to the specified node list tree data will modify the original data.</p>
|
||||
<h4>createUidForAppointNodes(appointNodes, createNewId)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>appointNodes</code>:Node instance list, array type.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>createNewId</code>:v0.7.3-fix.1+, <code>Boolean</code>, default is <code>false</code>, If the node does not have a 'uid', a new 'uid' will be created. If 'true' is passed, a new 'uid' will be created regardless of whether the node data originally exists or not`</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Adding a uid to the specified node list tree data (if the uid does not exist) will modify the original data.</p>
|
||||
<h4>getNodeIndex(node)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>node</code>:Node instance.</li>
|
||||
</ul>
|
||||
<p>Gets the position index of a node within its peers.</p>
|
||||
<h4>mergerIconList(list)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>list</code>:The array of node icons to be merged into the library.</li>
|
||||
</ul>
|
||||
<pre class="hljs"><code><span class="hljs-comment">// const data = [</span>
|
||||
<span class="hljs-comment">// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'b' }] },</span>
|
||||
<span class="hljs-comment">// { type: 'priority', name: '优先级图标', list: [{ name: '2', icon: 'c' }, { name: 3, icon: 'd' }] },</span>
|
||||
<span class="hljs-comment">// ];</span>
|
||||
|
||||
<span class="hljs-comment">// mergerIconList(data) result:</span>
|
||||
|
||||
<span class="hljs-comment">// [</span>
|
||||
<span class="hljs-comment">// { type: 'priority', name: '优先级图标', list: [{ name: '1', icon: 'a' }, { name: 2, icon: 'c' }, { name: 3, icon: 'd' }] },</span>
|
||||
<span class="hljs-comment">// ]</span>
|
||||
</code></pre>
|
||||
<p>Merge icon arrays.</p>
|
||||
<h4>htmlEscape(str)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>str</code>:String.</li>
|
||||
</ul>
|
||||
<p>Escape the incoming string, currently escaping the following three characters:</p>
|
||||
<pre class="hljs"><code>& -> &amp;
|
||||
< -> &lt;
|
||||
> -> &gt;
|
||||
</code></pre>
|
||||
<h4>generateColorByContent(str)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.2+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>str</code>:String.</li>
|
||||
</ul>
|
||||
<p>Generate colors based on incoming content, and the same content will generate the same color.</p>
|
||||
<h4>isSameObject(a, b)</h4>
|
||||
<blockquote>
|
||||
<p>v0.7.3+</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li><code>a</code>、<code>b</code>: Object | Array, Two objects to compare</li>
|
||||
</ul>
|
||||
<p>Determine whether two objects are the same, only handling objects or arrays.</p>
|
||||
<h2>Simulate CSS background in Canvas</h2>
|
||||
<p>Import:</p>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> drawBackgroundImageToCanvas <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/utils/simulateCSSBackgroundInCanvas'</span>
|
||||
|
||||
@@ -6,7 +6,19 @@ const data = {
|
||||
demo: {
|
||||
zh: '在线示例',
|
||||
en: 'Online Demo'
|
||||
}
|
||||
},
|
||||
help: {
|
||||
zh: '帮助文档',
|
||||
en: 'Help doc'
|
||||
},
|
||||
dev: {
|
||||
zh: '开发文档',
|
||||
en: 'Dev doc'
|
||||
},
|
||||
index: {
|
||||
zh: '首页',
|
||||
en: 'Home'
|
||||
},
|
||||
}
|
||||
|
||||
const t = (str, lang) => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user