Компонент Icicle и Flamegraph

Компонент Icicle в Nivo используется для визуализации иерархических структур через прямоугольное разбиение пространства, где каждый уровень дерева отображается в виде вложенных прямоугольников. Подобный подход позволяет компактно представлять большие деревья и анализировать распределение значений внутри ветвей.

Icicle-диаграммы основаны на принципе рекурсивного деления области: корневой узел занимает всю ширину, его дети делят пространство по горизонтали или вертикали (в зависимости от ориентации), далее каждый уровень повторяет тот же принцип внутри своего родителя.

Структура данных

Основой является иерархический JSON:

const data = {
  name: "root",
  children: [
    {
      name: "group A",
      children: [
        { name: "A1", value: 120 },
        { name: "A2", value: 80 }
      ]
    },
    {
      name: "group B",
      children: [
        { name: "B1", value: 200 },
        { name: "B2", value: 50 }
      ]
    }
  ]
};

Ключевые правила:

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

Базовая конфигурация Icicle

Компонент ResponsiveIcicle автоматически масштабируется под контейнер:

import { ResponsiveIcicle } from '@nivo/icicle';

const MyIcicle = () => (
  <ResponsiveIcicle
    data={data}
    identity="name"
    value="value"
    valueFormat=">-.2s"
    margin={{ top: 10, right: 10, bottom: 10, left: 10 }}
  />
);

Основные параметры

identity Определяет ключ узла:

identity="name"

Может быть функцией:

identity={node => node.name}

value Указывает поле, используемое для вычисления размера:

value="value"

Или вычисляемая функция:

value={node => node.value ?? 0}

colors Поддерживаются предустановленные палитры и кастомные функции:

colors={{ scheme: 'nivo' }}

или

colors={node => node.depth === 0 ? '#ffcc00' : '#3366ff'}

Оформление и стилизация

Icicle поддерживает настройку визуального оформления через:

  • borderWidth
  • borderColor
  • labels
  • labelTextColor
  • enableLabel
<ResponsiveIcicle
  data={data}
  identity="name"
  value="value"
  borderWidth={1}
  borderColor="#ffffff"
  labelSkipSize={10}
  labelTextColor={{ from: 'color', modifiers: [['darker', 2]] }}
/>

Поведение при взаимодействии

Поддерживаются интерактивные события:

  • onClick
  • onMouseEnter
  • onMouseLeave
<ResponsiveIcicle
  data={data}
  identity="name"
  value="value"
  onCl ick={node => console.log(node.data)}
/>

Tooltip

Tooltip позволяет выводить детальную информацию:

tooltip={({ id, value, color }) => (
  <div style={{ padding: 12, background: '#fff' }}>
    <strong style={{ color }}>{id}</strong>
    <div>{value}</div>
  </div>
)}

Flamegraph

Flamegraph в Nivo представляет иерархические данные в виде «пламенеющих» столбцов, где ширина каждого блока соответствует значению, а вертикальная ось отражает глубину стека вызовов или уровней вложенности.

Flamegraph широко применяется для профилирования производительности: отображение вызовов функций, распределение времени выполнения и анализ «горячих» участков кода.

Структура данных Flamegraph

Формат аналогичен Icicle:

const data = {
  name: "root",
  children: [
    {
      name: "render",
      children: [
        {
          name: "componentA",
          value: 30
        },
        {
          name: "componentB",
          value: 70
        }
      ]
    }
  ]
};

Особенность Flamegraph — интерпретация value как временной или ресурсной метрики.

Базовое использование

import { ResponsiveFlamegraph } from '@nivo/flamegraph';

const MyFlamegraph = () => (
  <ResponsiveFlamegraph
    data={data}
    identity="name"
    value="value"
  />
);

Ключевые параметры

orientation и layout

Flamegraph фиксирует вертикальную ориентацию, но допускает настройки отображения слоев через:

  • padding между блоками
  • высоту уровней
<ResponsiveFlamegraph
  data={data}
  identity="name"
  value="value"
  nodeOpacity={1}
  motionConfig="stiff"
/>

colors и семантика

Цветовая схема часто используется для отражения интенсивности:

colors={{ scheme: 'reds' }}

или динамически:

colors={node => node.depth * 20}

Подсветка и фокусировка

Flamegraph поддерживает взаимодействие, полезное для анализа глубоких стеков:

<ResponsiveFlamegraph
  data={data}
  identity="name"
  value="value"
  onCl ick={node => {
    console.log('selected', node.path);
  }}
/>

Tooltip в Flamegraph

Часто используется для отображения пути вызовов:

tooltip={({ node }) => (
  <div style={{ padding: 10, background: '#111', color: '#fff' }}>
    <div>{node.data.name}</div>
    <div>value: {node.value}</div>
    <div>depth: {node.depth}</div>
  </div>
)}

Отличия Icicle и Flamegraph

Оба компонента работают с иерархическими структурами, но визуально и семантически различаются.

Icicle

  • ориентирован на анализ структуры данных
  • равномерное распределение пространства
  • лучше подходит для категорий и вложенных группировок
  • визуально читается как «разрезанный пирог»

Flamegraph

  • ориентирован на анализ производительности
  • ширина = стоимость выполнения (time, CPU, memory)
  • вертикаль = глубина вызовов
  • визуально напоминает стек вызовов

Поведение при больших данных

При работе с глубокими деревьями важно учитывать:

  • рост количества DOM-элементов
  • стоимость пересчёта layout
  • сложность рендеринга анимаций

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

<ResponsiveIcicle
  data={data}
  animate={false}
  enableLabels={false}
/>

или ограничение глубины предварительной агрегацией данных:

function truncateDepth(node, depth = 3) {
  if (depth === 0) return null;

  return {
    ...node,
    children: node.children?.map(child => truncateDepth(child, depth - 1))
  };
}

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

Оба компонента поддерживают кастомный рендер узлов:

nodeComponent={({ node, style }) => (
  <g transform={style.transform}>
    <rect
      width={style.width}
      height={style.height}
      fill={style.color}
    />
    <text>
      {node.data.name}
    </text>
  </g>
)}

Это позволяет:

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

Градиенты и defs

Расширенная стилизация через defs:

defs={[
  {
    id: 'hot',
    type: 'linearGradient',
    colors: [
      { offset: 0, color: '#ff0000' },
      { offset: 100, color: '#ffff00' }
    ]
  }
]}
fill={[{ match: d => d.value > 100, id: 'hot' }]}

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

Оба компонента используют motion-систему:

motionConfig="gentle"

или отключение:

animate={false}

Анимации особенно затратны при:

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

Практическое использование Icicle и Flamegraph вместе

В сложных аналитических системах Icicle часто используется для:

  • анализа структуры данных
  • сегментации бизнес-логики

Flamegraph применяется для:

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

Совместное использование позволяет связать структуру данных и её поведение во времени, выявляя как организационные, так и производственные закономерности.