Utilizing Layout
Introduction
Graph layouts are the algorithms arranging the node positions to obtain a understandable visualizaiton. According to the differences of data strucutre, the layouts can be categorized into: general graph layout and tree graph layout. There are several layout algorithms for them respectively. By utilizing the built-in layouts, Translating the layouts and their configurations, translating the data can be achieved. Besides, G6 provides the web-worker for general graph layout in case layout calculation takes too long to block page interaction.
Besides, G6 supports Custom Layout mechanism for users to design their own layout algorithm.
In fact, 'layout' is a free mechanism in G6. The built-in layouts only calculate and manipulate the x
and y
in node data. In other word, users can assign x
and y
to nodes by any other ways including the algorithms from the third-party libraries. Once G6 find the x
and y
information on data, it will render the graph according to it.
In this ducoment, we will introduce the layout algorithms in detail.
G6 Layouts Overview
Graph
- Random Layout: Randomizes the node postions;
- Force Layout: Classical force-directed layout;
- Fruchterman Layout: A kind of force-directed layout;
- Circular Layout: Arranges the nodes on a circle;
- Radial Layout: Arranges the nodes around a focus node radially;
- MDS Layout: Multidemensional Scaling;
- Dagre Layout: Arranges the nodes hierarchically;
- Concentric Layout: Arranges the nodes on concentric circles;
- Grid Layout: Arranges the nodes on grid.
TreeGraph
- CompactBox Layout;
- Dendrogram Layout: Arrange the leaves on the same level;
- Intended Layout;
- Mindmap Layout.
Graph
Configure the Graph
Configure layout
to the Graph instance to assign the layout methods and their configurations. The following code assigns the layout with type: 'force'
, which means the classical force-directed layout algorithm. The configurations preventOverlap: true
and nodeSize: 30
are assigned to prevent node overlappings, where the nodeSize
is used for collide detection. More layout configurations can be found in the following sections.
const graph = new G6.Graph({
// ... // Other configurations for the graph
layout: {
// Object, the layout configuration. Random layout by default
type: 'force',
preventOverlap: true,
nodeSize: 30,
// ... // Other configurations for the layout
},
});
Different layout algorithms have different configurations. For all the general graph layout algorithms in G6, you can enable the web-worker by configure workerEnabled: true
in the layout
configuration above. With web-worker, layout algorithms performed on large data with high cost will not block the web page.
When the layout
is not assigned:
- If there is position information with
x
andy
in node data, G6 renders the graph with them; - If the position information does not exist in the node data, Random Layout will take effect by default.
Layouts for Graph
General graph layout API: General Graph Layout API.
Random
Description: Randomizes the node positions.
API: Random API
Configuration:
Name | Type | Example | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
width | Number | 300 | The width of the graph | |
height | Number | 300 | The height of the graph | |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Force
Description: Classical force-directed layout algorithm.
API: Force API
Configuration: Corresponds to the configurations in force-directed algorithm in d3.js
Name | Type | Example | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
linkDistance | Number / Function | Example 1: 50 Example 2: d => { // d is an edge if (d.id === 'edge1') { return 100; } return 50; } |
50 | The edge length. It can be a function to define the different edge lengths for different edges (Example 2) |
nodeStrength | Number / Function | Example 1: -30 Example 2: d => { // d is a node if (d.id === 'node1') { return -100; } return -30; } |
null | The strength of node force. Positive value means attractive force, negative value means repulsive force (Example 2) |
edgeStrength | Number | Example 1: 1 Example 2: d => { // d is a node if (d.id === 'node1') { return 10; } return 1; } |
null | The strength of edge force. Calculated according to the degree of nodes by default (Example 2) |
preventOverlap | Boolean | false | false | Whether to prevent node overlappings. To activate preventing node overlappings, nodeSize is required, which is used for collide detection. The size in the node data will take effect if nodeSize is not assigned. If the nodeSize and size in data are both undefiend, nodeSize will be assigned to 10 by default |
nodeSize | Array / Number | 20 | undefined | The diameter of the node. It is used for preventing node overlappings. If nodeSize is not assigned, the size property in node data will take effect. If the size in node data does not exist either, nodeSize is assigned to 10 by default |
nodeSpacing |
Number / Function | Example 1: 10 Example 2: d => { // d is a node if (d.id === 'node1') { return 100; } return 10; } |
0 | Takes effect when preventOverlap is true . It is the minimum distance between nodes to prevent node overlappings. It can be a function to define different distances for different nodes (example 2) |
alphaDecay | Number | 0.03 | 0.028 | The decay ratio of alpha for convergence. THe range is [0, 1]. 0.028 corresponds to 300 times iteration |
alphaMin | Number | 0.03 | 0.001 | The threshold to stop the iteration |
alpha | Number | 0.1 | 0.3 | The current alpha of convergence |
collideStrength | Number | 0.8 | 1 | The strength of force for preventing node overlappings. The range is [0, 1] |
forceSimulation | Object | null | Customed force simulation. If it is not assigned, the force simulation of d3.js will take effect | |
onTick | Function | {} | The callback function of each iteration | |
onLayoutEnd | Function | {} | The callback function after layout | |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Fruchterman
Description: Fruchterman is a kind of force-directed layout.
API: Fruchterman API
Configuration:
Name | Type | Example | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
maxIteration | Number | 1000 | 1000 | The maximum interation number |
gravity | Number | 10 | 10 | The gravity, which affects the compactness of the layout |
speed | Number | 1 | 1 | The moving speed in each iteration. Large value might lead to violent swing |
clustering | Boolean | false | false | Whether to layout by clustering |
clusterGravity | Number | 30 | 10 | The gravity of each clusterm which affects the compactness of each cluster |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Circular
Description: Arranges the nodes on a circle.
API: Circular API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
radius | Number | 50 | null | The radius of the circle. If the raidus exists, startRadius and endRadius do not take effect. |
startRadius | Number | 10 | null | The start radius of spiral layout |
endRadius | Number | 100 | null | The end radius of spiral layout |
clockwise | Boolean | true | true | Whether to layout clockwisely |
divisions | Number | 3 | 1 | The division number of the nodes on the circle. Takes effect when endRadius - startRadius !== 0 |
ordering | String | null | 'topology' | 'degree' |
angleRatio | Number | 1 | 1 | How many 2*PIs Between the first node and the last node |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Radial
Description: Arranges the nodes to concentrics centered at a focus node according to their shortest path length to the focus node.
API: Radial API
Configuration:
Name | Type | Example | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
linkDistance | Number | 50 | 50 | The edge length |
maxIteration | Number | 1000 | 1000 | The max iteration number. |
focusNode | String / Object | 'node1' | null | The focus node of the radial layout. The first node of the data is the default value. It can be the id of a node or the node item. |
unitRadius | Number | 10 | 100 | The separation between adjacent circles. If unitRadius is not assigned, the layout will fill the canvas automatically. |
preventOverlap | Boolean | false | false | Whether to prevent node overlappings. To activate preventing node overlappings, nodeSize is required, which is used for collide detection. The size in the node data will take effect if nodeSize is not assigned. |
maxPreventOverlapIteration | Number | 500 | 200 | The maximum iteration number of preventing node overlappings |
nodeSize | Number | 10 | 10 | The diameter of the node. It is used for preventing node overlappings. : The size in the node data will take effect if nodeSize is not assigned. If the size in node data does not exist either, nodeSize is assigned to 10 by default |
nodeSpacing |
Number / Function | Example 1: 10 Example 2: d => { // d is a node if (d.id === 'node1') { return 100; } return 10; } |
0 | Takes effect when preventOverlap is true . It is the minimum distance between nodes to prevent node overlappings. It can be a function to define different distances for different nodes (example 2) |
strictRadial | Boolean | true | false | Whether to layout the graph as strict radial, which means the nodes will be arranged on each circle strictly. Takes effect only when preventOverlap is true . Refer to Radial-strictRadial API- When preventOverlap is true , and strictRadial is false , the overlapped nodes are arranged along their circles strictly. But for the situation that there are too many nodes on a circle to be arranged, the overlappings might not be eliminated completely - When preventOverlap is true , and strictRadial is true , the overlapped nodes can be arranged around their circle with small offsets. |
sortBy | String | 'data' / 'cluster' | undefined | Sort the nodes of the same level. undefined by default, which means place the nodes with connections as close as possible; 'data' means place the node according to the ordering in data, the closer the nodes in data ordering, the closer the nodes will be placed. sortBy also can be assigned to any name of property in nodes data, such as 'cluster' , 'name' and so on (make sure the property exists in the data) |
sortStrength | Number | 10 | 10 | The strength to sort the nodes in the same circle. Larger number means place the nodes with smaller distance of sortBy more closely. Takes effect only when sortBy is not undefined |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
MDS
Description: MDS (Multidimensional scaling) is used for project high dimensional data onto low dimensional space.
API: MDS API
Configuration:
Name | Type | Example | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
linkDistance | Number | 50 | 50 | The edge length |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Dagre
Description: An hierarchical layout.
API: Dagre API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
rankdir | String | 'TB' / 'BT' / 'LR' / 'RL' | 'TB' | The layout direction. T: top; B: bottom; L: left; R: right |
align | String | 'UL' / 'UR' / 'DL' / 'DR' | 'UL' | The alignment of the nodes. U: upper; D: down; L: left; R: right |
nodesep | Number | 40 | 50 | The separation between nodes with unit px. When rankdir is 'TB' or 'BT' , nodesep represents the horizontal separations between nodes; When rankdir is 'LR' or 'RL' , nodesep represents the vertical separations between nodes |
ranksep | Number | 40 | 50 | The separations between adjacent levels with unit px. When rankdir is 'TB' or 'BT' , ranksep represents the vertical separations between adjacent levels; when rankdir is 'LR' or 'RL' , rankdir represents the horizontal separations between adjacent levels |
nodesepFunc |
Function | d => { // d is a node if (d.id === 'node1') { return 100; } return 10; } |
undefined | The function for node separation with unit px. You can adjust the separations between different node pairs by using this function instead of nodesep . When rankdir is 'LR' or 'RL' , nodesep represents the vertical separations between nodes. The priority of nodesepFunc is lower than nodesep , which means if nodesep is assigned, the nodesepFunc will not take effect |
ranksepFunc |
Function | d => { // d is a node if (d.id === 'node1') { return 100; } return 10; } |
undefined | The function for level separation with unit px. You can adjust the separations between different adjacent levels by using this function instead of ranksep . When rankdir is 'TB' or 'BT' , ranksep represents the vertical separations between adjacent levels; when rankdir is 'LR' or 'RL' , rankdir represents the horizontal separations between adjacent levels. The priority of ranksepFunc is lower than ranksep , which means if ranksep is assigned, the ranksepFunc will not take effect |
controlPoints | Boolean | true | true | Whether to keep the control points of layout |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Concentric
Tips: Concentric layout in G6 refers to cytoscape.js, we obey the MIT license
Description: Arranges the nodes on several concentric circles.
API: Concentric API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
center | Array | [ 0, 0 ] | The center of the graph | The center of the layout |
nodeSize | Number | 30 | 30 | The diameter of the node. It is used for preventing node overlappings |
minNodeSpacing | Number | 10 | 10 | The minimum separation between adjacent circles |
preventOverlap | Boolean | false | false | Whether to prevent node overlappings. To activate preventing node overlappings, nodeSize is required, which is used for collide detection. The size in the node data will take effect if nodeSize is not assigned. If the size in node data does not exist either, nodeSize is assigned to 30 by default |
sweep | Number | Math.PI | undefined | How many radians should be between the first and last node (defaults to full circle). If it is undefined, 2 * Math.PI * (1 - 1 / |
equidistant | Boolean | false | false | Whether levels have an equal radial distance between them, may cause bounding box overflow |
startAngle | Number | 3.14 | 3 / 2 * Math.PI | Where nodes start in radians |
clockwise | Boolean | false | false | Place the nodes in clockwise or not |
maxLevelDiff | Number | 0.5 | undefined | The sum of concentric values in each level. If it is undefined, maxValue / 4 will take place, where maxValue is the max value of ordering properties. For example, if sortBy='degree' , maxValue is the max degree value of all the nodes |
sortBy | String | 'property1' / 'weight' / ... | undefined | Order the nodes according to this parameter. It is the property's name of node. The node with higher value will be placed to the center. If it is undefined, the algorithm will order the nodes by their degree |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
Grid
Tips: Concentric layout in G6 refers to cytoscape.js, we obey the MIT license.
Description: Orders the nodes according to the configurations and arranged them onto grid.
API: Grid API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
begin | Array | [ 0, 0 ] | [ 0, 0 ] | 网格开始位置(左上角) |
preventOverlap | Boolean | false | false | Whether to prevent node overlappings. To activate preventing node overlappings, nodeSize is required, which is used for collide detection. The size in the node data will take effect if nodeSize is not assigned. If the size in node data does not exist either, nodeSize is assigned to 30 by default |
preventOverlapPadding | Number | 10 | 10 | The minimum padding between nodes to prevent node overlappings. Takes effect when preventOverlap is true |
nodeSize | Number | 30 | 30 | The diameter of the node. It is used for preventing node overlappings. |
condense | Boolean | false | false | Wheter to utilize the minimum space of the canvas. false means utilizing the full space, true means utilizing the minimum space. |
rows | Number | 5 | undefined | The row number of the grid. If rows is undefined, the algorithm will calculate it according to the space and node numbers automatically |
cols | Number | 5 | undefined | The column number of the grid. If cols is undefined, the algorithm will calculate it according to the space and node numbers automatically |
sortBy | String | 'property1' / 'weight' / ... | 'degree' | The ordering method for nodes. Smaller the index in the ordered array, more center the node will be placed. If sortBy is undefined, the algorithm order the nodes according to their degrees |
workerEnabled | Boolean | true / false | false | Whether to enable the web-worker in case layout calculation takes too long to block page interaction |
TreeGraph
In order to handle the tree data structure, G6 extends Graph to TreeGraph. Refer to: TreeGraph API. TreeGraph is appropriate for visualizing hierarchy data.
Configure the TreeGraph
Similar to Graph, assign layout
to Graph instance to set the layout for a TreeGraph. The Expand/Collapse behavior can be assigned to the TreeGraph by modes
.
const graph = new G6.TreeGraph({
container: 'mountNode',
modes: {
default: [
{
// Assign the collapse/expand behavior
type: 'collapse-expand',
},
'drag-canvas',
],
},
// Assign the layout
layout: {
type: 'dendrogram', // Layout type
direction: 'LR', // Layout direction is from the left to the right. Options: 'H' / 'V' / 'LR' / 'RL' / 'TB' / 'BT'
nodeSep: 50, // The distance between nodes
rankSep: 100, // The distance between adjacent levels
},
});
Layouts for TreeGraph
compactBox
Description: CompactBox is the default layout for TreeGraph. It will consider the bounding box of each node when layout.
API: CompactBox API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
direction | String | 'TB' / 'BT' / 'LR' / 'RL' / 'H' / 'V' | 'LR' | The direction of layout. - TB —— Root is on the top, layout from the top to the bottom - BT —— Root is on the bottom, layout from the bottom to the top (Left)TB. (Right)BT. - LR —— Root is on the left, layout from the left to the right - RL —— Root is on the right, layout from the right to the left (Left)LR. (Right)RL. - H —— Root is on the middle, layout in horizontal symmetry. - V —— Root is on the middle, layout in vertical symmetry. > (Left)H. (Right)V. |
getId | Function | (d) => { // d is a node return d.id + 'node'; } |
undefined | Sets the id for each node |
getHeight | Function | (d) => { // d is a node return 10; } |
undefined | The height of each node |
getWidth | Function | (d) => { // d is a node return 20; } |
undefined | he width of each node |
getVGap | Function | (d) => { // d is a node return 100; } |
undefined | The vertical separation of nodes |
getHGap | Function | (d) => { // d is a node return 50; } |
undefined | The horizontal separation of nodes |
radial | Boolean | true | false | If layout the graph in radial style. If radial is true , we recommend to set direction to 'LR' or 'RL' : |
dendrogram
Description: Arranges all the leaves on the same level. It is appropriate for hierarchical clustering. It does not consider the node size, which will be regarded as 1 px.
API: Dendrogram API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
direction | String | 'TB' / 'BT' / 'LR' / 'RL' / 'H' / 'V' | 'LR' | The direction of layout. - TB —— Root is on the top, layout from the top to the bottom - BT —— Root is on the bottom, layout from the bottom to the top > (Left)TB. (Right)BT. - LR —— Root is on the left, layout from the left to the right - RL —— Root is on the right, layout from the right to the left > (Left)LR. (Right)RL. - H —— Root is on the middle, layout in horizontal symmetry. - V —— Root is on the middle, layout in vertical symmetry. > (Left)H. (Right)V. |
nodeSep | Number | 50 | 0 | Node separation |
rankSep | Number | 100 | 0 | Level separation |
radial | Boolean | true | false | Wheter layout the graph in radial style. If radial is true , we recommend to set direction to 'LR' or 'RL' : |
indented
Description: Indented layout represents the hierarchy by indent between them. Each node will take a row/column. It is appropriate for file directory.
API: Indented API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
direction | String | 'LR' / 'RL' / 'H' | 'LR' | layout direction 'LR' —— Root is on the left, layout from the left to the right(left image below) 'RL' —— Root is on the right, layout from the right to the left(center image below) 'H' —— Root is on the middle, layout in horizontal symmetry(right image below) |
indent | Number | 80 | 20 | Colunm separation |
getHeight | Function | (d) => { // d is a node return 10; } |
undefined | The height of each node |
getWidth | Function | (d) => { // d is a node return 20; } |
undefined | The width of each node |
getSide | Function | (d) => { // d is a node return 'left'; } |
undefined | The callback function of node position(left or right of root node). Only affects the nodes which are connected to the root node directly. And the descendant nodes will be placed according to it |
mindmap
Description: Mindmap arranged the nodes with same depth on the same level. Different from compactBox, it does not consider the size of nodes while doing layout.
API: Mindmap API
Configuration:
Name | Type | Example/Options | Default | Description |
---|---|---|---|---|
direction | String | 'H' / 'V' | 'H' | layout direction - H: Root is on the middle, layout in horizontal symmetry. - V: Root is on the middle, layout in vertical symmetry. |
getHeight | Function | (d) => { // d is a node return 10; } |
undefined | The height of each node |
getWidth | Function | (d) => { // d is a node return 20; } |
undefined | The width of each node |
getVGap | Function | (d) => { // d is a node return 100; } |
18 | The vertical separation of nodes |
getHGap | Function | (d) => { // d is a node return 50; } |
18 | The horizontal separation of nodes |
getSide | String | Function | (d) => { // d is a node return 'left'; } / 'right' |
The callback function of node position(left or right of root node). Only affects the nodes which are connected to the root node directly. And the descendant nodes will be placed according to it |
Layout Transformation Mechanism
G6 provides two layout transformations:
updateLayout(params)
: Layout methods and configurations transformation;changeData()
: Data transformation.
Layout Methods and Configuration Transformation
Interface Definition:
/**
* Change the layout or its configurations
* @param {String | object} cfg New layout configurations
* If the cfg is a String or an object with the property type, and the type is different from the current layout method, the layout method will be changed into the new one;
* Only change the configurations for the current layout otherwise
*/
updateLayout(cfg);
Change the Layout Method:
If the cfg
is a String
or an object with property type
, and the type is different from the current layout method, the layout method will be changed into the new one;
Change the Configurations Only:
If the cfg
is an object without property type
, or the type
is the same as the current layout method, only the configurations for the current layout will be changed.
Data Transformation
Interface Definition:
/**
* Change the source data, render the graph with new data
* @param {object} data source data
* @return {object} this
*/
changeData(data);
Transformation Example
Expected Effect
In the first stage, the graph is arranged by random layout. Transform to force layout with node overlappings after 2000ms, force layout without node overlappings after 4000ms, change data to data2
after 6000ms.
Complete Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tutorial Layout Demo</title>
</head>
<body>
<div id="mountNode"></div>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.1.0/build/g6.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
<script>
const data = {
nodes: [
{ id: '0', label: '0' },
{ id: '1', label: '1' },
{ id: '2', label: '2' },
{ id: '3', label: '3' },
{ id: '4', label: '4' }
], edges: [
{ source: '0', target: '1' },
{ source: '0', target: '2' },
{ source: '0', target: '3' },
{ source: '0', target: '4' },
{ source: '1', target: '2' },
{ source: '1', target: '3' }
]
};
const data2 = {
nodes: [
{ id: '0', label: '0' },
{ id: '1', label: '1' },
{ id: '2', label: '2' }
], edges: [
{ source: '0', target: '1' },
{ source: '0', target: '2' }
]
};
const graph = new G6.Graph({
container: 'mountNode', // String | HTMLElement, Required, the id of the container or the container object
width: 300, // Number, Required, The width of the graph
height: 300, // Number, Required, The height of the graph
animate: true // Boolean, whether to activate the animation while changing the layout
});
// Load data and render
graph.data(data);
graph.render();
// Transform to force layout with node overlappings in 2000 ms
setTimeout(() => {
graph.updateLayout('force');
}, 8000);
// Transform to force layout without node overlappings in 4000 ms
setTimeout(() => {
graph.updateLayout({
type: 'force', // Layout name
preventOverlap: true, // Whether to prevent the node overlappings
nodeSize: 40, // The node size for collide detection
linkDistance: 100 // The edge length
});
}, 10000);
// Change the data to data2 in 6000 ms
setTimeout(() => {
graph.changeData(data2);
}, 12000);
</script>
</body>
</html>
Subgraph Layout
At present, the subgraph layout mechanism is independent to the graph layout. You can instantiate the layout method and load the data of subgraph onto the layout instance. This mechanism allows users to utilize G6's layout algorithms to calculate the node positions, and render the graph with another rendering engine.
Usage
// Instantiate the Layout
const subgraphLayout = new G6.Layout['force']({
center: [500, 450],
});
// Initialize the layout with sugbraph data
subgraphLayout.init({
nodes: subGraphNodes,
edges: subGraphEdges,
});
// Execute the layout
subgraphLayout.execute();
// Update the node positions after subgraph layout
graph.positionsAnimate();