Skip to content

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 } }]).

ts
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 },
  };
}
ts
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)):

ts
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 },
  };
}
ts
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;
}
OptionTypeDefaultDescription
gradientLegend.enabledbooleantrueshow the scale
gradientLegend.position'top' | 'right' | 'bottom' | 'left''right'placement side
gradientLegend.spacingPixels10gap from the plot area
gradientLegend.thicknessPixels12bar thickness
gradientLegend.label.enabledbooleantruelabel the ends of the scale
gradientLegend.label.formatstringformat string (',.2f')
gradientLegend.label.formatter({ value }) => stringthe valuetext 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):

ts
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 },
  };
}
ts
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:

ts
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 },
  };
}
ts
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;
}
OptionTypeDefaultDescription
xFieldstringaxis categories
yFieldstringaxis categories
colorFieldstringnumeric value → color
colorRangeColorValue[]blue-cyanscale stops (2+)
itemPaddingPixels2gap between cells
cornerRadiusPixelstheme (5)cell corner rounding
colorNamestringcolorField namevalue label in the tooltip
label.enabledbooleanfalseshow value labels
label.placementcenter, edges and corners (9 positions)'center'label position
label.formatstringformat string (',.2f'); the tooltip reads it too
label.formatter({ value, datum }) => stringthe valuelabel content
label.avoidOverlapbooleanfalsedrop a label that runs into one already drawn
label.fontSizePixels11label font size
label.fontWeightstring | numbernormalfont weight
label.fontFamilystringtheme fontfont family
label.colorColorValueforeground; auto-contrast when insidetext 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:

OptionTypeDefaultDescription
tooltip.renderer({ datum, value, xValue, yValue, color }) => …custom tooltip