Кастомизация узлов и рёбер

В визуализациях графов в Nivo структура данных строится вокруг двух фундаментальных сущностей — узлов (nodes) и рёбер (links или edges). Узлы представляют собой вершины графа, содержащие идентификатор, метаданные и визуальные параметры. Рёбра описывают связи между узлами и могут хранить дополнительную информацию: вес, тип связи, направление, а также стилизацию.

Типичная структура данных для сетевых визуализаций Nivo выглядит следующим образом:

  • nodes — массив объектов узлов
  • links — массив объектов связей между узлами

Каждый узел обычно содержит:

  • id — уникальный идентификатор
  • дополнительные поля (group, value, color, depth, data)

Каждое ребро содержит:

  • source — идентификатор исходного узла
  • target — идентификатор целевого узла
  • дополнительные атрибуты (weight, distance, color, thickness)

Эта модель используется в компонентах наподобие @nivo/network, @nivo/sankey, @nivo/force, где визуализация графа строится динамически на основе вычислений layout-алгоритма.


Базовая кастомизация узлов

В Nivo узлы рендерятся как изолированные компоненты, что позволяет полностью переопределять их внешний вид через nodeComponent.

Механизм кастомизации узла строится на функции:

  • принимает объект узла с координатами
  • возвращает JSX-элемент (SVG или HTML внутри SVG-контекста)

Стандартный узел может быть заменён на произвольную форму:

  • круг
  • прямоугольник
  • иконка
  • комбинированный элемент с текстом и индикаторами

Ключевые параметры, доступные в кастомизации:

  • node.x, node.y — позиция
  • node.size — базовый размер
  • node.color — вычисленный цвет
  • node.data — пользовательские данные
  • node.selected, node.isActive — состояния взаимодействия

Пример логики кастомного узла:

  • центрирование по координатам
  • изменение формы в зависимости от типа
  • отображение подписи при достаточном масштабе
  • визуальное выделение активных элементов

SVG-рендеринг узлов

SVG является основным режимом отрисовки в Nivo для графов. Он обеспечивает точное позиционирование и удобную работу с трансформациями.

Кастомный SVG-узел обычно строится вокруг группы <g>:

  • трансформация через translate(x, y)
  • использование базовых фигур (circle, rect, path)
  • текстовые элементы (text, tspan)

Основные принципы:

  • координаты узла не задают позицию напрямую элементов, используется transform
  • центр узла считается опорной точкой
  • стилизация зависит от состояния взаимодействия

Распространённые техники:

  • динамический радиус в зависимости от веса узла
  • изменение прозрачности при деактивации
  • обводка для выбранных элементов
  • использование градиентов и паттернов через <defs>

Canvas-рендеринг узлов

В режимах с высокой плотностью данных используется Canvas-рендеринг. В этом случае кастомизация узлов происходит через imperative API, а не JSX.

Особенности:

  • отсутствие DOM-элементов
  • прямое рисование через 2D context
  • оптимизация для больших графов (тысячи узлов)

Кастомизация включает:

  • ручное рисование форм (arc, rect, lineTo)
  • управление стилем через ctx.fillStyle, ctx.strokeStyle
  • контроль текста через fillText

Логика узла в Canvas:

  • вычисление состояния (active, hovered, selected)
  • выбор цвета
  • отрисовка формы
  • отрисовка подписи при необходимости

Canvas требует строгого контроля производительности, так как каждая перерисовка выполняется вручную.


Рёбра в Nivo определяют визуальные связи между узлами и могут быть полностью переопределены через linkComponent.

Базовые параметры ребра:

  • координаты начала и конца (sourceX, sourceY, targetX, targetY)
  • толщина линии (width)
  • цвет (color)
  • непрозрачность (opacity)

Основные подходы к кастомизации:

  • изменение формы линии
  • использование кривых Безье вместо прямых сегментов
  • визуализация направления через стрелки
  • адаптивная толщина в зависимости от веса связи

Часто применяется динамическая стилизация:

  • усиление толщины при увеличении веса
  • изменение цвета при наведении на узел
  • скрытие второстепенных связей при фокусировке

Маршрутизация рёбер

Рёбра могут быть реализованы не только как прямые линии, но и как кривые. Это особенно важно в плотных графах, где пересечения линий снижают читаемость.

Используемые подходы:

  • линейные сегменты (straight links)
  • кривые Безье (curved links)
  • ортогональные маршруты (horizontal/vertical routing)

Кривые позволяют:

  • избегать пересечений
  • визуально группировать связи
  • подчёркивать направление потока

При использовании кривых ключевым становится контроль контрольных точек, которые формируют изгиб линии между узлами.


Стрелки и направление связей

Направленные графы требуют визуального обозначения направления ребра. В Nivo это реализуется через:

  • маркеры SVG (marker-end)
  • кастомные отрисованные стрелки
  • изменение формы конца линии

Основные техники:

  • добавление треугольника на конце пути
  • вычисление угла наклона ребра
  • синхронизация стрелки с кривой линии

Стрелки часто масштабируются в зависимости от:

  • длины ребра
  • веса связи
  • уровня зума

Стилизация через theme

Система темы Nivo позволяет централизованно управлять внешним видом узлов и рёбер.

Параметры темы:

  • nodes: базовые цвета, обводки, шрифты
  • links: цвет линий, прозрачность, активные состояния
  • labels: типографика подписей

Кастомизация через тему обеспечивает:

  • единообразие визуального стиля
  • упрощение управления дизайн-системой
  • переиспользуемость конфигураций

Тема часто комбинируется с локальной кастомизацией компонентов для тонкой настройки отдельных элементов.


Состояния взаимодействия

Узлы и рёбра поддерживают интерактивные состояния:

  • hover
  • active
  • selected
  • highlighted

Каждое состояние может влиять на:

  • цвет
  • размер
  • прозрачность
  • толщину линии
  • отображение дополнительных меток

Типичная логика взаимодействия:

  • при наведении на узел подсвечиваются связанные рёбра
  • остальные элементы становятся менее заметными
  • активный узел увеличивается в размере
  • текст появляется только при фокусе

Анимации узлов и рёбер

Nivo использует анимационную систему для плавного перехода между состояниями графа.

Анимации применяются к:

  • перемещению узлов при пересчёте layout
  • изменению толщины рёбер
  • появлению/исчезновению элементов
  • смене цвета при взаимодействии

Ключевые особенности:

  • интерполяция координат
  • плавные переходы opacity
  • синхронизация анимаций узлов и связей

При больших графах анимации могут отключаться для повышения производительности.


Производительность при кастомизации

Кастомизация узлов и рёбер напрямую влияет на производительность графа.

Основные факторы:

  • сложность SVG-дерева
  • количество перерисовок
  • использование анимаций
  • глубина кастомных вычислений

Оптимизационные подходы:

  • упрощение узлов до базовых фигур
  • переход на Canvas при больших данных
  • мемоизация компонентов узлов
  • минимизация изменений props
  • отключение лишних hover-эффектов

Для графов с тысячами элементов критично избегать тяжёлых JSX-структур внутри nodeComponent.


Комбинированная кастомизация узлов и рёбер

Наиболее гибкие визуализации строятся на совместной настройке узлов и рёбер.

Распространённые комбинации:

  • узлы с динамическими индикаторами + рёбра с весовой толщиной
  • цветовая группировка узлов + цветовая дифференциация связей
  • интерактивный фокус + затемнение второстепенных элементов

Такая комбинация позволяет формировать сложные структуры данных:

  • социальные сети
  • зависимости в системах
  • потоки данных
  • иерархические связи