Custom heatmap functions
Write your own per-square calculation for generateHeatmap.
A heatmap function answers one small question — "what value should this square have?" — and generateHeatmap asks it 64 times, once per square. If you can write that one function, you can make any heatmap.
Here's one from scratch: "how much of the game did white pieces occupy each square?" (as a percentage of all half-moves):
import { generateHeatmap } from 'chessalyzer/trackers';
const heatmapData = generateHeatmap(tiles.state, ({ data, square }) => {
const cell = data.squares[square];
if (!cell) return 0;
return (cell.w.total.occupiedFor * 100) / data.movesTotal;
});Need an extra value in your function — a piece you care about, a precomputed average? Just close over it:
const queen = { color: 'w', name: 'Qd' };
const queenSquares = generateHeatmap(tiles.state, ({ data, square }) => {
const cell = data.squares[square];
if (!cell) return 0;
return cell[queen.color].byPiece[queen.name].movedTo;
});The arguments
Your function gets a single object with three properties:
| Property | Type | What it is |
|---|---|---|
data | your tracker state | Whatever you passed to generateHeatmap (e.g. TileTrackerState) |
square | Square | The square being calculated, e.g. 'a2' |
startingPiece | HeatmapPieceRef | null | The piece that starts the game on this square, or null if it's empty |
Most functions only need data and square — each cell is a board location. Reach for startingPiece when each cell should represent a piece identity instead (that's how PIECE_CAPTURED and TILE_OCC_BY_PIECE work):
import type { HeatmapFn } from 'chessalyzer/trackers';
// HeatmapPieceRef: { color: 'b' | 'w'; name: StartingPieceName }
const byPieceIdentity: HeatmapFn = ({ data, startingPiece }) => {
if (!startingPiece) return 0;
return lookUp(data, startingPiece.color, startingPiece.name);
};Type the function as HeatmapFn<YourState> and data is fully inferred.
Learn from the presets
The built-in presets are ordinary heatmap functions written with this exact API — if one is close to what you want, its behavior is a great starting point to copy and adjust.