# 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

思维导图数据结构:

{
  "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

# 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

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

# 居中展示

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

自适应缩放并居中显示

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

# 自定义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