В библиотеке Nivo механизм отображения столбчатых диаграмм поддерживает два основных режима компоновки многосерийных данных: grouped и stacked. Эти режимы определяют способ визуального представления нескольких наборов значений, относящихся к одним и тем же категориям по оси X.
Основа работы столбчатых диаграмм в Nivo — массив объектов, где каждый объект представляет категорию, а значения серий задаются отдельными полями.
const data = [
{
country: 'Kazakhstan',
sales: 120,
profit: 45,
loss: 10,
},
{
country: 'Russia',
sales: 180,
profit: 60,
loss: 20,
},
];
Поля sales, profit, loss
выступают как серии. Поле country используется как индекс
категории.
При передаче данных в компонент важно явно указать:
indexBy — поле категорииkeys — массив серийkeys={['sales', 'profit', 'loss']}
indexBy="country"
Режим grouped отображает серии рядом внутри одной категории. Каждое значение получает собственный столбец, что позволяет сравнивать величины внутри одной группы напрямую.
import { ResponsiveBar } from '@nivo/bar';
<ResponsiveBar
data={data}
keys={['sales', 'profit', 'loss']}
indexBy="country"
groupMode="grouped"
margin={{ top: 50, right: 130, bottom: 50, left: 60 }}
padding={0.3}
colors={{ scheme: 'nivo' }}
/>
Ось Y строится по максимальному значению среди всех серий. Это обеспечивает корректное сравнение величин между группами, но может снижать визуальную различимость малых значений при наличии выбросов.
Режим stacked объединяет серии в один столбец на категорию. Значения суммируются, образуя составную структуру.
<ResponsiveBar
data={data}
keys={['sales', 'profit', 'loss']}
indexBy="country"
groupMode="stacked"
margin={{ top: 50, right: 130, bottom: 50, left: 60 }}
padding={0.3}
colors={{ scheme: 'nivo' }}
/>
Каждая категория формирует один столбец, разбитый на сегменты:
Математически высота столбца выражается как:
y = _{i=1}^{n} x_i
где (x_i) — значения серий в пределах одной категории.
Различие режимов определяется не только визуально, но и логически.
Оба режима поддерживают отрицательные числа, но поведение различается.
Отрицательные значения отображаются ниже нулевой оси независимо от других серий. Пересечения отсутствуют.
Отрицательные значения формируют отдельную нижнюю часть стека. Итоговая структура может иметь как положительную, так и отрицательную составляющую, разделённую базовой линией.
Цвета назначаются на уровне keys и сохраняются между
режимами. Это обеспечивает сопоставимость восприятия при переключении
между grouped и stacked.
colors={{ scheme: 'category10' }}
При необходимости используется кастомная функция:
colors={(bar) => {
if (bar.id === 'sales') return '#4f46e5';
if (bar.id === 'profit') return '#22c55e';
return '#ef4444';
}}
В stacked режиме легенда отражает вклад компонентов в общий итог. В grouped режиме — отдельные независимые значения.
legends={[
{
dataFrom: 'keys',
anchor: 'bottom-right',
direction: 'column',
},
]}
Nivo поддерживает плавный переход между grouped и stacked при
изменении свойства groupMode. При этом:
const [mode, setMode] = useState('grouped');
<ResponsiveBar groupMode={mode} />
При увеличении числа серий различия между режимами становятся критичнее:
При высокой кардинальности серий stacked режим обеспечивает более компактное представление.
В grouped режиме padding влияет на расстояние между группами и внутри группы:
padding={0.2}
Используется для увеличения расстояния между столбцами внутри группы, особенно при большом числе keys.
Ось автоматически пересчитывается в зависимости от выбранного режима, однако при stacked значения часто требуют более широкого диапазона из-за суммирования.
Tooltip в grouped режиме показывает отдельное значение серии. В stacked режиме дополнительно доступна информация о суммарном значении категории и доле каждого сегмента относительно общего стека.
При работе с динамическими наборами данных используется нормализация keys:
const keys = Object.keys(data[0]).filter(k => k !== 'country');
Такой подход обеспечивает автоматическую адаптацию диаграммы при изменении структуры входных данных.
Использование одного и того же набора данных в двух режимах позволяет формировать два аналитических слоя:
Совмещение этих режимов в интерфейсных решениях повышает информативность без изменения структуры данных.