logo

G2

  • Chart Gallery
  • Docs
  • Examples
  • Theme
  • Ecosystem
  • Productsantv logo arrow
  • 5.3.5
  • Get Started
  • Introduction
    • What is G2
    • Using in Frontend Frameworks
    • Experimental Spec API
  • Chart API
  • Core Concepts
    • G2's complete configuration system
    • Chart
      • Components of G2 Charts
      • Chart Lifecycle
    • Mark
      • Overview
      • area
      • box
      • boxplot
      • cell
      • chord
      • density
      • gauge
      • heatmap
      • image
      • interval
      • line
      • lineX
      • lineY
      • link
      • liquid
      • sunburst
      • point
      • polygon
      • range
      • rangeX
      • rangeY
      • rect
      • shape
      • text
      • vector
      • connector
      • wordCloud
    • View
    • Data
      • Overview
      • custom
      • ema
      • fetch
      • filter
      • fold
      • inline
      • join
      • kde
      • log
      • map
      • pick
      • rename
      • slice
      • sort
      • sortBy
    • Encode
    • Scale
      • Overview
      • band
      • linear
      • log
      • ordinal
      • point
      • quantile
      • quantize
      • sqrt
      • threshold
      • time
      • pow
    • Transform
      • Overview
      • bin
      • binX
      • diffY
      • dodgeX
      • flexX
      • group
      • groupColor
      • groupX
      • groupY
      • jitter
      • jitterX
      • jitterY
      • normalizeY
      • pack
      • sample
      • select
      • selectX
      • selectY
      • sortColor
      • sortX
      • sortY
      • stackEnter
      • stackY
      • symmetryY
    • Coordinate
      • Overview
      • fisheye
      • parallel
      • polar
      • theta
      • transpose
      • radial
      • cartesian3D
      • helix
    • Style
    • Animate
      • Overview
      • fadeIn
      • fadeOut
      • growInX
      • growInY
      • morphing
      • pathIn
      • scaleInX
      • scaleInY
      • scaleOutX
      • scaleOutY
      • waveIn
      • zoomIn
      • zoomOut
    • State
    • Interaction
      • Overview
      • brushAxisHighlight
      • brushHighlight
      • brushXHighlight
      • brushYHighlight
      • brushFilter
      • brushXFilter
      • brushYFilter
      • chartIndex
      • elementHighlight
      • elementHighlightByColor
      • elementHighlightByX
      • elementSelect
      • elementSelectByColor
      • elementSelectByX
      • legendFilter
      • legendHighlight
      • poptip
      • scrollbarFilter
      • sliderFilter
      • fisheye
    • Composition
      • Overview
      • facetCircle
      • facetRect
      • repeatMatrix
      • spaceFlex
      • spaceLayer
      • timingKeyframe
    • Theme
      • Overview
      • academy
      • classic
      • classicDark
    • Events
    • Color Mapping
  • Chart Component
    • Title
    • Axis
    • Legend
    • Scrollbar
    • Slider
    • Tooltip
    • Data Label
  • Extra Topics
    • Graph
      • forceGraph
      • pack
      • sankey
      • tree
      • treemap
    • Geo
      • geoPath
      • geoView
    • 3D
      • Draw 3D Chart
      • point3D
      • line3D
      • interval3D
      • surface3D
    • Plugin
      • renderer
      • rough
      • lottie
      • a11y
    • Package on demand
    • Set pattern
    • Server-Side Rendering (SSR)
    • Spec Function Expression Support (Available in 5.3.0)
  • Whats New
    • New Version Features
    • Migration from v4 to v5
  • Frequently Asked Questions (FAQ)

band

Previous
Overview
Next
linear

Resource

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

Community

Ant Financial Experience Tech
seeconfSEE Conf-Experience Tech Conference
weavefoxWeaveFox-AI Developer Community

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-Interactive solution
weavefoxWeaveFox-AI Coding Assistant
© Copyright 2025 Ant Group Co., Ltd..备案号:京ICP备15032932号-38

Loading...

Overview

The band scale is a special type of ordinal scale that maps discrete domains (such as categories, names, etc.) to continuous numerical ranges, allocating equal-width intervals (bands) for each category. Unlike regular ordinal scales, band scales not only focus on point positions but also consider the interval width occupied by each category.

