Иерархические визуализации в Nivo строятся вокруг строгого расчёта координат узлов, где каждая вершина дерева получает позицию на плоскости в зависимости от выбранного направления раскладки и параметров компоновки. Ориентация дерева определяет базовую систему координат, а алгоритм позиционирования узлов отвечает за распределение пространства между уровнями и соседними элементами.
В Nivo для деревьев используется параметр layout,
который задаёт направление роста структуры. От него зависит, как
интерпретируются координаты x и y каждого
узла.
При вертикальной компоновке корневой узел располагается сверху, а дочерние элементы распределяются вниз по оси Y.
Такая схема часто применяется для классических организационных диаграмм.
import { ResponsiveTree } from '@nivo/tree'
const data = {
id: 'root',
children: [
{ id: 'A' },
{ id: 'B' }
]
}
const TreeChart = () => (
<ResponsiveTree
data={data}
identity="id"
layout="vertical"
nodeSize={{ x: 140, y: 60 }}
/>
)
Внутри алгоритма:
При горизонтальном расположении дерево разворачивается слева направо. Корень фиксируется слева, потомки уходят вправо.
<ResponsiveTree
data={data}
identity="id"
layout="horizontal"
nodeSize={{ x: 160, y: 80 }}
/>
Горизонтальная схема применяется для больших и глубоких деревьев, так как снижает визуальную перегруженность по вертикали.
Некоторые реализации Nivo поддерживают инвертированные направления:
bottom-to-top — рост вверхright-to-left — рост влевоЭти варианты не меняют структуру данных, но инвертируют систему координат:
Позиционирование строится на основе модифицированного дерева Рейнгольда–Тилфорда или аналогичных иерархических алгоритмов.
Основные этапы:
Каждый узел получает уровень вложенности:
depth(root) = 0
depth(child) = depth(parent) + 1
Глубина напрямую влияет на координату основной оси.
Каждое поддерево получает собственный сегмент пространства. Ширина сегмента зависит от количества листьев:
После распределения листьев выполняется обратный проход:
Это предотвращает перекосы структуры в одну сторону.
Для вертикальной ориентации:
x = horizontalPosition(node)
y = depth(node) * levelHeight
Для горизонтальной:
x = depth(node) * levelWidth
y = verticalPosition(node)
Параметр nodeSize определяет базовый шаг между
узлами:
nodeSize={{ x: 180, y: 90 }}
x — горизонтальный интервал между соседямиy — вертикальный интервал между уровнямиУвеличение значений:
Механизм separation управляет дополнительным расстоянием
между узлами одного уровня.
Функция имеет вид:
separation={(a, b) => a.parent === b.parent ? 1 : 2}
Логика:
Это влияет на «воздух» между поддеревьями, особенно при глубокой вложенности.
Рёбра (links) строятся на основе координат узлов. При смене ориентации меняется форма кривых:
Форма связи пересчитывается автоматически в зависимости от направления дерева, что сохраняет визуальную целостность.
Отдельный режим — radial layout — использует полярные координаты:
Преобразование:
x = r * cos(θ)
y = r * sin(θ)
Радиальная модель используется для компактного отображения больших деревьев.
Позиция корня задаёт систему отсчёта всей структуры:
Центрирование выполняется через смещение всего графа после первичного расчёта координат.
После вычисления позиций применяется нормализация:
Это обеспечивает корректное отображение вне зависимости от размера контейнера.
На одном уровне узлы могут выравниваться:
Выравнивание влияет на симметрию дерева, особенно при неравномерных ветвлениях.
Характер исходного графа напрямую влияет на итоговую геометрию:
Алгоритм позиционирования не изменяет структуру, а лишь оптимизирует её отображение.
При пересечении поддеревьев применяется локальная коррекция:
Это особенно заметно при плотных графах с большим количеством листьев.
Внутреннее представление каждого узла включает:
x, y — экранные координатыdepth — уровень вложенностиparent — ссылка на родителяtreePath — путь от корняЭти данные формируют основу для рендера и взаимодействия, а ориентация дерева определяет только интерпретацию осей и алгоритм распределения пространства.