Визуализации в Nivo строятся вокруг декларативной модели
React-компонентов, где каждый график не только отображает данные, но и
предоставляет слой взаимодействий поверх визуальных элементов. Для
региональных визуализаций (карты, хороплеты, heatmap-подобные слои,
диаграммы с областями) ключевую роль играют события hover и
click, позволяющие превращать статичную картину в
интерактивную систему анализа данных.
Интерактивность в Nivo реализуется через набор стандартных пропсов событий, которые передаются в компонент графика. Эти пропсы пробрасываются на уровень отдельных элементов (bar, arc, region, mesh feature), что обеспечивает точечное управление поведением.
Любая интерактивность в Nivo строится вокруг трёх основных событий:
onMouseEnteronMouseMoveonMouseLeaveonClickКаждое событие получает два ключевых аргумента:
Пример общей структуры:
onMouseEn ter={(datum, event) => {
// обработка наведения
}}
onCl ick={(datum, event) => {
// обработка клика
}}
В региональных визуализациях datum обычно представляет
географический объект: страну, регион, полигон или административную
единицу с привязанными значениями.
Наведение мыши в региональных графиках используется для:
Типичный сценарий — изменение визуального состояния элемента при наведении:
const [activeRegion, setActiveRegion] = useState(null);
<ResponsiveChoropleth
data={data}
features={features}
onMouseEn ter={(feature) => setActiveRegion(feature.id)}
onMouseLe ave={() => setActiveRegion(null)}
theme={{
labels: {
text: {
fill: '#333'
}
}
}}
/>
Дальнейшая стилизация выполняется через условные функции:
fill: ({ feature }) =>
feature.id === activeRegion ? '#ff6b6b' : '#4dabf7'
Tooltip в Nivo является встроенным механизмом отображения контекстной информации. Он активируется автоматически при hover, но может быть полностью кастомизирован.
Стандартный tooltip:
tooltip={({ feature }) => (
<div>
<strong>{feature.properties.name}</strong>
<div>Значение: {feature.value}</div>
</div>
)}
Кастомизация часто включает:
Hover фактически становится точкой входа в слой аналитики, а не просто визуальным эффектом.
Клик в Nivo чаще всего используется для фиксации состояния. Если hover — это временный контекст, то click — это закреплённый выбор.
Типовые сценарии:
Пример обработки клика:
const [selectedRegion, setSelectedRegion] = useState(null);
<ResponsiveChoropleth
data={data}
features={features}
onCl ick={(feature) => {
setSelectedRegion(feature.id);
}}
/>
Далее выбранный регион используется как фильтр:
const filteredData = allData.filter(
d => d.regionId === selectedRegion
);
В сложных интерфейсах важно разделять временное и фиксированное состояние:
Пример комбинированной логики:
fill: ({ feature }) => {
if (feature.id === selectedRegion) return '#fa5252';
if (feature.id === hoveredRegion) return '#74c0fc';
return '#ced4da';
}
onMouseEn ter={(feature) => setHoveredRegion(feature.id)}
onMouseLe ave={() => setHoveredRegion(null)}
onCl ick={(feature) => setSelectedRegion(feature.id)}
Такой подход позволяет строить интерфейсы с уровнем взаимодействия, близким к аналитическим системам BI-класса.
В компонентах вроде ResponsiveChoropleth или
ResponsiveGeoMap регионы представлены GeoJSON-объектами.
Это влияет на модель взаимодействия:
Nivo использует оптимизированные механизмы определения попадания курсора в регион, что позволяет сохранять производительность даже на больших наборах геоданных.
Во многих региональных графиках используется mesh-слой, который отвечает за точность hover-детекции.
Особенности:
<Choropleth
enableGraticule={true}
meshEnabled={true}
/>
Mesh часто невидим, но именно он отвечает за корректность событий.
Одной из сильных сторон Nivo является возможность связывать несколько графиков через общие состояния.
Пример:
const [activeRegion, setActiveRegion] = useState(null);
Передача в разные компоненты:
<GeoMap onHo ver={setActiveRegion} />
<BarChart activeRegion={activeRegion} />
<LineChart filter={activeRegion} />
Так формируется связанная аналитическая сцена, где hover становится глобальным триггером.
Nivo позволяет переопределять стандартное поведение событий через кастомные обработчики.
Пример блокировки tooltip при определённых условиях:
tooltip={(feature) => {
if (!feature.value) return null;
return (
<div>
{feature.properties.name}: {feature.value}
</div>
);
}}
Или подавление клика:
onCl ick={(feature, event) => {
if (feature.disabled) {
event.preventDefault();
return;
}
setSelected(feature.id);
}}
Интерактивность в региональных графиках часто реализуется через реактивные стили:
fillOpacity: feature =>
hoveredRegion && hoveredRegion !== feature.id ? 0.3 : 1
strokeWidth: feature =>
feature.id === selectedRegion ? 2 : 0.5
При большом количестве регионов возможны узкие места:
Оптимизация:
useCallbackconst handleMouseEnter = useCallback((feature) => {
setHoveredRegion(feature.id);
}, []);
Интерактивные модели в Nivo строятся на нескольких устойчивых принципах:
Эти принципы позволяют использовать hover и click не как декоративные эффекты, а как основу аналитического взаимодействия с пространственными данными.