Key characteristics of band scales:

  • Maps discrete data (such as categories) to continuous intervals
  • Allocates equal-width intervals (bands) for each category
  • Supports setting inner spacing between categories (paddingInner) and outer spacing (paddingOuter)
  • Commonly used in visualizations that need to represent categorical data, such as bar charts and column charts

In G2, the band scale is the default x-axis scale for bar charts (interval marks), automatically handling the mapping and layout of categorical data.

Configuration Options

PropertyDescriptionTypeDefaultRequired
domainSets the domain array, i.e., possible values of input datanumber[] | string[] | Date[][]
rangeSets the range of data mapping, i.e., the output rangenumber[] | string[][0, 1]
unknownReturn value for undefined, NaN, null empty valuesanyundefined
roundWhether to round the output valuesbooleanfalse
paddingInnerSets inner spacing between categories, in range [0, 1], larger values mean larger spacingnumber0
paddingOuterSets outer spacing at both ends, in range [0, 1], larger values mean larger spacingnumber0
paddingShortcut to set both paddingInner and paddingOuternumber0
alignAlignment, in range [0, 1], 0 means left-aligned, 0.5 means centered, 1 means right-alignednumber0.5
compareSorting function for domain mapping(a: string or number, b: string or number) => numberundefined
flexSets width allocation ratio for each categorynumber[][]

Layout Principles of Band Scale

The band scale divides the continuous range into equal-width intervals, with each interval corresponding to a discrete value in the domain. The following diagram illustrates the layout principles of the band scale:

|<------------------------------------------- range ------------------------------------------->|
| | | | | | |
|<--step*PO-->|<----bandWidth---->|<--step*PI-->|<----bandWidth---->|<--step*PI-->|<--step*PO-->|
| | ***************** | | ***************** | | |
| | ******* A ******* | | ******* B ******* | | |
| | ***************** | | ***************** | | |
| |<--------------step------------->| |
|-----------------------------------------------------------------------------------------------|

Where:

  • range: The entire range of the scale
  • bandWidth: The width occupied by each category
  • step: The distance between the center points of adjacent categories
  • step*PI (paddingInner): Inner spacing between categories
  • step*PO (paddingOuter): Outer spacing at both ends

Bandwidth Concept Explained

What is Bandwidth

Bandwidth is the actual width occupied by each category in a band scale. It determines the width of bars in bar charts, the height of bars in horizontal bar charts, etc. Bandwidth is the core concept that distinguishes band scales from other scales.

Bandwidth Calculation Formula

The bandwidth calculation involves multiple parameters, with the specific formula as follows:

step = rangeLength / (domain.length - paddingInner + paddingOuter * 2)
bandWidth = step * (1 - paddingInner)

Where:

  • rangeLength: The length of the range (range[1] - range[0])
  • domain.length: The number of categories in the domain
  • paddingInner: Inner spacing ratio [0, 1]
  • paddingOuter: Outer spacing ratio [0, 1]

Impact of Parameters on Bandwidth

1. Impact of paddingInner

paddingInner controls the spacing between categories and directly affects bandwidth size:

import { Chart } from '@antv/g2';
const data = [
{ category: 'A', value: 100 },
{ category: 'B', value: 80 },
{ category: 'C', value: 120 },
{ category: 'D', value: 90 },
];
// Create three charts showing different paddingInner effects
const charts = [
{ paddingInner: 0, title: 'paddingInner: 0 (Maximum bandwidth)' },
{ paddingInner: 0.3, title: 'paddingInner: 0.3 (Medium bandwidth)' },
{ paddingInner: 0.8, title: 'paddingInner: 0.8 (Minimum bandwidth)' },
];
charts.forEach((config, index) => {
const container = document.createElement('div');
container.style.width = '300px';
container.style.height = '200px';
container.style.display = 'inline-block';
container.style.margin = '10px';
document.getElementById('container').appendChild(container);
const chart = new Chart({
container,
autoFit: true,
});
chart.options({
type: 'interval',
data,
encode: {
x: 'category',
y: 'value',
color: 'category',
},
scale: {
x: {
type: 'band',
paddingInner: config.paddingInner,
paddingOuter: 0.1,
},
},
axis: {
x: { title: config.title },
y: { title: null },
},
});
chart.render();
});

2. Impact of paddingOuter

paddingOuter controls the spacing at both ends and indirectly affects bandwidth:

