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.valueAxes,
// 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
createHeatmap(rows, options)returns{ domain, colorScale, data, categoryAxis, valueAxes, series }. Each row is abarseries floating on a fixed one-unit band of the value axis viarangeProperty(rows[0]on top). The returnedvalueAxesfragment pins the axis to exactly the stacked bands and labels each band's center with the row name through explicitticks(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 fromcolorScalemakes 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'scolorScale.min/colorScale.maxto 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'scolorMin,colorMaxandcolorInterpolationoptions (default'lab'; they land in each row'scolorScale), or fix the scale across datasets withdomain(cell values outside it clamp to the end colors). - Each series sets
tooltipPropertyto the cell value, so the tooltip shows the value driving the color rather than the cell's band coordinates —valueFormatformats it as usual. null/undefinedcells leave a gap in the grid:missingValueMode: 'connect'skips them without disturbing their neighbours. PassmissingColorinstead to draw them as a full band in that colour (it becomes each row'scolorScale.missing) — pick one clearly off the ramp, so a missing cell reads as "no data" rather than as a value.cellPadding(default 0.03) sets the gap between cells as a fraction trimmed from each side (0 for a contiguous grid; it must be below 0.5), andcolumnLabelsnames the columns (defaults to 1-based numbers). They become the category values, so pass one per column and keep them unique —createHeatmapthrows otherwise.- The returned
colorScalemaps any value to its hex color anddomainis the extent the colors are scaled over — the pieces you need to render a color-ramp legend next to the chart.createHeatmapColorScale(domain, options)builds the same scale standalone.