Hammer.js Multi-touch Gestures
Hammer.js is a JavaScript library designed for detecting and handling multi-touch gestures such as tap, doubletap, press, pan, swipe, pinch, and rotate in web applications. It aims to provide a unified API across touch, mouse, and pointer events, offering a lightweight solution with no external dependencies and a small footprint (7.34 kB minified + gzipped for v2.0.8). However, the main `hammerjs` package has not seen active development since its last stable release, version 2.0.8, published over 10 years ago on April 22, 2016. While it was a popular choice for gesture recognition, its maintenance status means that users often look to forks like `@egjs/hammerjs` for continued support or migrate to newer, actively maintained gesture libraries.
Common errors
-
ReferenceError: window is not defined
cause Hammer.js is a browser-only library and attempts to access the global `window` object during initialization in a Server-Side Rendering (SSR) environment.fixConditionally load Hammer.js only on the client-side using dynamic imports or ensure its initialization is deferred until the browser environment is available. -
Uncaught ReferenceError: TOUCH_ACTION_COMPUTE is not defined
cause This error often occurs when the incorrect Hammer.js file is loaded, typically a source file (e.g., from `/src` directory) instead of the compiled distribution file.fixVerify that your HTML script tag or module bundler is pointing to the correct Hammer.js distribution file, usually `node_modules/hammerjs/hammer.js`. -
Cannot find namespace 'Hammer'.
cause This is a TypeScript error indicating that the TypeScript compiler cannot find type definitions for the global `Hammer` object.fixInstall the type definitions package: `npm install --save-dev @types/hammerjs`. -
Gesture is not recognized or conflicts (e.g., pan and pinch at the same time, swipe not firing)
cause Default configurations for gestures might be too restrictive (e.g., `pinch` and `rotate` are disabled by default), or conflicts exist between recognizers with overlapping conditions (e.g., horizontal pan and swipe).fixExplicitly enable disabled recognizers (e.g., `mc.get('pinch').set({ enable: true });`). Adjust `direction` (e.g., `Hammer.DIRECTION_ALL`) and `threshold` options for recognizers to resolve conflicts and ensure proper detection. For complex interactions, use `recognizeWith` or `requireFailure`.
Warnings
- breaking Migrating from Hammer.js v1.x to v2.x involves significant breaking changes. The library was completely rewritten, deprecating many gestures and introducing an entirely new API for recognizers and event management.
- deprecated The original `hammerjs` package is no longer actively maintained, with its last release being in April 2016. Users are encouraged to consider modern browser APIs for gesture handling or use alternative, actively maintained libraries. Angular, for example, has deprecated its direct HammerJS integration.
- gotcha Hammer.js can conflict with Server-Side Rendering (SSR) environments, throwing a `ReferenceError: window is not defined` because it expects a browser `window` object to be present on initialization.
- gotcha Common pitfalls include gesture conflicts (e.g., pan vs. swipe threshold settings, pinch with pan), performance issues from excessive event listeners, and memory leaks if event listeners are not properly cleaned up.
- gotcha Incorrectly referencing the Hammer.js file (e.g., `node_modules/hammerjs/src/hammer.js` instead of `node_modules/hammerjs/hammer.js`) can lead to `Uncaught ReferenceError` errors for internal Hammer.js variables like `TOUCH_ACTION_COMPUTE` or `ifUndefined`.
Install
-
npm install hammerjs -
yarn add hammerjs -
pnpm add hammerjs
Imports
- Hammer
import Hammer from 'hammerjs';
<!-- In HTML: --> <script src="path/to/hammer.js"></script> <script> const mc = new Hammer.Manager(element); </script>
- Hammer
const Hammer = require('hammerjs'); const mc = new Hammer.Manager(element); - Hammer.Manager, Hammer.Rotate
import { Manager, Rotate } from 'hammerjs'; // Incorrect named import for v2.xdeclare var Hammer: any; // For global Hammer object in TypeScript const mc = new Hammer.Manager(document.getElementById('myElement')); const rotate = new Hammer.Rotate(); mc.add(rotate);
Quickstart
document.addEventListener('DOMContentLoaded', () => {
const stage = document.getElementById('stage');
if (!stage) {
console.error('Element with ID "stage" not found.');
return;
}
// Create a manager for that element
const mc = new Hammer.Manager(stage);
// Create a recognizer for rotation
const rotateRecognizer = new Hammer.Rotate();
// Add the recognizer to the manager and enable it (pinch and rotate are often disabled by default)
mc.add(rotateRecognizer);
mc.get('rotate').set({ enable: true });
// Subscribe to the rotate event
mc.on('rotate', function(e) {
const rotation = Math.round(e.rotation);
stage.style.transform = `rotate(${rotation}deg)`;
console.log(`Rotation: ${rotation} degrees`);
});
// Example for a simple tap recognizer
const tapRecognizer = new Hammer.Tap();
mc.add(tapRecognizer);
mc.on('tap', function(e) {
console.log('Tap detected!', e.target);
e.target.style.backgroundColor = 'lightblue';
setTimeout(() => e.target.style.backgroundColor = 'transparent', 200);
});
// Enable pinch and pan for demonstration, if desired
mc.get('pinch').set({ enable: true });
mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });
console.log('Hammer.js initialized on #stage.');
});