import { Chart } from '@antv/g2';
const data = [
{ category: 'A', value: 100 },
{ category: 'B', value: 80 },
{ category: 'C', value: 120 },
{ category: 'D', value: 90 },
];
const charts = [
{ paddingOuter: 0, title: 'paddingOuter: 0' },
{ paddingOuter: 0.3, title: 'paddingOuter: 0.3' },
{ paddingOuter: 0.6, title: 'paddingOuter: 0.6' },
];
charts.forEach((config, index) => {
const container = document.createElement('div');
container.style.width = '300px';
container.style.height = '200px';
container.style.display = 'inline-block';
container.style.margin = '10px';
document.getElementById('container').appendChild(container);
const chart = new Chart({
container,
autoFit: true,
});
chart.options({
type: 'interval',
data,
encode: {
x: 'category',
y: 'value',
color: 'category',
},
scale: {
x: {
type: 'band',
paddingInner: 0.2,
paddingOuter: config.paddingOuter,
},
},
axis: {
x: { title: config.title },
y: { title: null },
},
});
chart.render();
});

3. Impact of Category Count

The more categories there are, the smaller the bandwidth for each category:

import { Chart } from '@antv/g2';
const datasets = [
{
data: [
{ category: 'A', value: 100 },
{ category: 'B', value: 80 },
],
title: '2 Categories',
},
{
data: [
{ category: 'A', value: 100 },
{ category: 'B', value: 80 },
{ category: 'C', value: 120 },
{ category: 'D', value: 90 },
],
title: '4 Categories',
},
{
data: [
{ category: 'A', value: 100 },
{ category: 'B', value: 80 },
{ category: 'C', value: 120 },
{ category: 'D', value: 90 },
{ category: 'E', value: 110 },
{ category: 'F', value: 95 },
],
title: '6 Categories',
},
];
datasets.forEach((dataset, index) => {
const container = document.createElement('div');
container.style.width = '300px';
container.style.height = '200px';
container.style.display = 'inline-block';
container.style.margin = '10px';
document.getElementById('container').appendChild(container);
const chart = new Chart({
container,
autoFit: true,
});
chart.options({
type: 'interval',
data: dataset.data,
encode: {
x: 'category',
y: 'value',
color: 'category',
},
scale: {
x: {
type: 'band',
padding: 0.3, // Fixed spacing ratio
},
},
axis: {
x: { title: dataset.title },
y: { title: null },
},
});
chart.render();
});

How to Get Bandwidth Value

In actual development, sometimes you need to get the calculated bandwidth value, which can be done in the following way:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ category: 'A', value: 100 },
{ category: 'B', value: 80 },
{ category: 'C', value: 120 },
{ category: 'D', value: 90 },
],
encode: {
x: 'category',
y: 'value',
color: 'category',
},
scale: {
x: {
type: 'band',
padding: 0.3,
},
},
});
chart.render().then(() => {
// Get x-axis scale
const xScale = chart.getScale().x;
// Get bandwidth value - use no-parameter call
const bandWidth = xScale.getBandWidth?.() ?? 0;
console.log('Current bandwidth value:', bandWidth);
// You can also get bandwidth for specific category (if needed)
const categoryABandWidth = xScale.getBandWidth?.(xScale.invert('A')) ?? 0;
console.log('Category A bandwidth value:', categoryABandWidth);
// Calculate step value (distance between adjacent category centers)
const domain = xScale.getOptions()?.domain || [];
const range = xScale.getOptions()?.range || [0, 1];
const rangeLength = range[1] - range[0];
const paddingInner = xScale.getOptions()?.paddingInner || 0;
const paddingOuter = xScale.getOptions()?.paddingOuter || 0;
const step = rangeLength / (domain.length - paddingInner + paddingOuter * 2);
console.log('Current step value:', step);
// Display bandwidth information on the chart
const container = chart.getContainer();
const info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '10px';
info.style.left = '10px';
info.style.background = 'rgba(0,0,0,0.8)';
info.style.color = 'white';
info.style.padding = '5px 10px';
info.style.borderRadius = '4px';
info.style.fontSize = '12px';
info.innerHTML = `Bandwidth: ${bandWidth.toFixed(2)}<br>Step: ${step.toFixed(2)}`;
container.appendChild(info);
});

Bandwidth Applications in Different Chart Types

1. Bandwidth in Bar Charts

