Интерактивность и подсказки

В библиотеке Nivo интерактивность строится вокруг событий пользовательского ввода и реактивного обновления состояния. Любой график (bar, line, pie, radar и др.) изначально поддерживает набор встроенных взаимодействий: наведение, выделение элементов, клики, управление легендой и отображение подсказок.

Интерактивность в Nivo не требует ручного управления DOM-элементами. Вместо этого используются декларативные свойства компонентов и callback-функции, которые позволяют реагировать на действия пользователя на уровне данных.

Ключевые источники интерактивности:

  • hover-события (onMouseEnter / onMouseMove / onMouseLeave)
  • click-события (onClick)
  • выделение элементов (active/selected state)
  • синхронизация с tooltip
  • кастомизация легенды и фильтрация данных

Модель событий и обработчики

Каждый график Nivo принимает набор обработчиков событий, которые привязываются к визуальным элементам: барам, точкам, дугам, сегментам.

Пример типового набора событий:

  • onClick
  • onMouseEnter
  • onMouseMove
  • onMouseLeave

Эти события возвращают объект данных, связанный с конкретным элементом визуализации. Это позволяет работать не с DOM, а с бизнес-данными.

<ResponsiveBar
    data={data}
    keys={['value']}
    indexBy="label"
    onCl ick={(datum) => {
        console.log('Клик по:', datum);
    }}
/>

Каждый datum содержит:

  • исходные данные строки
  • вычисленные координаты
  • идентификатор серии
  • цвет и стили

Hover-состояния и визуальная реакция

Наведение мыши является базовым способом взаимодействия с графиками. Nivo автоматически управляет состояниями hover, изменяя:

  • прозрачность неактивных элементов
  • подсветку активного элемента
  • масштабирование (в некоторых типах графиков)
  • появление tooltip

В line chart и bar chart поведение hover особенно выражено: элементы под курсором становятся визуально доминирующими, а остальные элементы приглушаются.

Пример настройки поведения:

<ResponsiveLine
    data={data}
    useMesh={true}
    enablePoints={true}
/>

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


Подсказки (Tooltips)

Подсказки — центральный элемент интерактивности. В Nivo tooltip строится как React-компонент, что позволяет полностью контролировать его содержимое и стили.

Базовый tooltip:

tooltip={({ point }) => (
    <div style={{ background: 'white', padding: 12 }}>
        <strong>{point.data.x}</strong>
        <div>{point.data.y}</div>
    </div>
)}

Tooltip получает контекст элемента:

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

Кастомизация структуры tooltip

Tooltip может быть полностью переопределён. Это позволяет внедрять:

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

Пример расширенного tooltip:

tooltip={({ datum }) => (
    <div>
        <div>Категория: {datum.label}</div>
        <div>Значение: {datum.value}</div>
        <div>Доля: {(datum.value / datum.total * 100).toFixed(1)}%</div>
    </div>
)}

Синхронизация tooltip и курсора

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

Используется режим mesh:

useMesh={true}

Он создаёт виртуальную триангуляцию между точками, позволяя точно определять ближайшее значение.

Дополнительно можно использовать:

  • crosshair (перекрёстие)
  • axis tooltip
  • floating tooltip

Выделение элементов и активные состояния

Nivo поддерживает концепцию активного элемента, который отличается от hover тем, что состояние может сохраняться.

Активное состояние применяется через:

  • внешнее состояние React
  • props isInteractive
  • кастомную логику фильтрации

Пример ручного управления:

const [activeId, setActiveId] = useState(null);

<ResponsiveBar
    data={data}
    onCl ick={(bar) => setActiveId(bar.id)}
    borderWidth={d => d.id === activeId ? 3 : 1}
/>

Это позволяет реализовывать:

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

Интерактивность легенды

Легенда в Nivo не является статическим элементом. Она может управлять видимостью данных.

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

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

Пример кастомной легенды:

legends={[
    {
        onClick: (datum) => {
            console.log('toggle series', datum.id);
        }
    }
]}

Легенда становится управляющим интерфейсом для графика, а не просто подписью.


Связанные состояния между компонентами

Интерактивность Nivo часто выходит за пределы одного графика. Распространённый паттерн — синхронизация нескольких визуализаций.

Пример сценария:

  • клик по bar chart
  • фильтрация line chart
  • обновление pie chart

Реализация через общий state:

const [selected, setSelected] = useState(null);

<Bar onCl ick={(d) => setSelected(d.id)} />
<Line data={filter(data, selected)} />

Это создаёт связанный аналитический интерфейс.


Анимации как часть интерактивности

Интерактивность в Nivo тесно связана с анимациями. Любое изменение состояния сопровождается переходами:

  • появление элементов
  • изменение значений
  • перерасчёт шкал

Параметр animate управляет этим поведением:

animate={true}
motionConfig="gentle"

Анимация усиливает восприятие изменений, особенно при:

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

Hover-эффекты в сложных графиках

В pie и radial графиках hover вызывает более сложные трансформации:

  • увеличение сегмента
  • смещение (pull effect)
  • изменение угла обзора
activeOuterRadiusOffset={8}

Это создаёт эффект “всплывающего” сегмента, который визуально отделяется от круга.


Пользовательские интерактивные слои

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

Слои могут:

  • реагировать на события мыши
  • отображать дополнительные маркеры
  • строить аннотации
  • рисовать вспомогательные линии
layers={[
    'grid',
    'axes',
    'bars',
    CustomLayer
]}

Custom layer получает доступ к координатам и данным, что позволяет строить сложные интерактивные оверлеи.


Drag-like взаимодействия и симуляция жестов

Хотя Nivo не является drag-and-drop библиотекой, можно реализовать поведение, близкое к перетаскиванию:

  • изменение диапазона
  • выбор области
  • zoom через выделение

Особенно это актуально для line charts.

Пример логики выделения диапазона:

  • mouseDown фиксирует стартовую точку
  • mouseMove обновляет область
  • mouseUp завершает выбор

Это используется для:

  • zoom-in аналитики
  • фильтрации временных рядов

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

При высокой плотности данных интерактивность становится узким местом. В Nivo применяются оптимизации:

  • виртуализация точек
  • упрощение mesh-расчётов
  • мемоизация tooltip-компонентов
  • отключение анимаций при больших датасетах

Критически важные параметры:

  • enablePoints
  • useMesh
  • animate
  • motionConfig

Доступность интерактивных элементов

Интерактивные элементы Nivo могут быть адаптированы для клавиатурной навигации и screen reader:

  • фокусируемые элементы
  • aria-labels
  • текстовые альтернативы tooltip

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


Контекстные действия через клик

Клик по элементу часто используется для вызова внешних действий:

  • открытие модального окна с деталями
  • переход на другую страницу
  • загрузка детализированного набора данных
onCl ick={(d) => {
    openModal(d.data);
}}

Таким образом график становится навигационным элементом интерфейса.


Комбинация hover и click состояний

Сложные интерфейсы часто комбинируют временное и фиксированное состояние:

  • hover — временное выделение
  • click — фиксация выбора

Логика разделения:

  • hover используется для исследования данных
  • click используется для принятия решения

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