{"id":12731,"library":"hammerjs","title":"Hammer.js Multi-touch Gestures","description":"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.","status":"abandoned","version":"2.0.8","language":"javascript","source_language":"en","source_url":"git://github.com/hammerjs/hammer.js","tags":["javascript","touch","gestures"],"install":[{"cmd":"npm install hammerjs","lang":"bash","label":"npm"},{"cmd":"yarn add hammerjs","lang":"bash","label":"yarn"},{"cmd":"pnpm add hammerjs","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The official `hammerjs` package (v2.x) does not provide a direct ES module export and exposes 'Hammer' as a global variable. For ES module support, consider the `@egjs/hammerjs` fork.","wrong":"import Hammer from 'hammerjs';","symbol":"Hammer","correct":"<!-- In HTML: -->\n<script src=\"path/to/hammer.js\"></script>\n<script>\n  const mc = new Hammer.Manager(element);\n</script>"},{"note":"CommonJS import for Node.js environments (though primarily a browser library). Note that this still expects `Hammer` to be globally exposed or bundled via UMD.","symbol":"Hammer","correct":"const Hammer = require('hammerjs');\nconst mc = new Hammer.Manager(element);"},{"note":"For TypeScript usage, install `@types/hammerjs` to get type definitions. The `Hammer` object itself contains nested classes like `Manager` and `Rotate`.","wrong":"import { Manager, Rotate } from 'hammerjs'; // Incorrect named import for v2.x","symbol":"Hammer.Manager, Hammer.Rotate","correct":"declare var Hammer: any; // For global Hammer object in TypeScript\nconst mc = new Hammer.Manager(document.getElementById('myElement'));\nconst rotate = new Hammer.Rotate();\nmc.add(rotate);"}],"quickstart":{"code":"document.addEventListener('DOMContentLoaded', () => {\n  const stage = document.getElementById('stage');\n  if (!stage) {\n    console.error('Element with ID \"stage\" not found.');\n    return;\n  }\n\n  // Create a manager for that element\n  const mc = new Hammer.Manager(stage);\n\n  // Create a recognizer for rotation\n  const rotateRecognizer = new Hammer.Rotate();\n\n  // Add the recognizer to the manager and enable it (pinch and rotate are often disabled by default)\n  mc.add(rotateRecognizer);\n  mc.get('rotate').set({ enable: true });\n\n  // Subscribe to the rotate event\n  mc.on('rotate', function(e) {\n    const rotation = Math.round(e.rotation);\n    stage.style.transform = `rotate(${rotation}deg)`;\n    console.log(`Rotation: ${rotation} degrees`);\n  });\n\n  // Example for a simple tap recognizer\n  const tapRecognizer = new Hammer.Tap();\n  mc.add(tapRecognizer);\n  mc.on('tap', function(e) {\n    console.log('Tap detected!', e.target);\n    e.target.style.backgroundColor = 'lightblue';\n    setTimeout(() => e.target.style.backgroundColor = 'transparent', 200);\n  });\n\n  // Enable pinch and pan for demonstration, if desired\n  mc.get('pinch').set({ enable: true });\n  mc.get('pan').set({ direction: Hammer.DIRECTION_ALL });\n\n  console.log('Hammer.js initialized on #stage.');\n});","lang":"typescript","description":"This example demonstrates how to initialize Hammer.js on an element, add a rotation recognizer, and listen for the 'rotate' event to dynamically transform the element. It also includes a basic tap event example."},"warnings":[{"fix":"Review the official Hammer.js v2.0 documentation carefully for API changes. Existing v1.x code will require substantial refactoring.","message":"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.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"For new projects, evaluate alternatives like `@use-gesture` or native DOM touch events. For existing projects, consider forks like `@egjs/hammerjs` if you require continued maintenance or specific features like ESM support.","message":"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.","severity":"deprecated","affected_versions":">=2.0.8"},{"fix":"Implement dynamic imports or conditional loading to ensure Hammer.js is only initialized client-side. For Webpack, `bundle-loader` can be used. Ensure all gesture-related logic runs after the component has mounted (e.g., `componentDidMount` in React or `ngAfterViewInit` in Angular).","message":"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.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Carefully configure recognizer options (like `direction`, `threshold`) to avoid conflicts. Use `Hammer.Manager` for complex scenarios to manage recognizers effectively. Ensure `mc.destroy()` is called or `mc.off()` is used to remove listeners when elements are removed from the DOM or components unmount.","message":"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.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Always ensure you are referencing the correct, pre-built distribution file (`hammer.js`) and not raw source files when including the library directly in HTML or bundling.","message":"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`.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Conditionally load Hammer.js only on the client-side using dynamic imports or ensure its initialization is deferred until the browser environment is available.","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.","error":"ReferenceError: window is not defined"},{"fix":"Verify that your HTML script tag or module bundler is pointing to the correct Hammer.js distribution file, usually `node_modules/hammerjs/hammer.js`.","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.","error":"Uncaught ReferenceError: TOUCH_ACTION_COMPUTE is not defined"},{"fix":"Install the type definitions package: `npm install --save-dev @types/hammerjs`.","cause":"This is a TypeScript error indicating that the TypeScript compiler cannot find type definitions for the global `Hammer` object.","error":"Cannot find namespace 'Hammer'."},{"fix":"Explicitly 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`.","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).","error":"Gesture is not recognized or conflicts (e.g., pan and pinch at the same time, swipe not firing)"}],"ecosystem":"npm"}