Подключение и настройка hammer.js

Hammer.js представляет собой библиотеку для обработки жестов касания и мыши в веб-приложениях. Она обеспечивает единый слой абстракции над событиями pointer/touch/mouse, позволяя работать с такими взаимодействиями, как swipe, pan, pinch и rotate без необходимости вручную обрабатывать низкоуровневые события браузера.

Библиотека строится вокруг концепции распознавателей жестов (recognizers). Каждый recognizer отвечает за определённый тип взаимодействия:

  • Pan — перемещение
  • Pinch — масштабирование
  • Press — длительное нажатие
  • Rotate — вращение
  • Swipe — быстрое движение

Каждый распознаватель подключается к единому менеджеру, который отслеживает входящие события и маршрутизирует их в соответствующие обработчики.

В основе лежит система state machine, где каждое касание проходит стадии:

  • possible
  • began
  • changed
  • ended
  • cancelled

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

Подключение библиотеки

Установка через npm

npm install hammerjs

После установки библиотека импортируется в проект:

import Hammer from 'hammerjs';

При использовании сборщиков (Webpack, Vite, Rollup) Hammer.js корректно включается в бандл без дополнительной настройки.

Подключение через CDN

<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8/hammer.min.js"></script>

После подключения глобальный объект Hammer становится доступен в window.

Создание базового экземпляра

Инициализация начинается с привязки к DOM-элементу:

const element = document.getElementById('canvas-area');
const hammer = new Hammer(element);

С этого момента элемент начинает отслеживать жесты касания и мыши.

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

Настройка распознавателей

По умолчанию активирован базовый набор жестов. Для точного контроля конфигурация изменяется через get и set:

hammer.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammer.get('pinch').set({ enable: true });

Возможные направления pan:

  • DIRECTION_HORIZONTAL
  • DIRECTION_VERTICAL
  • DIRECTION_ALL

Отключение ненужных жестов снижает нагрузку на обработку событий:

hammer.get('rotate').set({ enable: false });

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

События подписываются через метод on:

hammer.on('panmove', function (event) {
  console.log(event.deltaX, event.deltaY);
});

Основные события:

  • panstart / panmove / panend
  • pinchstart / pinchmove / pinchend
  • rotatestart / rotatemove / rotateend
  • tap / press / swipe

Объект события содержит параметры:

  • deltaX, deltaY — смещение
  • velocityX, velocityY — скорость
  • scale — коэффициент масштабирования
  • rotation — угол поворота
  • center — координаты центра жеста

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

Hammer.js позволяет комбинировать recognizers, но требует явного управления зависимостями:

const pinch = new Hammer.Pinch();
const pan = new Hammer.Pan();

pinch.recognizeWith(pan);

Такое связывание позволяет одновременно обрабатывать масштабирование и перемещение.

Использование с canvas и визуальными библиотеками

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

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

let scale = 1;
let offsetX = 0;
let offsetY = 0;

hammer.on('pinchmove', function (e) {
  scale = e.scale;
  render();
});

hammer.on('panmove', function (e) {
  offsetX += e.deltaX;
  offsetY += e.deltaY;
  render();
});

Функция render применяет трансформации к контексту canvas:

function render() {
  ctx.setTransform(scale, 0, 0, scale, offsetX, offsetY);
}

Интеграция с Chart.js

Chart.js не имеет встроенной полноценной системы жестов, поэтому Hammer.js часто используется как внешний слой интерактивности.

Типовой сценарий — управление масштабированием и панорамированием графика.

Панорамирование графика

const canvas = document.getElementById('chart');
const hammer = new Hammer(canvas);

let chartOffsetX = 0;

hammer.on('panmove', (e) => {
  chartOffsetX += e.deltaX;
  chart.update();
});

В реальных приложениях offset связывается с пользовательскими плагинами или кастомной логикой осей.

Pinch-to-zoom

let chartScale = 1;

hammer.get('pinch').set({ enable: true });

hammer.on('pinchmove', (e) => {
  chartScale = e.scale;
  chart.update();
});

Для корректной интеграции масштаб обычно применяется через обновление диапазона осей:

chart.options.scales.x.min *= chartScale;
chart.options.scales.x.max *= chartScale;

Конфигурация чувствительности

Hammer.js позволяет управлять порогами распознавания:

hammer.get('pan').set({
  threshold: 5,
  pointers: 1
});

Основные параметры:

  • threshold — минимальное смещение для активации
  • pointers — количество пальцев
  • enable — включение/выключение recognizer

Настройка влияет на отзывчивость интерфейса и точность жестов.

Управление конфликтами жестов

При одновременной работе нескольких recognizers возможны конфликты. Для их решения применяется:

  • recognizeWith — параллельное распознавание
  • requireFailure — последовательное распознавание
pan.requireFailure(pinch);

Это означает, что pan активируется только при отсутствии pinch.

Обработка событий pointer-системы

В современных браузерах Hammer.js использует Pointer Events как основной источник данных. Это обеспечивает поддержку:

  • мыши
  • сенсорных экранов
  • стилусов

Абстракция унифицирует различия между устройствами и приводит все события к единому формату.

Оптимизация производительности

При высокой частоте событий важно контролировать нагрузку:

  • отключение ненужных recognizers
  • ограничение обработчиков panmove/pinchmove
  • использование requestAnimationFrame для рендера
let ticking = false;

hammer.on('panmove', (e) => {
  if (!ticking) {
    requestAnimationFrame(() => {
      updateState(e);
      ticking = false;
    });
    ticking = true;
  }
});

Особенности поведения в мобильных браузерах

На мобильных устройствах возможны системные жесты браузера (scroll, zoom страницы), которые конфликтуют с Hammer.js. Для предотвращения применяется CSS:

touch-action: none;

Это отключает стандартную обработку касаний и передаёт управление библиотеке.

Расширение функциональности

Hammer.js поддерживает создание кастомных recognizers:

const mc = new Hammer.Manager(element);

mc.add(new Hammer.Pan({ direction: Hammer.DIRECTION_HORIZONTAL }));
mc.add(new Hammer.Swipe());

Такой подход позволяет строить специализированные системы взаимодействия, адаптированные под конкретные интерфейсы.

Связь жестов и состояния приложения

Интерактивные приложения часто используют жесты как входные данные для изменения состояния:

  • трансформация объектов
  • управление камерой
  • навигация по сцене
  • работа с диаграммами

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