Polar Scatter Chart
The Polar Scatter Chart plots points on a circular grid where each point's angle encodes one variable and its distance from the center another; a third can drive marker size. It suits directional and cyclical data — wind, radar returns, hourly measurements — where a cartesian scatter would break the wrap-around at the edge of the axis. levels sets the value rings, sectors the angular spokes, max pins the outer ring, and each series binds angleBy, radiusBy and optionally sizeBy between minRadius and maxRadius, with labels, legend and format for the annotation. Point it at a Canvas, SVG or terminal context and nothing else changes.
NOTE
For the full API, see the Charts API Reference.
Example
Usage
import {
createPolarScatterChart,
} from '@ripl/charts';
const chart = createPolarScatterChart('#container', {
data: [
{
angle: 45,
speed: 62,
gust: 80,
},
{
angle: 120,
speed: 34,
gust: 40,
},
{
angle: 250,
speed: 88,
gust: 95,
},
],
series: [
{
id: 'wind',
label: 'Wind',
angleBy: 'angle',
radiusBy: 'speed',
sizeBy: 'gust',
},
],
max: 100,
});Data Format
Each item provides an angle (in degrees, 0° at the top and increasing clockwise), a radial value, and optionally a size value:
const data = [
{
angle: 45,
speed: 62,
gust: 80,
},
{
angle: 120,
speed: 34,
gust: 40,
},
];Every series reads all rows through its own accessors. For multiple series, keep one row per observation and point each series at its own fields:
const data = [
{
morningAngle: 60,
morningSpeed: 32,
eveningAngle: 250,
eveningSpeed: 78,
},
];
const series = [
{
id: 'morning',
label: 'Morning',
angleBy: 'morningAngle',
radiusBy: 'morningSpeed',
},
{
id: 'evening',
label: 'Evening',
angleBy: 'eveningAngle',
radiusBy: 'eveningSpeed',
},
];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.
createPolarScatterChart('#container', {
data,
// Outer bound of the radial scale; omit to derive it from the data.
max: 100,
// Concentric value rings and angular spokes.
levels: 5,
sectors: 12,
labels: true,
legend: { position: 'bottom' },
format: 'number',
series: [
{
id: 'morning',
label: 'Morning',
color: '#7cacf8',
angleBy: 'bearing',
radiusBy: 'distance',
sizeBy: 'weight',
minRadius: 4,
maxRadius: 18,
},
],
});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 marker is clicked.
chart.on('markerclick', event => console.log(event.data)); // event.data: PolarScatterMarkerEvent
// Emitted when the pointer enters a marker.
chart.on('markerenter', event => console.log(event.data)); // event.data: PolarScatterMarkerEvent
// Emitted when the pointer leaves a marker.
chart.on('markerleave', event => console.log(event.data)); // event.data: PolarScatterMarkerEvent