Loading...
In G2, Data Labels are one of the means to add annotations to charts, providing content annotation for the current group of data. They include elements such as data points, connector lines, and text values, which are selected based on different chart types. Through concise text descriptions, they reduce misunderstandings, make charts easier to interpret, and emphasize key data or trends, guiding attention to important information.
Includes connector lines and text value elements, which are selected based on different chart types.
Among them, pie charts, donut charts, rose charts, etc., can use connector line elements to connect label text elements and mark graphics.
chart.options({type: 'interval',labels: [{ text: 'genre' }, // Specify the bound field{text: 'sold', // Specify the bound fieldfill: '#fff', // Specify style},],});
You can configure labelTransform
at the view
level to declare label transformations
// First methodchart.labelTransform({ type: 'overlapHide' }).labelTransform({ type: 'contrastReverse' });// Second methodchart.labelTransform([{ type: 'overlapHide' }, { type: 'contrastReverse' }]);
({type: 'view',labelTransform: [{ type: 'overlapHide' }, { type: 'contrastReverse' }],});
Each mark can have multiple labels. Here's a simple example:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'interval',height: 300,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' },labels: [{ text: 'genre', style: { dy: -15 } },{ text: 'sold', style: { fill: '#fff', dy: 5 } },],});chart.render();
Property | Description | Type | Default Value | Required |
---|---|---|---|---|
dx | Label text horizontal offset, can also be configured through style.dx | number | 0 | |
dy | Label text vertical offset, can also be configured through style.dy | number | 0 | |
offset | Label offset distance, can also be configured through style.offset | number | - | |
text | Label data channel, similar to mark's x channel, corresponds to text element, can use callback to customize string text | string | Function | - | |
innerHTML | Similar to text configuration, when both are configured, text becomes ineffective, can use callback to customize string text or HTMLElement complex html | string | Function | - | |
formatter | Label text formatting | string | Function<string> | - | |
render | Same configuration type as innerHTML | string | Function | - | |
selector | Label selector, can retain or hide labels | selector | {type: 'cartesian' } | |
transform | Label transformation, used to optimize label display, solving label overlap and color visibility issues | transform | - | |
position | Label position relative to graphics, not label direction | position | - | |
style | Label style configuration | style | - | |
background | Whether to show background color | boolean | See background | |
connector | Whether to show connector lines, used in non-Cartesian coordinate systems like pie and donut charts | boolean | See connector |
label
text element content configuration
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'interval',height: 340,insetTop: 20,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' },labels: [{ text: 'sold', style: { dy: -30 } }, // text maps to field sold{ text: ({ genre }) => genre, style: { dy: -20 } }, // text custom return string type{innerHTML: 'genre',dx: 20,dy: 10,style: { fill: '#fff', color: '#333', fontSize: 10 },}, // innerHTML maps to field genre Note: background color might be black sometimes, need to configure fill background color. color is text color, HTMLElement itself can also configure styles{// innerHTML custom return HTMLElement type datainnerHTML: ({ genre, sold }) =>`<div style="padding:0 4px;border-radius: 10px;background: #f5f5f5;border: 2px solid #5ea9e6;font-size: 11px;">${genre}:${sold}</div>`,dx: 10,dy: 50,style: { fill: 'rgba(0,0,0,0)', color: '#333' },},],});chart.render();
You can also try configuring HTMLElement with render
, the parameters differ from innerHTML, but the return is consistent.
type RenderFunc = (text: string, datum: object, index: number, {channel: Record<string, Channel>}) => String | HTMLElement;
label
selector
For marks that correspond to multiple data items per graphic, we can use selector
to choose which marks to retain. Currently supported values are:
first
- First onelast
- Last onefunction
- Custom selectorimport { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,insetLeft: 40,insetRight: 40,data: {type: 'fetch',value: 'https://assets.antv.antgroup.com/g2/indices.json',},encode: { x: (d) => new Date(d.Date), y: 'Close', color: 'Symbol' },scale: { y: { type: 'log' } },axis: { y: { title: '↑ Change in price (%)' } },labels: [{text: ({ Symbol }) => `first ${Symbol}`,selector: 'first', // First in mark graphicsfontSize: 13,style: { fill: 'blue', fontWeight: 600, dx: -50 },},{text: ({ Symbol }) => `last ${Symbol}`,selector: 'last', // Last in mark graphicsfontSize: 13,style: { fill: 'red', fontWeight: 600 },},{text: ({ Symbol }) => `custom ${Symbol}`,selector: (v) => {// Custom filtering, returns all label arrays containing coordinates and other info. Need to return this info, can filter and process.return v.filter(({ bounds }) => {const bound = bounds[0];return (// Filter labels in chart coordinates x:[200,200.5] y:[200,350]bound[0] > 200 &&bound[0] < 200.5 &&bound[1] > 200 &&bound[1] < 350);});},fontSize: 13,style: { fill: '#ac1ce6', fontWeight: 600 },},],});chart.render();
label
transformation
When label display doesn't meet expectations, such as overlapping or unclear colors, we can use Label Transform to optimize label display. It can also be configured directly at the view level to process labels for the entire view.
Currently supported label transformations:
type | Description |
---|---|
overlapDodgeY | Adjusts overlapping labels in the y direction to prevent label overlap |
contrastReverse | When label color has low contrast on graphic background, selects optimal contrast color from specified palette |
overflowHide | Hides labels when they don't fit on the graphic |
overlapHide | Hides overlapping labels, by default keeps the first one and hides subsequent ones |
exceedAdjust | Automatically detects and corrects label overflow, moving labels in reverse direction when they exceed view area |
Different transformation types target different label issues. Understanding the differences between each transform
label transformation is essential.
Targets chaotic situations caused by crowded overlapping labels, adjusting overlapping labels in the y direction.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,insetLeft: 40,insetRight: 40,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv',},encode: {x: (d) => new Date(d.date).getFullYear(),y: 'price',color: 'symbol',},transform: [{ type: 'groupX', y: 'mean' }],labels: [{ text: 'price' }],});chart.render();
overlapDodgeY
Label Transformationimport { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,insetLeft: 40,insetRight: 40,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv',},encode: {x: (d) => new Date(d.date).getFullYear(),y: 'price',color: 'symbol',},transform: [{ type: 'groupX', y: 'mean' }],labels: [{ text: 'price', transform: [{ type: 'overlapDodgeY' }] }],});chart.render();
Property | Description | Type | Default Value | Required |
---|---|---|---|---|
maxIterations | Maximum iterations for position adjustment | number | 10 | |
padding | Expected spacing between labels after adjustment | number | 1 | |
maxError | Maximum error, the difference between actual and expected spacing padding | number | 0.1 |
contrastReverse
selects an optimal contrast color from a specified palette when label color has low color contrast on the graphic background. Targets issues where graphic colors and label
colors are similar making them hard to see, commonly occurring in multi-colored bar charts (mark interval) where colors vary and manual label
color changes are difficult.
When some graphic colors are close to label colors, visibility issues occur.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'interval',height: 300,data: [{ genre: 'Sports', sold: 40 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],encode: { x: 'genre', y: 'sold', color: 'genre' },scale: {color: { range: ['#ff0000', '#f0d2fc', '#2b00ff', '#ff8000', '#064501'] },},labels: [{ text: 'genre' }],});chart.render();
contrastReverse
Label TransformationOptimizes unclear label
colors.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'interval',height: 300,data: [{ genre: 'Sports', sold: 40 },{ genre: 'Strategy', sold: 115 },{ genre: 'Action', sold: 120 },{ genre: 'Shooter', sold: 350 },{ genre: 'Other', sold: 150 },],encode: { x: 'genre', y: 'sold', color: 'genre' },scale: {color: { range: ['#ff0000', '#f0d2fc', '#2b00ff', '#ff8000', '#064501'] },},labels: [{ text: 'genre', transform: [{ type: 'contrastReverse' }] }],});chart.render();
Property | Description | Type | Default Value | Required |
---|---|---|---|---|
threshold | Color contrast threshold between label and background graphic, colors are recommended only when exceeding threshold | Type | 4.5 | |
palette | Alternative color palette in contrast enhancement algorithm | Type | ['#000', '#fff'] |
overflowHide
hides labels when they don't fit on the graphic. The difference from overlapDodgeY
:
overlapDodgeY
targets between label
and label
, handling multiple label
overlaps causing blur.overflowHide
targets between label
and mark
graphics, handling multiple small graphics causing blur.When a chart consists of many small graphics, if each small graphic maps to a label
, overlapping and unclear charts occur. Examples include sunburst charts, treemap charts, etc.
overflowHide
Label TransformationHides label
that exceeds corresponding graphics. Note: Some special charts have built-in label
configuration and can be configured at the view level.
Try this:
overlapHide
hides overlapping labels, by default keeping the first one and hiding subsequent ones. The difference from overlapDodgeY
is that overlapHide
hides rather than moves.
When some graphic colors are close to label colors, visibility issues occur.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,insetLeft: 40,insetRight: 40,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv',},encode: {x: (d) => new Date(d.date).getFullYear(),y: 'price',color: 'symbol',},transform: [{ type: 'groupX', y: 'mean' }],labels: [{ text: 'price' }],});chart.render();
overlapHide
Label TransformationOptimizes unclear label
colors.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,insetLeft: 40,insetRight: 40,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv',},encode: {x: (d) => new Date(d.date).getFullYear(),y: 'price',color: 'symbol',},transform: [{ type: 'groupX', y: 'mean' }],labels: [{ text: 'price', transform: [{ type: 'overlapHide' }] }],});chart.render();
exceedAdjust
automatically detects and corrects label overflow, moving labels in the reverse direction when they exceed the view area.
label
will exceed the chart, and the exceeding part will be cut off.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv',},encode: {x: (d) => new Date(d.date).getFullYear(),y: 'price',color: 'symbol',},transform: [{ type: 'groupX', y: 'mean' }],labels: [{ text: 'price' }],});chart.render();
exceedAdjust
Label TransformationOptimizes direction for label
that exceeds the view.
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'line',autoFit: true,height: 300,data: {type: 'fetch',value:'https://gw.alipayobjects.com/os/bmw-prod/cb99c4ab-e0a3-4c76-9586-fe7fa2ff1a8c.csv',},encode: {x: (d) => new Date(d.date).getFullYear(),y: 'price',color: 'symbol',},transform: [{ type: 'groupX', y: 'mean' }],labels: [{ text: 'price', transform: [{ type: 'exceedAdjust' }] }],});chart.render();
Supports 9 positions: top
, left
, right
, bottom
, top-left
, top-right
, bottom-left
, bottom-right
, inside
.
(() => {const chart = new G2.Chart();chart.options({height: 300,type: 'cell',data: [{ x: 'x-a', y: 'y-a', data: 1 },{ x: 'x-a', y: 'y-b', data: 3 },{ x: 'x-a', y: 'y-c', data: 2 },{ x: 'x-b', y: 'y-a', data: 8 },{ x: 'x-b', y: 'y-b', data: 5 },{ x: 'x-b', y: 'y-c', data: 6 },{ x: 'x-c', y: 'y-a', data: 7 },{ x: 'x-c', y: 'y-b', data: 4 },{ x: 'x-c', y: 'y-c', data: 9 },],legend: false,axis: false,encode: {x: 'x', // Encode x axisy: 'y', // Encode y axiscolor: 'data', // Use data field from data},labels: [{text: 'data',style: { fontSize: 16, stroke: '#fff', lineWidth: 2 },},],style: {inset: 5,lineWidth: 10,},});// Insert Encode-Color selectorconst selectorContainer = document.createElement('div');selectorContainer.textContent = 'position: ';const selector = document.createElement('select');selector.innerHTML = ['top','left','right','bottom','top-left','top-right','bottom-left','bottom-right','inside',].reduce((v, position) => {return `${v}<option value="${position}" ${position === 'top' ? 'selected' : ''}>${position}</option>`;}, '');selector.onchange = (e) => {chart.options({labels: [{text: 'data',position: e.target.value,style: { fontSize: 16, stroke: '#fff', lineWidth: 2 },},],});chart.render(); // Re-render chart};selectorContainer.appendChild(selector);const node = chart.getContainer();node.insertBefore(selectorContainer, node.childNodes[0]);chart.render();return node;})();
Supports 2 types: outside
, inside
. See Pie/Donut Charts.
position | Purpose | Before Use | After Use |
---|---|---|---|
spider | Adjusts labels to align along coordinate axis edges, suitable for polar coordinate systems | ||
surround | Adjusts labels to surround coordinate system in circle, suitable for rose charts in polar coordinate systems |
Additionally, a special area
is provided for area charts, see Special Area Chart Labels. For radial type charts, spider
and surround
types are added.
position | Purpose | Before Use | After Use |
---|---|---|---|
area | Displays area chart labels in the center of area regions with certain rotation angles |
style
label style configuration. Internal processing is done, so styles can be configured directly in configuration options. For specific style configurations, refer to Text Style Configuration, Connector Line Style, Background Style.
({labels: [{style: {fontSize: 20,fontWeight: 600,lineHeight: 30,textAlign: 'center',connectorStroke: '#000',connectorLineWidth: 2,backgroundFill: '#f5f5f5',backgroundRadius: 4,},},],});
Label text style configuration, inherited from G engine's Text
, all its styles are universal.
Property | Description | Type | Default Value | Required |
---|---|---|---|---|
fontSize | Label text font size | number | Function | - | |
fontFamily | Label text font family | string | Function | - | |
fontWeight | Label text font weight | number | Function | - | |
lineHeight | Label text line height | number | Function | - | |
textAlign | Label text horizontal alignment, supports: center | end | left | right | start , default is start | string | Function | start | |
textBaseline | Label text vertical baseline, supports: top | middle | bottom | alphabetic | hanging , default is bottom | string | Function | bottom | |
fill | Label text fill color | string | Function | - | |
fillOpacity | Label text fill opacity | number | Function | - | |
stroke | Label text stroke | string | Function | - | |
strokeOpacity | Label text stroke opacity | number | Function | - | |
lineWidth | Label text stroke width | number | Function | - | |
lineDash | Label text stroke dash configuration, first value is segment length, second is gap distance. Setting lineDash to [0, 0] removes stroke | [number,number] | Function<[number, number]> | - | |
opacity | Label text overall opacity | number | Function | - | |
shadowColor | Label text shadow color | string | Function | - | |
shadowBlur | Label text shadow blur coefficient | number | Function | - | |
shadowOffsetX | Label text shadow horizontal offset | number | Function | - | |
shadowOffsetY | Label text shadow vertical offset | number | Function | - | |
cursor | Mouse cursor style. Same as CSS cursor style, default 'default' | string | Function | default | |
dx | Label text horizontal offset | number | Function | 0 | |
dy | Label text vertical offset | number | Function | 0 |
({labels: [{fill: '#000',fontSize: 20,lineHeight: 30,fontWeight: 600,textAlign: 'center',textBaseline: 'middle',fontFamily: 'sans-serif',opacity: 0.9,cursor: 'pointer',lineDash: [3, 4],lineWidth: 2,stroke: '#fff',strokeOpacity: 0.4,shadowOffsetX: 10,shadowOffsetY: 10,shadowColor: '#000',shadowBlur: 2,},],});
Label connector line style configuration, format: connector${style}
, e.g., connectorStroke
represents connector line color. Requires position spider
, surround
to have connector elements.
Parameter | Description | Type | Default Value | Required |
---|---|---|---|---|
connectorStroke | Connector line color | string | - | |
connectorStrokeOpacity | Connector line opacity | number | - | |
connectorLineWidth | Connector line stroke width | number | - | |
connectorLineDash | Connector line dash configuration, first value is segment length, second is gap distance. Setting lineDash to [0,0] removes stroke | [number,number] | - | |
connectorOpacity | Connector line overall opacity | number | - | |
connectorShadowColor | Connector line shadow color | string | - | |
connectorShadowBlur | Connector line shadow blur coefficient | number | - | |
connectorShadowOffsetX | Connector line shadow horizontal offset | number | - | |
connectorShadowOffsetY | Connector line shadow vertical offset | number | - | |
connectorCursor | Mouse cursor style. Same as CSS cursor style | string | default | |
connectorDistance | Distance between connector line and text | number | - |
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'interval',width: 500,height: 400,data: [{ id: 'c', value: 526 },{ id: 'sass', value: 220 },{ id: 'php', value: 325 },{ id: 'elixir', value: 561 },],encode: { y: 'value', color: 'id' },transform: [{ type: 'stackY' }],coordinate: { type: 'theta', innerRadius: 0.25, outerRadius: 0.8 },legend: false,labels: [{text: 'id',position: 'spider',fontWeight: 'bold',fontSize: 14,textBaseline: 'bottom',textAlign: (d) => (['c', 'sass'].includes(d.id) ? 'end' : 'start'),connectorDistance: 5, // Distance between text and connector lineconnectorStroke: '#0649f2',connectorLineWidth: 1,connectorLineDash: [3, 4],connectorOpacity: 0.8,},],});chart.render();
Label text background box style configuration, format: background${style}
, e.g., backgroundFill
represents background box fill color.
Parameter | Description | Type | Default Value | Required |
---|---|---|---|---|
backgroundFill | Background box fill color | string | - | |
backgroundFillOpacity | Background box fill opacity | number | - | |
backgroundStroke | Background box stroke | string | - | |
backgroundStrokeOpacity | Background box stroke opacity | number | - | |
backgroundLineWidth | Background box stroke width | number | - | |
backgroundLineDash | Background box stroke dash configuration, first value is segment length, second is gap distance. Setting lineDash to [0,0] removes stroke | [number,number] | - | |
backgroundOpacity | Background box overall opacity | number | - | |
backgroundShadowColor | Background box shadow color | string | - | |
backgroundShadowBlur | Background box shadow blur coefficient | number | - | |
backgroundShadowOffsetX | Background box shadow horizontal offset | number | - | |
backgroundShadowOffsetY | Background box shadow vertical offset | number | - | |
backgroundCursor | Mouse cursor style. Same as CSS cursor style | string | default | |
backgroundRadius | Background box border radius | number | - | |
backgroundPadding | Background box inner padding | number[] | - |
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});chart.options({type: 'interval',width: 500,height: 400,data: [{ id: 'c', value: 526 },{ id: 'sass', value: 220 },{ id: 'php', value: 325 },{ id: 'elixir', value: 561 },],encode: { y: 'value', color: 'id' },transform: [{ type: 'stackY' }],coordinate: { type: 'theta', innerRadius: 0.25, outerRadius: 0.8 },legend: false,labels: [{text: 'value',fill: '#0700fa', // Text stylebackground: true, // Background displaybackgroundFill: '#fff',backgroundRadius: 4,backgroundPadding: [10, 10, 10, 10],backgroundOpacity: 0.4,backgroundStroke: '#000',backgroundLineDash: [3, 4],backgroundLineWidth: 1,},],});chart.render();