Skip to content

Heatmap

The createHeatmap helper turns a grid of values into heatmap pieces: rows become full-width bar series stacked on a row-labelled axis, and each cell's value colors it from a shared sequential ramp.

ts
// createHeatmap turns a grid of values into heatmap pieces: each row becomes
// a full-width bar series floating on a one-unit band of the value axis
// (labelled with the row names via explicit ticks), and each cell's value
// colors it from a shared sequential ramp.
import { createHeatmap } from '@mochart/core';
import type { MochartInputConfig } from '@mochart/core';

const heatmap = createHeatmap(
  [
    { label: 'Mon', values: [58, 54, 49, 43, 38, 34, 32, 35, 40, 46, 52, 57] },
    { label: 'Tue', values: [61, 56, 50, 44, 39, 35, 33, 36, 42, 48, 54, 59] },
    { label: 'Wed', values: [63, 58, 52, 46, 40, 36, 34, 38, 44, 50, 56, 62] },
    { label: 'Thu', values: [59, 55, 49, 43, 38, 33, 31, 35, 41, 47, 53, 58] },
    { label: 'Fri', values: [52, 48, 43, 38, 33, 29, 27, 30, 36, 41, 46, 51] },
    // null leaves a gap in the grid (no data collected that month).
    { label: 'Sat', values: [24, 22, 19, null, 15, 13, 12, 14, 16, 19, 21, 23] },
    { label: 'Sun', values: [20, 18, 16, 14, 12, 10, 9, 11, 13, 15, 17, 19] }
  ],
  { columnLabels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] }
);

export const config: MochartInputConfig = {
  version: '1.0.0',
  title: { text: 'Support Tickets by Weekday (fictional)' },
  categoryAxis: heatmap.categoryAxis,
  valueAxes: [heatmap.valueAxisConfig],
  // valueFormat formats the tooltip's cell values (via tooltipProperty).
  series: heatmap.series.map(seriesConfig => ({ ...seriesConfig, valueFormat: ',.0f' }))
};

export const data = heatmap.data;

How it works

  • Each row is a bar series floating on a fixed one-unit band of the value axis via rangeProperty (rows[0] on top). The returned valueAxisConfig pins the axis to exactly the stacked bands and labels each band's center with the row name through explicit ticks (auto numeric ticks would land on the band edges and mislabel the rows). The row series stay out of the legend (showInLegend: false) — hiding a row from a legend would read as missing data, and a color-ramp strip built from colorScale makes the better legend.
  • Cell colors come from colorProperty: each cell's value drives its fill (see color by value for the basic per-bar usage). The core color scale spans each series' own extent, so the helper sets every row's colorScale.min/colorScale.max to the global ramp sampled at that row's min/max — keeping cell colors comparable across rows. The default ramp is a light-to-dark sequential blue; override it with the helper's colorMin, colorMax and colorInterpolation options (which land in each row's colorScale), or fix the scale across datasets with domain.
  • Each series sets tooltipProperty to the cell value, so the tooltip shows the value driving the color rather than the cell's band coordinates — valueFormat formats it as usual.
  • null/undefined cells leave a gap in the grid: missingValues: 'connect' skips them without disturbing their neighbours. cellPadding sets the gap between cells (0 for a contiguous grid), and columnLabels names the columns (defaults to 1-based numbers).
  • The returned colorScale maps any value to its hex color and domain is the scaled extent — the pieces you need to render a color-ramp legend next to the chart. createHeatmapColorScale(domain, options) builds the same scale standalone.

Released under the BSD-3-Clause License.