A scatter draw layer: one mark per finite point at (x, column-value)
— x from the series' key / axis column (time or value axis) —
with data-driven radius + colour (the signed-off exception — encode from
columns via scales, not a per-event style callback). Reads column into a
ChartSeries (gaps as NaN → no mark), registers into the enclosing
Layers (scaling against its axis), and renders nothing to the DOM —
the row draws it.
Interactions. Hover snaps the tracker dot to the nearest point
(sampleAt), and that sample flows to the container's onTrackerChanged —
the nearest-point readout. Scatter reuses the shared tracker rather than
adding a separate onNearest channel, so a scatter reads out exactly like a
line. Click selection hit-tests each point's disc (hitTest) — opt-in via
id; the selected point (matching the selection's series id and the sample
key) gets a highlight ring. Without an id the scatter is display-only.
<Layers>
<ScatterChart
series={s}
column="price"
radius={{ column: 'volume', range: [3, 14] }}
color={{ column: 'change', range: ['#e8836b', '#15B3A6'] }}
/>
</Layers>
Props
Name of the numeric value column — each point's y.
seriesTimeSeriesTimeSeriesclasspond-tsAn immutable, schema-typed, ordered collection of events — the batch
layer's core primitive. A series is constructed whole from complete data
and never mutated: every transform (filter, align, rollup, …)
returns a new TimeSeries, so the full analytical surface can sort,
scan, or index freely. Example:
new TimeSeries({ name, schema, rows }).
<S> | ValueSeriesValueSeriesclasspond-tsA value-keyed series — the closed value-axis counterpart of
TimeSeries. Its key is a monotonic non-time axis (distance, cumulative
work, …). Two doors in: project a TimeSeries onto one of its monotonic
columns (TimeSeries.byValue(axis) — a track re-keyed by cumulative
distance), or construct directly from columnar arrays
(`ValueSeries.fromC…
<VS>requiredThe source series. A TimeSeries scatters against the time axis; a
ValueSeries (series.byValue('cumDist'), or ValueSeries.fromColumns
for natively value-keyed data — IV marks keyed by strike) against its
value axis — the container infers which from the data, no axis-type prop
(mirrors <LineChart>). Either way the key / axis column supplies each
point's x and column supplies y.
Live charts: series.byValue(…) mints a fresh projection each call,
so passing series={s.byValue('dist')} inline re-registers this layer
every render — memoize the projection (useMemo) on a frequently
re-rendering chart.
asstringThe scatter's semantic identifier — what the marks are / how they should
read. The theme maps it to a ScatterStyle (theme.scatter[as] ?? theme.scatter.default) — the base fill, radius, outline, and label
colour. Omitted ⇒ the default style. This is the single styling
channel for the base mark; per-point size / colour come from the data-driven
radius / color encodings below (the deliberate, signed-off scatter
exception), not a per-component style override.
axisstringWhich <YAxis> (by its id) this scatter scales against — picks the
scale, where as picks the style. Omitted ⇒ the row's default axis.
colorColorEncodingColorEncodinginterface@pond-ts/charts{ column: string; range: readonly [string, string] }Per-point colour encoding — { column, range }: map the column's finite
extent linearly onto a two-stop colour ramp [atMin, atMax] (interpolated in
sRGB). A point whose colour column is non-finite falls back to the base colour
(the single styling channel — theme.scatter[as].color).
Data-driven point colour — { column, range }: colour each point from a
numeric column (its finite extent → a two-stop hex ramp via a linear scale).
A point whose colour column is non-finite falls back to the base colour.
Omitted ⇒ the style's base colour for every point (the single styling
channel). Same discipline as radius: a column + range, not a callback.
idstringThe stable series identity for selection + hover. Optional, and it
gates interactivity: the scatter is selectable/hoverable only when given an
id — omit it and the points render + read out but can't be clicked (a click
on them reads as empty space ⇒ deselect). Distinct from as (a theme role
that can repeat): id must be unique among the selectable layers, and it is
the key the controlled selected echo, dedup, and (later) multi-select all
match on — so a selection survives a data update where a sample key goes
stale.
A point's identity within the series is its x (key / axis value). The
key contract allows duplicate x's (equal timestamps; a value-axis plateau
from byValue('cumDist')) — points sharing an x share identity, so
selecting one highlights the last drawn point at that x.
labelstring | booleanAn optional per-point text label, drawn just right of each mark, in the
style's label colour + the theme font. Two forms:
- a column name ⇒ that column's value at each point, stringified;
true⇒ the plottedcolumn's value, stringified.
Omitted / false ⇒ no labels. Keep it sparse — a label per point on a
dense scatter is noise; this is for a handful of called-out marks.
offsetnumberA pixel shift applied to every point's x — zoom-stable. Default 0.
For pairing marks that share a key side by side (a call and a put mark at one
strike: offset={-4} / offset={+4}). Pairs with <BoxPlot offset>; on the
scatter the shift is exact — both the draw and the click hit-test move
together, so a nudged point still selects.
radiusRadiusEncodingRadiusEncodingtype@pond-ts/chartsnumber | { column: string; range: readonly [number, number] }Per-point radius encoding. Either:
- a fixed radius in CSS px (every point the same size — the common case), or
{ column, range }: map the column's finite extent linearly onto
[minR, maxR] px. A point whose radius column is non-finite falls back to
the base radius (it still draws, at the default size).
Data-driven point radius — the signed-off exception to one-channel
styling. Either a fixed px radius, or { column, range } to size each point
from a numeric column (its finite extent → [minR, maxR] px via a linear
scale). A point whose radius column is non-finite falls back to the base
radius. Omitted ⇒ the style's base radius. The encoding is a column +
range, not a per-datum callback — there's no place for a styling bug to
hide (the trap the package avoids).