vue2-mind-map
v0.1.17
Published
`vue2-mind-map` 是一个功能丰富的思维导图可视化组件。该组件提供了完整的思维导图展示和交互功能,支持多种数据格式输入、灵活的布局配置、丰富的样式定制和流畅的用户交互体验。目前基于 Vue 2 构建。
Downloads
40
Readme
vue2-mind-map 组件使用文档
vue2-mind-map 是一个功能丰富的思维导图可视化组件。该组件提供了完整的思维导图展示和交互功能,支持多种数据格式输入、灵活的布局配置、丰富的样式定制和流畅的用户交互体验。目前基于 Vue 2 构建。
TODO
- 支持 Vue 3
- 触摸屏支持
- 操作历史及回滚
- 小地图
数据结构说明
TreeNode(树形数据结构)
用于描述具有层级关系的思维导图节点,通过 children 数组直接表示父子关系:
- id
string(可选) - 节点唯一标识符 - position
object(可选) - 节点位置坐标,格式:{ x: number, y: number } - size
object(可选) - 节点尺寸,格式:{ x: number, y: number } - children
array(可选) - 子节点数组,每个元素都是 TreeNode 结构 - collapsed
boolean(可选) - 节点是否折叠,默认为false - content
string|HTMLElement|array|function(可选) - 节点显示内容 - [自定义属性]
any- 可以添加任意自定义属性
示例:
const treeData = {
id: 'root',
content: '根节点',
children: [
{
id: 'child1',
content: '子节点1',
collapsed: false,
children: [
{ id: 'grandchild1', content: '孙节点1' }
]
},
{ id: 'child2', content: '子节点2' }
]
}FlatNode(扁平数据结构)
用于描述扁平化的思维导图节点,通过 parentId 间接表示父子关系:
- id
string(可选) - 节点唯一标识符 - parentId
string(可选) - 父节点ID,根节点可以不设置 - position
object(可选) - 节点位置坐标,格式:{ x: number, y: number } - size
object(可选) - 节点尺寸,格式:{ x: number, y: number } - collapsed
boolean(可选) - 节点是否折叠,默认为false - content
string|HTMLElement|array|function(可选) - 节点显示内容 - [自定义属性]
any- 可以添加任意自定义属性
示例:
const flatData = [
{ id: 'root', content: '根节点' },
{ id: 'child1', parentId: 'root', content: '子节点1' },
{ id: 'child2', parentId: 'root', content: '子节点2' },
{ id: 'grandchild1', parentId: 'child1', content: '孙节点1' }
]配置选项说明
对齐配置 (MindMapAlign)
控制思维导图节点的对齐方式:
- mode
string- 对齐模式,可选值:"cross-axis-start-edge"- 交叉轴起始边对齐(默认)"cross-axis-center"- 交叉轴居中对齐"node-center"- 以指定节点为中心对齐
- targetNodeId
string(可选) - 目标节点ID,仅在mode为"node-center"时使用
拖拽配置 (MindMapDragOptions)
控制思维导图的拖拽行为:
- enableNodeDrag
boolean(可选) - 是否启用节点拖拽,默认true - enableCanvasDrag
boolean(可选) - 是否启用画布拖拽,默认true - dragNodeButton
number|array(可选) - 拖拽节点的鼠标按钮,默认左键(0) - dragCanvasButton
number|array(可选) - 拖拽画布的鼠标按钮,默认右键(2)和中键(1) - useThrottle
boolean(可选) - 是否使用节流减少事件触发频率,默认true - throttleWait
number(可选) - 节流函数的等待时间,默认16毫秒
鼠标按钮值:左键=0,中键=1,右键=2
缩放配置 (MindMapZoomOptions)
控制思维导图的缩放行为:
- enableWheelZoom
boolean(可选) - 是否启用滚轮缩放,默认true - zoomStep
number(可选) - 每次缩放步长,默认0.1(10%) - invertWheelDirection
boolean(可选) - 是否反转滚轮方向,默认false - minZoom
number(可选) - 最小缩放比例,默认0.1(10%) - maxZoom
number(可选) - 最大缩放比例,默认5.0(500%) - useThrottle
boolean(可选) - 是否使用节流减少事件触发频率,默认true - throttleWait
number(可选) - 节流函数的等待时间,默认16毫秒
全屏配置 (FullscreenOptions)
控制思维导图的全屏行为:
- fullscreenBgColor
string(可选) - 全屏模式下的背景颜色,默认#FFFFFF - fullscreenMode
string(可选) - 全屏模式,可选值:"native"- 使用浏览器原生全屏 API(默认)"pseudo"- 使用 CSS 模拟全屏效果
Props
基础配置
data (必填)
- 类型: TreeNode 对象 或 FlatNode 数组
- 描述: 思维导图的数据源
direction
- 类型:
"horizontal" | "vertical" - 默认值:
"horizontal" - 描述: 思维导图的布局方向
样式配置
line-style
- 类型:
"straight" | "curved" | "zigzag" - 默认值:
"curved" - 描述: 连接线的样式
line-color
- 类型:
String - 默认值:
"#000000" - 描述: 连接线的颜色
line-width
- 类型:
Number - 默认值:
1 - 描述: 连接线的宽度,单位像素
node-border-width
- 类型:
Number - 默认值:
1 - 描述: 节点边框的宽度,单位像素
node-bg-color
- 类型:
String - 默认值:
"#FFFFFF" - 描述: 节点背景颜色
node-border-color
- 类型:
String - 默认值:
"#000000" - 描述: 节点边框颜色
布局配置
align
- 类型: MindMapAlign 配置对象
- 默认值:
{ mode: "cross-axis-start-edge" } - 描述: 思维导图对齐方式配置
sibling-separation
- 类型:
Number - 默认值:
25 - 描述: 同级节点之间的间距,单位像素
level-separation
- 类型:
Number - 默认值:
50 - 描述: 层级之间的间距,单位像素
initial-offset
- 类型:
Object - 默认值:
undefined - 描述: 思维导图的初始偏移量,格式:
{ x: number, y: number }
交互配置
drag-options
- 类型:
MindMapDragOptions配置对象 - 默认值:
{ enableNodeDrag: true, enableCanvasDrag: true, dragNodeButton: 0, dragCanvasButton: [2, 1], useThrottle: true, throttleWait: 16 } - 描述: 拖拽相关配置。
dragNodeButton和dragCanvasButton的值可以是单个鼠标按钮或按钮数组 (左键=0, 中键=1, 右键=2)。
zoom-options
- 类型:
MindMapZoomOptions配置对象 - 默认值:
{ enableWheelZoom: true, zoomStep: 0.1, invertWheelDirection: false, minZoom: 0.1, maxZoom: 5.0, useThrottle: true, throttleWait: 16 } - 描述: 缩放相关配置。
full-screen-options
- 类型:
FullscreenOptions配置对象 - 默认值:
{ fullscreenBgColor: '#FFFFFF', fullscreenMode: 'native' } - 描述: 全屏相关配置。
方法 (Methods)
你可以通过获取 MindMap.vue 组件的引用 (ref) 来调用其公开方法。
示例:
<template>
<mind-map ref="mindMapRef" :data="mindMapData" />
</template>
<script>
export default {
mounted() {
// 调用 rebuild 方法
this.$refs.mindMapRef.rebuild();
}
};
</script>布局和渲染控制
rebuild()
- 描述: 重置思维导图布局并重新渲染
- 返回:
void
clear()
- 描述: 清空思维导图实例的所有内容和状态
- 返回:
void
setHorizontal(isHorizontal)
- 参数:
isHorizontal: boolean- 布局方向,true为水平,false为垂直 - 描述: 设置思维导图布局方向
- 返回:
void
缩放控制
zoomIn(cx?, cy?)
- 参数:
cx?: number- 缩放中心点的 X 坐标(可选)cy?: number- 缩放中心点的 Y 坐标(可选)
- 描述: 放大思维导图
- 返回:
void
zoomOut(cx?, cy?)
- 参数:
cx?: number- 缩放中心点的 X 坐标(可选)cy?: number- 缩放中心点的 Y 坐标(可选)
- 描述: 缩小思维导图
- 返回:
void
resetZoom(cx?, cy?)
- 参数:
cx?: number- 缩放中心点的 X 坐标(可选)cy?: number- 缩放中心点的 Y 坐标(可选)
- 描述: 重置思维导图缩放比例到 1.0
- 返回:
void
节点操作
setNodeSize(nodeId, size)
- 参数:
nodeId: string- 要设置尺寸的节点 IDsize: { width?: number; height?: number }- 新的节点尺寸
- 描述: 设置指定节点的尺寸
- 返回:
boolean | undefined- 如果节点找到并成功设置尺寸,则返回true;否则返回false
focusOnNode(nodeId)
- 参数:
nodeId: string- 节点ID - 描述: 将指定节点聚焦到视口中心
- 返回:
boolean | undefined- 如果节点找到并成功聚焦,则返回true;否则返回false
toggleNodeCollapse(nodeId)
- 参数:
nodeId: string- 节点ID - 描述: 切换节点的折叠状态
- 返回:
boolean | undefined- 如果节点找到并成功切换状态,则返回true;否则返回false
setNodeCollapsed(nodeId, collapsed)
- 参数:
nodeId: string- 节点IDcollapsed: boolean- 要设置的折叠状态
- 描述: 设置节点的折叠状态
- 返回:
boolean | undefined- 如果节点找到并成功设置状态,则返回true;否则返回false
getNodeCollapsed(nodeId)
- 参数:
nodeId: string- 节点ID - 描述: 获取节点的折叠状态
- 返回:
boolean | undefined- 节点的折叠状态,如果节点不存在则返回undefined
expandAllNodes()
- 描述: 展开所有节点
- 返回:
number- 成功展开的节点数量
collapseAllNodes()
- 描述: 折叠所有非根节点
- 返回:
number- 成功折叠的节点数量
updateNodeContents(nodeIds?)
- 参数:
nodeIds?: string[]- 要更新内容的节点 ID 数组,不传参时默认更新所有节点 - 描述: 更新指定节点的内容,此方法会根据节点的
content属性或外部传入的contentCallback来重新解析和设置节点内部的内容 - 返回:
Promise<number>- 成功更新的节点个数
全屏控制
enterFullscreen(mode?)
- 参数:
mode?: "native" | "pseudo"(可选) - 全屏模式 ('native' 或 'pseudo')。如果未提供,则使用组件 prop 中配置的默认模式。
- 描述: 进入全屏模式。
- 返回:
Promise<boolean | undefined>- 成功时 resolve true,失败时 reject error。
exitFullscreen()
- 描述: 退出全屏模式。会自动检测并退出当前激活的全屏模式 (原生或模拟)。
- 返回:
Promise<boolean | undefined>- 成功时 resolve true,失败时 reject error。
toggleFullscreen(mode?)
- 参数:
mode?: "native" | "pseudo"(可选) - 全屏模式 ('native' 或 'pseudo')。如果未提供,则使用组件 prop 中配置的默认模式。
- 描述: 切换全屏状态。
- 返回:
Promise<boolean | undefined>- 成功时 resolve 新的全屏状态 (true 为进入,false 为退出)。
插槽 (Slots)
默认插槽
- 名称:
default(默认插槽) - 作用域:
{ node: TreeNode | FlatNode } - 描述: 自定义节点内容的显示。你可以通过这个作用域插槽来为每个节点提供自定义的 HTML 结构。
node: 当前正在渲染的节点对象,包含节点的 ID、位置、子节点等信息。也就是你通过 prop data 传入的节点。
基础示例:
<template>
<mind-map :data="mindMapData">
<template v-slot="{ node }">
<div class="custom-node">
<strong>{{ node.id }}</strong>
<p v-if="node.data && node.data.description">{{ node.data.description }}</p>
</div>
</template>
</mind-map>
</template>条件渲染示例:
<template>
<mind-map :data="mindMapData">
<template v-slot="{ node }">
<!-- 方式1: 使用 v-show 控制显示 -->
<div v-show="slotIndex === 1" class="node-style-1">
样式1 - {{ node.id }}
</div>
<div v-show="slotIndex === 2" class="node-style-2">
样式2 - {{ node.id }}
</div>
<!-- 方式2: 使用 v-if 条件渲染 -->
<div v-if="node.type === 'important'" class="important-node">
重要节点: {{ node.id }}
</div>
<div v-else class="normal-node">
普通节点: {{ node.id }}
</div>
</template>
</mind-map>
</template>注意事项:
- 插槽内容会被缓存以提高性能,每个节点对应一个 Vue 实例
- 插槽渲染失败时会显示错误信息,并回退到默认渲染
事件 (Events)
你可以通过监听 MindMap.vue 组件的事件来响应思维导图的状态变化。
画布拖拽事件
canvas-drag-start
- 触发时机: 当画布开始被拖拽时触发
- 事件数据:
MindMapCanvasEvent对象originalEvent: MouseEvent- 原始鼠标事件button: MouseButton | null- 按下的鼠标按钮mouseX: number- 拖拽开始时鼠标在容器内的 X 坐标mouseY: number- 拖拽开始时鼠标在容器内的 Y 坐标
- 描述: 此事件在画布拖拽开始时触发,可以用于记录拖拽开始状态或执行相关初始化操作
canvas-drag
- 触发时机: 当画布正在被拖拽时触发
- 事件数据:
MindMapCanvasEvent对象originalEvent: MouseEvent- 原始鼠标事件button: MouseButton | null- 按下的鼠标按钮mouseX: number- 当前鼠标在容器内的 X 坐标mouseY: number- 当前鼠标在容器内的 Y 坐标deltaX: number- X 轴拖拽距离deltaY: number- Y 轴拖拽距离
- 描述: 此事件在画布拖拽过程中持续触发,可以用于同步画布位置状态或执行跟随操作
canvas-drag-end
- 触发时机: 当画布拖拽结束时触发
- 事件数据:
MindMapCanvasEvent对象originalEvent: MouseEvent- 原始鼠标事件button: MouseButton | null- 按下的鼠标按钮mouseX: number- 拖拽结束时鼠标在容器内的 X 坐标mouseY: number- 拖拽结束时鼠标在容器内的 Y 坐标
- 描述: 此事件在画布拖拽结束时触发,可以用于保存最终状态或执行清理操作
使用示例:
<template>
<mind-map
:data="mindMapData"
@canvas-drag-start="handleCanvasDragStart"
@canvas-drag="handleCanvasDrag"
@canvas-drag-end="handleCanvasDragEnd"
/>
</template>
<script>
export default {
methods: {
handleCanvasDragStart(event) {
console.log('画布开始拖拽:', event.mouseX, event.mouseY);
},
handleCanvasDrag(event) {
console.log('画布拖拽中:', `移动了 ${event.deltaX}, ${event.deltaY}`);
},
handleCanvasDragEnd(event) {
console.log('画布拖拽结束');
}
}
};
</script>缩放事件
zoom-change
- 触发时机: 当思维导图的缩放比例发生变化时触发
- 事件数据:
MindMapZoomEvent对象originalEvent?: WheelEvent- 原始滚轮事件(如果是滚轮触发的缩放)scale: Vector- 当前的缩放比例向量 {x, y}mouseX: number- 缩放中心在容器内的 X 坐标mouseY: number- 缩放中心在容器内的 Y 坐标
- 描述: 此事件在缩放操作(放大、缩小、重置)完成后触发,可以用于同步缩放状态或执行相关联的操作
使用示例:
<template>
<mind-map
:data="mindMapData"
@zoom-change="handleZoomChange"
/>
</template>
<script>
export default {
methods: {
handleZoomChange(event) {
console.log('缩放比例变化:', `${event.scale.x * 100}%`);
console.log('缩放中心:', event.mouseX, event.mouseY);
// 同步外部缩放状态
this.currentZoomLevel = event.scale.x;
}
}
};
</script>容器尺寸变化事件
container-resize
- 触发时机: 当思维导图容器尺寸发生变化时触发
- 事件数据:
MindMapContainerResizeEvent对象width: number- 新的容器宽度height: number- 新的容器高度
- 描述: 此事件在容器尺寸变化时触发,可以用于响应式布局调整或执行相关的重新计算操作
使用示例:
<template>
<mind-map
:data="mindMapData"
@container-resize="handleContainerResize"
/>
</template>
<script>
export default {
methods: {
handleContainerResize(event) {
console.log('容器尺寸变化:', `${event.width} x ${event.height}`);
// 根据新尺寸调整相关组件
this.adjustUIForNewSize(event.width, event.height);
},
adjustUIForNewSize(width, height) {
// 执行尺寸相关的调整逻辑
}
}
};
</script>布局更新事件
layout-updated
- 触发时机: 当思维导图的布局发生变化并更新完成后触发(例如,从水平切换到垂直布局,或重新计算布局后)
- 事件数据:
MindMapLayoutEvent对象direction: 'horizontal' | 'vertical'- 当前的布局方向
- 描述: 此事件在思维导图完成布局计算和渲染后触发,可以用于同步外部状态或执行需要在布局稳定后进行的操作
使用示例:
<template>
<mind-map
:data="mindMapData"
@layout-updated="handleLayoutUpdated"
/>
</template>
<script>
export default {
methods: {
handleLayoutUpdated(event) {
console.log('布局已更新,当前方向:', event.direction);
// 执行布局更新后的逻辑
}
}
};
</script>节点折叠状态变化事件
node-collapse-changed
- 触发时机: 当任何节点的折叠/展开状态发生变化时触发
- 事件数据:
MindMapNodeCollapseEvent对象nodeId: string- 折叠状态发生变化的节点 IDcollapsed: boolean- 当前的折叠状态,true表示已折叠,false表示已展开node: TreeNode | FlatNode- 被折叠/展开的节点对应的原始数据
- 描述: 此事件在调用折叠相关方法(如
toggleNodeCollapse、setNodeCollapsed、expandAllNodes、collapseAllNodes)时触发,可以用于同步外部状态或记录操作历史
使用示例:
<template>
<mind-map
:data="mindMapData"
@node-collapse-changed="handleNodeCollapseChanged"
/>
</template>
<script>
export default {
methods: {
handleNodeCollapseChanged(event) {
console.log(`节点 ${event.nodeId} ${event.collapsed ? '折叠' : '展开'}了`);
console.log('节点数据:', event.node);
// 同步外部状态
this.updateNodeState(event.nodeId, event.collapsed);
},
updateNodeState(nodeId, collapsed) {
// 更新外部数据或状态管理
}
}
};
</script>批量操作事件:
当调用 expandAllNodes() 或 collapseAllNodes() 方法时,每个状态发生变化的节点都会单独触发一次 node-collapse-changed 事件。
