Skip to content
commit-766c8d6756a1

Scatter chart

Repeated observations across an ordered set for trends, clusters, density, and outliers.

Purpose
Compare repeated observations, trends, clusters, and outliers across an ordered set of categories.
Use when
Use when point position, overlap, and density reveal variation that bars would hide.
Avoid when
Avoid when categories lack meaningful order, values need a continuous numeric x-axis, or every observation must be read immediately.
Equivalent data
Names, captions, symbols, and selected-label summaries do not depend on color. For dense data, keep an equivalent caller-owned table, download, or drill-down instead of expanding thousands of values into page text.
Usage Example
@scatter.Scatter(scatter.Config{
  Label: "Basic scatter chart with one missing Email observation",
  Categories: []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"},
  Series: []scatter.Series{
    {Name: "Email", Values: [][]float64{{120}, {132}, {101}, {}, {90}, {230}, {210}}},
    // Four more named series retain the same seven aligned categories.
  },
  Options: scatter.Options{Symbol: scatter.SymbolDot, Size: 4},
  Title: scatter.TitleOptions{Text: "Scatter", FontSize: 16},
  Legend: scatter.LegendOptions{Padding: scatter.Padding{Left: 100}},
  Width: 600, Height: 400,
})

Per-series symbols

Circle, diamond, square, and filled-dot markers preserve the upstream four-series comparison and add a non-color channel for identification.

Per-series symbols
@scatter.Scatter(scatter.Config{
  Label: "Scatter series with distinct point symbols",
  Categories: week,
  Series: []scatter.Series{
    {Name: "Email", Values: email, Options: scatter.Options{Symbol: scatter.SymbolCircle}},
    {Name: "Union Ads", Values: union, Options: scatter.Options{Symbol: scatter.SymbolDiamond}},
    {Name: "Video Ads", Values: video, Options: scatter.Options{Symbol: scatter.SymbolSquare}},
    {Name: "Direct", Values: direct, Options: scatter.Options{Symbol: scatter.SymbolDot}},
  },
  Options: scatter.Options{Size: 4},
  Width: 600, Height: 400,
})

Dense multi-value observations

Three deterministic 1,000-category bounded random walks retain repeated samples, SMA(100) trends, maximum reference lines, compact points, sampled and rotated axis labels, explicit bounds and units, right-side vertical legend, padding, and responsive theme tokens.

Dense multi-value observations
@scatter.Scatter(scatter.Config{
	Label: "Dense scatter data",
	Categories: labels,
	Width: 600, Height: 400,
	Options: scatter.Options{Size: 0.5, Trend: scatter.TrendLine{
		Kind: scatter.TrendSimpleMovingAverage, Period: 100,
	}},
	Series: []scatter.Series{
		{Name: "One", Values: values[0], Options: scatter.Options{ReferenceLine: scatter.ReferenceLineMaximum}},
		{Name: "Two", Values: values[1], Options: scatter.Options{ReferenceLine: scatter.ReferenceLineMaximum}},
		{Name: "Three", Values: values[2]},
	},
})

Top value labels

Select exactly the highest N observations with deterministic input-order tie handling. Labels use chart-theme tokens by default; the accessible summary keeps every exact value and selection state available without color dependence.

Exact values and selected labels
CategorySeriesValueSelected label
Day 1Daily Visitors (k)15.2No
Day 2Daily Visitors (k)18.5No
Day 3Daily Visitors (k)22.1No
Day 4Daily Visitors (k)19.8No
Day 5Daily Visitors (k)25.4No
Day 6Daily Visitors (k)21.3No
Day 7Daily Visitors (k)17.9No
Day 8Daily Visitors (k)32.6No
Day 9Daily Visitors (k)28.1No
Day 10Daily Visitors (k)24.7No
Day 11Daily Visitors (k)31.5No
Day 12Daily Visitors (k)29.3No
Day 13Daily Visitors (k)26.8No
Day 14Daily Visitors (k)35.2No
Day 15Daily Visitors (k)41.7Yes
Day 16Daily Visitors (k)38.9No
Day 17Daily Visitors (k)33.1No
Day 18Daily Visitors (k)29.6No
Day 19Daily Visitors (k)27.4No
Day 20Daily Visitors (k)30.8No
Day 21Daily Visitors (k)36.3No
Day 22Daily Visitors (k)42.1Yes
Day 23Daily Visitors (k)39.5No
Day 24Daily Visitors (k)44.8Yes
Day 25Daily Visitors (k)48.3Yes
Day 26Daily Visitors (k)45.6Yes
Day 27Daily Visitors (k)40.2No
Day 28Daily Visitors (k)37.9No
Day 29Daily Visitors (k)34.5No
Day 30Daily Visitors (k)26.1No
Top value labels
@scatter.Scatter(scatter.Config{
	Label: "Website traffic over 30 days with peak-day labels",
	Categories: days,
	Series: []scatter.Series{{Name: "Daily Visitors (k)", Values: values}},
	Options: scatter.Options{TopNLabels: scatter.TopNLabels{
		Count: 5, FontSize: 16, Color: "var(--color-chart-danger)",
	}},
	Title: scatter.TitleOptions{Text: "Website Traffic Over 30 Days - Peak Days Highlighted", Subtext: "(Only top 5 traffic days show labels)"},
	Legend: scatter.LegendOptions{Hidden: true},
	YAxis: scatter.ValueAxisOptions{Min: &zero, Max: &maximum},
	Padding: scatter.Padding{Top: 20, Right: 20, Bottom: 20, Left: 20},
	Width: 800, Height: 500,
})

Whole-number formatting

The option-function source reuses the basic data with hollow circles and integer axis labels. Goshtoso expresses that visual result through typed options, without exposing callbacks or renderer option functions.

Whole-number formatting
@scatter.Scatter(scatter.Config{
  Label: "Basic scatter chart with circle symbols and integer labels",
  Categories: week,
  Series: series,
  Options: scatter.Options{
    Symbol: scatter.SymbolCircle,
    ValueFormat: scatter.ValueFormatInteger,
  },
  Width: 600, Height: 400,
})

Static/vector behavior

Scatter renders inline SVG on the server, follows Goshtoso and AraiHu tokens in light and dark mode, preserves print and no-JavaScript readability, and supports resolved SVG plus opaque or transparent PNG download through the shared wrapper. Wrapper lifecycle, modes, controls, export, and client events stay in the shared chart controls and chart modes guides.

Go API

v0.0.1

The examples above cover behavior and composition. pkg.go.dev is the canonical reference for exported types, functions, methods, and Go documentation.

github.com/araihu/goshtoso-charts/components/scatter

Enabled, disabled, hidden, and omitted wrapper behavior, controls, export, and client transitions are shared by every chart. Review chart controls, then compare static/vector and interactive capabilities.

Open v0.0.1 API