Визуальные компоненты Nivo для круговых и радиальных диаграмм опираются на концепцию взаимодействия состояний сегментов: каждый сектор может находиться в активном, неактивном или нейтральном состоянии. Эта модель используется для управления визуальным фокусом пользователя и построения интерактивной анимации, где внимание направляется на конкретную дугу, а остальные элементы приглушаются.
В основе механики лежит разделение визуального веса между элементами графика через параметры масштаба, прозрачности и смещения. При наведении курсора или программной активации сегмента библиотека пересчитывает параметры отрисовки, изменяя геометрию дуги и её визуальное выделение.
Каждый сектор диаграммы в Nivo описывается набором геометрических параметров: углы начала и конца, радиус, цвет и идентификатор. Поверх этого базового описания накладываются состояния:
Активная дуга — сегмент, который находится в фокусе взаимодействия. Характеризуется увеличением радиуса, усилением контраста и возможным изменением тени или смещения.
Неактивные дуги — остальные сегменты, которые теряют визуальную значимость. Обычно они становятся полупрозрачными или слегка уменьшаются визуально.
Ключевой принцип — сохранение структуры данных при изменении только визуального представления.
Компонент ResponsivePie предоставляет набор свойств,
отвечающих за поведение активных и неактивных сегментов:
activeOuterRadiusOffset — увеличение внешнего радиуса
активного сегментаactiveInnerRadiusOffset — изменение внутреннего радиуса
(для кольцевых диаграмм)inactiveOuterRadiusOffset — смещение неактивных
сегментов внутрьinactiveOuterRadiusOpacity — прозрачность неактивных
дугinactiveInnerRadiusOffset — дополнительная деформация
внутреннего радиусаКомбинация этих параметров формирует эффект «выдвижения» активного сектора на передний план.
<ResponsivePie
data={data}
margin={{ top: 40, right: 80, bottom: 80, left: 80 }}
innerRadius={0.6}
activeOuterRadiusOffset={8}
inactiveOuterRadiusOffset={4}
inactiveOuterRadiusOpacity={0.4}
animate={true}
motionConfig="gentle"
/>
В этом примере активный сектор визуально «поднимается», а остальные теряют насыщенность.
Интерактивность чаще всего строится вокруг события наведения. Nivo использует внутренний механизм управления состоянием activeIndex или activeId, который изменяется при событиях мыши.
Типовой сценарий:
Дополнительно можно управлять активным сегментом вручную:
const [activeId, setActiveId] = useState(null);
<ResponsivePie
data={data}
activeId={activeId}
onMouseEn ter={(datum) => setActiveId(datum.id)}
onMouseLe ave={() => setActiveId(null)}
/>
Такой подход позволяет синхронизировать график с внешними компонентами интерфейса.
Nivo использует react-spring для построения плавных
переходов между геометрическими состояниями дуг. При смене активного
сегмента происходит интерполяция:
Анимация не является дискретной, что позволяет избежать резких скачков при переключении активных элементов.
motionConfig="stiff"
Конфигурации анимации определяют поведение переходов:
gentle — плавные и медленные переходыstiff — быстрые, более резкие измененияwobbly — с небольшим эффектом «пружины»Помимо стандартных offset-параметров, часто применяется стратегия масштабирования через кастомные слои или модификацию радиуса.
Активная дуга может:
Пример кастомного выделения:
const CustomLayer = ({ arcs, activeId }) => {
return arcs.map(arc => {
const isActive = arc.data.id === activeId;
return (
<path
key={arc.data.id}
d={arc.path}
fill={arc.color}
opacity={isActive ? 1 : 0.3}
transform={isActive ? "scale(1.05)" : "scale(1)"}
/>
);
});
};
Такой слой полностью переопределяет визуальную логику выделения, обходя стандартные настройки.
Одним из наиболее эффективных способов визуального разделения является управление opacity. В Nivo это реализуется через параметры неактивного состояния, однако часто требуется более тонкая настройка.
Логика обычно строится так:
inactiveOuterRadiusOpacity={0.35}
В более сложных интерфейсах прозрачность может зависеть от расстояния до активного сектора в данных или от категории.
В реальных интерфейсах график редко существует изолированно. Активная дуга часто синхронизируется с:
Пример синхронизации:
const [active, setActive] = useState(null);
<ResponsivePie
data={data}
activeOuterRadiusOffset={10}
onMouseEn ter={(d) => setActive(d.id)}
onMouseLe ave={() => setActive(null)}
/>
<DataPanel activeId={active} />
Изменение активного сектора становится триггером для обновления других частей интерфейса.
Стандартная визуализация Nivo ограничена геометрией SVG-дуг. Для
более выразительных эффектов применяется переопределение слоя
arcLinkLabels или создание полностью кастомного слоя.
Расширенные эффекты включают:
const CustomArc = ({ arc }) => {
return (
<g>
<path d={arc.path} fill={arc.color} />
{arc.isActive && (
<path
d={arc.path}
fill="none"
stroke={arc.color}
strokeWidth={4}
/>
)}
</g>
);
};
В некоторых сценариях требуется поддержка нескольких активных дуг одновременно. Это используется в сравнительных интерфейсах или при выделении групп данных.
Логика в этом случае меняется:
const isActive = activeIds.includes(arc.data.id);
Визуально такие дуги могут не увеличиваться, а лишь менять цветовую интенсивность, чтобы избежать перегрузки композиции.
При работе с большими наборами данных (50–200 сегментов) важно контролировать производительность анимации.
Практики оптимизации:
animate={true}
motionConfig="gentle"
Дополнительно можно анимировать только активный сектор, оставляя остальные статичными.
Цвет часто используется как дополнительный канал выделения. При активации дуги происходит:
Неактивные элементы переходят в приглушённую палитру, что усиливает иерархию данных.
Логика может строиться на функциях:
fill: (d) =>
d.id === activeId
? d.color
: lighten(d.color, 0.4)
Наиболее сложные визуальные схемы строятся через комбинацию:
Такая многослойная модель позволяет формировать эффект «всплывающего» сегмента, который воспринимается как физически приближённый к пользователю элемент, в то время как остальные уходят в фон.