In bar charts, bandwidth directly determines the width of bars:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ month: 'Jan', sales: 1200 },
{ month: 'Feb', sales: 1100 },
{ month: 'Mar', sales: 1350 },
{ month: 'Apr', sales: 1280 },
],
encode: {
x: 'month',
y: 'sales',
color: 'month',
},
scale: {
x: {
type: 'band',
padding: 0.2, // Smaller spacing, wider bars
},
},
style: {
stroke: '#fff',
strokeWidth: 2,
},
});
chart.render();

2. Bandwidth in Horizontal Bar Charts

In horizontal bar charts, bandwidth determines the height of bars:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
coordinate: { transform: [{ type: 'transpose' }] },
data: [
{ department: 'Sales', count: 45 },
{ department: 'Marketing', count: 32 },
{ department: 'Technology', count: 28 },
{ department: 'HR', count: 15 },
],
encode: {
x: 'department',
y: 'count',
color: 'department',
},
scale: {
x: {
type: 'band',
padding: 0.4, // Larger spacing between bars
},
},
});
chart.render();

3. Bandwidth in Grouped Bar Charts

In grouped bar charts, the overall bandwidth is divided equally among the sub-groups:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ quarter: 'Q1', type: 'Actual', value: 120 },
{ quarter: 'Q1', type: 'Budget', value: 100 },
{ quarter: 'Q2', type: 'Actual', value: 140 },
{ quarter: 'Q2', type: 'Budget', value: 130 },
{ quarter: 'Q3', type: 'Actual', value: 160 },
{ quarter: 'Q3', type: 'Budget', value: 150 },
],
encode: {
x: 'quarter',
y: 'value',
color: 'type',
},
transform: [{ type: 'dodgeX' }],
scale: {
x: {
type: 'band',
padding: 0.3, // Overall bandwidth for each quarter
},
},
});
chart.render();

Bandwidth Optimization Recommendations

1. Adjust Spacing Based on Data Volume

  • Small data (< 5 categories): Use smaller padding (0.1-0.3) to make bars wider and more prominent
  • Medium data (5-10 categories): Use medium padding (0.3-0.5) to balance readability and visual effect
  • Large data (> 10 categories): Use larger padding (0.5-0.8) or consider paginated display

2. Consider Chart Container Size

import { Chart } from '@antv/g2';
// Simulate bandwidth effects under different container widths
const widths = [300, 600, 900];
const data = Array.from({ length: 8 }, (_, i) => ({
category: `Category ${String.fromCharCode(65 + i)}`,
value: Math.random() * 100 + 50,
}));
widths.forEach((width, index) => {
const container = document.createElement('div');
container.style.width = `${width}px`;
container.style.height = '200px';
container.style.display = 'inline-block';
container.style.margin = '10px';
container.style.border = '1px solid #ccc';
document.getElementById('container').appendChild(container);
const chart = new Chart({
container,
width,
height: 200,
});
chart.options({
type: 'interval',
data,
encode: {
x: 'category',
y: 'value',
color: 'category',
},
scale: {
x: {
type: 'band',
padding: 0.2, // Fixed spacing ratio
},
},
axis: {
x: { title: `Container width: ${width}px` },
y: { title: null },
},
});
chart.render();
});

3. Responsive Bandwidth Design

For charts that need to adapt to different screen sizes, you can dynamically adjust padding:

// Dynamically adjust padding based on container width
function getResponsivePadding(containerWidth, dataLength) {
const baseWidth = containerWidth / dataLength;
if (baseWidth > 100) {
return 0.6; // Increase spacing when container is very wide
} else if (baseWidth > 50) {
return 0.4; // Medium width
} else {
return 0.2; // Reduce spacing when container is narrow
}
}

By deeply understanding the bandwidth concept, you can better control the visual effects of charts and create both beautiful and practical data visualizations.

Usage Examples

Basic Bar Chart

The most common application of band scales is in bar charts. By setting padding, you can control the spacing between bars:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ genre: 'Sports', sold: 275 },
{ genre: 'Strategy', sold: 115 },
{ genre: 'Action', sold: 120 },
{ genre: 'Shooter', sold: 350 },
{ genre: 'Other', sold: 150 },
],
encode: {
x: 'genre',
y: 'sold',
color: 'genre',
},
scale: {
x: {
type: 'band',
padding: 0.5, // Set spacing between bars
},
},
});
chart.render();

Grouped Bar Chart

