使用布局

阅读时间约 4 分钟

想让画布中图形按照一定的规则进行排列,少不了布局算法。 我们在 Layout 中提供了很多布局算法,下面介绍一下 X6Layout 的搭配使用。

安装

# npm
$ npm install @antv/layout --save

# yarn
$ yarn add @antv/layout

如果是直接通过 script 标签引入,可以使用下面两个 CDN 中的任何一个:

使用

下面是一个网格布局的简单使用:

import { Graph } from '@antv/x6'
import { GridLayout } from '@antv/layout' // umd模式下, const { GridLayout } = window.layout

const graph = new Graph({
  container: document.getElementById('container'),
  width: 600,
  height: 400,
})

const model = {
  nodes: [
    {
      id: 'node1',
    }, {
      id: 'node2',
    },
  ],
  edges: [
    {
      source: 'node1',
      target: 'node2',
    },
  ],
}

const gridLayout = new GridLayout({
  type: 'grid',
  width: 600,
  height: 400,
  center: [300, 200],
  rows: 4,
  cols: 4,
})

const newModel = gridLayout.layout(model)

graph.fromJSON(newModel)

布局流程

  • 选定一种布局方式,比如上面的 grid,如果不知道使用哪种布局方式,可以在这里 看效果图,布局配置可以参考对应的文档。
  • 构造布局数据,其实布局所需要的数据很简单:

    // 下面是布局所需要的数据格式
    {
    nodes: [
    {
      id: 'node1',
      size: {
        width: 30,
        height: 40,
      }
    },
    {
      id: 'node2',
      size: {
        width: 30,
        height: 40,
      }
    }
    ],
    edges: [
    {
      source: 'node1',
      target: 'node2',
    }
    ]
    }
  • 执行布局方法后,布局算法会在你传入的数据基础上增加节点的 x、y 属性,拿到节点的位置后,就可以将节点移动到指定位置。

需要注意的是,布局算法返回的 x、y 其实是节点的中心点坐标,在 X6 中,节点的 x、y 其实是左上角坐标,所以布局之后,我们需要做一次坐标转换。

const layoutData = gridLayout.layout(originData);
layoutData.nodes.forEach(node => {
  node.x -= node.size.width / 2;
  node.y -= node.size.height / 2;
})

常用布局

网格布局

网格布局根据参数指定的排序方式对节点进行排序后,将节点排列在网格上。

import { GridLayout } from '@antv/layout'

const gridLayout = new GridLayout({
  type: 'grid',
  width: 600,
  height: 400,
  center: [300, 200],
  rows: 4,
  cols: 4,
})

支持以下配置:

名称类型必选默认值描述
typestringtruegrid布局类型
begin[number, number]false[0, 0]网格开始位置(左上角
widthnumberfalse-布局区域宽度
heightnumberfalse-布局区域高度
center[number, number]false-布局中心点
preventOverlapbooleanfalsefalse是否防止重叠
preventOverlapPaddingnumberfalse10防止叠时节点的间距 paddingpreventOverlaptrue 时生效
rowsnumberfalse-网格的行数,不设置时算法根据节点数量、布局空间、cols(若指定)自动计算
colsnumberfalse-网格的列数,不设置时算法根据节点数量、布局空间、rows(若指定)自动计算
condensebooleanfalsefalsefalse 时表示利用所有可用画布空间,为 true 时表示利用最小的画布空间
sortBystringfalse-指定排序的依据(节点属性名),数值越高则该节点被放置得越中心。若不设置,则会计算节点的度数,度数越高,节点将被放置得越中心
nodeSizenumber | number[]false30统一设置节点的尺寸

环形布局

布局将所有节点布局在一个圆环上,可以选择节点在圆环上的排列顺序。可以通过参数的配置扩展出环的分组布局、螺旋形布局等

import { CircularLayout } from '@antv/layout'

const circularLayout = new CircularLayout({
  type: 'circular',
  width: 600,
  height: 400,
  center: [300, 200],
  radius: 50,
})

支持以下配置:

名称类型必选默认值描述
typestringtruecircular布局类型
widthnumberfalse-布局区域宽度
heightnumberfalse-布局区域高度
center[number, number]false-布局中心点
radiusnumberfalsenull圆的半径。若设置了 radius,则 startRadiusendRadius 不生效
startRadiusnumberfalsenull螺旋状布局的起始半径
endRadiusnumberfalsenull螺旋状布局的结束半径
clockwisebooleanfalsetrue是否顺时针排列
divisionsnumberfalse1节点在环上的分段数(几个段将均匀分布),在 endRadius - startRadius != 0 时生效
orderingstringfalsenull节点在环上排序的依据。默认 null 代表直接使用数据中的顺序。topology 按照拓扑排序。degree 按照度数大小排序
angleRationumberfalse1从第一个节点到最后节点之间相隔多少个 2*PI

Dagre

Dagre 是一种层次布局。

import { DagreLayout } from '@antv/layout'

const dagreLayout = new DagreLayout({
  type: 'dagre',
  rankdir: 'LR',
  align: 'UL',
  ranksep: 30,
  nodesep: 15,
  controlPoints: true,
})

支持以下配置:

名称类型必选默认值描述
typestringtruedagre布局类型
begin[number, number]false-布局左上角对齐位置
rankdir'TB' | 'BT' | 'LR' | 'RL'falseTB布局的方向。T:top(上);B:bottom(下);L:left(左);R:right(右)
align'UL' | 'UR' | 'DL' | 'DR' | undefinedfalse-节点对齐方式。U:upper(上);D:down(下);L:left(左);R:right(右);undefined (居中)
nodesepnumberfalse50节点间距(px)。在 rankdirTBBT 时是节点的水平间距;在 rankdirLRRL 时代表节点的竖直方向间距
ranksepnumberfalse50层间距(px)。在 rankdirTBBT 时是竖直方向相邻层间距;在 rankdirLRRL 时代表水平方向相邻层间距
nodesepFuncfunctionfalse-节点间距(px)的回调函数,通过该参数可以对不同节点设置不同的节点间距。
ranksepFuncfunctionfalse-层间距(px)的回调函数,通过该参数可以对不同节点设置不同的层间距。
controlPointsbooleanfalsetrue是否保留布局连线的控制点