Skip to main content

Scatter Plot

Real measurements from the Palmer penguins dataset: flipper length against bill length, colored by species and sized by body mass. Each click picks a different random half of the 342 penguins.

Hover the charts, click the legends, switch the site theme or resize the window
Pick a preset to reconfigure every chart

What to look for​

  • Size encoding. The Unovis example scales body mass to pixels from the full dataset in its size accessor, so hiding a species keeps the remaining points the same size. Chart.js expects sizes in pixels, so you scale the values yourself. ECharts takes pixels in symbolSize, or maps values to sizes with a visualMap.
  • Pick other penguins. Every penguin has a stable id, so Unovis moves the points that stay, fades in the new ones and fades out the rest, and the axes follow. TanStack Charts keys the points by id too and animates them the same way (svgAnimation).
  • Colors from CSS. The Unovis example colors each species with the palette's CSS variables (var(--vis-color0)…), so the same code gives dark mode colors in dark mode.
  • Axis titles. Unovis takes a label on each axis. Recharts needs label positioning and extra margins for the same result.
  • Shapes. Each species has its own shape (shape), in the chart and in the legend. Recharts, Chart.js, ECharts and AG Charts have the same shapes built in, and so do Observable Plot (symbol) and Vega-Lite (shape); Nivo's scatter plot and TanStack Charts' dot draw circles only.
  • Hover. The Unovis crosshair (snapMode: 'xy') snaps to the point nearest the pointer and draws guide lines to both axes. Nivo, AG Charts, Observable Plot (tip) and TanStack Charts also pick the nearest point, while Recharts shows a tooltip only when the pointer is over one. So do the Chart.js and Vega-Lite demos, which keep their defaults; Chart.js' interaction: { mode: 'nearest', intersect: false } and a Vega-Lite nearest selection change that.
  • Presets. Labels gives every penguin a body mass label (label) and hides the ones that would cover a point or another label (labelHideOverlapping, on by default). AG Charts hides those too; ECharts (labelLayout.hideOverlap) and Chart.js (chartjs-plugin-datalabels, display: 'auto') hide only the labels that overlap another label and keep the ones that cover a point; Recharts, Observable Plot, Vega-Lite and TanStack Charts would draw every one; and Nivo has no point labels. Rings draws hollow points in the species colors (strokeColor, strokeWidth): ECharts' documented borderColor values don't take its palette (the undocumented 'auto' does), so that demo sets the ring colors by hand; Nivo's points have no stroke; and TanStack Charts' dot takes one stroke color for every species. Average lines adds two VisPlotlines, which every library can draw, Chart.js with chartjs-plugin-annotation.

Feature comparison​

FeatureUnovis1.8.0Recharts3.10.1Chart.js4.5.1ECharts6.1.0Nivo0.99.0AG Charts14.2.0Observable Plot0.6.17Vega-Lite6.5.0TanStack Charts1.1.0
Bubble
Point shapes
Hover snaps to the nearest point
Label overlap avoidance
Brush / range selection
Zoom and pan XY charts
Animated data updates
Dark mode

Every cell links to its source. See how we compare for the rules we followed.