In grouped bar charts, band scales work together with dodgeX transform to create grouping effects:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ month: 'Jan', value: 86.5, type: 'Precipitation' },
{ month: 'Feb', value: 86.5, type: 'Precipitation' },
{ month: 'Mar', value: 86.5, type: 'Precipitation' },
{ month: 'Apr', value: 86.5, type: 'Precipitation' },
{ month: 'May', value: 86.5, type: 'Precipitation' },
{ month: 'Jun', value: 86.5, type: 'Precipitation' },
{ month: 'Jan', value: 30.5, type: 'Evaporation' },
{ month: 'Feb', value: 30.5, type: 'Evaporation' },
{ month: 'Mar', value: 30.5, type: 'Evaporation' },
{ month: 'Apr', value: 30.5, type: 'Evaporation' },
{ month: 'May', value: 30.5, type: 'Evaporation' },
{ month: 'Jun', value: 30.5, type: 'Evaporation' },
],
encode: {
x: 'month',
y: 'value',
color: 'type',
},
transform: [{ type: 'dodgeX' }],
scale: {
x: {
type: 'band',
padding: 0.2, // Set spacing between groups
},
},
});
chart.render();

Custom Bar Width

Using the flex property allows setting different width ratios for different categories:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ country: 'USA', value: 12394, gdp: 21.4 },
{ country: 'China', value: 9608, gdp: 14.7 },
{ country: 'Japan', value: 4731, gdp: 5.0 },
{ country: 'Germany', value: 3861, gdp: 4.2 },
{ country: 'UK', value: 2678, gdp: 2.9 },
],
encode: {
x: 'country',
y: 'value',
color: 'country',
},
scale: {
x: {
type: 'band',
padding: 0.4,
flex: [2.14, 1.47, 0.5, 0.42, 0.29], // Set different widths based on GDP
},
},
});
chart.render();

Horizontal Bar Chart

By transposing the coordinate system, you can create horizontal bar charts where band scales still apply:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
coordinate: { transform: [{ type: 'transpose' }] },
data: [
{ genre: 'Sports', sold: 275 },
{ genre: 'Strategy', sold: 115 },
{ genre: 'Action', sold: 120 },
{ genre: 'Shooter', sold: 350 },
{ genre: 'Other', sold: 150 },
],
encode: {
x: 'genre',
y: 'sold',
color: 'genre',
},
scale: {
x: {
type: 'band',
padding: 0.5,
},
},
});
chart.render();

Stacked Bar Chart

Using stackY transform can create stacked bar charts showing cumulative effects of each part:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ quarter: 'Q1', department: 'Sales', value: 120 },
{ quarter: 'Q1', department: 'Marketing', value: 100 },
{ quarter: 'Q1', department: 'Technology', value: 80 },
{ quarter: 'Q2', department: 'Sales', value: 140 },
{ quarter: 'Q2', department: 'Marketing', value: 110 },
{ quarter: 'Q2', department: 'Technology', value: 90 },
{ quarter: 'Q3', department: 'Sales', value: 160 },
{ quarter: 'Q3', department: 'Marketing', value: 95 },
{ quarter: 'Q3', department: 'Technology', value: 120 },
{ quarter: 'Q4', department: 'Sales', value: 180 },
{ quarter: 'Q4', department: 'Marketing', value: 100 },
{ quarter: 'Q4', department: 'Technology', value: 130 },
],
encode: {
x: 'quarter',
y: 'value',
color: 'department',
},
transform: [{ type: 'stackY' }],
scale: {
x: {
type: 'band',
padding: 0.3,
},
},
});
chart.render();

Variable-Width Bar Chart (Using flexX Transform)

Automatically adjust bar width based on specified field values, suitable for representing weight or proportional relationships:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ region: 'East', sales: 8500, population: 2.4 },
{ region: 'South', sales: 6200, population: 1.8 },
{ region: 'North', sales: 7800, population: 2.1 },
{ region: 'Southwest', sales: 4500, population: 1.2 },
{ region: 'Northeast', sales: 3200, population: 0.9 },
{ region: 'Northwest', sales: 2800, population: 0.7 },
],
encode: {
x: 'region',
y: 'sales',
color: 'region',
},
transform: [{ type: 'flexX', field: 'population' }], // Adjust bar width based on population data
scale: {
x: {
type: 'band',
padding: 0.2,
},
},
});
chart.render();

Time Series Bar Chart

