目标
支持节点分组,拆分群组及群组嵌套的功能。
形态
- 支持以下Group形态:
- rect群组;
- Circle群组。
思路
从数据上支持group,根据数据渲染,数据结构定义如下:
{
nodes: [
{
id: 'node1',
label: 'node1'
},
{
id: 'node2',
label: 'node2'
},
],
edges: [
{
source: 'node1',
target: 'node2'
}
],
groups: [
{
id: 'group1',
title: '',
nodes: ['node1', 'node2']
},
{
id: 'group2',
title: '',
nodes: ['node1'],
children: [
{
id: 'group2.1',
title: '',
nodes: ['node3', 'node4']
},
{
id: 'group2.2',
title: '',
children: [
{
id: 'group2.2.1',
title: '',
nodes: ['node5', 'node6']
}
]
}
]
}
]
}
数据中包括groups字段时,表示有群组存在,可能会存在多个群组的情况。每个群组中字段说明:
- id:必填,唯一标识群组;
- title:可选,群组名称,为空时不显示名称;
- nodes:表示该群组中包括的节点;
- children:表示嵌套群组,即群组中还包括其他群组。
改进后的数据结构
{
nodes: [
{
id: 'node1',
label: 'node1',
groupId: 'group1'
},
{
id: 'node2',
label: 'node2',
groupId: 'group1'
},
{
id: 'node3',
label: 'node3',
groupId: 'group2'
},
],
edges: [
{
source: 'node1',
target: 'node2'
}
],
groups: [
{
id: 'group1',
title: '',
parentId: 'p1'
},
{
id: 'group2',
title: '',
parentId: 'p1'
},
{
id: 'p1',
title: '',
parentId: 'p0'
},
{
id: 'p0',
parentId: 'p'
},
{
id: 'p'
}
]
}
说明:
- 每个node中添加一个groupId字段,表示该节点所在的群组;
- groups表示所有的群组,group中如果有parentId字段,表示该群组是属于parentId中的一个群组。
这种方式存在以下两个问题:
- 绘制单个group时,需要遍历所有node,获取到group中所有的节点,用于计算群组的宽高;
- group存在多层嵌套时,处理起来特别麻烦,如上面的示例中,如何确定p1, p0及p三个群组的宽高;
- 绘制group时如何确定绘制顺序?
实现思路
- 绘制所有node和edge;
- 通过groupId进行groupBy分组,获取到每个群组中的节点;
- 根据groups中的数据,获取到每个group中的node,需要排除,计算group的边界,绘制group。
问题
- 群组与节点及边之间的相互遮挡问题,及节点、边、群组三者之前的层级问题;
- 群组中节点与群组外部的节点之间有边时,边应该是在群组上面,当群组收起时,边应该连接到群组上面;
- 群组收起后与节点区分的问题;
- 群组收起或展开后,与群组相关的其他节点及边的更新;
- 移动群组时,群组中所有节点都一起跟着移动,性能上会不会有问题;
- 如何支持群组名称,及群组上面的操作;
- 是否支持自定义群组上面的操作图标,如果要支持,可以通过在数据中定义,当所有群组的图标都一样时,不要每个数据中都加相同的字段;
- 同一个图上面群组的形态会不会不同,比如有圆形的,有矩形的:
- 如果同一个图上不支持多种形态,则形态可以由开发人员在渲染时候决定;
- 如果支持,则可能需要在每个group中增加一个type字段,表示类型。
方案
group作为一种特殊类型的Node,在原数据结构的基础上,增加groups字段,用于表示数据中存在的群组,group支持嵌套,同样是通过在数据中进行区分。
group的最终形式是展示位矩形还是圆形,由开发人员自己决定,render时需要传入一个表示类型的参数。
Group只作为辅助元素,先布局Node,再根据数据绘制Group。
通用部分
- Group在node和edge的底层;
- 拖动Group中的节点,Group会随着更新宽度和高度;
- 拖动Group,Group中的节点或Group会跟着一起移动;
- 双击或其他操作会收起Group,整个Group中缩成一个虚拟节点,连接到Group中节点的边此时会连接到虚拟节点上;
- Rect的Group,支持自定义Group名称、图标及操作按钮;
- 缩放时候需要重新计算位置;
- 默认全部展开(后期考虑支持自定义);
- 动态改变群组所属层级;
- 节点拖入拖出到Group,动态改变节点的所属群组;
- 【待定】第一期是否支持group拖入到其他group中。
不嵌套的Group
- 收起Group后,位置可以不受影响,不需要重新计算;
嵌套的Group
- 收起Group后,需要根据虚拟节点及Group中其他节点,重新计算Group大小和位置;
- 拖动嵌套Group中的Group,最外层的Group也会随着拖动改变大小。