Trend Chart
The Trend Chart puts line, bar and area series on the same axes. It earns its place when one picture has to carry measures that want different marks — volume as bars under a rate as a line, actuals as an area behind a forecast line. Each series declares its type ('line', 'bar' or 'area') plus that type's own options, and the chart reuses the same renderers as the standalone line, bar and area charts. Series paint back-to-front as area → bar → line so lines never hide behind fills or bars, and overlaid areas are drawn largest-first so smaller areas stay visible. stacked stacks same-type series, and an overview strip beneath the plot windows the visible x-range while navigator adds wheel and drag pan-zoom on the plot itself. It works against any Ripl rendering target: Canvas, SVG or a terminal.
NOTE
For the full API, see the Charts API Reference.
Example
Usage
import {
createTrendChart,
} from '@ripl/charts';
const chart = createTrendChart('#container', {
data: [/* ... */],
key: 'month',
series: [
{ type: 'area', id: 'revenue', label: 'Revenue', value: 'revenue' },
{ type: 'bar', id: 'orders', label: 'Orders', value: 'orders' },
{ type: 'line', id: 'target', label: 'Target', value: 'target' },
],
});Data Format
A single flat dataset is shared by every series; each series reads its own numeric field via value, and key gives the category plotted along the x axis:
const data = [
{
month: 'Jan',
revenue: 620,
orders: 140,
target: 700,
},
{
month: 'Feb',
revenue: 780,
orders: 190,
target: 720,
},
{
month: 'Mar',
revenue: 550,
orders: 120,
target: 680,
},
];Variants
Stacked
Same-type series stack independently, so bars stack among bar series and areas among area series:
createTrendChart('#container', {
data,
key: 'month',
stacked: true,
series: [
{ type: 'area', id: 'revenue', label: 'Revenue', value: 'revenue' },
{ type: 'area', id: 'expenses', label: 'Expenses', value: 'expenses' },
{ type: 'line', id: 'target', label: 'Target', value: 'target' },
],
});Navigator
Enable the overview strip to window the visible x-range (and pan/zoom on the plot):
createTrendChart('#container', {
data,
key: 'month',
overview: true,
series: [
{ type: 'bar', id: 'orders', label: 'Orders', value: 'orders' },
{ type: 'line', id: 'target', label: 'Target', value: 'target' },
],
});Segmented line styles
lineStyle also accepts spans anchored to data keys, so one line can change style along its length — actuals solid and a forecast dashed, say. The line is still a single polyline, so the draw-on animation and point morphing are unaffected.
createTrendChart('#container', {
data,
key: 'month',
series: [
{
type: 'line',
id: 'revenue',
value: 'revenue',
label: 'Revenue',
lineStyle: [
{
from: 'Feb',
to: 'Jun',
style: 'dashed',
},
{
// A function receives the dataset and returns the key to anchor to.
from: data => data[data.length - 3].month,
style: 'dotted',
},
],
},
],
});from defaults to the start of the line and to — which is inclusive — to its end. Use the object form to name the fallback style explicitly:
createTrendChart('#container', {
data,
key: 'month',
series: [
{
type: 'line',
id: 'revenue',
value: 'revenue',
label: 'Revenue',
lineStyle: {
default: 'solid',
segments: [
{
from: 'Feb',
to: 'Jun',
style: 'dashed',
},
],
},
},
],
});See the line chart for the full rules.
Options
A full configuration for this chart. The options every chart shares — padding, title, animation, theme and the rest — behave the same everywhere and are documented on Shared Options.
createTrendChart('#container', {
data,
key: 'month',
borderRadius: 4,
labels: true,
format: 'number',
// `stacked` cumulates same-type series onto one scale, so it is shown on its own in Variants
// above. Each series declares its own `type` and the options that type supports.
series: [
{
type: 'area',
id: 'revenue',
value: 'revenue',
label: 'Revenue',
color: '#7cacf8',
lineType: 'monotoneX',
lineStyle: 'solid',
lineWidth: 2,
fillOpacity: 0.25,
markers: false,
},
{
type: 'bar',
id: 'orders',
value: 'orders',
label: 'Orders',
color: '#6dd5b1',
},
{
type: 'line',
id: 'target',
value: 'target',
label: 'Target',
color: '#b197fc',
markerRadius: 3,
},
],
});Events
Subscribe with chart.on(...). A handler receives an Event object, not the payload directly — the payload is on event.data, and carries the interacted datum plus its { x, y } anchor in chart pixels. event.target and event.stopPropagation() are also available.
// Emitted when a bar is clicked.
chart.on('barclick', event => console.log(event.data)); // event.data: TrendChartBarEvent
// Emitted when the pointer enters a bar.
chart.on('barenter', event => console.log(event.data)); // event.data: TrendChartBarEvent
// Emitted when the pointer leaves a bar.
chart.on('barleave', event => console.log(event.data)); // event.data: TrendChartBarEvent
// Emitted when a line/area marker is clicked.
chart.on('markerclick', event => console.log(event.data)); // event.data: TrendChartMarkerEvent
// Emitted when the pointer enters a line/area marker.
chart.on('markerenter', event => console.log(event.data)); // event.data: TrendChartMarkerEvent
// Emitted when the pointer leaves a line/area marker.
chart.on('markerleave', event => console.log(event.data)); // event.data: TrendChartMarkerEvent