When handling time data, band scales can well handle the visualization of time intervals:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ month: '2024-01', sales: 1200 },
{ month: '2024-02', sales: 1100 },
{ month: '2024-03', sales: 1350 },
{ month: '2024-04', sales: 1280 },
{ month: '2024-05', sales: 1400 },
{ month: '2024-06', sales: 1520 },
{ month: '2024-07', sales: 1680 },
{ month: '2024-08', sales: 1590 },
{ month: '2024-09', sales: 1450 },
{ month: '2024-10', sales: 1380 },
{ month: '2024-11', sales: 1250 },
{ month: '2024-12', sales: 1600 },
],
encode: {
x: 'month',
y: 'sales',
color: (d) => (d.sales > 1500 ? 'high' : d.sales > 1300 ? 'medium' : 'low'),
},
scale: {
x: {
type: 'band',
padding: 0.1,
},
color: {
domain: ['low', 'medium', 'high'],
range: ['#faad14', '#1890ff', '#52c41a'],
},
},
});
chart.render();

Multi-Level Categorical Bar Chart

Displaying categorical data with hierarchical structure:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ category: 'Clothing-Men', subcategory: 'Shirts', value: 850 },
{ category: 'Clothing-Men', subcategory: 'Pants', value: 750 },
{ category: 'Clothing-Men', subcategory: 'Jackets', value: 650 },
{ category: 'Clothing-Women', subcategory: 'Dresses', value: 950 },
{ category: 'Clothing-Women', subcategory: 'Tops', value: 800 },
{ category: 'Clothing-Women', subcategory: 'Skirts', value: 700 },
{ category: 'Electronics-Phones', subcategory: 'iPhone', value: 1200 },
{ category: 'Electronics-Phones', subcategory: 'Huawei', value: 1100 },
{ category: 'Electronics-Phones', subcategory: 'Xiaomi', value: 900 },
{ category: 'Electronics-Computers', subcategory: 'Laptops', value: 1500 },
{ category: 'Electronics-Computers', subcategory: 'Desktops', value: 800 },
{ category: 'Electronics-Computers', subcategory: 'Tablets', value: 600 },
],
encode: {
x: 'category',
y: 'value',
color: 'subcategory',
},
transform: [{ type: 'dodgeX' }],
scale: {
x: {
type: 'band',
padding: 0.4, // Larger spacing to distinguish different main categories
paddingInner: 0.3, // Inner spacing
paddingOuter: 0.1, // Outer spacing
},
},
});
chart.render();

Comparative Analysis Bar Chart

Using paddingInner and paddingOuter to precisely control spacing, suitable for comparative analysis:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: [
{ product: 'Product A', current: 320, target: 400 },
{ product: 'Product B', current: 280, target: 350 },
{ product: 'Product C', current: 410, target: 450 },
{ product: 'Product D', current: 180, target: 250 },
{ product: 'Product E', current: 350, target: 380 },
].flatMap((d) => [
{ product: d.product, type: 'Current Sales', value: d.current },
{ product: d.product, type: 'Target Sales', value: d.target },
]),
encode: {
x: 'product',
y: 'value',
color: 'type',
},
transform: [{ type: 'dodgeX' }],
scale: {
x: {
type: 'band',
paddingInner: 0.2, // Smaller intra-group spacing
paddingOuter: 0.3, // Larger inter-group spacing
},
color: {
domain: ['Current Sales', 'Target Sales'],
range: ['#1890ff', '#52c41a'],
},
},
});
chart.render();

Dynamic Bar Width Chart

Combine compare function to sort data and use different bar width strategies:

import { Chart } from '@antv/g2';
const data = [
{ brand: 'Apple', market_share: 23.4, revenue: 365 },
{ brand: 'Samsung', market_share: 20.1, revenue: 220 },
{ brand: 'Huawei', market_share: 15.8, revenue: 180 },
{ brand: 'Xiaomi', market_share: 12.3, revenue: 120 },
{ brand: 'OPPO', market_share: 8.9, revenue: 95 },
{ brand: 'vivo', market_share: 7.2, revenue: 85 },
{ brand: 'Others', market_share: 12.3, revenue: 150 },
];
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data,
encode: {
x: 'brand',
y: 'market_share',
color: 'brand',
},
scale: {
x: {
type: 'band',
padding: 0.2,
compare: (a, b) => {
// Sort by market share in descending order
const dataA = data.find((d) => d.brand === a);
const dataB = data.find((d) => d.brand === b);
return (dataB?.market_share || 0) - (dataA?.market_share || 0);
},
flex: [2.34, 2.01, 1.58, 1.23, 0.89, 0.72, 1.23], // Set width based on market share
},
},
});
chart.render();

