Heatmap
Categories on both axes; the colorField value sets the cell color on a continuous scale. A gradient legend automatically appears on the right.
By default, heatmap axes are drawn without lines, ticks, or grid — only the category labels remain (bring them back via axes: [{ ..., line: { enabled: true } }]).
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';
export function createOptions(): ChartOptions {
return {
data: getData(),
title: { text: 'Load by hour' },
series: [
{
type: 'heatmap',
xField: 'day',
yField: 'hour',
colorField: 'load',
colorName: 'Load',
colorRange: ['#e8f0fe', '#1d4fd7'],
},
],
legend: { enabled: false },
};
}export function getData() {
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
const hours = ['00', '04', '08', '12', '16', '20'];
const data: Array<{ day: string; hour: string; load: number }> = [];
days.forEach((day, d) => {
hours.forEach((hour, h) => {
const base = h === 2 || h === 3 ? 60 : h === 4 ? 45 : 15;
const weekend = d >= 5 ? 0.5 : 1;
data.push({ day, hour, load: Math.round(base * weekend + ((d * 7 + h * 3) % 13)) });
});
});
return data;
}Color scale placement
gradientLegend controls the scale's position, spacing, thickness, and the labels of its ends (in a grafit-charts/core build the scale is a separate module: register(gradientLegendModule)):
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';
export function createOptions(): ChartOptions {
return {
data: getData(),
title: { text: 'Scale at the bottom with spacing' },
series: [{ type: 'heatmap', xField: 'week', yField: 'day', colorField: 'deploys', colorName: 'Deploys' }],
gradientLegend: { position: 'bottom', spacing: 14, thickness: 10 },
legend: { enabled: false },
};
}export function getData() {
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
const weeks = ['W1', 'W2', 'W3', 'W4'];
const data: Array<{ week: string; day: string; deploys: number }> = [];
weeks.forEach((week, w) => {
days.forEach((day, d) => {
data.push({ week, day, deploys: ((w * 5 + d * 3) % 11) + (d === 2 ? 6 : 1) });
});
});
return data;
}| Option | Type | Default | Description |
|---|---|---|---|
gradientLegend.enabled | boolean | true | show the scale |
gradientLegend.position | 'top' | 'right' | 'bottom' | 'left' | 'right' | placement side |
gradientLegend.spacing | Pixels | 10 | gap from the plot area |
gradientLegend.thickness | Pixels | 12 | bar thickness |
gradientLegend.label.enabled | boolean | true | label the ends of the scale |
gradientLegend.label.format | string | — | format string (',.2f') |
gradientLegend.label.formatter | ({ value }) => string | the value | text of an end label |
A scale beside the plot ('left', 'right') is a vertical bar with its ends above and below it; one over or under the plot ('top', 'bottom') is a horizontal bar with the ends level with it, on either side.
The ends carry the raw minimum and maximum of the data, so a series with a formatted value passes the same format (or formatter) here. The strip is as wide as the ends it actually draws, so shortening them gives the room back to the plot; with label: { enabled: false } it shrinks to the bar itself.
Value labels
label: { enabled: true } shows the value in each cell; the text color is chosen automatically based on the background luminance. The tooltip here is anchored to the cell center (tooltip.position.anchorTo: 'center'; the default is the top edge):
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';
export function createOptions(): ChartOptions {
return {
data: getData(),
title: { text: 'Value labels' },
series: [
{
type: 'heatmap',
xField: 'week',
yField: 'day',
colorField: 'deploys',
colorName: 'Deploys',
// text color is chosen automatically based on cell luminance
label: { enabled: true },
},
],
// tooltip at the cell center
tooltip: { position: { anchorTo: 'center' } },
legend: { enabled: false },
};
}export function getData() {
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
const weeks = ['W1', 'W2', 'W3', 'W4'];
const data: Array<{ week: string; day: string; deploys: number }> = [];
weeks.forEach((week, w) => {
days.forEach((day, d) => {
data.push({ week, day, deploys: ((w * 5 + d * 3) % 11) + (d === 2 ? 6 : 1) });
});
});
return data;
}Custom labels
formatter, font, color, and placement (placement: 'top') are configurable; the scale can be disabled:
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';
export function createOptions(): ChartOptions {
return {
data: getData(),
title: { text: 'Custom labels' },
subtitle: { text: 'formatter, font and color; scale disabled' },
series: [
{
type: 'heatmap',
xField: 'week',
yField: 'day',
colorField: 'deploys',
colorRange: ['#fef3e2', '#e8590c'],
itemPadding: 4,
cornerRadius: 8,
label: {
enabled: true,
placement: 'top-left',
formatter: ({ value }) => `${value}×`,
fontSize: 13,
fontWeight: 'bold',
},
},
],
gradientLegend: { enabled: false },
legend: { enabled: false },
};
}export function getData() {
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
const weeks = ['W1', 'W2', 'W3', 'W4'];
const data: Array<{ week: string; day: string; deploys: number }> = [];
weeks.forEach((week, w) => {
days.forEach((day, d) => {
data.push({ week, day, deploys: ((w * 5 + d * 3) % 11) + (d === 2 ? 6 : 1) });
});
});
return data;
}| Option | Type | Default | Description |
|---|---|---|---|
xField | string | — | axis categories |
yField | string | — | axis categories |
colorField | string | — | numeric value → color |
colorRange | ColorValue[] | blue-cyan | scale stops (2+) |
itemPadding | Pixels | 2 | gap between cells |
cornerRadius | Pixels | theme (5) | cell corner rounding |
colorName | string | colorField name | value label in the tooltip |
label.enabled | boolean | false | show value labels |
label.placement | center, edges and corners (9 positions) | 'center' | label position |
label.format | string | — | format string (',.2f'); the tooltip reads it too |
label.formatter | ({ value, datum }) => string | the value | label content |
label.avoidOverlap | boolean | false | drop a label that runs into one already drawn |
label.fontSize | Pixels | 11 | label font size |
label.fontWeight | string | number | normal | font weight |
label.fontFamily | string | theme font | font family |
label.color | ColorValue | foreground; auto-contrast when inside | text color |
Options
Options common to all series (name, showInLegend, …) are covered in Common series options. The heatmap tooltip has both categories to name, so its renderer is handed those instead of x/y:
| Option | Type | Default | Description |
|---|---|---|---|
tooltip.renderer | ({ datum, value, xValue, yValue, color }) => … | — | custom tooltip |