mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-24 18:38:26 +08:00
Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47328236f7 | ||
|
|
566147c530 | ||
|
|
54fad1ee08 | ||
|
|
8c8e283a88 | ||
|
|
4553bc37f5 | ||
|
|
41b0b21354 | ||
|
|
39b55b0cd7 | ||
|
|
ede01c069e | ||
|
|
aa56e53c4d | ||
|
|
3a723a15bf | ||
|
|
1b2da4eb72 | ||
|
|
6f351d4cee | ||
|
|
dba93d4363 | ||
|
|
b46a94bd96 | ||
|
|
fadd8217e8 | ||
|
|
b0d898054e | ||
|
|
3e84892a28 | ||
|
|
f663f8d60a | ||
|
|
0aeee0ff28 | ||
|
|
140e9cf893 | ||
|
|
89e426e522 | ||
|
|
c77062b660 | ||
|
|
bca2912390 | ||
|
|
ed7177e29d | ||
|
|
12ca3ed556 | ||
|
|
d7de86209c | ||
|
|
e53c6cd559 | ||
|
|
352711c871 | ||
|
|
d304ebc544 | ||
|
|
27291fe5c9 | ||
|
|
f714e47722 | ||
|
|
ce135dd111 | ||
|
|
fb4bfedef4 | ||
|
|
5cbe5d2906 | ||
|
|
b6c15164ac | ||
|
|
1960e96a19 | ||
|
|
7a0fd5adfb | ||
|
|
9ae40cff32 | ||
|
|
0070cab9f1 | ||
|
|
79ae876eeb | ||
|
|
ca35b84308 | ||
|
|
3b4f386900 | ||
|
|
34ef1e908e | ||
|
|
6a3f016920 | ||
|
|
d1ab67cd4c | ||
|
|
0d81f9ff9c | ||
|
|
471bd3c5e5 | ||
|
|
5d4cf8a3c3 | ||
|
|
5a5062ecaf | ||
|
|
13c4b51f69 | ||
|
|
a3ddcc93e5 | ||
|
|
365e51e2e9 | ||
|
|
fd096c4444 | ||
|
|
4c1786e127 | ||
|
|
bfeb59d43f | ||
|
|
aa998b1829 | ||
|
|
c8f5c94683 | ||
|
|
2aea7a3c88 | ||
|
|
9f16691cd6 | ||
|
|
8363819933 | ||
|
|
7d6149dbdf | ||
|
|
b088c40101 | ||
|
|
5b5aab1c9e | ||
|
|
13a4b12ad4 | ||
|
|
3e59d84e6b | ||
|
|
cd987a382a | ||
|
|
fdada41327 | ||
|
|
46d44e6753 | ||
|
|
d63d9873ac | ||
|
|
7eeb7ab51b | ||
|
|
7a2075df51 | ||
|
|
ba5ff54b9a | ||
|
|
8af44b2d45 | ||
|
|
72c989ae11 | ||
|
|
861309d517 | ||
|
|
2f0d64cf41 | ||
|
|
5df8a28403 | ||
|
|
3c9940e076 | ||
|
|
0b11aff105 | ||
|
|
3e4fe06197 | ||
|
|
8bf23f8397 | ||
|
|
10d04549fc | ||
|
|
b4193d50a3 | ||
|
|
0620d31d0a | ||
|
|
a804a5e2fa | ||
|
|
06daffbaab | ||
|
|
b901c08156 | ||
|
|
e27eb63627 | ||
|
|
990a4e5c4c | ||
|
|
7f79d4881d | ||
|
|
2d8643015f | ||
|
|
30f7713af1 | ||
|
|
7ab9db4bbd | ||
|
|
fa7548afaf | ||
|
|
676efa792a | ||
|
|
9ffa1e2744 | ||
|
|
1108b29da0 | ||
|
|
b00d5f6adb | ||
|
|
c6438668f2 | ||
|
|
608adb21e1 | ||
|
|
495cb4c62a | ||
|
|
3048cba1ae | ||
|
|
5b1f5f803e | ||
|
|
0d79e28ec9 | ||
|
|
806be0b537 | ||
|
|
c15b9be7ef | ||
|
|
f6ac2c80ed | ||
|
|
5f19509079 | ||
|
|
4677b11dfb | ||
|
|
b3e9797b0e | ||
|
|
f72deb0478 | ||
|
|
455e97074f | ||
|
|
3e52fa6585 | ||
|
|
48172bc035 | ||
|
|
09d1f82021 | ||
|
|
786e183091 | ||
|
|
0ebac39716 | ||
|
|
10b8a33ab7 | ||
|
|
72b9001b56 | ||
|
|
1efabd44ec | ||
|
|
5e66bd29ff | ||
|
|
2f1114b722 | ||
|
|
4428028146 | ||
|
|
e660a74630 | ||
|
|
8f29d63441 | ||
|
|
98afa6eb5b | ||
|
|
c06971987d | ||
|
|
e385ecf35d | ||
|
|
62fb0b15e0 | ||
|
|
19da1a4ff3 | ||
|
|
a798a40fab | ||
|
|
7982a1373f | ||
|
|
a812637cf0 | ||
|
|
53c4d3945a | ||
|
|
2e7519cf29 | ||
|
|
acad210d57 | ||
|
|
ba5807932e | ||
|
|
59d572ae18 | ||
|
|
14aa8659ee | ||
|
|
59c8ed4ef8 | ||
|
|
b886a0572d | ||
|
|
42755cac8a | ||
|
|
ab1306357e | ||
|
|
fa506f4212 | ||
|
|
364aed858f | ||
|
|
58703597e3 | ||
|
|
5d4b42d519 | ||
|
|
cd55db7ed7 | ||
|
|
ca9b3678dc | ||
|
|
395e802b6b | ||
|
|
f38b92a2e2 | ||
|
|
5c6fef71bd | ||
|
|
f3780baedc | ||
|
|
388656f6e0 | ||
|
|
df60f103cc | ||
|
|
7a977d74dc | ||
|
|
7336c57e80 | ||
|
|
66963ca3ac | ||
|
|
1bb1afd1b7 | ||
|
|
52cfc40c24 | ||
|
|
debb058889 | ||
|
|
3d5e3ac9a0 | ||
|
|
a06cb2e031 |
16
README.md
16
README.md
@@ -93,7 +93,7 @@ npm run build
|
||||
|
||||
# 安装
|
||||
|
||||
> 当前仓库版本:0.2.16,当前npm版本:0.2.16
|
||||
> 当前仓库版本:0.2.20,当前npm版本:0.2.20
|
||||
|
||||
```bash
|
||||
npm i simple-mind-map
|
||||
@@ -423,6 +423,14 @@ v0.1.5+
|
||||
|
||||
将节点移动到另一个节点的后面
|
||||
|
||||
#### moveNodeToCenter(node)
|
||||
|
||||
v0.2.17+
|
||||
|
||||
移动节点到画布中心。
|
||||
|
||||
目前如果是存在缩放的情况下回到中心会重置缩放。
|
||||
|
||||
## keyCommand实例
|
||||
|
||||
`keyCommand`实例负责快捷键的添加及触发,内置了一些快捷键,也可以自行添加。可通过`mindMap.keyCommand`获取到该实例。
|
||||
@@ -550,6 +558,12 @@ v0.1.1+
|
||||
|
||||
动态设置变换数据,可以通过getTransformData方法获取变换数据
|
||||
|
||||
#### setScale(scale)
|
||||
|
||||
v0.2.17+
|
||||
|
||||
设置缩放
|
||||
|
||||
## MiniMap实例
|
||||
|
||||
v0.2.11+
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>一个简单的web思维导图实现</title><link href="dist/js/chunk-2d20ec02.81d632f4.js" rel="prefetch"><link href="dist/js/chunk-2d216b67.228f2009.js" rel="prefetch"><link href="dist/js/chunk-35b0a040.cb76da7d.js" rel="prefetch"><link href="dist/css/app.2abc5635.css" rel="preload" as="style"><link href="dist/css/chunk-vendors.faba1249.css" rel="preload" as="style"><link href="dist/js/app.938c190b.js" rel="preload" as="script"><link href="dist/js/chunk-vendors.b39e98f0.js" rel="preload" as="script"><link href="dist/css/chunk-vendors.faba1249.css" rel="stylesheet"><link href="dist/css/app.2abc5635.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="dist/js/chunk-vendors.b39e98f0.js"></script><script src="dist/js/app.938c190b.js"></script></body></html>
|
||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>一个简单的web思维导图实现</title><link href="dist/js/chunk-2d20ec02.10aa67e3.js" rel="prefetch"><link href="dist/js/chunk-2d216b67.2d06497a.js" rel="prefetch"><link href="dist/js/chunk-5397ae43.e756f28b.js" rel="prefetch"><link href="dist/css/app.f735ed26.css" rel="preload" as="style"><link href="dist/css/chunk-vendors.f631d5ff.css" rel="preload" as="style"><link href="dist/js/app.2fa527aa.js" rel="preload" as="script"><link href="dist/js/chunk-vendors.68a34765.js" rel="preload" as="script"><link href="dist/css/chunk-vendors.f631d5ff.css" rel="stylesheet"><link href="dist/css/app.f735ed26.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="dist/js/chunk-vendors.68a34765.js"></script><script src="dist/js/app.2fa527aa.js"></script></body></html>
|
||||
@@ -15,6 +15,7 @@ import { layoutValueList } from './src/utils/constant'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import xmind from './src/parse/xmind'
|
||||
import { simpleDeepClone } from './src/utils'
|
||||
import KeyboardNavigation from './src/KeyboardNavigation'
|
||||
|
||||
// 默认选项配置
|
||||
const defaultOpt = {
|
||||
@@ -133,6 +134,11 @@ class MindMap {
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 键盘导航类
|
||||
this.keyboardNavigation = new KeyboardNavigation({
|
||||
mindMap: this
|
||||
})
|
||||
|
||||
// 批量执行类
|
||||
this.batchExecution = new BatchExecution()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.2.16",
|
||||
"version": "0.2.20",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -76,12 +76,11 @@ class Drag extends Base {
|
||||
// 计算鼠标按下的位置距离节点左上角的距离
|
||||
this.drawTransform = this.mindMap.draw.transform()
|
||||
let { scaleX, scaleY, translateX, translateY } = this.drawTransform
|
||||
this.offsetX = e.clientX - (node.left * scaleX + translateX)
|
||||
this.offsetY = e.clientY - (node.top * scaleY + translateY)
|
||||
//
|
||||
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
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
this.mouseDownX = x
|
||||
this.mouseDownY = y
|
||||
})
|
||||
@@ -275,7 +274,7 @@ class Drag extends Base {
|
||||
}
|
||||
}
|
||||
// 检测兄弟节点位置
|
||||
if (!this.prevNode && !this.nextNode && this.node.isBrother(node)) {
|
||||
if (!this.prevNode && !this.nextNode && !node.isRoot) {// && this.node.isBrother(node)
|
||||
if (left <= checkRight && right >= this.cloneNodeLeft) {
|
||||
if (this.cloneNodeTop > bottom && this.cloneNodeTop <= bottom + 10) {
|
||||
this.prevNode = node
|
||||
|
||||
@@ -48,6 +48,7 @@ class Event extends EventEmitter {
|
||||
this.onMousewheel = this.onMousewheel.bind(this)
|
||||
this.onContextmenu = this.onContextmenu.bind(this)
|
||||
this.onSvgMousedown = this.onSvgMousedown.bind(this)
|
||||
this.onKeyup = this.onKeyup.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,6 +70,7 @@ class Event extends EventEmitter {
|
||||
this.mindMap.el.addEventListener('mousewheel', this.onMousewheel)
|
||||
}
|
||||
this.mindMap.svg.on('contextmenu', this.onContextmenu)
|
||||
window.addEventListener('keyup', this.onKeyup)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,6 +86,7 @@ class Event extends EventEmitter {
|
||||
window.removeEventListener('mouseup', this.onMouseup)
|
||||
this.mindMap.el.removeEventListener('mousewheel', this.onMousewheel)
|
||||
this.mindMap.svg.off('contextmenu', this.onContextmenu)
|
||||
window.removeEventListener('keyup', this.onKeyup)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,6 +180,16 @@ class Event extends EventEmitter {
|
||||
e.preventDefault()
|
||||
this.emit('contextmenu', e)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 11:12:11
|
||||
* @Desc: 按键松开事件
|
||||
*/
|
||||
onKeyup(e) {
|
||||
this.emit('keyup', e)
|
||||
}
|
||||
}
|
||||
|
||||
export default Event
|
||||
|
||||
276
simple-mind-map/src/KeyboardNavigation.js
Normal file
276
simple-mind-map/src/KeyboardNavigation.js
Normal file
@@ -0,0 +1,276 @@
|
||||
import { isKey } from './utils/keyMap'
|
||||
import { bfsWalk } from './utils'
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 11:06:50
|
||||
* @Desc: 键盘导航类
|
||||
*/
|
||||
export default class KeyboardNavigation {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 11:07:24
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.onKeyup = this.onKeyup.bind(this)
|
||||
this.mindMap.on('keyup', this.onKeyup)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 14:12:27
|
||||
* @Desc: 处理按键事件
|
||||
*/
|
||||
onKeyup(e) {
|
||||
;['Left', 'Up', 'Right', 'Down'].forEach(dir => {
|
||||
if (isKey(e, dir)) {
|
||||
if (this.mindMap.renderer.activeNodeList.length > 0) {
|
||||
this.focus(dir)
|
||||
} else {
|
||||
let root = this.mindMap.renderer.root
|
||||
this.mindMap.renderer.moveNodeToCenter(root)
|
||||
root.active()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 14:12:39
|
||||
* @Desc: 聚焦到下一个节点
|
||||
*/
|
||||
focus(dir) {
|
||||
// 当前聚焦的节点
|
||||
let currentActiveNode = this.mindMap.renderer.activeNodeList[0]
|
||||
// 当前聚焦节点的位置信息
|
||||
let currentActiveNodeRect = this.getNodeRect(currentActiveNode)
|
||||
// 寻找的下一个聚焦节点
|
||||
let targetNode = null
|
||||
let targetDis = Infinity
|
||||
// 保存并维护距离最近的节点
|
||||
let checkNodeDis = (rect, node) => {
|
||||
let dis = this.getDistance(currentActiveNodeRect, rect)
|
||||
if (dis < targetDis) {
|
||||
targetNode = node
|
||||
targetDis = dis
|
||||
}
|
||||
}
|
||||
|
||||
// 第一优先级:阴影算法
|
||||
this.getFocusNodeByShadowAlgorithm({
|
||||
currentActiveNode,
|
||||
currentActiveNodeRect,
|
||||
dir,
|
||||
checkNodeDis
|
||||
})
|
||||
|
||||
// 第二优先级:区域算法
|
||||
if (!targetNode) {
|
||||
this.getFocusNodeByAreaAlgorithm({
|
||||
currentActiveNode,
|
||||
currentActiveNodeRect,
|
||||
dir,
|
||||
checkNodeDis
|
||||
})
|
||||
}
|
||||
|
||||
// 第三优先级:简单算法
|
||||
if (!targetNode) {
|
||||
this.getFocusNodeBySimpleAlgorithm({
|
||||
currentActiveNode,
|
||||
currentActiveNodeRect,
|
||||
dir,
|
||||
checkNodeDis
|
||||
})
|
||||
}
|
||||
|
||||
// 找到了则让目标节点聚焦
|
||||
if (targetNode) {
|
||||
this.mindMap.renderer.moveNodeToCenter(targetNode)
|
||||
targetNode.active()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-12 16:22:54
|
||||
* @Desc: 1.简单算法
|
||||
*/
|
||||
getFocusNodeBySimpleAlgorithm({
|
||||
currentActiveNode,
|
||||
currentActiveNodeRect,
|
||||
dir,
|
||||
checkNodeDis
|
||||
}) {
|
||||
// 遍历节点树
|
||||
bfsWalk(this.mindMap.renderer.root, node => {
|
||||
// 跳过当前聚焦的节点
|
||||
if (node === currentActiveNode) return
|
||||
// 当前遍历到的节点的位置信息
|
||||
let rect = this.getNodeRect(node)
|
||||
let { left, top, right, bottom } = rect
|
||||
let match = false
|
||||
// 按下了左方向键
|
||||
if (dir === 'Left') {
|
||||
// 判断节点是否在当前节点的左侧
|
||||
match = right <= currentActiveNodeRect.left
|
||||
// 按下了右方向键
|
||||
} else if (dir === 'Right') {
|
||||
// 判断节点是否在当前节点的右侧
|
||||
match = left >= currentActiveNodeRect.right
|
||||
// 按下了上方向键
|
||||
} else if (dir === 'Up') {
|
||||
// 判断节点是否在当前节点的上面
|
||||
match = bottom <= currentActiveNodeRect.top
|
||||
// 按下了下方向键
|
||||
} else if (dir === 'Down') {
|
||||
// 判断节点是否在当前节点的下面
|
||||
match = top >= currentActiveNodeRect.bottom
|
||||
}
|
||||
// 符合要求,判断是否是最近的节点
|
||||
if (match) {
|
||||
checkNodeDis(rect, node)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-12 16:24:54
|
||||
* @Desc: 2.阴影算法
|
||||
*/
|
||||
getFocusNodeByShadowAlgorithm({
|
||||
currentActiveNode,
|
||||
currentActiveNodeRect,
|
||||
dir,
|
||||
checkNodeDis
|
||||
}) {
|
||||
bfsWalk(this.mindMap.renderer.root, node => {
|
||||
if (node === currentActiveNode) return
|
||||
let rect = this.getNodeRect(node)
|
||||
let { left, top, right, bottom } = rect
|
||||
let match = false
|
||||
if (dir === 'Left') {
|
||||
match =
|
||||
left < currentActiveNodeRect.left &&
|
||||
top < currentActiveNodeRect.bottom &&
|
||||
bottom > currentActiveNodeRect.top
|
||||
} else if (dir === 'Right') {
|
||||
match =
|
||||
right > currentActiveNodeRect.right &&
|
||||
top < currentActiveNodeRect.bottom &&
|
||||
bottom > currentActiveNodeRect.top
|
||||
} else if (dir === 'Up') {
|
||||
match =
|
||||
top < currentActiveNodeRect.top &&
|
||||
left < currentActiveNodeRect.right &&
|
||||
right > currentActiveNodeRect.left
|
||||
} else if (dir === 'Down') {
|
||||
match =
|
||||
bottom > currentActiveNodeRect.bottom &&
|
||||
left < currentActiveNodeRect.right &&
|
||||
right > currentActiveNodeRect.left
|
||||
}
|
||||
if (match) {
|
||||
checkNodeDis(rect, node)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-13 16:15:36
|
||||
* @Desc: 3.区域算法
|
||||
*/
|
||||
getFocusNodeByAreaAlgorithm({
|
||||
currentActiveNode,
|
||||
currentActiveNodeRect,
|
||||
dir,
|
||||
checkNodeDis
|
||||
}) {
|
||||
// 当前聚焦节点的中心点
|
||||
let cX = (currentActiveNodeRect.right + currentActiveNodeRect.left) / 2
|
||||
let cY = (currentActiveNodeRect.bottom + currentActiveNodeRect.top) / 2
|
||||
bfsWalk(this.mindMap.renderer.root, node => {
|
||||
if (node === currentActiveNode) return
|
||||
let rect = this.getNodeRect(node)
|
||||
let { left, top, right, bottom } = rect
|
||||
// 遍历到的节点的中心点
|
||||
let ccX = (right + left) / 2
|
||||
let ccY = (bottom + top) / 2
|
||||
// 节点的中心点坐标和当前聚焦节点的中心点坐标的差值
|
||||
let offsetX = ccX - cX
|
||||
let offsetY = ccY - cY
|
||||
if (offsetX === 0 && offsetY === 0) return
|
||||
let match = false
|
||||
if (dir === 'Left') {
|
||||
match = offsetX <= 0 && offsetX <= offsetY && offsetX <= -offsetY
|
||||
} else if (dir === 'Right') {
|
||||
match = offsetX > 0 && offsetX >= -offsetY && offsetX >= offsetY
|
||||
} else if (dir === 'Up') {
|
||||
match = offsetY <= 0 && offsetY < offsetX && offsetY < -offsetX
|
||||
} else if (dir === 'Down') {
|
||||
match = offsetY > 0 && -offsetY < offsetX && offsetY > offsetX
|
||||
}
|
||||
if (match) {
|
||||
checkNodeDis(rect, node)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 14:12:50
|
||||
* @Desc: 获取节点的位置信息
|
||||
*/
|
||||
getNodeRect(node) {
|
||||
let { scaleX, scaleY, translateX, translateY } =
|
||||
this.mindMap.draw.transform()
|
||||
let { left, top, width, height } = node
|
||||
return {
|
||||
right: (left + width) * scaleX + translateX,
|
||||
bottom: (top + height) * scaleY + translateY,
|
||||
left: left * scaleX + translateX,
|
||||
top: top * scaleY + translateY
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 14:13:04
|
||||
* @Desc: 获取两个节点的距离
|
||||
*/
|
||||
getDistance(node1Rect, node2Rect) {
|
||||
let center1 = this.getCenter(node1Rect)
|
||||
let center2 = this.getCenter(node2Rect)
|
||||
return Math.sqrt(
|
||||
Math.pow(center1.x - center2.x, 2) + Math.pow(center1.y - center2.y, 2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 14:13:11
|
||||
* @Desc: 获取节点的中心点
|
||||
*/
|
||||
getCenter({ left, right, top, bottom }) {
|
||||
return {
|
||||
x: (left + right) / 2,
|
||||
y: (top + bottom) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -549,32 +549,30 @@ class Render {
|
||||
if (node.isRoot) {
|
||||
return
|
||||
}
|
||||
let parent = node.parent
|
||||
let childList = parent.children
|
||||
// 要移动节点的索引
|
||||
let index = childList.findIndex(item => {
|
||||
// 移动节点
|
||||
let nodeParent = node.parent
|
||||
let nodeBorthers = nodeParent.children
|
||||
let nodeIndex = nodeBorthers.findIndex(item => {
|
||||
return item === node
|
||||
})
|
||||
if (index === -1) {
|
||||
if (nodeIndex === -1) {
|
||||
return
|
||||
}
|
||||
// 目标节点的索引
|
||||
let existIndex = childList.findIndex(item => {
|
||||
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 === exist
|
||||
})
|
||||
if (existIndex === -1) {
|
||||
return
|
||||
}
|
||||
// 当前节点在目标节点前面
|
||||
if (index < existIndex) {
|
||||
existIndex = existIndex - 1
|
||||
}
|
||||
// 节点实例
|
||||
childList.splice(index, 1)
|
||||
childList.splice(existIndex, 0, node)
|
||||
// 节点数据
|
||||
parent.nodeData.children.splice(index, 1)
|
||||
parent.nodeData.children.splice(existIndex, 0, node.nodeData)
|
||||
existBorthers.splice(existIndex, 0, node)
|
||||
existParent.nodeData.children.splice(existIndex, 0, node.nodeData)
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
@@ -588,34 +586,31 @@ class Render {
|
||||
if (node.isRoot) {
|
||||
return
|
||||
}
|
||||
let parent = node.parent
|
||||
let childList = parent.children
|
||||
// 要移动节点的索引
|
||||
let index = childList.findIndex(item => {
|
||||
// 移动节点
|
||||
let nodeParent = node.parent
|
||||
let nodeBorthers = nodeParent.children
|
||||
let nodeIndex = nodeBorthers.findIndex(item => {
|
||||
return item === node
|
||||
})
|
||||
if (index === -1) {
|
||||
if (nodeIndex === -1) {
|
||||
return
|
||||
}
|
||||
// 目标节点的索引
|
||||
let existIndex = childList.findIndex(item => {
|
||||
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 === exist
|
||||
})
|
||||
if (existIndex === -1) {
|
||||
return
|
||||
}
|
||||
// 当前节点在目标节点前面
|
||||
if (index < existIndex) {
|
||||
// do nothing
|
||||
} else {
|
||||
existIndex = existIndex + 1
|
||||
}
|
||||
// 节点实例
|
||||
childList.splice(index, 1)
|
||||
childList.splice(existIndex, 0, node)
|
||||
// 节点数据
|
||||
parent.nodeData.children.splice(index, 1)
|
||||
parent.nodeData.children.splice(existIndex, 0, node.nodeData)
|
||||
existIndex++
|
||||
existBorthers.splice(existIndex, 0, node)
|
||||
existParent.nodeData.children.splice(existIndex, 0, node.nodeData)
|
||||
this.mindMap.render()
|
||||
}
|
||||
|
||||
@@ -1097,6 +1092,28 @@ class Render {
|
||||
this.mindMap.render()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 11:46:57
|
||||
* @Desc: 移动节点到画布中心
|
||||
*/
|
||||
moveNodeToCenter(node) {
|
||||
let halfWidth = this.mindMap.width / 2
|
||||
let halfHeight = this.mindMap.height / 2
|
||||
let { left, top, width, height } = node
|
||||
let nodeCenterX = left + width / 2
|
||||
let nodeCenterY = top + height / 2
|
||||
let { state } = this.mindMap.view.getTransformData()
|
||||
let targetX = halfWidth - state.x
|
||||
let targetY = halfHeight - state.y
|
||||
let offsetX = targetX - nodeCenterX
|
||||
let offsetY = targetY - nodeCenterY
|
||||
this.mindMap.view.translateX(offsetX)
|
||||
this.mindMap.view.translateY(offsetY)
|
||||
this.mindMap.view.setScale(1)
|
||||
}
|
||||
}
|
||||
|
||||
export default Render
|
||||
|
||||
@@ -88,6 +88,9 @@ export default class TextEdit {
|
||||
this.textEditNode = document.createElement('div')
|
||||
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none;`
|
||||
this.textEditNode.setAttribute('contenteditable', true)
|
||||
this.textEditNode.addEventListener('keyup', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
document.body.appendChild(this.textEditNode)
|
||||
}
|
||||
node.style.domText(this.textEditNode, this.mindMap.view.scale)
|
||||
|
||||
@@ -213,6 +213,18 @@ class View {
|
||||
this.transform()
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2022-12-09 16:31:59
|
||||
* @Desc: 设置缩放
|
||||
*/
|
||||
setScale(scale) {
|
||||
this.scale = scale
|
||||
this.transform()
|
||||
this.mindMap.emit('scale', this.scale)
|
||||
}
|
||||
}
|
||||
|
||||
export default View
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Count v-if="!isZenMode"></Count>
|
||||
<Navigator :mindMap="mindMap"></Navigator>
|
||||
<NavigatorToolbar :mindMap="mindMap" v-if="!isZenMode"></NavigatorToolbar>
|
||||
<Outline></Outline>
|
||||
<Outline :mindMap="mindMap"></Outline>
|
||||
<Style v-if="!isZenMode"></Style>
|
||||
<BaseStyle :data="mindMapData" :mindMap="mindMap"></BaseStyle>
|
||||
<Theme :mindMap="mindMap"></Theme>
|
||||
@@ -328,6 +328,11 @@ export default {
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// left: 100px;
|
||||
// top: 100px;
|
||||
// right: 100px;
|
||||
// bottom: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
v-model="link"
|
||||
size="mini"
|
||||
placeholder="http://xxxx.com/"
|
||||
@keyup.native.stop
|
||||
></el-input>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="name">{{ $t('nodeHyperlink.name') }}</span>
|
||||
<el-input v-model="linkTitle" size="mini"></el-input>
|
||||
<el-input v-model="linkTitle" size="mini" @keyup.native.stop></el-input>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
v-model="note"
|
||||
>
|
||||
</el-input> -->
|
||||
<div class="noteEditor" ref="noteEditor"></div>
|
||||
<div class="noteEditor" ref="noteEditor" @keyup.stop></div>
|
||||
<!-- <div class="tip">换行请使用:Enter+Shift</div> -->
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<el-input
|
||||
v-model="tag"
|
||||
@keyup.native.enter="add"
|
||||
@keyup.native.stop
|
||||
:disabled="tagArr.length >= max"
|
||||
:placeholder="$t('nodeTag.addTip')"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" :title="$t('outline.title')">
|
||||
<el-tree :data="data" :props="defaultProps" default-expand-all></el-tree>
|
||||
<el-tree
|
||||
class="outlineTree"
|
||||
:data="data"
|
||||
:props="defaultProps"
|
||||
:expand-on-click-node="false"
|
||||
default-expand-all
|
||||
>
|
||||
<span class="customNode" slot-scope="{ node, data }">
|
||||
<span
|
||||
class="nodeEdit"
|
||||
:key="getKey()"
|
||||
contenteditable="true"
|
||||
@keydown.stop
|
||||
@keyup.stop
|
||||
@blur="onBlur($event, node)"
|
||||
v-html="node.label"
|
||||
></span>
|
||||
</span>
|
||||
</el-tree>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
@@ -18,12 +36,17 @@ export default {
|
||||
components: {
|
||||
Sidebar
|
||||
},
|
||||
props: {
|
||||
mindMap: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
defaultProps: {
|
||||
label(data) {
|
||||
return data.data.text
|
||||
return data.data.text.replaceAll(/\n/g, '</br>')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,10 +65,68 @@ export default {
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on('data_change', data => {
|
||||
this.data = [data]
|
||||
this.data = [this.mindMap.renderer.renderTree]
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onBlur(e, node) {
|
||||
node.data._node.setText(e.target.innerText)
|
||||
},
|
||||
|
||||
getKey() {
|
||||
return Math.random()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less" scoped>
|
||||
.customNode {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 7px;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeEdit {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.outlineTree {
|
||||
/deep/ .el-tree-node__content {
|
||||
height: auto;
|
||||
margin: 5px 0;
|
||||
|
||||
.el-tree-node__expand-icon.is-leaf {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
background-color: #c0c4cc;
|
||||
left: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user