Библиотека визуализации данных Nivo опирается на строго определённые
форматы иерархических структур, которые напрямую влияют на корректность
построения таких компонентов, как деревья, treemap, sunburst и circle
packing. Основой служит модель вложенных объектов, соответствующая
принципам d3-hierarchy, где каждый узел содержит ссылку на
дочерние элементы и описывает часть общей структуры.
Ключевой принцип заключается в том, что иерархические компоненты не работают с плоскими массивами напрямую. Им требуется дерево, в котором каждый уровень вложенности формирует отдельный слой визуализации.
Наиболее распространённая форма представления иерархии — вложенный JSON-объект:
const data = {
name: "root",
children: [
{
name: "branch A",
children: [
{ name: "leaf A1", value: 10 },
{ name: "leaf A2", value: 20 }
]
},
{
name: "branch B",
children: [
{ name: "leaf B1", value: 15 }
]
}
]
};
В компонентах Nivo значение value может быть либо задано
явно, либо вычислено через суммирование дочерних узлов.
Внутренне Nivo использует алгоритмы суммирования, аналогичные
d3.sum. Если у родительского узла отсутствует
value, оно вычисляется рекурсивно:
Пример логики:
branch A = leaf A1 + leaf A2
branch B = leaf B1
root = branch A + branch B
Это критически важно для treemap и sunburst, где площадь или угол пропорциональны величине значения.
Treemap-компонент в Nivo ожидает тот же вложенный формат, но с акцентом на числовые значения:
const treemapData = {
name: "root",
children: [
{
name: "group 1",
children: [
{ name: "item 1", value: 100 },
{ name: "item 2", value: 300 }
]
}
]
};
Дополнительно поддерживаются параметры:
Sunburst использует тот же иерархический JSON, но интерпретирует структуру как радиальные сектора.
const sunburstData = {
name: "total",
children: [
{
name: "segment A",
children: [
{ name: "A1", value: 40 },
{ name: "A2", value: 60 }
]
}
]
};
Особенность заключается в том, что каждый уровень иерархии
преобразуется в кольцо, а value определяет угловую
долю.
Circle packing требует строгой древовидной структуры без пропусков уровней.
const circleData = {
name: "root",
children: [
{
name: "cluster 1",
children: [
{ name: "node 1", value: 5 },
{ name: "node 2", value: 8 }
]
}
]
};
Здесь важен не только value, но и глубина вложенности,
так как она влияет на радиус и позиционирование окружностей.
Некоторые сценарии требуют хранения данных в плоском виде. В этом
случае используется преобразование через d3.stratify,
которое поддерживается в экосистеме Nivo.
Пример плоской структуры:
const flatData = [
{ id: "root" },
{ id: "A", parent: "root", value: 0 },
{ id: "B", parent: "root", value: 0 },
{ id: "A1", parent: "A", value: 10 },
{ id: "A2", parent: "A", value: 20 }
];
parentПосле преобразования структура становится иерархической и может использоваться всеми tree-компонентами.
import { stratify } from "d3-hierarchy";
const root = stratify()
.id(d => d.id)
.parentId(d => d.parent)(flatData);
Результат — объект с вложенными children, совместимый с
Nivo.
type HierarchyNode = {
id?: string;
name?: string;
value?: number;
color?: string;
children?: HierarchyNode[];
};
Для плоской модели:
type FlatNode = {
id: string;
parent?: string;
value?: number;
};
Разные компоненты Nivo интерпретируют одни и те же данные по-разному:
Несмотря на общий формат, глубина и распределение value
радикально изменяют визуальный результат.
Перед использованием иерархии часто выполняется подготовка:
idПример нормализованного узла:
{
id: "metrics.cpu",
name: "CPU",
value: 72,
children: []
}
Иерархии могут содержать пропуски уровней, однако некоторые компоненты Nivo требуют плотной структуры:
{
name: "A",
children: [
{
name: "B",
children: [
{ name: "C", value: 1 }
]
}
]
}
При отсутствии промежуточных узлов визуализация может изменять геометрию распределения элементов, особенно в radial-компонентах.
Узлы могут содержать дополнительные поля, не влияющие на расчёты, но используемые для кастомизации:
{
name: "node",
value: 10,
metadata: {
region: "EU",
status: "active"
}
}
Nivo игнорирует неизвестные поля, но они доступны в кастомных tooltip, слоях и форматтерах.
Если value отсутствует:
{ name: "empty branch", children: [] }
Такие узлы часто фильтруются на этапе подготовки данных.
Для корректного обновления анимаций важно поддерживать стабильные идентификаторы:
name без изменения структуры приводит к
пересозданию узлаid обеспечивает устойчивость
diff-алгоритма{ id: "node-1", value: 50 }
Единая модель дерева позволяет использовать один и тот же набор данных в разных визуализациях Nivo без изменения структуры, меняя только способ интерпретации: