Компонент ScatterPlot из библиотеки Nivo предназначен
для отображения наборов точек в двумерной системе координат. Каждая
точка имеет координаты x и y, а сами точки
объединяются в серии.
Базовая структура данных выглядит следующим образом:
const data = [
{
id: 'series-1',
data: [
{ x: 10, y: 20 },
{ x: 15, y: 35 },
{ x: 25, y: 12 },
],
},
{
id: 'series-2',
data: [
{ x: 5, y: 8 },
{ x: 12, y: 28 },
{ x: 18, y: 40 },
],
},
]
Каждый объект верхнего уровня представляет отдельную серию данных.
| Поле | Назначение |
|---|---|
id |
Уникальный идентификатор серии |
data |
Массив точек |
x |
Координата точки по оси X |
y |
Координата точки по оси Y |
Каждая точка внутри массива data является обычным
объектом JavaScript.
{
x: 12,
y: 30
}
{
x: 12,
y: 30,
label: 'Точка A',
color: '#ff0000',
size: 16
}
Дополнительные свойства могут использоваться в:
Наиболее распространённый вариант — использование чисел.
const data = [
{
id: 'temperature',
data: [
{ x: 0, y: 15 },
{ x: 10, y: 18 },
{ x: 20, y: 25 },
{ x: 30, y: 31 },
],
},
]
Такой формат подходит для:
ScatterPlot поддерживает строковые значения координат.
const data = [
{
id: 'sales',
data: [
{ x: 'Январь', y: 120 },
{ x: 'Февраль', y: 180 },
{ x: 'Март', y: 90 },
],
},
]
При использовании строк ось становится категориальной.
ScatterPlot поддерживает отображение временных данных.
const data = [
{
id: 'traffic',
data: [
{ x: '2025-01-01', y: 1200 },
{ x: '2025-01-02', y: 1700 },
{ x: '2025-01-03', y: 900 },
],
},
]
xScale={{
type: 'time',
format: '%Y-%m-%d',
precision: 'day'
}}
Вместо строк допускается применение объектов Date.
const data = [
{
id: 'events',
data: [
{ x: new Date(2025, 0, 1), y: 12 },
{ x: new Date(2025, 0, 2), y: 28 },
{ x: new Date(2025, 0, 3), y: 19 },
],
},
]
ScatterPlot особенно эффективен при сравнении наборов данных.
const data = [
{
id: 'men',
data: [
{ x: 170, y: 65 },
{ x: 180, y: 78 },
{ x: 190, y: 90 },
],
},
{
id: 'women',
data: [
{ x: 160, y: 50 },
{ x: 170, y: 60 },
{ x: 180, y: 72 },
],
},
]
Каждая серия автоматически получает:
Во многих приложениях данные приходят из API в неподходящем формате.
const apiData = [
{
country: 'Germany',
stats: {
population: 83,
gdp: 4200,
},
},
{
country: 'France',
stats: {
population: 67,
gdp: 3100,
},
},
]
const data = [
{
id: 'countries',
data: apiData.map(item => ({
x: item.stats.population,
y: item.stats.gdp,
country: item.country,
})),
},
]
ScatterPlot часто используется вместе с map.
const values = [10, 15, 22, 30]
const data = [
{
id: 'dynamic',
data: values.map((value, index) => ({
x: index,
y: value,
})),
},
]
[
{
"year": 2020,
"profit": 120
},
{
"year": 2021,
"profit": 180
}
]
async function loadChartData() {
const response = await fetch('/api/stats')
const result = await response.json()
return [
{
id: 'profit',
data: result.map(item => ({
x: item.year,
y: item.profit,
})),
},
]
}
Каждая точка может содержать произвольные поля.
const data = [
{
id: 'users',
data: [
{
x: 20,
y: 1500,
userId: 15,
username: 'alex',
active: true,
},
],
},
]
Эти данные особенно полезны в tooltip:
tooltip={({ node }) => (
<div>
<strong>{node.data.username}</strong>
<div>ID: {node.data.userId}</div>
</div>
)}
ScatterPlot может работать как bubble chart.
const data = [
{
id: 'products',
data: [
{
x: 12,
y: 30,
z: 100,
},
{
x: 20,
y: 18,
z: 250,
},
],
},
]
nodeSize={node => node.data.z / 10}
Поле z обычно обозначает:
Иногда данные содержат пропуски.
const data = [
{
id: 'metrics',
data: [
{ x: 1, y: 10 },
{ x: 2, y: null },
{ x: 3, y: 25 },
],
},
]
Следует учитывать:
null может привести к ошибкам рендераconst filtered = sourceData.filter(
item => item.y !== null
)
ScatterPlot часто используется для визуализации тысяч точек.
const data = [
{
id: 'random',
data: Array.from({ length: 1000 }, (_, i) => ({
x: i,
y: Math.random() * 100,
})),
},
]
type Point = {
x: number
y: number
}
type Serie = {
id: string
data: Point[]
}
type UserPoint = {
x: number
y: number
username: string
age: number
}
type UserSerie = {
id: string
data: UserPoint[]
}
Компонент ResponsiveScatterPlot использует тот же
формат.
<ResponsiveScatterPlot
data={data}
/>
Различий между ScatterPlot и
ResponsiveScatterPlot в структуре данных нет.
Перед передачей данных в ScatterPlot часто выполняется нормализация.
[
{ valueX: 12, valueY: 55 },
{ valueX: 18, valueY: 70 },
]
const normalized = raw.map(item => ({
x: item.valueX,
y: item.valueY,
}))
Неверно:
[
{
id: 'test'
}
]
Верно:
[
{
id: 'test',
data: []
}
]
Неверно:
{
x: {},
y: []
}
Верно:
{
x: 10,
y: 20
}
Неверно:
[
{ id: 'series', data: [] },
{ id: 'series', data: [] },
]
Идентификаторы серий должны быть уникальными.
const data = [
{
id: 'sales',
data: [
{ x: 1, y: 5000 },
{ x: 2, y: 7200 },
{ x: 3, y: 6100 },
],
},
]
const data = [
{
id: 'cities',
data: [
{
x: 37.6173,
y: 55.7558,
city: 'Москва',
},
{
x: 30.3141,
y: 59.9386,
city: 'Санкт-Петербург',
},
],
},
]
const data = [
{
id: 'experiment',
data: [
{
x: 0.1,
y: 12.4,
},
{
x: 0.2,
y: 15.9,
},
],
},
]
При работе с большими массивами данных желательно:
{
x: {
value: {
current: 12
}
}
}
{
x: 12
}
function validateData(data) {
return data.every(series =>
Array.isArray(series.data)
)
}
function isValidPoint(point) {
return (
typeof point.x !== 'undefined' &&
typeof point.y !== 'undefined'
)
}
function createScatterData(items, xKey, yKey, id) {
return [
{
id,
data: items.map(item => ({
x: item[xKey],
y: item[yKey],
})),
},
]
}
const chartData = createScatterData(
users,
'age',
'salary',
'employees'
)
Тип данных напрямую влияет на настройки xScale и
yScale.
xScale={{
type: 'linear'
}}
Используется для чисел.
xScale={{
type: 'time'
}}
Используется для дат.
xScale={{
type: 'point'
}}
Используется для строковых значений.
ScatterPlot допускает смешанные форматы.
const data = [
{
id: 'hybrid',
data: [
{
x: '2025-01',
y: 120,
region: 'EU',
users: 500,
},
],
},
]
Главное условие — корректная настройка шкалы.
При обновлении данных желательно создавать новые объекты.
data[0].data.push({
x: 10,
y: 20,
})
const updated = [
{
...data[0],
data: [
...data[0].data,
{
x: 10,
y: 20,
},
],
},
]
Такой подход особенно важен в React-приложениях.