# MindElixir生成思维导图
文档:https://docs.mind-elixir.com/zh-Hans/docs/getting-started/quick-start
Github:https://github.com/ssshooter/mind-elixir-core
import MindElixir, { E } from 'mind-elixir';
// 获取 DOM 容器
const container = document.getElementById('map-container');
// 初始化 Mind-Elixir
const mind = new MindElixir({
el: container, // 绑定 DOM
direction: MindElixir.LEFT, // 思维导图方向(LEFT, RIGHT, TOP, BOTTOM)
editable: true, // 是否可编辑
contextMenu: true, // 是否启用右键菜单
toolBar: true, // 是否显示工具栏
nodeMenu: true, // 是否启用节点菜单
keypress: true, // 是否启用键盘快捷键
});
// 思维导图数据结构
const data = MindElixir.new('思维导图');
mind.init(data);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
思维导图数据结构:
{
"nodeData": {
"id": "root",
"topic": "思维导图",
"children": [
{
"id": "node1",
"topic": "子节点 1",
"children": []
},
{
"id": "node2",
"topic": "子节点 2",
"children": []
}
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Vue组件
<template>
<div ref="mindmapContainer" id="mindmap-container"></div>
</template>
<script setup lang="ts">
import MindElixir, { type NodeObj } from 'mind-elixir'
import { nextTick, ref, watch } from 'vue'
const props = defineProps<{ data: any }>()
const mindmapContainer = ref<HTMLDivElement>()
const renderMindMap = (mindMapData: NodeObj) => {
if (!mindMapData) return
nextTick(() => {
if (mindmapContainer.value) {
const mind = new MindElixir({
el: mindmapContainer.value,
direction: MindElixir.RIGHT,
draggable: false,
contextMenu: true,
toolBar: false,
nodeMenu: false
})
mind.init({ nodeData: mindMapData })
}
})
}
watch(
() => props.data,
(newVal) => {
if (newVal) {
renderMindMap(newVal)
}
},
{ immediate: true }
)
</script>
<style lang="css" scoped>
#mindmap-container {
width: 100%;
height: 100%;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
toolbar设置
new MindElixir({
el: mindmapContainer.value,
direction: MindElixir.RIGHT,
draggable: false,
contextMenu: true,
toolBar: false, // 可以开启toolbar
nodeMenu: false
})
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 居中展示
mind.toCenter()
# 实现画布居中
const toCenter = () => {
mind.toCenter()
const mainNode = mind.map.querySelector('.main-node-container') as HTMLElement
if (mainNode) {
mainNode.style.transform = 'translateX(-25%)'
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
自适应缩放并居中显示
const toCenter = () => {
mind.toCenter()
const mainNode = mind.map.querySelector('.main-node-container') as HTMLElement
const containerNode = mindmapContainer.value
if (mainNode && containerNode) {
const padding = 40
const scaleToWidth = containerNode.clientWidth - padding // 需要缩放至的数值
const scaleToHeight = containerNode.clientHeight - padding
const originalWidth = mainNode.clientWidth // 原始宽度
const originalHeight = mainNode.clientHeight
const scaleX = scaleToWidth / originalWidth // 需要缩放的比例
const scaleY = scaleToHeight / originalHeight
const scale = Math.min(scaleX, scaleY, 1) // 计算需要缩放的比例,不超过1
mind.scale(scale)
// 设置居中
mainNode.style.left = '50%'
mainNode.style.top = '50%'
mainNode.style.transform = `translate(-50%, -50%)`
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 自定义toolbar
<template>
<div ref="mindmapContainer" id="mindmap-container"></div>
<div class="mind-elixir-toolbar">
<ElIcon class="center-screen" title="居中展示" @click="toCenter">
<LocationFilled />
</ElIcon>
<ElIcon class="full-screen" title="全屏展示" @click="toFullScreen">
<FullScreen />
</ElIcon>
</div>
</template>
<script setup lang="ts">
import useFullScreen from '@/hooks/useFullScreen'
import { FullScreen, LocationFilled } from '@element-plus/icons-vue'
import { ElIcon } from 'element-plus'
import MindElixir, { type MindElixirInstance, type NodeObj } from 'mind-elixir'
import { nextTick, ref, watch } from 'vue'
/**
* 思维导图数据结构
*/
/* const Data = {
id: 'root',
topic: '思维导图',
children: [
{
id: 'node1',
topic: '子节点 1',
children: []
},
{
id: 'node2',
topic: '子节点 2',
children: []
}
]
} */
const props = defineProps<{ data: any }>()
let mind: MindElixirInstance
const mindmapContainer = ref<HTMLDivElement | null>(null)
const { toggle } = useFullScreen(mindmapContainer)
const renderMindMap = (mindMapData: NodeObj) => {
if (!mindMapData) return
nextTick(() => {
if (mindmapContainer.value) {
mind = new MindElixir({
el: mindmapContainer.value,
direction: MindElixir.RIGHT,
draggable: false,
contextMenu: true,
toolBar: false,
nodeMenu: false
})
mind.init({ nodeData: mindMapData })
}
})
}
const toCenter = () => {
mind.toCenter()
}
const toFullScreen = () => {
toggle()
}
watch(
() => props.data,
(newVal) => {
if (newVal) {
renderMindMap(newVal)
}
},
{ immediate: true }
)
defineExpose({
toCenter
})
</script>
<style lang="css" scoped>
#mindmap-container {
width: 100%;
height: 100%;
position: relative;
}
.mind-elixir-toolbar {
background-color: #fff;
position: absolute;
right: 10px;
bottom: 10px;
z-index: 999;
.center-screen,
.full-screen {
cursor: pointer;
}
.center-screen {
margin-right: 10px;
}
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
← Video.js视频播放 图标的使用 →