chart gallery
Chart Zoom, Pan and Measure Tool, Live
Zoom into a long history and the table follows, then measure a move between two points. Both are live below, with the code that drives them.
Chart zoom, pan and follow
Give a chart zoom and a reader can narrow it to the stretch they care about with the wheel, a drag, a pinch or the buttons. Add viewportFilter and the grid follows: once the zoom settles, the table and every other chart over the same grid show only the rows in view. On a time axis that is the dates in range, and on a category axis it is the categories left on screen. Zoom back out, or clear the filter in the grid, and everything returns. Use it for long histories, busy time series and any chart where the table should answer what exactly is in this window.
Try it. Zoom the line with the wheel, and the bars with the zoom-in button that appears when you hover over them. The grid narrows to the rows in view. Reset with the 0 key or a double-click.
The code
createChart({
grid,
container: containers[0],
type: 'line',
x: 'day',
y: 'sessions',
axis: { x: { scale: 'time' } },
zoom: true,
viewportFilter: true,
title: 'Sessions by day',
});
createChart({
grid,
container: containers[1],
type: 'bar',
x: 'channel',
y: 'sessions',
zoom: true,
viewportFilter: true,
title: 'Sessions by channel',
});
Options used:
zoom, viewportFilter
Sample data
({
columns: [
{ field: 'day', title: 'Day', type: 'datetime', layout: { width: 140 } },
{ field: 'channel', title: 'Channel' },
{ field: 'sessions', title: 'Sessions', type: 'number' },
],
rows: ['Search', 'Email', 'Social', 'Direct', 'Referral', 'Paid', 'Video', 'Partner'].flatMap((channel, c) =>
Array.from({ length: 21 }, (v, d) => ({
id: channel + d,
day: new Date(Date.UTC(2026, 8, 1 + d)),
channel,
sessions: Math.round(120 + c * 35 + 60 * Math.sin((d + c) / 3) + d * (4 - (c % 3))),
}))),
})
Chart measure tool
The measure tool turns a chart into a ruler. Press its button, or M with the chart focused, then drag between two points and a band appears with the change in time, the change in value, the percentage change and the slope. Ends snap to the nearest reading, so the numbers come from the data rather than a guess at the pixels. Press Enter or click the band to pin it, and a pinned measurement stays put as you zoom and pan. Use it on prices, usage or any series where someone asks how much, and how fast.
Try it. Press the measure button, or M with the chart focused, then drag between two points. Press Enter to pin the measurement.
The code
createChart({
grid,
container,
type: 'line',
x: 'at',
y: 'close',
axis: { x: { scale: 'time' } },
measure: true,
title: 'Closing price',
});
Options used:
measure, measure.snap
Sample data
({
columns: [
{ field: 'at', title: 'Date', type: 'datetime', layout: { width: 140 } },
{ field: 'close', title: 'Close', type: 'number' },
],
rows: Array.from({ length: 30 }, (v, i) => ({
id: i,
at: new Date(Date.UTC(2026, 8, 1 + i)),
close: Math.round((100 + i * 1.2 + 9 * Math.sin(i / 2.5)) * 10) / 10,
})),
})
Every chart type, live → The charts API reference → How a chart binds to a grid →