logo

G6

  • Docs
  • API
  • Playground
  • Community
  • Productsantv logo arrow
  • 5.0.47
  • Introduction
  • Data
  • Getting Started
    • Quick Start
    • Installation
    • Integration
      • react
      • vue
      • angular
    • Step-by-step guide
  • Graph
    • Extensions En
    • Graph
    • Options
    • extension
  • Element
    • Element Overview
    • Element State
    • Node
      • Node Overview
      • Build-in Node
        • Common Node Configurations
        • Diamond
        • Donut
        • Ellipse
        • Hexagon
        • Html
        • Image
        • Rect
        • Star
        • Triangle
        • Circle
      • Custom Node
      • Define Nodes with React
    • Edge
      • Edge Overview
      • Build-in Edge
        • Common Edge Configurations
        • Cubic Bezier Curve
        • CubicHorizontal Bezier Curve
        • CubicVertical Bezier Curve
        • Line
        • Polyline
        • Quadratic Bezier Curve
      • Custom Edge
    • Combo
      • Combo Overview
      • Build-in Combo
        • Circle
        • Combo Configuration Options
        • Rect
      • Custom Combo
    • Shape
      • Shape and KeyShape
      • Atomic Shapes and Their Properties
      • Design and Implementation of Composite Shape
  • Layout
    • Layout Overview
    • Build-in Layout
      • 3D Force-Directed Layout
      • AntvDagre Layout
      • Circular Layout
      • ComboCombined Layout
      • Common Layout Configuration Options
      • CompactBox
      • Concentric Layout
      • D3 Force-Directed Layout
      • Dagre Layout
      • Dendrogram Layout
      • Fishbone Layout
      • Force Force-directed Layout
      • ForceAtlas2 Force-directed Layout
      • Fruchterman Force-directed Layout
      • Grid Layout
      • Indented Tree
      • MDS High-dimensional Data Dimensionality Reduction Layout
      • Mindmap Tree
      • Radial Layout
      • Random Layout
      • Snake Layout
    • Custom Layout
  • Behavior
    • Behavior Overview
    • Build-in Behavior
      • AutoAdaptLabel
      • BrushSelect
      • ClickSelect
      • CollapseExpand
      • CreateEdge
      • DragCanvas
      • DragElement
      • DragElementForce
      • FixElementSize
      • FocusElement
      • HoverActivate
      • LassoSelect
      • OptimizeViewportTransform
      • ScrollCanvas
      • ZoomCanvas
    • Custom Behavior
  • Plugin
    • Plugin Overview
    • Build-in Plugin
      • Background
      • BubbleSets
      • Contextmenu
      • EdgeBundling
      • EdgeFilterLens
      • Fisheye
      • Fullscreen
      • GridLine
      • History
      • Hull
      • Legend
      • Minimap
      • Snapline
      • Timebar
      • Toolbar
      • Tooltip
      • Watermark
    • Custom Plugin
  • Transform
    • Data Transformation Overview
    • Build-in Transform
      • MapNodeSize
      • PlaceRadialLabels
      • ProcessParallelEdges
    • Custom Transform
  • Theme
    • Theme Overview
    • Custom Theme
    • Palette
    • Custom Palette
  • Animation
    • Animation Overview
    • Custom Animation
  • Further Reading
    • Event
    • renderer
    • coordinate
    • download-image
    • Using Iconfont
    • Use 3D
    • Bundle Project
  • What's new
    • Feature
    • Upgrade To 5.0
  • FAQ
  • contribute

Custom Layout

Previous
Snake Layout
Next
Behavior Overview

Resources

Ant Design
Galacea Effects
Umi-React Application Framework
Dumi-Component doc generator
ahooks-React Hooks Library

Community

Ant Financial Experience Tech
seeconfSEE Conf-Experience Tech Conference

Help

GitHub
StackOverflow

more productsMore Productions

Ant DesignAnt Design-Enterprise UI design language
yuqueYuque-Knowledge creation and Sharing tool
EggEgg-Enterprise-class Node development framework
kitchenKitchen-Sketch Tool set
GalaceanGalacean-互动图形解决方案
xtechLiven Experience technology
© Copyright 2025 Ant Group Co., Ltd..备案号:京ICP备15032932号-38

Loading...

Overview

In G6, layouts are divided into two types: 'iterative layout' and 'non-iterative layout'. An iterative layout refers to a layout algorithm that iterates multiple times until convergence, while a non-iterative layout refers to a layout algorithm that executes only once.

Implement Layout

Non-Iterative Layout

Implementing a non-iterative layout is relatively straightforward; you only need to implement the execute method in BaseLayout. Below is a simple implementation of a custom layout:

