Компонент 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 отсутствует, он агрегируется из
потомковКомпонент 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 поддерживает настройку визуального оформления через:
borderWidthborderColorlabelslabelTextColorenableLabel<ResponsiveIcicle
data={data}
identity="name"
value="value"
borderWidth={1}
borderColor="#ffffff"
labelSkipSize={10}
labelTextColor={{ from: 'color', modifiers: [['darker', 2]] }}
/>
Поддерживаются интерактивные события:
onClickonMouseEnteronMouseLeave<ResponsiveIcicle
data={data}
identity="name"
value="value"
onCl ick={node => console.log(node.data)}
/>
Tooltip позволяет выводить детальную информацию:
tooltip={({ id, value, color }) => (
<div style={{ padding: 12, background: '#fff' }}>
<strong style={{ color }}>{id}</strong>
<div>{value}</div>
</div>
)}
Flamegraph в Nivo представляет иерархические данные в виде «пламенеющих» столбцов, где ширина каждого блока соответствует значению, а вертикальная ось отражает глубину стека вызовов или уровней вложенности.
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 фиксирует вертикальную ориентацию, но допускает настройки отображения слоев через:
<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={({ 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>
)}
Оба компонента работают с иерархическими структурами, но визуально и семантически различаются.
При работе с глубокими деревьями важно учитывать:
Оптимизационные подходы:
<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={[
{
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 применяется для:
Совместное использование позволяет связать структуру данных и её поведение во времени, выявляя как организационные, так и производственные закономерности.