TreeGraph

阅读时间约 6 分钟

TreeGraph 是 G6 专门为树图场景打造的图。TreeGraph 继承自 Graph。G6.TreeGraphG6.Graph 最大的区别就是数据结构和内置布局计算。主要出于以下考虑:

  • 数据结构:树图的数据一般是嵌套结构,边的数据隐含在嵌套结构中,并不会特意指定 edge 。此布局要求数据中一个节点需要有 idchildren 两个数据项,最精简的数据结构如下所示:
const data = {
  id: 'root',
  children: [
    {
      id: 'subTree1',
      children: [...]
    }, 
    {
      id: 'subTree2',
      children: [...]           
    }
  ]
};
  • 布局特殊性:

    • 树图的布局算法一般是不改变源数据的,而是重新生成一份数据,将源数据作为新数据的一个属性。如果每次都需要做次遍历转换数据到节点和边的数据增加了用户的实现复杂度。
    • 树图的每次新增/删除/展开/收缩节点,都需要重新计算布局。遍历一份结构化数据对应到图上每个节点去做更新操作,也很麻烦。

初始化

G6.TreeGraph

参数

名称 类型 默认值 描述
layout Object null V3.0.4 版本开始支持树布局算法配置。V3.0.4 版本之前是 function 形式。建议开发者使用配置形式,操作粒度更细。
animate Boolean true 默认打开重布局动画开关。

用法

const treeGraph = new G6.TreeGraph({
  container: 'mountNode',
  width: 800,
  height: 600,
  modes: {
    default: [
      {
        type: 'collapse-expand',
        onChange(item, collapsed) {
          const icon = item.get('group').findByClassName('collapse-icon');
          if (collapsed) {
            icon.attr('symbol', EXPAND_ICON);
          } else {
            icon.attr('symbol', COLLAPSE_ICON);
          }
        },
      },
      'drag-canvas',
      'zoom-canvas',
    ],
  },
  layout: {
    type: 'dendrogram',
    direction: 'LR', // H / V / LR / RL / TB / BT
    nodeSep: 50,
    rankSep: 100,
    radial: true,
  },
});

layout 配置项

layout 目前支持 dendrogram、compactBox、mindmap 和 indeted 四种布局方式。

通用配置项

名称 类型 默认值 描述
type String dendrogram 布局类型,支持 dendrogram、compactBox、mindmap 和 indeted。
direction String LR 布局方向,有 LR , RL , TB , BT , H , V 可选。
L:左;R:右;T:上;B:下;H:垂直;V:水平。
getChildren Function 返回当前节点的所有子节点

⚠️注意:type='indeted' 时,direction 只能取 'LR''RL''H' 这三个值。

dendrogram

dendrogram 示意图

使用 dendrogram 方式布局时,direction 取不同值时的效果如下所示。

LR RL H
TB BT V

dendrogram 配置项

名称 类型 默认值 描述
nodeSep Number 20 同层次节点之间的间距
rankSep Number 200 相邻层级节点之间的间距
nodeSize Number 20 节点大小
subTreeSep Number 10 子树之间的间距
isHorizontal Boolean true 是否是水平方向,默认为水平方向

compactBox

compactBox示意图

使用 compactBox 方式布局时,direction 取不同值时的效果如下所示。

LR RL H
TB BT V

compactBox配置项

名称 类型 默认值 描述
getId Function 指定节点 ID
getHeight Function 36 指定节点高度
getWidth Function 18 指定节点宽度
getVGap Function 18 指定节点之间的垂直间距
getHGap Function 18 指定节点之间的水平间距

⚠️注意:使用 getWidthgetHeightgetVGapgetHGap 指定节点的宽高及间距后,并不会改变节点的大小,具体原理如下所示:

/*
 * Gaps: filling space between nodes
 * (x, y) ----------------------
 * |            vgap            |
 * |    --------------------    h
 * | h |                    |   e
 * | g |                    |   i
 * | a |                    |   g
 * | p |                    |   h
 * |   ---------------------    t
 * |                            |
 *  -----------width------------
 */

🦁以上原理同样适用于 indented 和 mindmap 布局。

indented

indented 示意图

使用 indented 方式布局时,direction 取不同值时的效果如下所示。

LR RL H

indented配置项

名称 类型 默认值 描述
indent Number 20 与直接父节点的缩进值
getVGap Function 18 指定节点之间的垂直间距
getHeight Function 36 指定节点的高度

mindmap

mindmap示意图

mindmap配置项

名称 类型 默认值 描述
getId Function 指定节点ID
getHeight Function 36 指定节点高度
getWidth Function 18 指定节点宽度
getSide Function 指定当前节点在主体的左边 (left) 还是右边 (right)
getSubTreeSep Function 0 指定子节点之间的高度间隔
getVGap Function 18 指定节点的垂直间距
getHGap Function 18 指定节点的水平间距

更新

addChild(data, parent)

在指定的父节点下添加子树。

参数

名称 类型 是否必选 描述
data Object true 子树的数据
parent Node String true

用法

const data = {
  id: 'sub1',
  children: [
    {
      id: 'subTree1',
      children: [...]
    }, 
    {
      id: 'subTree2',
      children: [...]           
    }
  ]
};

treeGraph.addChild(data, 'root')

updateChild(data, parent)

更新数据,差量更新子树。

参数

名称 类型 是否必选 描述
data Object true 子树的数据
parent Node String false

⚠️注意:parent 参数为空时,则全量更新。

用法

const data = {
  id: 'sub1',
  children: [
    {
      id: 'subTree1',
      children: [...]
    }, 
    {
      id: 'subTree2',
      children: [...]           
    }
  ]
};

treeGraph.updateChild(data, 'root')

removeChild(id)

删除指定的子树。

参数

名称 类型 是否必选 描述
id String true 要删除的子树的 ID

用法

treeGraph.removeChild('sub');

布局

changeLayout(layout)

更改并应用指定的布局。

参数

名称 类型 是否必选 描述
layout Object false 指定的布局配置,如不传,则不做变更

用法

const layout = {
  type: 'mindmap',
  dirction: 'H',
  getSubTreeSep: () => 20,
  getVGap: () => 25,
  getHeight: () => 30,
  getWidth: () => 30,
};
treeGraph.changeLayout(layout);

refreshLayout(fitView)

数据变更后,重新布局,刷新视图,并更新到画布。

参数

名称 类型 是否必选 描述
fitView Boolean false 更新布局后,是否需要自适应窗口

用法

treeGraph.refreshLayout(true);

查找

findDataById(id, target)

根据指定的 ID 获取对应的源数据。

参数

名称 类型 是否必选 描述
id String true 指定的元素 ID
target Object false 从指定的节点开始查找,为空时从根节点开始查找

返回值

  • 返回值类型:Object;
  • 返回值为查找到的节点的源数据。

用法

const target = {
	id: 'sub1',
  children: [...]
}

// 从 target 节点开始查找 sub1.1 节点
const subData = treeGraph.findDataById('sub1.1', target)
  
// 从根节点开始查找 sub1.1 节点
const subData = treeGraph.findDataById('sub1.1')