import { BaseLayout } from '@antv/g6';
import type { GraphData } from '@antv/g6';
class DiagonalLayout extends BaseLayout {
id = 'diagonal-layout';
async execute(data: GraphData): Promise<GraphData> {
const { nodes = [] } = data;
return {
nodes: nodes.map((node, index) => ({
id: node.id,
style: {
x: 50 * index + 25,
y: 50 * index + 25,
},
})),
};
}
}

In the code above, we implemented a simple layout algorithm that arranges nodes along a diagonal line starting from the top-left corner.

(async () => {
const { Graph, BaseLayout, register, ExtensionCategory } = window.g6;
class DiagonalLayout extends BaseLayout {
id = 'diagonal-layout';
async execute(data) {
const { nodes = [] } = data;
return {
nodes: nodes.map((node, index) => ({
id: node.id,
style: {
x: 50 * index + 25,
y: 50 * index + 25,
},
})),
};
}
}
register(ExtensionCategory.LAYOUT, 'diagonal', DiagonalLayout);
const container = createContainer({ width: 200, height: 200 });
const graph = new Graph({
container,
width: 200,
height: 200,
data: {
nodes: [{ id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }],
},
layout: {
type: 'diagonal',
},
});
await graph.render();
return container;
})();

info

The execute method returns a GraphData object, which only needs to contain the basic information of the elements (such as id, source, target) and the properties added by the layout (such as x, y, control points of edges, etc.), and does not need to contain other unnecessary information. If you only need to layout the nodes, you can return only the node information and do not need to return the edge information.

Iterative Layout

The implementation of an iterative layout also requires inheriting from BaseLayout, but in addition to execute, you also need to implement the tick and stop methods. The tick method is used to iterate the layout to a specified number of rounds, and the stop method is used to stop the layout iteration.

In addition, in iterative layouts, you need to call options.onTick each time the layout iterates to trigger the graph update.

type onTick = (data: GraphData) => void;

Below is a simple implementation of an iterative layout:

import { BaseLayout } from '@antv/g6';
import type { GraphData, BaseLayoutOptions } from '@antv/g6';
interface TickTockLayoutOptions extends BaseLayoutOptions {
onTick: (data: GraphData) => void;
}
class TickTockLayout extends BaseLayout<TickTockLayoutOptions> {
public id = 'custom-layout';
private tickCount = 0;
private data?: GraphData;
private timer?: number;
private resolve?: () => void;
private promise?: Promise<void>;
async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {
const { onTick } = { ...this.options, ...options };
this.tickCount = 0;
this.data = data;
this.promise = new Promise((resolve) => {
this.resolve = resolve;
});
this.timer = window.setInterval(() => {
onTick(this.simulateTick());
if (this.tickCount === 10) this.stop();
}, 200);
await this.promise;
return this.simulateTick();
}
simulateTick = () => {
const x = this.tickCount++ % 2 === 0 ? 50 : 150;
return {
nodes: (this?.data?.nodes || []).map((node, index) => ({
id: node.id,
style: { x, y: (index + 1) * 30 },
})),
};
};
tick = () => {
return this.simulateTick();
};
stop = () => {
clearInterval(this.timer);
this.resolve?.();
};
}

In this example, we have implemented a simple iterative layout algorithm that toggles the x-coordinate of the nodes between 50 and 150 every 200 milliseconds and arranges them in order along the y-axis according to the sequence of the nodes.

(async () => {
const { Graph, BaseLayout, register, ExtensionCategory } = window.g6;
class TickTockLayout extends BaseLayout {
id = 'tick-tock-layout';
async execute(data, options) {
const { onTick } = { ...this.options, ...options };
this.tickCount = 0;
this.data = data;
this.promise = new Promise((resolve) => {
this.resolve = resolve;
});
this.timer = window.setInterval(() => {
onTick(this.simulateTick());
if (this.tickCount === 10) this.stop();
}, 200);
await this.promise;
return this.simulateTick();
}
simulateTick = () => {
const x = this.tickCount++ % 2 === 0 ? 50 : 150;
return {
nodes: (this?.data?.nodes || []).map((node, index) => ({
id: node.id,
style: { x, y: (index + 1) * 30 },
})),
};
};
tick = () => {
return this.simulateTick();
};
stop = () => {
clearInterval(this.timer);
this.resolve?.();
};
}
register(ExtensionCategory.LAYOUT, 'tick-tock', TickTockLayout);
const container = createContainer({ width: 200, height: 200 });
const graph = new Graph({
container,
width: 200,
height: 200,
animation: true,
data: {
nodes: [{ id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],
},
layout: {
type: 'tick-tock',
},
});
graph.render();
return container;
})();

Register Layout

You can register through the register method provided by G6. For more details, please refer to Register Layout

Configure Layout

The type and parameters of the layout can be configured in options.layout. For more details, please refer to Configure Layout