Circular Layout
Overview
Circular layout arranges nodes evenly or at intervals on a circle, and also supports spiral layouts by configuring different startRadius and endRadius. See more circular layout examples or source code.
Usage Scenarios
Circular layout:
- Suitable for networks with equal relationships and no hierarchical structure
Spiral layout:
- Suitable for implicit hierarchies or time series graphs (such as organizational charts, propagation networks)
Basic Usage
Other settings use the default configuration (layout width and height default to the entire canvas container)
const graph = new Graph({
// other configurations
layout: {
type: 'circular',
},
});
Options
| Property | Description | Type | Default | Required |
|---|---|---|---|---|
| type | Layout type | circular | - | ✓ |
| angleRatio | How many 2*PI between the first and last node | number | 1 | |
| center | Center of the layout | [number, number]|[number, number, number] | [layout width / 2, layout height / 2] |
|
| clockwise | Whether to arrange clockwise | boolean | true | |
| divisions | Number of segments on the ring (segments will be evenly distributed, effective when endRadius - startRadius != 0) | number | 1 | |
| nodeSize | Node size (diameter), used for collision detection | Size | ((nodeData: Node) => Size) | 10 | |
| nodeSpacing | Minimum spacing between rings, used to adjust radius | number | ((nodeData: Node) => number) | 10 | |
| ordering | Node ordering on the ring, see details | topology | topology-directed | degree |
- | |
| radius | Circle radius, if set, spiral layout configs startRadius and endRadius are ignored, see details |
number | - | |
| startAngle | Start angle of the layout | number | 0 | |
| endAngle | End angle of the layout | number | 2 * Math.PI | |
| startRadius | Start radius for spiral layout, usage | number | - | |
| endRadius | End radius for spiral layout | number | - | |
| width | Layout width | number | canvas width | |
| height | Layout height | number | canvas height |
ordering
Node ordering on the ring
topology: topological ordertopology-directed: topological order (directed graph)degree: order by degree
If not set (null), the order in the array is used directly
radius
If radius, startRadius, and endRadius are not set, the default is Math.min(layout width, layout height) / 2, i.e., fills the entire layout area
Code Examples
Basic Circular Layout
const graph = new Graph({
// other configurations
layout: {
type: 'circular',
},
});
import { Graph } from '@antv/g6';
fetch('https://assets.antv.antgroup.com/g6/circular.json')
.then((res) => res.json())
.then((data) => {
const graph = new Graph({
container: 'container',
autoFit: 'view',
data,
node: {
style: {
labelText: (d) => d.id,
labelFill: '#fff',
labelPlacement: 'center',
},
},
layout: {
type: 'circular',
},
behaviors: ['drag-canvas', 'drag-element'],
});
graph.render();
});
import { Graph } from '@antv/g6';
import GUI from 'lil-gui';
export function addPanel(renderPanel: (gui: GUI) => void) {
const gui = new GUI({ container: document.body });
gui.title('Control');
Object.assign(gui.domElement.style, { position: 'absolute', top: '0', right: '0', zIndex: '10' });
renderPanel(gui);
addEventListener('pagehide', () => gui.destroy(), { once: true });
}
export async function createGraph(
options: ConstructorParameters<typeof Graph>[0],
size: { width?: number; height?: number } = {},
renderPanel?: (gui: GUI, graph: Graph) => void,
) {
const container = document.createElement('div');
Object.assign(container.style, {
width: '100%',
maxWidth: `${size.width || 600}px`,
height: `${size.height || 400}px`,
});
document.getElementById('container')!.append(container);
const graph = new Graph({ ...size, ...options, width: container.clientWidth, container, autoResize: true });
addEventListener('pagehide', () => graph.destroy(), { once: true });
await graph.render();
if (renderPanel) addPanel((gui) => renderPanel(gui, graph));
return container;
}Spiral Layout
const graph = new Graph({
// other configurations
layout: {
type: 'circular',
startRadius: 10,
endRadius: 300,
},
});
import { Graph } from '@antv/g6';
fetch('https://assets.antv.antgroup.com/g6/circular.json')
.then((res) => res.json())
.then((data) => {
const graph = new Graph({
container: 'container',
autoFit: 'center',
data,
node: {
style: {
labelText: (d) => d.id,
labelFill: '#fff',
labelPlacement: 'center',
},
},
layout: {
type: 'circular',
startRadius: 10,
endRadius: 300,
},
behaviors: ['drag-canvas', 'drag-element'],
});
graph.render();
});
import { Graph } from '@antv/g6';
import GUI from 'lil-gui';
export function addPanel(renderPanel: (gui: GUI) => void) {
const gui = new GUI({ container: document.body });
gui.title('Control');
Object.assign(gui.domElement.style, { position: 'absolute', top: '0', right: '0', zIndex: '10' });
renderPanel(gui);
addEventListener('pagehide', () => gui.destroy(), { once: true });
}
export async function createGraph(
options: ConstructorParameters<typeof Graph>[0],
size: { width?: number; height?: number } = {},
renderPanel?: (gui: GUI, graph: Graph) => void,
) {
const container = document.createElement('div');
Object.assign(container.style, {
width: '100%',
maxWidth: `${size.width || 600}px`,
height: `${size.height || 400}px`,
});
document.getElementById('container')!.append(container);
const graph = new Graph({ ...size, ...options, width: container.clientWidth, container, autoResize: true });
addEventListener('pagehide', () => graph.destroy(), { once: true });
await graph.render();
if (renderPanel) addPanel((gui) => renderPanel(gui, graph));
return container;
}