坐标轴(Axis)
概述
G2 中 Axis(坐标轴) 就像是图表的 “尺子”,用于建立数据与视觉位置的映射关系,并通过刻度、标签、网格线等元素帮助用户直观理解数据的分布与比例。它能帮你快速看懂图形的位置和数值大小。
简单来说,坐标轴可以帮助我们把数据数字和图表上的位置对应起来,让图表更容易理解。
举个例子:在柱状图中,横轴通常表示时间,纵轴表示销售额,这样你就能一眼看出 “3 月卖了 200 万,4 月涨到 300 万”
构成元素
使用方式
通过前面的概述内容,相信你对坐标轴已经有了一个清晰的认识。那么具体该如何使用呢?接下来,我将手把手教你如何配置坐标轴。
配置坐标轴其实就像搭积木,只需记住一个简单的核心口诀:“用 axis 属性,按方向配置,哪里需要改哪里改。”
第一步:启用坐标轴(默认已开启)
G2 会根据你的数据类型 自动生成坐标轴,不需要任何配置就能看到基础坐标轴
chart.options({
type: 'interval',
width: 500,
height: 300,
data: [
{ id: 1, 月份: '三月', 销售额: 200 },
{ id: 3, 月份: '四月', 销售额: 300 },
{ id: 4, 月份: '五月', 销售额: 400 },
{ id: 5, 月份: '六月', 销售额: 500 },
{ id: 6, 月份: '七月', 销售额: 600 },
{ id: 7, 月份: '八月', 销售额: 700 },
],
encode: { x: '月份', y: '销售额', color: '月份' },
// 不需要 axis 配置也能自动生成坐标轴
// axis: {},
});
第二步:按方向单独配置
配置 x(水平方向) 坐标轴
chart.options({
type: 'interval',
width: 500,
height: 300,
data: [
{ id: 1, 月份: '三月', 销售额: 200 },
{ id: 3, 月份: '四月', 销售额: 300 },
{ id: 4, 月份: '五月', 销售额: 400 },
{ id: 5, 月份: '六月', 销售额: 500 },
{ id: 6, 月份: '七月', 销售额: 600 },
{ id: 7, 月份: '八月', 销售额: 700 },
],
encode: { x: '月份', y: '销售额', color: '月份' },
// 配置 axis(坐标轴)
axis: {
// 配置水平方向的坐标轴属性
x: {
// 配置参数以及示例可以继续往下看..
},
},
});
配置 y(垂直方向) 坐标轴
chart.options({
type: 'interval',
width: 500,
height: 300,
data: [
{ id: 1, 月份: '三月', 销售额: 200 },
{ id: 3, 月份: '四月', 销售额: 300 },
{ id: 4, 月份: '五月', 销售额: 400 },
{ id: 5, 月份: '六月', 销售额: 500 },
{ id: 6, 月份: '七月', 销售额: 600 },
{ id: 7, 月份: '八月', 销售额: 700 },
],
encode: { x: '月份', y: '销售额', color: '月份' },
// 配置 axis(坐标轴)
axis: {
// 配置垂直方向的坐标轴属性
y: {
// 配置参数以及示例可以继续往下看..
},
},
});
配置层级
坐标轴可以在 Mark 层级配置。在 G2 中每个标记(Mark)都有自己的坐标轴。如果标记对应比例尺是同步的,那么坐标轴也会合并。
({
type: 'interval',
axis: {
x: { labelFormatter: '%0' },
y: { tickCount: 5 },
},
});
坐标轴也可以在 View 层级配置。坐标轴具有传递性。视图上声明的坐标轴会传递给 children 声明的标记,如果该标记有对应通道的坐标轴,就合并;否则不影响。
({
type: 'view',
axis: {
x: { labelFormatter: '%0' },
y: { tickCount: 5 },
},
});
隐藏坐标轴
隐藏每个通道的坐标轴:
隐藏 x 坐标轴:
({
type: 'interval',
axis: { x: false }, // 隐藏 x 水平方向坐标轴
});
隐藏 y 坐标轴:
({
type: 'interval',
axis: { y: false }, // 隐藏 y 垂直方向坐标轴
});
隐藏多个坐标轴
({
type: 'interval',
axis: false,
});
配置项
每个坐标轴由 标题(title)、轴线(line)、刻度(tick)、刻度值(label)、网格线(grid)以及断轴(breaks)组成。
| 属性 | 描述 | 类型 | 默认值 | 必选 |
|---|---|---|---|---|
| title | 设置坐标轴的标题文本及其样式 | title | - | |
| line | 设置坐标轴线的显示及其样式 | line | - | |
| tick | 设置坐标轴刻度线的显示及其样式 | tick | - | |
| label | 设置坐标轴刻度值的显示及其样式 | label | - | |
| grid | 设置坐标轴网格线的显示及其样式 | grid | - | |
| breaks | 设置坐标轴断轴的显示及其样式 | breaks | - | |
| animate | 设置坐标轴动画效果 | boolean | animate |
- | |
| position | 设置坐标轴的位置 | left | right | top | bottom |
x: bottom | y: left |
:::warning{title=注意} 标题(title)、轴线(line)、刻度(tick)、刻度值(label)以及网格线(grid)的配置同级,不是以对象的形式来配置,而是以前缀加属性的方式来配置。 :::
例如配置刻度值的旋转,不是在 label 对象下配置,而是通过如下的方式:
({
axis: {
x: {
title: 'x 轴标题',
labelFontSize: 12,
labelFormatter: (d) => `2025-${d}`,
transform: [
// 旋转
{
type: 'rotate',
optionalAngles: [0, 45, 90], // 尝试旋转 0 度、45 度、90 度
recoverWhenFailed: true, // 如果旋转后无法解决问题,恢复到默认角度
},
],
},
},
});
title
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| title | 关闭标题或设置标题内容 | false|string | number | DisplayObject |
- | |
| titleSpacing | 标题到坐标轴的距离 | number | (datum, index, data) => number |
10 | |
| titlePosition | 标题相对坐标轴的位置,支持首字母简写形式,如'top'简写为't' |
'top'|'bottom'|'left'|'right' |
'lb' |
|
| titleFontSize | 标题文字大小 | number | (datum, index, data) => number |
- | |
| titleFontWeight | 标题文字字体粗细 | number | (datum, index, data) => number |
- | |
| titleFontFamily | 标题文字字体 | string | (datum, index, data) => string |
- | |
| titleLineHeight | 标题文字行高 | number | (datum, index, data) => number |
1 | |
| titleTextAlign | 标题文字水平对齐方式 | 'center' | 'end' | 'left' | 'right' | 'start' | (datum, index, data) => string |
'start' |
|
| titleTextBaseline | 标题文字垂直基线 | 'top' | 'middle' | 'bottom' | 'alphabetic' | 'hanging' | (datum, index, data) => string |
'middle' |
|
| titleFill | 标题文字填充色 | string | (datum, index, data) => string |
- | |
| titleFillOpacity | 标题文字填充透明度 | number | (datum, index, data) => number |
1 | |
| titleStroke | 标题文字描边颜色 | string | (datum, index, data) => string |
transparent |
|
| titleStrokeOpacity | 标题文字描边透明度 | number | (datum, index, data) => number |
1 | |
| titleLineWidth | 标题文字描边宽度 | number | (datum, index, data) => number |
0 | |
| titleLineDash | 标题文字描边虚线配置 | number[] | (datum, index, data) => number[] |
[] | |
| titleOpacity | 标题文字整体透明度 | number | (datum, index, data) => number |
1 | |
| titleShadowColor | 标题文字阴影颜色 | string | (datum, index, data) => string |
transparent |
|
| titleShadowBlur | 标题文字阴影高斯模糊系数 | number | (datum, index, data) => number |
0 | |
| titleShadowOffsetX | 标题文字阴影水平偏移量 | number | (datum, index, data) => number |
0 | |
| titleShadowOffsetY | 标题文字阴影垂直偏移量 | number | (datum, index, data) => number |
0 | |
| titleCursor | 标题文字鼠标样式 | string | (datum, index, data) => string |
default |
|
| titleDx | 标题文字水平偏移量 | number | (datum, index, data) => number |
0 | |
| titleDy | 标题文字垂直偏移量 | number | (datum, index, data) => number |
0 |
配置方式
({
// 配置坐标轴
axis: {
// 配置 y 轴
y: {
// 这部分是轴标题的配置
title: 'Frequency', // 设置 y 轴标题
titleSpacing: 30, // 设置 y 轴标题与轴线之间的间距
titlePosition: 'left', // 设置 y 轴标题位置
titleFill: 'steelblue', // 设置 y 轴标题的颜色
titleFontSize: 16, // 设置 y 轴标题字体大小
titleFontWeight: 'bold', // 设置 y 轴标题字体粗细
titleFontFamily: 'Arial', // 设置 y 轴标题字体
titleTextAlign: 'center', // 设置 y 轴标题水平对齐方式
titleTextBaseline: 'middle', // 设置 y 轴标题垂直基线
titleOpacity: 0.9, // 设置 y 轴标题整体透明度
titleStroke: '#333', // 设置 y 轴标题描边颜色
titleLineWidth: 1, // 设置 y 轴标题描边宽度
titleShadowColor: 'rgba(0,0,0,0.3)', // 设置 y 轴标题阴影颜色
titleShadowBlur: 3, // 设置 y 轴标题阴影模糊度
titleShadowOffsetX: 2, // 设置 y 轴标题阴影水平偏移
titleShadowOffsetY: 2, // 设置 y 轴标题阴影垂直偏移
titleDx: 5, // 设置 y 轴标题水平偏移量
titleDy: 0, // 设置 y 轴标题垂直偏移量
titleCursor: 'pointer', // 设置 y 轴标题鼠标样式
},
// 配置 x 轴
x: {
// 这部分是轴标题的配置
title: 'Letter', // 设置 x 轴标题
titleSpacing: 20, // 设置 x 轴标题与轴线之间的间距
titlePosition: 'bottom', // 设置 x 轴标题位置
titleFontSize: 14, // 设置 x 轴标题字体大小
titleFontWeight: 'normal', // 设置 x 轴标题字体粗细
titleFill: '#666', // 设置 x 轴标题颜色
titleTextAlign: 'center', // 设置 x 轴标题水平对齐方式
titleOpacity: 1, // 设置 x 轴标题透明度
titleLineHeight: 1.2, // 设置 x 轴标题行高
titleFillOpacity: 0.8, // 设置 x 轴标题填充透明度
},
},
});
line
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| line | 是否显示轴线 | boolean |
false | |
| arrow | 是否显示箭头 | boolean |
true | |
| lineExtension | 轴线两侧的延长线 | [number, number] |
- | |
| lineArrow | 定义轴线箭头形状,默认为箭头形状 | DisplayObject | - | |
| lineArrowOffset | 箭头偏移长度 | number |
15 | |
| lineArrowSize | 箭头尺寸 | number |
- | |
| lineStroke | 轴线描边颜色 | string | (datum, index, data) => string |
- | |
| lineStrokeOpacity | 轴线描边透明度 | number | (datum, index, data) => number |
- | |
| lineLineWidth | 轴线描边宽度 | number | (datum, index, data) => number |
- | |
| lineLineDash | 轴线描边虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | [number,number] | (datum, index, data) => [number,number] |
- | |
| lineOpacity | 轴线整体透明度 | number | (datum, index, data) => number |
1 | |
| lineShadowColor | 轴线阴影颜色 | string | (datum, index, data) => string |
- | |
| lineShadowBlur | 轴线阴影高斯模糊系数 | number | (datum, index, data) => number |
- | |
| lineShadowOffsetX | 轴线阴影水平偏移量 | number | (datum, index, data) => number |
- | |
| lineShadowOffsetY | 轴线阴影垂直偏移量 | number | (datum, index, data) => number |
- | |
| lineCursor | 轴线鼠标样式 | string | (datum, index, data) => string |
default |
配置方式
({
axis: {
x: {
line: true, // 是否显示轴线
arrow: true, // 是否显示箭头
lineArrowOffset: 10, // 箭头偏移长度
lineArrowSize: 30, // 箭头尺寸
lineLineWidth: 10, // 轴线描边宽度
lineExtension: [5, 5], // 轴线两侧的延长线
lineStroke: '#333', // 轴线描边颜色
lineStrokeOpacity: 0.8, // 轴线描边透明度
lineLineDash: [5, 5], // 轴线描边虚线配置
lineOpacity: 1, // 轴线整体透明度
lineShadowColor: 'rgba(0,0,0,0.3)', // 轴线阴影颜色
lineShadowBlur: 3, // 轴线阴影高斯模糊系数
lineShadowOffsetX: 2, // 轴线阴影水平偏移量
lineShadowOffsetY: 2, // 轴线阴影垂直偏移量
lineCursor: 'pointer', // 轴线鼠标样式
},
y: {
line: true, // 是否显示轴线
arrow: true, // 是否显示箭头
lineArrowOffset: 10, // 箭头偏移长度
lineArrowSize: 30, // 箭头尺寸
lineLineWidth: 10, // 轴线描边宽度
lineStroke: '#666', // 轴线描边颜色
lineOpacity: 0.9, // 轴线整体透明度
},
},
});
tick
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| tick | 是否显示刻度 | boolean |
true | |
| tickCount | 设置推荐生成的刻度数量;tickCount 只是一个建议值 | number |
- | |
| tickMethod | 自定义刻度生成方法 | (start: number | Date, end: number | Date, tickCount: number) => number[] |
- | |
| tickFilter | 刻度线过滤 | (datum, index, data)=>boolean |
- | |
| tickFormatter | 刻度线格式化,可用于自定义刻度样式,回调函数中会额外返回该刻度的方向 | DisplayObject | (datum, index, data, Vector)=> DisplayObject |
- | |
| tickDirection | 刻度朝向,为 positive 时,位于侧轴方向(即主轴顺时针 90 度方向), 为 negative 时,刻度位于侧轴负方向 |
'positive' | 'negative' |
positive |
|
| tickLength | 刻度线长度 | number|(datum, index, data)=>number |
15 | |
| tickStroke | 刻度线描边颜色 | string | (datum, index, data, Vector)=>string |
- | |
| tickStrokeOpacity | 刻度线描边透明度 | number | (datum, index, data, Vector)=>number |
- | |
| tickLineWidth | 刻度线描边宽度 | number | (datum, index, data, Vector)=>number |
- | |
| tickLineDash | 刻度线描边虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | [number,number] | (datum, index, data, Vector)=>[number,number] |
- | |
| tickOpacity | 刻度线整体透明度 | number | (datum, index, data, Vector)=>number |
- | |
| tickShadowColor | 刻度线阴影颜色 | string | (datum, index, data, Vector)=>string |
- | |
| tickShadowBlur | 刻度线阴影高斯模糊系数 | number | (datum, index, data, Vector)=>number |
- | |
| tickShadowOffsetX | 刻度线阴影水平偏移量 | number | (datum, index, data, Vector)=>number |
- | |
| tickShadowOffsetY | 刻度线阴影垂直偏移量 | number | (datum, index, data, Vector)=>number |
- | |
| tickCursor | 刻度线鼠标样式 | string | (datum, index, data, Vector)=>string |
default |
({
// 配置坐标轴
axis: {
y: {
tickCount: 10, // 设置推荐生成的刻度数量
tickLength: 20, // 设置 y 轴刻度线的长度
tickFilter: (_, i) => i % 3 !== 0, // 过滤 y 轴刻度线,只显示每隔 3 个刻度线
tick: true, // 是否显示刻度
tickDirection: 'positive', // 刻度朝向
tickStroke: '#333', // 刻度线描边颜色
tickStrokeOpacity: 0.8, // 刻度线描边透明度
tickLineWidth: 2, // 刻度线描边宽度
tickLineDash: [2, 2], // 刻度线描边虚线配置
tickOpacity: 1, // 刻度线整体透明度
tickShadowColor: 'rgba(0,0,0,0.2)', // 刻度线阴影颜色
tickShadowBlur: 2, // 刻度线阴影高斯模糊系数
tickShadowOffsetX: 1, // 刻度线阴影水平偏移量
tickShadowOffsetY: 1, // 刻度线阴影垂直偏移量
tickCursor: 'crosshair', // 刻度线鼠标样式
},
x: {
tick: true, // 是否显示刻度
tickCount: 8, // 设置推荐生成的刻度数量
tickMethod: (start, end, count) => {
// 自定义刻度生成方法
const step = (end - start) / (count - 1);
return Array.from({ length: count }, (_, i) => start + i * step);
},
tickLength: 10, // 刻度线长度
tickDirection: 'positive', // 刻度朝向
tickStroke: '#3366ff', // 刻度线描边颜色
tickLineWidth: 5, // 刻度线描边宽度
tickOpacity: 0.9, // 刻度线整体透明度
tickFilter: (_, i) => i % 2 === 0, // 过滤刻度线,只显示偶数索引的刻度
},
},
});
label
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| label | 是否显示刻度值 | boolean |
- | |
| labelFontSize | 刻度标签文字大小 | number | (datum, index, data)=>number |
- | |
| labelFontFamily | 刻度标签文字字体 | string | (datum, index, data)=>string |
- | |
| labelFontWeight | 刻度标签文字字体粗细 | number |(datum, index, data)=>number |
- | |
| labelLineHeight | 刻度标签文字行高 | number | (datum, index, data)=>number |
- | |
| labelTextAlign | 刻度标签文字水平对齐方式 | 'center' | 'end' | 'left' | 'right' | 'start' | (datum, index, data)=>string |
'start' |
|
| labelTextBaseline | 刻度标签文字垂直基线 | 'top' | 'middle' | 'bottom' | 'alphabetic' | 'hanging' | (datum, index, data)=>string |
'bottom' |
|
| labelAlign | 刻度值对齐方式 - ‘horizontal’ 始终保持水平 - ‘parallel’ 平行于坐标轴 - ‘perpendicular’ 垂直于坐标轴 |
'horizontal' | 'parallel' | 'perpendicular' |
parallel |
|
| labelFilter | 刻度值过滤 | (datum, index, data)=> boolean |
- | |
| labelFormatter | 刻度值格式化,可以传入一个函数或者是 d3-format 支持的字符串 | string | (datum, index, data) => string |
- | |
| labelRender | 自定义 label 渲染,支持 HtmlString,用法同 labelFormatter |
string | (datum, index, data) => string |
- | |
| transform | 刻度值转换,避免文本之间发生重叠。当前支持超长文本缩略、重叠刻度值隐藏、自动旋转 | Transform[] |
- | |
| labelTransform | 刻度值转换,在局部坐标系下进行变换的快捷方式,包括缩放、平移、旋转、拉伸、矩阵变换,具体见transform | string |
- | |
| labelAutoHide | 自动隐藏重叠的刻度值,设置 size 值的时候生效 | boolean | HideOverlapCfg |
- | |
| labelAutoRotate | 自动旋转刻度,设置 size 值的时候生效值 | boolean | RotateOverlapCfg |
- | |
| labelAutoEllipsis | 自动缩略刻度值,设置 size 值的时候生效 | boolean | EllipsisOverlapCfg |
- | |
| labelAutoWrap | 自动换行刻度值,设置 size 值的时候是生效 | boolean | WrapOverlapCfg |
- | |
| labelDirection | 刻度值位于轴线的位置,参考tickDirection |
'positive' | 'negative' |
positive |
|
| labelSpacing | 刻度值到其对应刻度的间距 | number |
0 | |
| labelFill | 刻度标签文字填充色 | string | (datum, index, data)=>string |
- | |
| labelFillOpacity | 刻度标签文字填充透明度 | number | (datum, index, data)=>number |
- | |
| labelStroke | 刻度标签文字描边颜色 | string | (datum, index, data)=>string |
- | |
| labelStrokeOpacity | 刻度标签文字描边透明度 | number | (datum, index, data)=>number |
- | |
| labelLineWidth | 刻度标签文字描边宽度 | number |(datum, index, data)=>number |
- | |
| labelLineDash | 刻度标签文字描边虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | [number,number] | (datum, index, data)=>[number, number] |
- | |
| labelOpacity | 刻度标签文字整体透明度 | number | (datum, index, data)=>number |
- | |
| labelShadowColor | 刻度标签文字阴影颜色 | string | (datum, index, data)=>string |
- | |
| labelShadowBlur | 刻度标签文字阴影高斯模糊系数 | number | (datum, index, data)=>number |
- | |
| labelShadowOffsetX | 刻度标签文字阴影水平偏移量 | number | (datum, index, data)=>number |
- | |
| labelShadowOffsetY | 刻度标签文字阴影垂直偏移量 | number | (datum, index, data)=>number |
- | |
| labelCursor | 刻度标签文字鼠标样式 | string | (datum, index, data)=>string |
default |
|
| labelDx | 刻度标签文字水平偏移量 | number | (datum, index, data)=>number |
0 | |
| labelDy | 刻度标签文字垂直偏移量 | number | (datum, index, data)=>number |
0 |
labelFormatter
labelFormatter 视觉通道用于调整标签的格式。
基本用法
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 500,
height: 300,
data: [
{ id: 1, 月份: '03', 销售额: 200 },
{ id: 3, 月份: '04', 销售额: 300 },
{ id: 4, 月份: '05', 销售额: 400 },
{ id: 5, 月份: '06', 销售额: 500 },
{ id: 6, 月份: '07', 销售额: 600 },
{ id: 7, 月份: '08', 销售额: 700 },
],
encode: { x: '月份', y: '销售额', color: '月份' },
axis: {
y: {
title: '销售额',
},
x: {
title: '月份',
labelFontSize: 12,
labelFormatter: (d) => `2025-${d}`, // 刻度值线格式化
},
},
});
chart.render();
D3 Format 格式化字符串
G2 支持使用 d3-format 兼容的格式化字符串,这是一套强大且标准化的数值格式化规范。
格式化语法
D3 format 的基本语法:[[fill]align][sign][symbol][0][width][,][.precision][~][type]
- fill: 填充字符,默认是空格
- align: 对齐方式(
<左对齐,^居中,>右对齐,=数字右对齐) - sign: 符号显示(
+总是显示符号,-只显示负号,(负数用括号) - symbol: 前缀符号(
#进制前缀,$货币符号) - 0: 零填充
- width: 最小宽度
- ,: 千分位分隔符
- precision: 精度
- ~: 去除尾随零
- type: 格式类型
常用格式化类型
| 类型 | 描述 | 示例 |
|---|---|---|
d |
整数 | 42 |
f |
固定小数位 | 42.00 |
e |
科学计数法 | 4.2e+1 |
s |
SI 前缀 | 42k, 1.5M |
% |
百分比 | 42% |
$ |
货币格式 | $42.00 |
r |
有效数字 | 42.0 |
g |
通用格式 | 42 |
D3-format 完整格式化参考
// 常用数值格式
'.2f'; // 固定2位小数:23.45
'.0f'; // 整数:23
'.1%'; // 百分比:23.4%
',.0f'; // 千分位:1,234,567
// SI前缀格式(推荐用于大数值)
's'; // SI前缀:1.2M, 3.4k
'.1s'; // 1位小数SI:1.2M, 3.4k
'~s'; // 去尾随零SI:1.2M, 3k
'.0s'; // 整数SI:1M, 3k
// 货币格式
'$,.2f'; // 美元:$1,234.56
'$.2s'; // 美元SI:$1.23M
// 科学计数法
'.2e'; // 科学计数:1.23e+6
'.2g'; // 通用格式:1.2e+6 或 1234
// 进制格式
'd'; // 十进制整数:1234
'x'; // 十六进制:4d2
'o'; // 八进制:2322
'b'; // 二进制:10011010010
格式化示例
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 600,
height: 400,
data: [
{ 类型: '收入', 值: 1234567.89 },
{ 类型: '支出', 值: -987654.32 },
{ 类型: '利润', 值: 246913.57 },
{ 类型: '投资', 值: 5000000 },
],
encode: { x: '类型', y: '值', color: '类型' },
axis: {
y: {
title: '金额(元)',
// 使用 d3-format 格式化字符串
labelFormatter: ',.2s', // 千分位 + 两位有效数字 + SI前缀
},
x: {
title: '业务类型',
},
},
});
chart.render();
自定义格式化函数
除了使用 d3-format 字符串,你也可以传入自定义函数:
axis: {
y: {
labelFormatter: (value, index, data) => {
// 自定义逻辑
if (value >= 1000000) {
return (value / 1000000).toFixed(1) + 'M';
} else if (value >= 1000) {
return (value / 1000).toFixed(1) + 'K';
}
return value.toString();
},
},
}
labelTransform
labelTransform 是 G 提供的在局部坐标系下进行变换的快捷方式,同时与 CSS Transform 保持一致。
下面的例子展示了如何配置 labelTransform 来让 x 轴刻度值旋转 90 度。
({
axis: {
x: {
title: 'x 轴标题',
labelFontSize: 12,
labelFormatter: (d) => `2025-${d}`,
labelTransform: 'rotate(90)',
},
},
});
transform
transform 为了避免刻度标签重叠或超出显示范围,系统提供了多种优化方式,包括缩略、旋转、隐藏和换行。
这些功能可通过两种方式配置:
transform数组(多策略组合)labelAutoXXX系列属性(单策略快捷配置)推荐
两者的核心功能完全一致,区别在于使用场景和配置方式。
transform数组(多策略组合)
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 500,
height: 500,
data: [
{ id: 1, label: 'x 轴刻度值标签1', value: 200 },
{ id: 3, label: 'x 轴刻度值标签2', value: 300 },
{ id: 4, label: 'x 轴刻度值标签3', value: 400 },
{ id: 5, label: 'x 轴刻度值标签4', value: 500 },
{ id: 6, label: 'x 轴刻度值标签5', value: 600 },
{ id: 7, label: 'x 轴刻度值标签6', value: 700 },
{ id: 8, label: 'x 轴刻度值标签999', value: 800 },
],
encode: { x: 'label', y: 'value' },
axis: {
y: {
title: 'y 轴标题',
},
x: {
title: 'x 轴标题',
labelFontSize: 12,
labelFormatter: (d) => `2025-${d}`,
size: 100,
transform: [
// 缩略
{
type: 'ellipsis',
suffix: '..', // 缩略符(默认...)
minLength: 8, // 少于8字符不缩略
maxLength: 12, // 超过12字符强制缩略
},
// 换行
{
type: 'wrap',
wordWrapWidth: 80, // 单行最大宽度为 80px
maxLines: 2, // 最多显示两行
recoverWhenFailed: true, // 如果换行失败恢复到默认布局
},
// 旋转
{
type: 'rotate',
optionalAngles: [0, 45, 90], // 尝试旋转 0 度、45 度、90 度
recoverWhenFailed: true, // 如果旋转后无法解决问题,恢复到默认角度
},
// 隐藏
{
type: 'hide',
keepHeader: true, // 保留第一个刻度值
keepTail: true, // 保留最后一个刻度值
},
],
},
},
});
chart.render();
labelTransform 是 G 提供的在局部坐标系下进行变换的快捷方式,同时与 CSS Transform 保持一致。
下面的例子展示了如何配置 labelTransform 来让 x 轴刻度值旋转 90 度。
({
axis: {
x: {
title: 'x 轴标题',
labelFontSize: 12,
labelFormatter: (d) => `2025-${d}`,
labelTransform: 'rotate(90)',
},
},
});
- 使用
labelAutoHide、labelAutoRotate、labelAutoEllipsis、labelAutoWrap、 属性(需设置size)
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 500,
height: 500,
data: [
{ id: 1, label: 'x 轴刻度值标签1', value: 200 },
{ id: 3, label: 'x 轴刻度值标签2', value: 300 },
{ id: 4, label: 'x 轴刻度值标签3', value: 400 },
{ id: 5, label: 'x 轴刻度值标签4', value: 500 },
{ id: 6, label: 'x 轴刻度值标签5', value: 600 },
{ id: 7, label: 'x 轴刻度值标签6', value: 700 },
{ id: 8, label: 'x 轴刻度值标签999', value: 800 },
],
encode: { x: 'label', y: 'value' },
axis: {
y: {
title: 'y 轴标题',
},
x: {
title: 'x 轴标题',
labelFontSize: 12,
labelFormatter: (d) => `2025-${d}`,
size: 100, // 必须设置 size
labelAutoEllipsis: {
suffix: '..',
minLength: 8,
maxLength: 12,
},
labelAutoWrap: {
wordWrapWidth: 80,
maxLines: 2,
recoverWhenFailed: true,
},
labelAutoRotate: {
optionalAngles: [0, 45, 90], // 尝试旋转 0 度、45 度、90 度
recoverWhenFailed: true, // 如果旋转后无法解决问题,恢复到默认角度
},
labelAutoHide: {
keepHeader: true, // 保留第一个刻度值
keepTail: true, // 保留最后一个刻度值
},
},
},
});
chart.render();
export interface Transform {
/** 避免刻度值重叠时的额外边距 */
margin?: number[];
}
export interface EllipsisOverlapCfg extends Transform {
type: 'ellipsis';
/** 缩略替换字符,默认为 ... */
suffix?: string;
/** 文本短于该长度时不再缩略 */
minLength: string | number;
/** 文本短于该长度时一定会进行缩略 */
maxLength?: string | number;
/** 每次缩略执行步长 */
step?: string | number;
}
export interface RotateOverlapCfg extends Transform {
type: 'rotate';
/** 可选的旋转角度值 */
optionalAngles: number[];
/** 当旋转无法避免重叠时,是否恢复为默认旋转角度 */
recoverWhenFailed?: boolean;
}
export interface HideOverlapCfg extends Transform {
type: 'hide';
/** 保证第一个刻度值不被隐藏 */
keepHeader?: boolean;
/** 保证最后一个刻度值不被隐藏 */
keepTail?: boolean;
}
export interface WrapOverlapCfg extends Transform {
type: 'wrap';
/** 单行最大宽度 */
wordWrapWidth?: number;
/** 最大行数 */
maxLines?: number;
recoverWhenFailed?: boolean;
}
grid
在不同坐标系下网格线会具有不同的样式
| 场景标签 | 样式 |
|---|---|
直角坐标系 |
|
极坐标系 |
|
极坐标系 |
|
极坐标系 雷达图 |
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| grid | 是否显示网格线 | boolean |
false | |
| gridFilter | 网格线过滤 | (datum, index, data)=> boolean |
- | |
| gridLength | 网格线长度。一般情况下,不需要用户配置。 | number | (datum, index, data)=> number |
0 | |
| gridAreaFill | 网格线区域填充色 | string | string[]| (datum, index, data)=> string |
- | |
| gridStroke | 网格线描边颜色 | string | (datum, index, data)=> string |
- | |
| gridStrokeOpacity | 网格线描边透明度 | number | (datum, index, data)=> number |
- | |
| gridLineWidth | 网格线描边宽度 | number | (datum, index, data)=> number |
- | |
| gridLineDash | 网格线描边虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | [number,number] | (datum, index, data)=> [number,number] |
- | |
| gridOpacity | 网格线整体透明度 | number | (datum, index, data)=> number |
- | |
| gridShadowColor | 网格线阴影颜色 | string | (datum, index, data)=> string |
- | |
| gridShadowBlur | 网格线阴影高斯模糊系数 | number | (datum, index, data)=> number |
- | |
| gridShadowOffsetX | 网格线阴影水平偏移量 | number | (datum, index, data)=> number |
- | |
| gridShadowOffsetY | 网格线阴影垂直偏移量 | number | (datum, index, data)=> number |
- | |
| gridCursor | 网格线鼠标样式 | string | (datum, index, data)=> string |
default |
网格线配置示例
基础网格线
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 600,
height: 400,
data: [
{ 月份: '1月', 销售额: 2000 },
{ 月份: '2月', 销售额: 1500 },
{ 月份: '3月', 销售额: 3000 },
{ 月份: '4月', 销售额: 2500 },
{ 月份: '5月', 销售额: 4000 },
{ 月份: '6月', 销售额: 3500 },
],
encode: { x: '月份', y: '销售额', color: '月份' },
axis: {
y: {
title: '销售额(万元)',
// 显示基础网格线
grid: true,
gridStroke: '#e6e6e6', // 网格线颜色
gridLineWidth: 2, // 网格线宽度
gridStrokeOpacity: 0.7, // 网格线透明度
gridLineDash: [0, 0],
},
x: {
title: '月份',
// x 轴通常不需要网格线
grid: false,
},
},
});
chart.render();
虚线网格线
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'line',
width: 600,
height: 400,
data: [
{ 时间: '9:00', 温度: 18 },
{ 时间: '12:00', 温度: 24 },
{ 时间: '15:00', 温度: 28 },
{ 时间: '18:00', 温度: 22 },
{ 时间: '21:00', 温度: 20 },
],
encode: { x: '时间', y: '温度' },
style: { stroke: '#5B8FF9', lineWidth: 2 },
axis: {
y: {
title: '温度(°C)',
grid: true,
gridStroke: '#d9d9d9',
gridLineDash: [4, 4], // 虚线配置:4px 实线,4px 空白
gridStrokeOpacity: 0.8,
},
x: {
title: '时间',
grid: true,
gridStroke: '#f0f0f0',
gridLineDash: [2, 2], // 更细的虚线
gridStrokeOpacity: 0.6,
},
},
});
chart.render();
带背景填充的网格线
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 600,
height: 400,
data: [
{ 产品: 'A产品', 销量: 120 },
{ 产品: 'B产品', 销量: 200 },
{ 产品: 'C产品', 销量: 150 },
{ 产品: 'D产品', 销量: 300 },
{ 产品: 'E产品', 销量: 250 },
],
encode: { x: '产品', y: '销量', color: '产品' },
axis: {
y: {
title: '销量(件)',
grid: true,
gridStroke: '#e8e8e8',
gridLineWidth: 1,
gridAreaFill: ['#fafafa', '#ffffff'], // 交替填充颜色
gridOpacity: 0.9,
},
x: {
title: '产品类型',
grid: false,
},
},
});
chart.render();
自定义网格线过滤
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'area',
width: 600,
height: 400,
data: [
{ 季度: 'Q1', 收入: 100, 支出: 80 },
{ 季度: 'Q2', 收入: 120, 支出: 90 },
{ 季度: 'Q3', 收入: 150, 支出: 110 },
{ 季度: 'Q4', 收入: 180, 支出: 140 },
],
encode: { x: '季度', y: '收入' },
style: { fillOpacity: 0.6 },
axis: {
y: {
title: '金额(万元)',
grid: true,
gridStroke: '#cccccc',
gridLineWidth: 1,
// 只显示偶数索引的网格线
gridFilter: (datum, index) => index % 2 === 0,
gridStrokeOpacity: 0.8,
},
x: {
title: '季度',
grid: true,
gridStroke: '#e6e6e6',
gridLineDash: [3, 3],
gridStrokeOpacity: 0.5,
},
},
});
chart.render();
breaks
{
breaks: [
{
start: 5000,
end: 50000,
gap: '3%',
}
]
}
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| start | 断轴开始值 | number |
- | |
| end | 断轴结束值 | number |
- | |
| gap | 断轴主轴方向区间占比,支持 0 ~ 1 和百分比两种类型 | number | string |
- | |
| vertices | 断轴起伏顶点数 | number |
50 | |
| verticeOffset | 断轴振幅 | number |
3 | |
| compress | 断轴压缩方式,middle: 居中压缩,start: 起始值附近压缩,end:结束值附近压缩 |
middle | start | end |
middle | |
| stroke | 断轴描边色 | string |
#fff |
|
| fill | 断轴填充色 | string |
#aaa |
|
| lineDash | 断轴描边虚线样式 | string |
2 2 |
更多配置参考 canvas 基本绘图属性。
animate
支持设置更新时的动画效果
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| animate | 是否开启动画 | boolean | EffectTiming |
- |
EffectTiming 支持配置的属性如下:
| 属性 | 描述 | 类型 | 默认值 | 必须 |
|---|---|---|---|---|
| delay | 延迟执行时间 (ms) | number |
- | |
| duration | 动画持续时间 (ms) | number |
- | |
| easing | 动画的缓动函数 | Easing |
- | |
| endDelay | 延迟执行时间 (ms) | number |
- | |
| fill | 动画处于非运行状态时的展示效果 | Fill |
- |
事件
坐标轴(axis)组件本身没有专属的事件类型。
示例
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval', // 设置图表类型为柱状图
marginTop: 40, // 设置图表的上边距像素
data: [
{ id: 1, label: 'x 轴刻度值标签1', value: 200 },
{ id: 3, label: 'x 轴刻度值标签2', value: 300 },
{ id: 4, label: 'x 轴刻度值标签3', value: 400 },
{ id: 5, label: 'x 轴刻度值标签4', value: 500 },
{ id: 6, label: 'x 轴刻度值标签5', value: 600 },
{ id: 7, label: 'x 轴刻度值标签6', value: 700 },
],
// 设置数据编码
encode: { x: 'label', y: 'value' },
axis: {
// 配置 x 轴
x: {
position: 'bottom', // 设置坐标轴的位置
// 这部分是轴标题的配置
title: 'x 轴标题', // 轴标题内容
titleFontWeight: 500, // 标题文字字体粗细
titleSpacing: 15, // 标题到坐标轴的距离
titlePosition: 'bottom', // 标题相对坐标轴的位置
titleFontSize: 14, // 标题文字大小
titleFill: '#333', // 标题文字填充色
// 这部分是网格线的配置
grid: true, // 是否显示网格线
gridLineWidth: 2, // 网格线描边宽度
gridStroke: '#f0f0f0', // 网格线描边颜色
gridStrokeOpacity: 0.8, // 网格线描边透明度
gridLineDash: [3, 3], // 网格线描边虚线配置
gridOpacity: 0.9, // 网格线整体透明度
gridAreaFill: ['#fafafa', '#ffffff'], // 网格线区域填充色
gridFilter: (_, i) => i % 2 === 0, // 网格线过滤
// 这部分是轴线的配置
line: true, // 是否显示轴线
lineLineWidth: 5, // 轴线描边宽度
lineStroke: '#f50', // 轴线描边颜色
arrow: true, // 是否显示箭头
lineArrowOffset: 8, // 箭头偏移长度
// 这部分是轴刻度的配置
tick: true, // 是否显示刻度
tickCount: 8, // 设置推荐生成的刻度数量
tickLineWidth: 5, // 刻度线描边宽度
tickLength: 10, // 刻度线长度
tickStroke: '#3366ff', // 刻度线描边颜色
tickDirection: 'positive', // 刻度朝向
tickOpacity: 0.9, // 刻度线整体透明度
// 这部分是轴刻度值标签的配置
label: true, // 是否显示刻度值
labelFontSize: 12, // 刻度标签文字大小
labelFill: '#009900', // 刻度标签文字填充色
labelFontWeight: 500, // 刻度标签文字字体粗细
labelFontFamily: 'Arial', // 刻度标签文字字体
labelTextAlign: 'center', // 刻度标签文字水平对齐方式
labelTextBaseline: 'middle', // 刻度标签文字垂直基线
labelAlign: 'horizontal', // 刻度值对齐方式
labelDirection: 'positive', // 刻度值位于轴线的位置
labelSpacing: 5, // 刻度值到其对应刻度的间距
labelFillOpacity: 0.9, // 刻度标签文字填充透明度
labelStroke: '#ffffff', // 刻度标签文字描边颜色
labelStrokeOpacity: 0.5, // 刻度标签文字描边透明度
labelLineWidth: 1, // 刻度标签文字描边宽度
labelOpacity: 1, // 刻度标签文字整体透明度
labelDx: 2, // 刻度标签文字水平偏移量
labelDy: 0, // 刻度标签文字垂直偏移量
labelCursor: 'pointer', // 刻度标签文字鼠标样式
},
// 配置 y 轴
y: {
position: 'left', // 设置坐标轴的位置
// 这部分是轴标题的配置
title: 'y 轴标题', // 轴标题内容
titleFontWeight: 500, // 标题文字字体粗细
titleSpacing: 20, // 标题到坐标轴的距离
titlePosition: 'left', // 标题相对坐标轴的位置
titleFontSize: 14, // 标题文字大小
titleFill: '#333', // 标题文字填充色
// 这部分是网格线的配置
grid: true, // 是否显示网格线
gridLineWidth: 2, // 网格线描边宽度
gridStroke: '#e6e6e6', // 网格线描边颜色
gridStrokeOpacity: 0.7, // 网格线描边透明度
gridLineDash: [5, 5], // 网格线描边虚线配置
gridOpacity: 0.8, // 网格线整体透明度
// 这部分是轴线的配置
line: true, // 是否显示轴线
lineLineWidth: 5, // 轴线描边宽度
lineStroke: '#f50', // 轴线描边颜色
arrow: false, // 是否显示箭头
lineOpacity: 1, // 轴线整体透明度
// 这部分是轴刻度的配置
tick: true, // 是否显示刻度
tickCount: 8, // 设置推荐生成的刻度数量
tickLineWidth: 5, // 刻度线描边宽度
tickLength: 10, // 刻度线长度
tickStroke: '#3366ff', // 刻度线描边颜色
tickDirection: 'negative', // 刻度朝向
tickStrokeOpacity: 0.8, // 刻度线描边透明度
// 这部分是轴刻度值标签的配置
label: true, // 是否显示刻度值
labelFontSize: 12, // 刻度标签文字大小
labelFill: '#009900', // 刻度标签文字填充色
labelFontWeight: 500, // 刻度标签文字字体粗细
labelFontFamily: 'Helvetica', // 刻度标签文字字体
labelTextAlign: 'right', // 刻度标签文字水平对齐方式
labelTextBaseline: 'middle', // 刻度标签文字垂直基线
labelAlign: 'perpendicular', // 刻度值对齐方式
labelSpacing: 8, // 刻度值到其对应刻度的间距
labelLineHeight: 1.2, // 刻度标签文字行高
labelFormatter: (d) => `${d}万`, // 刻度值格式化
},
},
});
chart.render();
更多的案例,可以查看 图表示例 - 坐标轴 页面。
刻度值格式化示例
示例 1:金融股票图表格式化
金融数据需要精确的价格显示和简洁的时间轴,常用于股票价格、基金净值等场景:
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'line',
width: 600,
height: 400,
data: [
{ date: '2024-01-01', price: 23.45, volume: 120000 },
{ date: '2024-01-02', price: 24.12, volume: 150000 },
{ date: '2024-01-03', price: 23.89, volume: 98000 },
{ date: '2024-01-04', price: 25.3, volume: 200000 },
{ date: '2024-01-05', price: 24.78, volume: 175000 },
{ date: '2024-01-08', price: 26.15, volume: 220000 },
],
encode: { x: 'date', y: 'price' },
style: { stroke: '#ff6b35', lineWidth: 2 },
axis: {
x: {
title: '交易日期',
// 时间格式化需要自定义函数
labelFormatter: (d) => {
const date = new Date(d);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${month}-${day}`;
},
labelFontSize: 11,
},
y: {
title: '股价(¥)',
// 使用 d3-format:固定2位小数
labelFormatter: '.2f', // 相当于 d.toFixed(2)
grid: true,
gridStroke: '#f5f5f5',
tickCount: 6,
},
},
});
chart.render();
D3-format vs 自定义函数对比:
// ✅ D3-format(推荐用于标准数值格式)
labelFormatter: '.2f'; // 固定2位小数:23.45
labelFormatter: '.1%'; // 百分比:23.4%
labelFormatter: '$,.2f'; // 货币格式:$1,234.56
// ✅ 自定义函数(复杂逻辑、特殊需求)
labelFormatter: (d) => `¥${d.toFixed(2)}`; // 人民币符号
labelFormatter: (d) => {
/* 复杂业务逻辑 */
};
示例 2:电商销售数据智能单位转换
销售数据通常涉及大金额,需要自动转换为合适的单位显示。对比 d3-format 和自定义函数的应用场景:
使用 D3-format(国际化标准格式)
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 600,
height: 400,
data: [
{ category: '电子产品', sales: 8500000 },
{ category: '服装鞋帽', sales: 12300000 },
{ category: '家居用品', sales: 6800000 },
{ category: '美妆护肤', sales: 15600000 },
{ category: '食品饮料', sales: 9200000 },
],
encode: { x: 'category', y: 'sales', color: 'category' },
axis: {
x: {
title: '商品类别',
labelFontSize: 12,
},
y: {
title: '销售额',
// 使用 d3-format:SI前缀格式,自动K/M单位
labelFormatter: '~s', // 8.5M, 12.3M, 6.8M, 15.6M, 9.2M
grid: true,
gridStroke: '#e8e8e8',
tickCount: 5,
},
},
});
chart.render();
使用自定义函数(中文格式)
import { Chart } from '@antv/g2';
const chart2 = new Chart({
container: 'container',
});
chart2.options({
type: 'interval',
width: 600,
height: 400,
data: [
{ category: '电子产品', sales: 8500000 },
{ category: '服装鞋帽', sales: 12300000 },
{ category: '家居用品', sales: 6800000 },
{ category: '美妆护肤', sales: 15600000 },
{ category: '食品饮料', sales: 9200000 },
],
encode: { x: 'category', y: 'sales', color: 'category' },
axis: {
x: {
title: '商品类别',
labelFontSize: 12,
},
y: {
title: '销售额',
// 自定义中文单位格式
labelFormatter: (value) => {
if (value >= 100000000) {
return `${(value / 100000000).toFixed(1)}亿`;
} else if (value >= 10000) {
return `${(value / 10000).toFixed(0)}万`;
} else {
return value.toString();
}
},
grid: true,
gridStroke: '#e8e8e8',
tickCount: 5,
},
},
});
chart2.render();
示例 3:用户增长数据国际化格式
用户数据通常使用国际标准的 K、M 单位,D3-format 提供了简洁的实现方式:
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'area',
width: 600,
height: 400,
data: [
{ quarter: '2023 Q1', users: 125000 },
{ quarter: '2023 Q2', users: 158000 },
{ quarter: '2023 Q3', users: 234000 },
{ quarter: '2023 Q4', users: 312000 },
{ quarter: '2024 Q1', users: 425000 },
{ quarter: '2024 Q2', users: 586000 },
],
encode: { x: 'quarter', y: 'users' },
style: {
fill: 'linear-gradient(270deg, #667eea 0%, #764ba2 100%)',
fillOpacity: 0.6,
},
axis: {
x: {
title: '季度',
// 时间字符串处理需要自定义函数
labelFormatter: (d) => {
return d.replace('2023 ', '').replace('2024 ', '24');
},
labelFontSize: 11,
},
y: {
title: '用户数量',
// 使用 d3-format:国际标准K/M格式
labelFormatter: '.0s', // 125k, 158k, 234k, 312k, 425k, 586k
grid: true,
gridStroke: '#f0f0f0',
gridLineDash: [3, 3],
tickCount: 6,
},
},
});
chart.render();
长刻度值标签处理方案详解
在实际业务场景中,经常会遇到坐标轴刻度值过长导致重叠、超出显示范围的问题。G2 提供了四种核心解决方案,各有其最佳适用场景:
方案选择指南
| 方案 | 适用场景 | 优点 | 缺点 | 推荐业务场景 |
|---|---|---|---|---|
| 缩略(ellipsis) | 文本长度差异大、用户可通过其他方式获取完整信息 | 保持整洁、不改变布局 | 信息丢失 | 产品名称、用户 ID、文件名 |
| 旋转(rotate) | 文本长度相近、空间充足 | 保留完整信息、视觉清晰 | 需要更多垂直空间、阅读体验稍差 | 日期时间、地区名称、分类标签 |
| 换行(wrap) | 中等长度文本、有充足垂直空间 | 保留完整信息、易阅读 | 占用更多垂直空间 | 产品描述、部门名称 |
| 隐藏(hide) | 标签密度过高、主要关注趋势 | 解决重叠、保持关键节点 | 信息缺失 | 时间序列、大数据量可视化 |
示例 1:电商产品销量排行榜(缩略方案)
电商平台需要展示热销产品排行,产品名称长短不一,从“iPhone”到“Apple iPhone 15 Pro Max 1TB 深空黑色”
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 650, // 适当减小宽度以触发缩略
data: [
{ product: 'iPhone 15 Pro Max', sales: 2500 },
{ product: 'Samsung Galaxy S24 Ultra 512GB 幻夜黑色版本', sales: 1800 },
{
product: 'Apple MacBook Pro 16英寸 M3 Max芯片 1TB 深空灰色',
sales: 1200,
},
{ product: 'Sony WH-1000XM5 无线降噪头戴式耳机 午夜黑色', sales: 3200 },
{ product: '小米14 Ultra 摄影套装版 16GB+1TB 白色限量版', sales: 2100 },
{ product: 'iPad Pro 12.9英寸 M2芯片 1TB WiFi版 深空灰色', sales: 1600 },
{ product: 'MacBook Air 15英寸 M2芯片 512GB 星光色', sales: 1400 },
{ product: 'AirPods Pro 第二代 主动降噪无线耳机', sales: 2800 },
],
encode: { x: 'product', y: 'sales', color: 'product' },
axis: {
x: {
title: '热销产品',
labelFontSize: 11,
// 缩略方案:适合产品名称场景
size: 100,
transform: [
{
type: 'ellipsis',
suffix: '...', // 缩略符号
},
],
},
y: {
title: '销量(台)',
labelFormatter: ',.0f', // 千分位格式
grid: true,
gridStroke: '#f0f0f0',
},
},
tooltip: {
// 悬浮时显示完整产品名称
title: (d) => d.product,
items: [{ field: 'sales', name: '销量', formatter: ',.0f' }],
},
});
chart.render();
特点
- 保持图表整洁,避免产品名称重叠
- 用户可通过 tooltip 查看完整产品名称
- 适合产品名称长短差异很大的场景
示例 2:用户活跃度时间分析(旋转方案)
需要展示每小时用户活跃度,时间标签需要显示“YYYY-MM-DD HH:mm”格式
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'line',
width: 600, // 减小宽度以触发旋转
marginBottom: 30, // 预留旋转的空间
data: [
{ time: '2024-01-15 08:00', activeUsers: 1200 },
{ time: '2024-01-15 09:00', activeUsers: 1800 },
{ time: '2024-01-15 10:00', activeUsers: 2800 },
{ time: '2024-01-15 11:00', activeUsers: 3200 },
{ time: '2024-01-15 12:00', activeUsers: 4500 },
{ time: '2024-01-15 13:00', activeUsers: 4200 },
{ time: '2024-01-15 14:00', activeUsers: 3200 },
{ time: '2024-01-15 15:00', activeUsers: 3600 },
{ time: '2024-01-15 16:00', activeUsers: 3800 },
{ time: '2024-01-15 17:00', activeUsers: 4800 },
{ time: '2024-01-15 18:00', activeUsers: 5200 },
{ time: '2024-01-15 19:00', activeUsers: 4800 },
{ time: '2024-01-15 20:00', activeUsers: 4100 },
{ time: '2024-01-15 21:00', activeUsers: 3500 },
{ time: '2024-01-15 22:00', activeUsers: 2600 },
{ time: '2024-01-15 23:00', activeUsers: 1900 },
],
encode: { x: 'time', y: 'activeUsers' },
style: { stroke: '#5B8FF9', lineWidth: 2 },
axis: {
x: {
title: '时间',
labelFontSize: 10,
// 旋转方案:适合时间标签
size: 100,
transform: [
{
type: 'rotate',
optionalAngles: [0, 30, 45, 60, 90], // 尝试多个角度
recoverWhenFailed: true, // 失败时恢复默认角度
},
],
},
y: {
title: '活跃用户数',
labelFormatter: ',.0f',
grid: true,
gridStroke: '#e6e6e6',
gridLineDash: [3, 3],
},
},
});
chart.render();
特点
- 保留完整时间信息,便于精确分析
- 自动选择最佳旋转角度避免重叠
- 适合时间序列、地区名称等固定格式标签
示例 3:部门绩效评估(换行方案)
展示各部门季度绩效,部门名称中等长度,需要完整显示
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 800,
data: [
{ department: '市场营销部门', score: 85 },
{ department: '产品研发中心', score: 92 },
{ department: '客户服务部', score: 78 },
{ department: '人力资源管理部', score: 81 },
{ department: '财务审计部门', score: 89 },
{ department: '战略规划中心', score: 87 },
],
encode: { x: 'department', y: 'score', color: 'department' },
axis: {
x: {
title: '部门',
labelFontSize: 12,
// 换行方案:适合部门名称
size: 100,
transform: [
{
type: 'wrap',
wordWrapWidth: 60, // 单行最大60像素
maxLines: 2, // 最多显示2行
recoverWhenFailed: true, // 换行失败时恢复默认布局
},
],
},
y: {
title: '绩效得分',
grid: true,
gridStroke: '#f5f5f5',
domain: [0, 100],
},
},
});
chart.render();
特点
- 保留完整部门名称,便于准确识别
- 换行布局保持良好的可读性
- 适合中等长度的标签文本
示例 4:股票价格大数据趋势(隐藏方案)
展示连续交易日股价趋势,数据点密集,重点关注趋势而非具体日期
import { Chart } from '@antv/g2';
// 生成模拟股价数据
const generateStockData = () => {
const data = [];
let price = 100;
const startDate = new Date('2024-01-01');
for (let i = 0; i < 90; i++) {
// 增加到90个数据点
const currentDate = new Date(startDate);
currentDate.setDate(startDate.getDate() + i);
// 随机价格波动
price += (Math.random() - 0.5) * 4;
price = Math.max(80, Math.min(120, price)); // 限制在80-120范围
data.push({
date: currentDate.toISOString().split('T')[0],
price: Math.round(price * 100) / 100,
});
}
return data;
};
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'line',
width: 700, // 减小宽度增加密度
marginRight: 30, // 预留右侧保留最后一个刻度值的宽度
data: generateStockData(),
encode: { x: 'date', y: 'price' },
style: { stroke: '#722ed1', lineWidth: 1.5 },
axis: {
x: {
title: '交易日期',
labelFontSize: 9,
// 隐藏方案:适合密集数据
size: 100,
transform: [
{
type: 'hide',
keepHeader: true, // 保留第一个日期
keepTail: true, // 保留最后一个日期
},
],
},
y: {
title: '股价(元)',
labelFormatter: '.2f',
grid: true,
gridStroke: '#f0f0f0',
gridLineDash: [2, 2],
},
},
});
chart.render();
特点
- 解决密集数据点的标签重叠问题
- 保留首尾关键时间节点
- 重点突出数据趋势而非具体数值
示例 5 快捷配置( 推荐 )
对于简单场景,推荐使用 labelAutoXXX 系列属性:
import { Chart } from '@antv/g2';
const chart = new Chart({
container: 'container',
});
chart.options({
type: 'interval',
width: 650, // 减小宽度以触发变换效果
marginBottom: 50, // 为多重变换预留空间
marginRight: 100,
data: [
{ region: '北京市朝阳区CBD核心商务区金融中心', revenue: 8500 },
{ region: '上海市浦东新区陆家嘴金融贸易区总部基地', revenue: 9200 },
{ region: '深圳市南山区高新技术产业园区', revenue: 7800 },
{ region: '广州市天河区珠江新城国际商务中心', revenue: 6900 },
{ region: '杭州市西湖区互联网创新产业园区', revenue: 5600 },
{ region: '成都市高新区软件产业园科技创新区', revenue: 4800 },
{ region: '苏州市工业园区生物纳米科技园', revenue: 5200 },
{ region: '南京市江宁区未来科技城创新基地', revenue: 4500 },
],
encode: { x: 'region', y: 'revenue', color: 'region' },
axis: {
x: {
title: '业务区域',
labelFontSize: 10,
size: 100,
// 快捷配置,等价于 transform 数组
labelAutoEllipsis: true, // 启用自动缩略
labelAutoRotate: true, // 启用自动旋转
labelAutoHide: true, // 启用自动隐藏
labelAutoWrap: true, // 启用自动换行
},
y: {
title: '营收(万元)',
labelFormatter: ',.0f',
grid: true,
gridStroke: '#e8e8e8',
},
},
});
chart.render();