Scatter
Scatter plots place one point per [x, y] observation — the standard chart for correlation and distribution. Point density is controlled through the marker options.
Usage
Create a chart atom with standard Highcharts options,
then render Chart(chart) anywhere in a
mates template. Every later chart.set(…) or
chart.update(…) re-renders the chart — no
imperative Highcharts code.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "scatter"
},
title: {
text: "Height vs weight"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
title: {
text: "Height (cm)"
}
},
yAxis: {
title: {
text: "Weight (kg)"
}
},
plotOptions: {
scatter: {
marker: {
radius: 5,
fillOpacity: 0.65,
symbol: "circle"
}
}
},
series: [
{
type: "scatter",
name: "Measurements",
data: [
[
160,
55
],
[
165,
60
],
[
170,
62
],
[
172,
70
],
[
178,
72
],
[
180,
78
],
[
185,
80
],
[
190,
88
],
[
168,
58
],
[
176,
68
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Live examples
Data as [x, y] tuples; markers carry the visual weight.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "scatter"
},
title: {
text: "Height vs weight"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
title: {
text: "Height (cm)"
}
},
yAxis: {
title: {
text: "Weight (kg)"
}
},
plotOptions: {
scatter: {
marker: {
radius: 5,
fillOpacity: 0.65,
symbol: "circle"
}
}
},
series: [
{
type: "scatter",
name: "Measurements",
data: [
[
160,
55
],
[
165,
60
],
[
170,
62
],
[
172,
70
],
[
178,
72
],
[
180,
78
],
[
185,
80
],
[
190,
88
],
[
168,
58
],
[
176,
68
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Multiple scatter series form natural groups — legend + marker shape distinguish them without colour alone.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "scatter"
},
title: {
text: "A/B test conversion"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
title: {
text: "Sessions"
}
},
yAxis: {
title: {
text: "Conversion %"
}
},
plotOptions: {
scatter: {
marker: {
radius: 5,
fillOpacity: 0.6
}
}
},
series: [
{
type: "scatter",
name: "Control",
marker: {
symbol: "circle"
},
data: [
[
10,
2.1
],
[
22,
2.6
],
[
31,
2.2
],
[
44,
3
],
[
58,
2.8
],
[
71,
3.3
]
]
},
{
type: "scatter",
name: "Variant",
marker: {
symbol: "diamond"
},
data: [
[
12,
2.8
],
[
25,
3.4
],
[
37,
3.9
],
[
49,
4.2
],
[
61,
4.6
],
[
74,
5.1
]
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Mix a scatter series with a plain line series to overlay a regression — a combo chart, no extra series math.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
animation: false
},
title: {
text: "Ad spend vs conversions"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: true
},
xAxis: {
title: {
text: "Ad spend ($k)"
}
},
yAxis: {
title: {
text: "Conversions"
}
},
series: [
{
type: "scatter",
name: "Weeks",
data: [
[
2,
21
],
[
3,
28
],
[
4,
30
],
[
5,
38
],
[
6,
41
],
[
7,
49
],
[
8,
52
],
[
9,
58
]
],
marker: {
radius: 5,
fillOpacity: 0.65
}
},
{
type: "line",
name: "Trend (y = 6.2x + 8)",
data: [
[
2,
20.4
],
[
9,
63.8
]
],
marker: {
enabled: false
},
dashStyle: "Dash",
lineWidth: 2
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
marker.radius, fillOpacity and symbol tune density and emphasis; per-point overrides highlight outliers.
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "scatter"
},
title: {
text: "Deploy duration vs size"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
title: {
text: "Diff size (files)"
}
},
yAxis: {
title: {
text: "Duration (s)"
}
},
plotOptions: {
scatter: {
marker: {
radius: 6,
fillOpacity: 0.5,
symbol: "circle"
}
}
},
series: [
{
type: "scatter",
name: "Deploys",
data: [
{
x: 2,
y: 42
},
{
x: 3,
y: 55
},
{
x: 4,
y: 61
},
{
x: 5,
y: 58
},
{
x: 7,
y: 74
},
{
x: 9,
y: 82
},
{
x: 12,
y: 95
},
{
x: 18,
y: 210,
marker: {
radius: 10,
fillColor: "#dc2626"
}
}
]
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Dense scatter clouds cluster automatically; clicking a cluster zooms into it. Marker size fades by cluster depth.
import "highcharts/modules/marker-clusters";
import { html } from "mates";
import { Chart, chartAtom } from "mates-charts";
const chart = chartAtom({
chart: {
type: "scatter",
zooming: {
type: "xy"
}
},
title: {
text: "Sensor readings (clustered)"
},
credits: {
enabled: false
},
colors: [
"#00968c",
"#06b6d4",
"#d97706",
"#7c3aed",
"#dc2626",
"#16a34a",
"#0172ad",
"#9333ea"
],
legend: {
enabled: false
},
xAxis: {
min: -5,
max: 15
},
yAxis: {
min: -5,
max: 15
},
plotOptions: {
scatter: {
cluster: {
enabled: true,
allowOverlap: false,
layoutAlgorithm: {
type: "grid",
gridSize: 70
},
marker: {
radius: 14,
fillColor: "rgba(0, 150, 140, 0.45)"
}
}
}
},
series: [
{
type: "scatter",
name: "Readings",
data: [
[
0,
0
],
[
4,
7
],
[
7,
15
],
[
11,
2
],
[
15,
9
],
[
19,
17
],
[
2,
4
],
[
6,
11
],
[
10,
18
],
[
13,
6
],
[
17,
13
],
[
1,
0
],
[
4,
8
],
[
8,
15
],
[
12,
2
],
[
16,
10
],
[
19,
17
],
[
3,
4
],
[
7,
11
],
[
10,
19
],
[
14,
6
],
[
18,
13
],
[
1,
1
],
[
5,
8
],
[
9,
15
],
[
13,
3
],
[
16,
10
],
[
20,
17
],
[
4,
4
],
[
7,
12
],
[
11,
19
],
[
15,
6
],
[
18,
14
],
[
2,
1
],
[
6,
8
],
[
10,
16
],
[
13,
3
],
[
17,
10
],
[
1,
17
],
[
4,
5
],
[
8,
12
],
[
12,
19
],
[
15,
7
],
[
19,
14
],
[
3,
1
],
[
7,
9
],
[
10,
16
],
[
14,
3
],
[
18,
10
],
[
1,
18
],
[
5,
5
],
[
9,
12
],
[
12,
20
],
[
16,
7
],
[
20,
14
],
[
4,
2
],
[
7,
9
],
[
11,
16
],
[
15,
3
],
[
18,
11
],
[
2,
18
],
[
6,
5
],
[
9,
13
],
[
13,
20
],
[
17,
7
],
[
1,
15
],
[
4,
2
],
[
8,
9
],
[
12,
16
],
[
15,
4
],
[
19,
11
],
[
3,
18
],
[
6,
6
],
[
10,
13
],
[
14,
0
],
[
18,
8
],
[
1,
15
],
[
5,
2
],
[
9,
9
],
[
12,
17
],
[
16,
4
],
[
20,
11
],
[
3,
19
],
[
7,
6
],
[
11,
13
],
[
15,
1
],
[
18,
8
],
[
2,
15
],
[
6,
2
],
[
9,
10
],
[
13,
17
],
[
17,
4
],
[
0,
12
],
[
4,
19
],
[
8,
6
],
[
12,
14
],
[
15,
1
],
[
19,
8
],
[
3,
15
],
[
6,
3
],
[
10,
10
],
[
14,
17
],
[
17,
5
],
[
1,
12
],
[
5,
19
],
[
9,
7
],
[
12,
14
],
[
16,
1
],
[
20,
8
],
[
3,
16
],
[
7,
3
],
[
11,
10
],
[
14,
18
],
[
18,
5
],
[
2,
12
],
[
6,
20
],
[
9,
7
],
[
13,
14
],
[
17,
1
],
[
0,
9
],
[
4,
16
],
[
8,
3
],
[
11,
11
],
[
15,
18
],
[
19,
5
],
[
3,
13
],
[
6,
20
],
[
10,
7
],
[
14,
14
],
[
17,
2
],
[
1,
9
],
[
5,
16
],
[
8,
4
],
[
12,
11
],
[
16,
18
],
[
20,
6
],
[
3,
13
],
[
7,
0
],
[
11,
7
],
[
14,
15
],
[
18,
2
],
[
2,
9
],
[
5,
17
],
[
9,
4
],
[
13,
11
],
[
17,
19
],
[
0,
6
],
[
4,
13
],
[
8,
0
],
[
11,
8
],
[
15,
15
],
[
19,
2
],
[
2,
10
],
[
6,
17
],
[
10,
4
],
[
14,
12
],
[
17,
19
],
[
1,
6
],
[
5,
13
],
[
8,
1
],
[
12,
8
],
[
16,
15
],
[
19,
3
],
[
3,
10
],
[
7,
17
],
[
11,
5
],
[
14,
12
],
[
18,
19
],
[
2,
6
],
[
5,
14
],
[
9,
1
],
[
13,
8
],
[
16,
16
],
[
0,
3
],
[
4,
10
],
[
8,
18
],
[
11,
5
],
[
15,
12
],
[
19,
19
],
[
2,
7
],
[
6,
14
],
[
10,
1
],
[
13,
9
],
[
17,
16
],
[
1,
3
],
[
5,
11
],
[
8,
18
],
[
12,
5
],
[
16,
12
],
[
19,
20
],
[
3,
7
],
[
7,
14
],
[
10,
2
],
[
14,
9
],
[
18,
16
],
[
2,
4
],
[
5,
11
],
[
9,
18
],
[
13,
5
],
[
16,
13
],
[
0,
0
],
[
4,
7
],
[
7,
15
],
[
11,
2
],
[
15,
9
],
[
19,
17
],
[
2,
4
],
[
6,
11
],
[
10,
18
],
[
13,
6
],
[
17,
13
],
[
1,
0
],
[
4,
8
],
[
8,
15
],
[
12,
2
],
[
16,
10
],
[
19,
17
],
[
3,
4
],
[
7,
11
],
[
10,
19
],
[
14,
6
],
[
18,
13
],
[
1,
1
],
[
5,
8
],
[
9,
15
],
[
13,
3
],
[
16,
10
],
[
20,
17
],
[
4,
4
],
[
7,
12
],
[
11,
19
],
[
15,
6
],
[
18,
14
],
[
2,
1
],
[
6,
8
],
[
10,
16
],
[
13,
3
],
[
17,
10
],
[
1,
17
],
[
4,
5
],
[
8,
12
],
[
12,
19
],
[
15,
7
],
[
19,
14
],
[
3,
1
],
[
7,
9
],
[
10,
16
],
[
14,
3
],
[
18,
10
],
[
1,
18
],
[
5,
5
],
[
9,
12
],
[
12,
20
],
[
16,
7
],
[
20,
14
],
[
4,
2
],
[
7,
9
],
[
11,
16
],
[
15,
3
],
[
18,
11
],
[
2,
18
],
[
6,
5
],
[
9,
13
],
[
13,
20
],
[
17,
7
],
[
1,
15
],
[
4,
2
],
[
8,
9
],
[
12,
16
],
[
15,
4
],
[
19,
11
],
[
3,
18
],
[
6,
6
],
[
10,
13
],
[
14,
0
],
[
18,
8
],
[
1,
15
],
[
5,
2
],
[
9,
9
],
[
12,
17
],
[
16,
4
],
[
20,
11
],
[
3,
19
],
[
7,
6
],
[
11,
13
],
[
15,
1
],
[
18,
8
],
[
2,
15
],
[
6,
2
],
[
9,
10
],
[
13,
17
],
[
17,
4
],
[
0,
12
],
[
4,
19
],
[
8,
6
],
[
12,
14
],
[
15,
1
],
[
19,
8
],
[
3,
15
],
[
6,
3
]
],
marker: {
radius: 3,
fillOpacity: 0.5
}
}
]
});
// render inside any mates template — give the wrapper a height:
export const MyChart = () =>
html`<div style="height: 22rem">${Chart(chart)}</div>`;
Options reference
mates-charts passes options straight through to Highcharts — these are the keys that matter for scatter charts. See the full Highcharts API for everything else.
| Option | Type | Default | Description |
|---|---|---|---|
chart.type |
"scatter" | — | Selects the scatter series type. |
plotOptions.scatter.marker.radius |
number | 4 | Marker size in pixels. |
plotOptions.scatter.marker.fillOpacity |
number | 1 | Marker transparency — dial down for dense clouds. |
plotOptions.scatter.marker.symbol |
"circle" | "square" | "diamond" | "triangle" | "circle" | Marker shape per series or per point. |
series[].data[].marker |
{ radius, fillColor, symbol } | — | Per-point overrides — highlight outliers. |
series[].data |
[x, y][] | — | Numeric x/y tuples — both axes are true value axes. |