Advanced Application Scenarios

Waterfall Chart (Using Band Scale)

Displaying step-by-step cumulative changes in values:

import { Chart } from '@antv/g2';
// Waterfall chart data processing
const rawData = [
{ name: 'Initial Balance', value: 1000, type: 'start' },
{ name: 'Revenue Increase', value: 500, type: 'positive' },
{ name: 'Cost Expense', value: -200, type: 'negative' },
{ name: 'Tax Expense', value: -150, type: 'negative' },
{ name: 'Other Income', value: 100, type: 'positive' },
{ name: 'Final Balance', value: 1250, type: 'end' },
];
// Calculate cumulative values
let cumulative = 0;
const data = rawData.map((d, i) => {
if (d.type === 'start' || d.type === 'end') {
const result = { ...d, start: 0, end: d.value };
cumulative = d.value;
return result;
} else {
const start = cumulative;
cumulative += d.value;
return { ...d, start, end: cumulative };
}
});
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'interval',
data: data.flatMap((d) => [
{ name: d.name, value: d.end - d.start, position: d.start, type: d.type },
]),
encode: {
x: 'name',
y: ['position', (d) => d.position + d.value],
color: 'type',
},
scale: {
x: {
type: 'band',
padding: 0.4,
},
color: {
domain: ['start', 'positive', 'negative', 'end'],
range: ['#722ed1', '#52c41a', '#ff4d4f', '#1890ff'],
},
},
});
chart.render();

Faceted Bar Chart

Using band scales with faceted layout to display multi-dimensional data:

import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
autoFit: true,
});
chart.options({
type: 'facetRect',
data: [
{ region: 'North', quarter: 'Q1', product: 'Product A', sales: 120 },
{ region: 'North', quarter: 'Q1', product: 'Product B', sales: 100 },
{ region: 'North', quarter: 'Q1', product: 'Product C', sales: 80 },
{ region: 'North', quarter: 'Q2', product: 'Product A', sales: 140 },
{ region: 'North', quarter: 'Q2', product: 'Product B', sales: 110 },
{ region: 'North', quarter: 'Q2', product: 'Product C', sales: 90 },
{ region: 'South', quarter: 'Q1', product: 'Product A', sales: 150 },
{ region: 'South', quarter: 'Q1', product: 'Product B', sales: 130 },
{ region: 'South', quarter: 'Q1', product: 'Product C', sales: 110 },
{ region: 'South', quarter: 'Q2', product: 'Product A', sales: 170 },
{ region: 'South', quarter: 'Q2', product: 'Product B', sales: 140 },
{ region: 'South', quarter: 'Q2', product: 'Product C', sales: 120 },
],
encode: { x: 'region', y: 'quarter' },
children: [
{
type: 'interval',
encode: {
x: 'product',
y: 'sales',
color: 'product',
},
scale: {
x: {
type: 'band',
padding: 0.3,
},
},
},
],
});
chart.render();

Common Questions

How to adjust the width of bars?

You can adjust the spacing between bars by setting the padding property, which indirectly adjusts the width of the bars. The larger the padding value, the narrower the bars; the smaller the value, the wider the bars.

chart.interval().encode('x', 'type').encode('y', 'sale').scale('x', {
type: 'band',
padding: 0.5, // Value range is [0, 1]
});

What's the difference between band scale and point scale?

  • Band Scale: Allocates an interval (bandwidth) for each category, suitable for bar charts and other charts that need to occupy width
  • Point Scale: Allocates a point for each category, equivalent to a band scale with bandWidth = 0, suitable for scatter plots and other charts that only need point positions

How to set different widths for bars?

There are two methods:

  1. Use the flex property to set different width ratios for different categories
  2. Use the flexX transform to automatically set bar width based on specified field values
// Method 1: Using flex property
chart
.interval()
.encode('x', 'country')
.encode('y', 'value')
.scale('x', {
type: 'band',
flex: [2, 1, 3, 1.5], // Manually set width ratios
});
// Method 2: Using flexX transform
chart
.interval()
.encode('x', 'country')
.encode('y', 'value')
.transform({ type: 'flexX', field: 'gdp' }); // Automatically set width based on gdp field