Обработка событий onClick и onHover

Chart.js предоставляет встроенную модель событий, основанную на обработке canvas-элемента и системе взаимодействий (interaction system). События onClick и onHover работают не как DOM-события для отдельных элементов графика, а как интерпретация координат курсора относительно отрисованных элементов (точек, столбцов, сегментов и т.д.), что требует понимания механизма определения активных элементов (active elements).

Внутри Chart.js события взаимодействия строятся вокруг трёх ключевых сущностей:

  • событие браузера (MouseEvent / PointerEvent)
  • активные элементы графика (elements)
  • конфигурация interaction (mode, intersect, axis)

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

Основной механизм поиска элементов:

  • определение координат pointer-а
  • сопоставление с геометрией dataset-ов
  • фильтрация по interaction.mode
  • проверка intersect

Обработка клика onClick

Событие onClick задаётся в конфигурации графика и вызывается при каждом клике по canvas.

Базовая структура:

const config = {
  type: 'bar',
  data,
  options: {
    onClick: (event, elements, chart) => {
      // логика обработки клика
    }
  }
};

Параметры onClick

event Сырой DOM-событие. Используется для получения координат:

  • event.x / event.y
  • event.native (в некоторых версиях)
  • event.type

elements Массив активных элементов под курсором:

[
  {
    datasetIndex: 0,
    index: 3
  }
]
  • datasetIndex — индекс набора данных
  • index — индекс элемента внутри dataset

chart Экземпляр графика, позволяющий:

  • обновлять данные
  • перерисовывать график
  • получать доступ к scales и datasets

Определение элемента под кликом

Частый сценарий — получение данных точки:

onClick: (event, elements, chart) => {
  if (!elements.length) return;

  const el = elements[0];
  const dataset = chart.data.datasets[el.datasetIndex];
  const value = dataset.data[el.index];

  console.log(value);
}

Здесь важно, что elements уже отфильтрован системой взаимодействия, поэтому дополнительная геометрическая проверка не требуется.


Использование getElementsAtEventForMode

При более сложных сценариях используется ручной запрос элементов:

const elements = chart.getElementsAtEventForMode(
  event,
  'nearest',
  { intersect: true },
  true
);

Параметры:

  • mode — стратегия поиска (nearest, index, dataset, x, y)
  • options — правила пересечения
  • useFinalPosition — учитывать ли анимацию

Этот подход полезен, когда требуется переопределить поведение стандартного onClick.


Сценарии применения onClick

1. Drill-down (проваливание в данные) Клик по сегменту диаграммы открывает детализированный уровень данных.

2. Навигация Использование графика как интерактивного меню.

3. Изменение состояния интерфейса Выбор элемента графика как фильтра для таблицы.


Обработка наведения onHover

Событие onHover вызывается при движении курсора над canvas. Оно тесно связано с системой tooltip и hover interaction.

options: {
  onHover: (event, elements, chart) => {
    // логика при наведении
  }
}

Поведение hover в interaction system

Работа hover зависит от:

interaction: {
  mode: 'nearest',
  intersect: true
}
  • mode: 'nearest' — ближайший элемент к курсору
  • intersect: true — курсор должен пересекать элемент

Параметры onHover

event Содержит координаты движения мыши.

elements Массив активных элементов под курсором, аналогично onClick.

chart Экземпляр графика для динамических изменений.


Пример динамического изменения курсора

onHover: (event, elements, chart) => {
  const target = event.native ? event.native.target : event.target;

  target.style.cursor = elements.length
    ? 'pointer'
    : 'default';
}

Это распространённый паттерн для создания ощущения интерактивности.


Связь onHover и tooltip

Chart.js автоматически использует hover-события для управления tooltip.

Поведение можно контролировать:

options: {
  plugins: {
    tooltip: {
      enabled: true
    }
  }
}

При наведении система:

  1. вычисляет active elements
  2. обновляет tooltip state
  3. перерисовывает canvas

Программное управление hover

Иногда требуется эмулировать hover:

chart.setActiveElements([
  { datasetIndex: 0, index: 2 }
]);

chart.tooltip.setActiveElements([
  { datasetIndex: 0, index: 2 }
]);

chart.update();

Это используется для синхронизации нескольких графиков.


Отличия onClick и onHover

onClick

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

onHover

  • непрерывное событие
  • используется для визуальной обратной связи
  • влияет на tooltip и подсветку

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

При интенсивных графиках (большие datasets) важно учитывать:

  • частота вызова onHover (может быть десятки раз в секунду)
  • перерасчёт active elements
  • перерисовка canvas

Практика оптимизации:

1. Минимизация логики внутри onHover Тяжёлые операции выносятся в debounce:

let timer;

onHover: (event, elements) => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    // тяжёлая логика
  }, 50);
}

2. Проверка наличия элементов

if (!elements.length) return;

Работа с несколькими datasets

При наличии нескольких наборов данных:

elements = [
  { datasetIndex: 0, index: 4 },
  { datasetIndex: 1, index: 4 }
]

Это характерно для stacked charts и комбинированных визуализаций.

Логика обработки должна учитывать приоритет dataset:

  • верхний слой
  • активный dataset
  • пересечение по оси X

Использование в кастомных interaction сценариях

При отключении стандартного поведения:

options: {
  events: [],
  onClick: customHandler
}

График перестаёт автоматически вычислять active elements, и разработчик полностью управляет логикой через:

  • getElementsAtEventForMode
  • getDatasetMeta
  • scales.getValueForPixel

Связь с системой координат

В основе обработки событий лежит преобразование:

  • pixel → chart area
  • chart area → scale values
  • scale values → dataset index

Это позволяет точно определять элементы даже при масштабировании и анимациях.


Работа с touch-событиями

Chart.js унифицирует mouse и touch:

  • touchstart → onHover / onClick
  • touchmove → hover updates
  • touchend → click confirmation

На мобильных устройствах hover часто заменяется кратковременным активным состоянием элемента.