Relationship · Basic
Scatter plot
How two numbers relate, one dot per item, colored by series.
- Use when
- How two numeric values relate, such as cost and latency per request, with up to 4 series
- Avoid when
- x is time (a line works better), or there are more than 50,000 dots
Try it
36
Scatter plot
Cost and latency per request by model
- Large
- Medium
- Small
Hover over the chart, or Tab in and use the arrow keys to move between items. The numbers are sample data.
Variants
Named looks for this chart. Each one is the example above with a few options or fields changed. The CLI (ztd-charts example scatter --variant <id>) and the MCP server know the same names.
Trend line
Cost and latency per request by model
- Large
- Medium
- Small
Quadrants
Cost and latency per request by model
- Large
- Medium
- Small
Jitter
Cost and latency per request by model
- Large
- Medium
- Small
Code
ScatterChart.tsx
import { ChartCard, ScatterChart } from "ztd-charts";
const data = [
{"id":"Request 1","model":"Large","cost":7,"ms":2400},
{"id":"Request 2","model":"Medium","cost":6,"ms":1500},
{"id":"Request 3","model":"Small","cost":3,"ms":660},
{"id":"Request 4","model":"Large","cost":7,"ms":2390},
{"id":"Request 5","model":"Medium","cost":7,"ms":1560},
{"id":"Request 6","model":"Small","cost":1,"ms":410},
// … 48 more rows
];
export function Example() {
return (
<ChartCard number="36" title="Scatter plot" subtitle="Cost and latency per request by model" takeaway="Only the large model goes over 2 s" level="basic" replay>
<ScatterChart
data={data}
x="cost"
y="ms"
series="model"
label="id"
highlight="Large"
xLabel="Cost (¢)"
yLabel="Latency (ms)"
unit="ms"
refLines={{"y":2000}}
quadrants={["Slow and cheap","Slow and costly","Fast and cheap","Fast and costly"]}
/>
</ChartCard>
);
}
Props
<ScatterChart> takes these props. Rows marked Common work the same on every chart.
38 props
| Prop |
|---|
dataRequiredAn array of objects. Pass CSV, REST or database rows as they areobject[] |
xRequiredx valuestring | (d, i) => number |
yRequiredy valuestring | (d, i) => number |
seriesSeries field (one color per series)string | (d, i) => string |
labelNamestring | (d, i) => string |
xLabelx axis titlestring |
yLabely axis titlestring |
zeroInclude 0 on the axesbooleanDefault false |
maxLabelsMaximum number of dot labels. With a series channel the series names are labeled instead, and this defaults to 0numberDefault 6 |
canvasThresholdDot count that switches to canvasnumberDefault 1500 |
xFormatx value format"number" | "percent" | "compact" | … |
yScaley axis scale. "log" spaces 1, 10, 100 and 1,000 evenly, so values spread over 1,000 times or more stay readable. Values at or below 0 are left out"linear" | "log"Default "linear" |
fitTrend line over the visible dots (least squares). The tooltip shows its slope and R²"linear" |
refLinesReference lines { x, y }. With both, they split the plot into four quadrantsobject |
quadrantsQuadrant names, drawn when refLines has both x and y. In reading order: top left, top right, bottom left, bottom rightstring[] |
jitter{ amount, seed }: spreads dots that share an x value sideways, by up to amount × the smallest gap between x values (default 0.4). The seed (default 1) keeps the picture the same on every renderobject |
heightCommonHeight in px. Without it, each chart picks a default that fits its widthnumber |
widthCommonFixed width in px. Without it, the chart fits its parentnumber |
highlightCommonItem to highlight. An index, a name, an array, or "max" | "min" | "first" | "last" | "none"number | string | (number|string)[] | "max" … |
formatCommonValue format. "number" | "integer" | "percent" (values are already percents: 42 → "42%") | "ratio" (0.42 → "42%") | "compact" | "currency" (KRW for Korean locales, otherwise USD; for another currency pass Intl options with currency) | "decimal" or Intl.NumberFormat options"number" | "percent" | "compact" | … |
unitCommonUnit appended to values. For example "%" or "ms"string |
localeCommonLocale for numbers, dates and the text a chart writes itself (tooltips, screen reader sentences). "ko" or "ko-*" switches to Korean. Falls back to the ThemeProvider localestringDefault "en-US" |
animateCommonEntry and update animationbooleanDefault true |
durationCommonAnimation length (ms)number |
easingCommonMotion curve"spring" | "easeOut" | "easeInOut" | "linear"Default "spring" |
staggerCommonDelay between items as they enter (ms)number |
reducedMotionCommon"auto" follows the OS setting. true always turns motion offanyDefault "auto" |
animateOnViewCommonPlay when the chart scrolls into viewbooleanDefault true |
showLabelsCommonLabels drawn on the chart (values and names)booleanDefault true |
tooltipCommonShow tooltips. { template: "{label} · {value} · owner {owner}" } writes them: {label}, {value}, {series} or any other column of the row. \n starts a new line, and a line with an empty value is left outtooltipDefault true |
syncIdCommonCharts with the same syncId show the hovered x together (line, area, bar, candlestick). <ChartGrid sync> sets one for every chart inside itstring |
ariaLabelCommonName for screen readersstring |
descriptionCommonDescription for screen readers. Built from the data when omittedstring |
onHoverCommonRuns when hover or keyboard focus moves to another item(e: ChartEvent | null) => void |
onClickCommonRuns on click, Enter or Space(e: ChartEvent) => void |
replayKeyCommonReplays the entry animation when it changesstring | number |
themeCommonChanges theme tokens for this chart onlyPartial<ChartTheme> |
Above 1,500 items it draws on a canvas. Axes and labels stay SVG.