- Hammer
- Hammer.defaults
- Hammer.Manager
- Hammer.Recognizer
- Hammer.input event
- Event object
- Constants
- Utils
Hammer
Creates a Manager instance with a default set of recognizers and returns the manager instance. The default set contains tap
, doubletap
, pan
, swipe
, press
, pinch
and rotate
recognizer instances.
You should only use this when you’re fine with the default setup, or have set your own initial setup.
Constructor(HTMLElement, [options])
Just your element, and options. the options will be merged with Hammer.defaults. Also, the recognizer set as defined in Hammer.defaults.preset
will be added.
If you’ll pass an empty recognizer
option, no initial recognizers will be added.
var myElement = document.getElementById('hitarea');
var mc = new Hammer(myElement);
Hammer.defaults
The defaults when creating an instance that are merged being with your options.
touchAction: ‘compute’
Accepts the compute
, auto
, pan-y
, pan-x
and none
values. The default option will choose the correct value for you, based on the recognizers.
domEvents: false
Let Hammer also fire DOM events. This is a bit slower, so disabled by default. Recommended to set to true
if you want to play with event delegation.
enable: true
Accepts a boolean, or a function that should return a boolean which is.
cssProps: {….}
preset: [….]
Default recognizer setup when calling Hammer()
. When creating a new Manager these will be skipped.
By default it adds a set of tap
, doubletap
, press
, horizontal pan
and swipe
, and the multi-touch pinch
and rotate
recognizers. The pinch and rotate recognizers are disabled by default because they would make the element blocking.
Hammer.Manager
The Manager is the container of all the recognizer instances for your element. It sets up the input event listeners, and sets the touch-action property for you on the element.
constructor(HTMLElement, [options])
Just your element, and options. the options will be merged with Hammer.defaults.
var mc = new Hammer.Manager(myElement);
You can setup an initial recognizer set with the option recognizers
. The Array should be structured like this;
var mc = new Hammer.Manager(myElement, {
recognizers: [
// RecognizerClass, [options], [recognizeWith, ...], [requireFailure, ...]
[Hammer.Rotate],
[Hammer.Pinch, { enable: false }, ['rotate']],
[Hammer.Swipe,{ direction: Hammer.DIRECTION_HORIZONTAL }],
]
});
set(options)
Change an option on the manager instance. Using this method is recommended, because it will update the touchAction
value if needed.
mc.set({ enable: true });
get(string), add(Recognizer) and remove(Recognizer)
Add a new Recognizer
instance to the Manager. The order of adding is also the order of the recognizers being executed. Just like the get
method, it returns the added Recognizer
instance. The get
and remove
methods takes the event name (from a recognizer) or a recognizer instance as an argument.
Add and remove also accept an array of recognizers.
// both return instance of myPinchRecognizer
mc.get('pinch');
mc.get(myPinchRecognizer);
mc.add(myPinchRecognizer); // returns the recognizer
mc.add([mySecondRecogizner, myThirdRecognizer]);
mc.remove(myPinchRecognizer);
mc.remove('rotate');
mc.remove([myPinchRecognizer, 'rotate']);
on(events, handler) and .off(events, [handler])
Listen to events triggered by the added recognizers, or remove the binded events. Accepts multiple events seperated by a space.
mc.on("pinch", function(ev) {
console.log(ev.scale);
});
stop([force])
Stop recognizing for the current input session. When forced, the recognizer cycle is stopped immediately.
destroy()
Unbinds all events and input events and makes the manager unusable. It does NOT unbind any domEvent listeners.
Hammer.Recognizer
Every Recognizer extends from this class. All recognizers also have the option enable
, which is a boolean value or a callback function to enable/disable the recognizer on the fly.
constructor([options])
Just set the options.
var pinch = new Hammer.Pinch();
mc.add(pinch); // add it to the Manager instance
set(options)
Change an option on the recognizer instance. Using this method is recommended, because it will update the touchAction
value if needed.
recognizeWith(otherRecognizer) and dropRecognizeWith(otherRecognizer)
Run the recognizer simultaneous with the given other recognizer, in both directions. This is usable for like combining a pan with a swipe at the end, or a pinch with the ability to rotate the target as well. Dropping the connection only removes the link on the recognizer, not on the other recognizer. Both accept an array of recognizers.
If the recognizer is added to a manager, then this method also accepts the other recognizer’s event name as a string.
requireFailure(otherRecognizer) and dropRequireFailure(otherRecognizer)
Run the recognizer only when the other recognizer fails. Dropping the connection only removes the link on the recognizer, not on the other recognizer. Both accept an array of recognizers.
If the recognizer is added to a manager, then this method also accepts the other recognizer’s event name as a string.
A secret event is being triggered by Hammer, hammer.input
. It is being emitted on every input that is being received, and enabled you to things with the raw input. Small, but powerful feature.
hammertime.on("hammer.input", function(ev) {
console.log(ev.pointers);
});
Event object
All events that Hammer triggers all receive an event object containing the following properties.
Name | Value |
type | Name of the event. Like panstart . |
deltaX | Movement of the X axis. |
deltaY | Movement of the Y axis. |
deltaTime | Total time in ms since the first input. |
distance | Distance moved. |
angle | Angle moved. |
velocityX | Velocity on the X axis, in px/ms. |
velocityY | Velocity on the Y axis, in px/ms |
velocity | Highest velocityX/Y value. |
direction | Direction moved. Matches the DIRECTION constants. |
offsetDirection | Direction moved from it’s starting point. Matches the DIRECTION constants. |
scale | Scaling that has been done when multi-touch. 1 on a single touch. |
rotation | Rotation (in deg) that has been done when multi-touch. 0 on a single touch. |
center | Center position for multi-touch, or just the single pointer. |
srcEvent | Source event object, type TouchEvent , MouseEvent or PointerEvent . |
target | Target that received the event. |
pointerType | Primary pointer type, could be touch , mouse , pen or kinect . |
eventType | Event type, matches the INPUT constants. |
isFirst | true when the first input. |
isFinal | true when the final (last) input. |
pointers | Array with all pointers, including the ended pointers (touchend , mouseup ). |
changedPointers | Array with all new/moved/lost pointers. |
preventDefault | Reference to the srcEvent.preventDefault() method. Only for experts! |
Constants
All constants are defined at the Hammer
object. Since it are binary flags, you can use bitwise operators on it. MDN has some excellentdocumentation about this.
Directions
Used for setting the direction of a recognizer, and for reading the value of an event.
Name | Value |
DIRECTION_NONE | 1 |
DIRECTION_LEFT | 2 |
DIRECTION_RIGHT | 4 |
DIRECTION_UP | 8 |
DIRECTION_DOWN | 16 |
DIRECTION_HORIZONTAL | 6 |
DIRECTION_VERTICAL | 24 |
DIRECTION_ALL | 30 |
Hammer maps all types of input (mousedown, mousemove, touchmove, pointercancel) to these constants.
Name | Value |
INPUT_START | 1 |
INPUT_MOVE | 2 |
INPUT_END | 4 |
INPUT_CANCEL | 8 |
Recognizer States
Used internally by the recognizers to define its state.
Name | Value |
STATE_POSSIBLE | 1 |
STATE_BEGAN | 2 |
STATE_CHANGED | 4 |
STATE_ENDED | 8 |
STATE_RECOGNIZED | STATE_ENDED |
STATE_CANCELLED | 16 |
STATE_FAILED | 32 |
Utils
Hammer.on(element, types, handler)
Wrapper around addEventListener
that accepts multiple event types.
Hammer.on(window, "load resize scroll", function(ev) {
console.log(ev.type);
});
Hammer.off(element, types, handler)
Like Hammer.on
, this is a wrapper around removeEventListener
that accepts multiple event types.
Hammer.each(obj, handler)
Iterate an array or an object’s own properties.
Hammer.each([10,20,30,40], function(item, index, src) { });
Hammer.each({a:10, b:20, c:30}, function(item, key, src) { });
Hammer.merge(obj1, obj2)
Merge properties from obj2 into obj1. Properties won’t be overwritten.
var options = {
b: false
};
var defaults = {
a: true,
b: true,
c: [1,2,3]
};
Hammer.merge(options, defaults);
// options.a == true
// options.b == false
// options.c == [1,2,3]
Hammer.extend(obj1, obj2)
Extend obj1 with the properties from obj2. Properties will be overwritten.
var obj1 = {
a: true,
b: false,
c: [1,2,3]
};
var obj2 = {
b: true,
c: [4,5,6]
};
Hammer.extend(obj1, obj2);
// obj1.a == true
// obj1.b == true
// obj1.c == [4,5,6]
Hammer.inherit(child, base, [properties])
Simple class inheritance.
function Animal(name) {
this.name = name;
}
function Dog() {
Animal.apply(this, arguments);
}
Hammer.inherit(Dog, Animal, {
bark: function() {
alert(this.name);
}
});
var dog = new Dog('Spaikie');
dog.bark();
Hammer.bindFn(fn, scope)
Simple alternative for Function.bind
.
function myFunction(ev) {
console.log(this === myContext); // is true
}
var myContext = {
a: true,
b: false
};
window.addEventListener('load', Hammer.bindFn(myFunction, myContext), false);
Hammer.prefixed(obj, name)
Get the (prefixed) property from the browser.
Hammer.prefixed(document.body.style, 'userSelect');
// returns "webkitUserSelect" on Chrome 35
The Touch-action property
Chrome 35+, IE10+ and soon FireFox, support the touch-action
property. This property tells the browser how to handle touches on an element. It improves the detection and experience of the gestures a lot, because it can prevent scrolling of the page without any JavaScript has to be executed, which can be too late in some cases.
Hammer uses a javascript fallback for this property when needed, so it is working with non-supporting browsers too. Still, on some (unpopular) devices the fallback might not work as good as the native support.
By default it sets a value based on the recognizer settings. You can overwrite this by giving the option touchAction
to the Manager.
When you set the touchAction to auto
it doesn’t prevent any defaults, and Hammer would probably break. You have to call preventDefault
manually to fix this. You should only use this if you know what you’re doing.
Preferred touch-action values per gesture
If you do want to set your own value, then the table below should help you a bit…
Gesture | Least restrictive touch-action value |
press | auto |
tap | auto |
multitap | manipulation |
vertical pan/swipe | pan-x |
horizontal pan/swipe | pan-y |
rotate | pan-x pan-y |
pinch | pan-x pan-y |
With the method requireFailure()
you can let a recognizer require the failure of an other recognizer before recognizing. This could become useful when you want to nest two gestures, like pan-horizontal and pan-vertical. Removing the dependency could be done with the dropRequireFailure()
method.
var horizontal = new Hammer.Pan({
event: 'panh',
direction: Hammer.DIRECTION_HORIZONTAL
});
var vertical = new Hammer.Pan({
event: 'panv',
direction: Hammer.DIRECTION_VERTICAL
});
vertical.requireFailure(horizontal);
Using requireFailure to recognize multiple taps
Because multiple gestures can be recognized simultaneously and a gesture can be recognized based on the failure of other gestures. Multiple taps on the same element can be easily recognized on this way:
var hammer = new Hammer(el, {});
var singleTap = new Hammer.Tap({ event: 'singletap' });
var doubleTap = new Hammer.Tap({event: 'doubletap', taps: 2 });
var tripleTap = new Hammer.Tap({event: 'tripletap', taps: 3 });
hammer.add([tripleTap, doubleTap, singleTap]);
tripleTap.recognizeWith([doubleTap, singleTap]);
doubleTap.recognizeWith(singleTap);
doubleTap.requireFailure(tripleTap);
singleTap.requireFailure([tripleTap, doubleTap]);
When a tap gesture requires a failure to be recognized, its recognizer will wait a short period to check that the other gesture has been failed. In this case, you should not assume that its tap gesture event will be fired immediately.
Toggle recognizers at runtime
A gesture can be enabled/disabled based on its enable
property which must setup through the set
call or its constructor parameter.
hammer.get('tap').set({ enable: false });
//Then you could enable it again when necessary
hammer.get('tap').set({ enable: true });
Instead of toggling the enable
property each time on your app, you could delegate this responsibility to a custom function which will be checked with each new incoming touch event to decide if the event can be dispatched to the recognizer or not. This feature provides support to build complex gesture scenarios based on App/UI logic.
var view = View.extend({
state: 'ACTIVE',
score: 0,
canRecognizeTap: function(recognizer, event) {
return this.state !== 'INACTIVE' && this.score > 0;
});
};
var mc = new Hammer.Manager(viewElement, {});
var canEnable = function(rec, input) {
return view.canRecognizeTap(rec, input);
}
mc.add(new Hammer.Tap({enable: canEnable}));
The Manager.enable
option also works this way.
Hammer.Pan(options)
Recognized when the pointer is down and moved in the allowed direction.
Option | Default | Description |
event | pan | Name of the event. |
pointers | 1 | Required pointers. 0 for all pointers. |
threshold | 10 | Minimal pan distance required before recognizing. |
direction | DIRECTION_ALL | Direction of the panning. |
Events
- pan, together with all of below
- panstart
- panmove
- panend
- pancancel
- panleft
- panright
- panup
- pandown
Notes
When calling Hammer()
to create a simple instance, the pan and swipe recognizers are configured to only detect horizontal gestures.
Hammer.Pinch(options)
Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
Option | Default | Description |
event | pinch | Name of the event. |
pointers | 2 | Required pointers, with a minimal of 2. |
threshold | 0 | Minimal scale before recognizing. |
Events
- pinch, together with all of below
- pinchstart
- pinchmove
- pinchend
- pinchcancel
- pinchin
- pinchout
Notes
This recognizer is disabled by default because it would make the element blocking. You can enable it by calling: javascript hammertime.get('pinch').set({ enable: true });
Hammer.Press(options)
Recognized when the pointer is down for x ms without any movement.
Option | Default | Description |
event | press | Name of the event. |
pointers | 1 | Required pointers. |
threshold | 9 | Minimal movement that is allowed while pressing. |
time | 251 | Minimal press time in ms. |
Events
Hammer.Rotate(options)
Recognized when two or more pointer are moving in a circular motion.
Option | Default | Description |
event | rotate | Name of the event. |
pointers | 2 | Required pointers, with a minimal of 2. |
threshold | 0 | Minimal rotation before recognizing. |
Events
- rotate, together with all of below
- rotatestart
- rotatemove
- rotateend
- rotatecancel
Notes
This recognizer is disabled by default because it would make the element blocking. You can enable it by calling: javascript hammertime.get('rotate').set({ enable: true });
Hammer.Swipe(options)
Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
Option | Default | Description |
event | swipe | Name of the event. |
pointers | 1 | Required pointers. |
threshold | 10 | Minimal distance required before recognizing. |
direction | DIRECTION_ALL | Direction of the panning. |
velocity | 0.3 | Minimal velocity required before recognizing, unit is in px per ms. |
Events
- swipe, together with all of below
- swipeleft
- swiperight
- swipeup
- swipedown
Notes
When calling Hammer()
to create a simple instance, the pan and swipe recognizers are configured to only detect horizontal gestures.
Hammer.Tap(options)
Recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur between the given interval and position. The eventData from the emitted event contains the property tapCount
, which contains the amount of multi-taps being recognized.
If an Tap recognizer has a failing requirement, it waits the interval time before emitting the event. This is because if you want to only trigger a doubletap, hammer needs to see if any other taps are coming in. Read more about requireFailure
Option | Default | Description |
event | tap | Name of the event. |
pointers | 1 | Required pointers. |
taps | 1 | Amount of taps required. |
interval | 300 | Maximum time in ms between multiple taps. |
time | 250 | Maximum press time in ms. |
threshold | 2 | While doing a tap some small movement is allowed. |
posThreshold | 10 | The maximum position difference between multiple taps. |
Events
jQuery plugin
A small jQuery plugin is available, and is just a small wrapper around the Hammer()
class. It also extends the Manager.emit
method by triggering jQuery events.
$(element).hammer(options).bind("pan", myPanHandler);
The Hammer instance is stored at $element.data("hammer")
.
Angular.js directive
An Angular.js directive has been made by Ryan Mullins, which allows you to easy integrate Hammer in your Angular.js based projects. You can find documentation at the project page on GitHub.
Emulate touch on a desktop
Hammer provides a debug tool to emulate touch support in the browser. It fires DOM touch events as specified by W3C. When pressing the shift
key, you can also use multi-touch events like pinch and rotate. You can also use this in other projects without Hammer.js.
How to use
Include the javascript file, and call the TouchEmulator()
function before any other libraries that do something with the touch input. It will set some fake properties to spoof the touch detection of some libraries, and triggers touchstart
, touchmove
and touchend
events on the mouse target.
<script src="touch-emulator.js"></script>
<script> TouchEmulator(); </script>
function log(ev) {
console.log(ev);
}
document.body.addEventListener('touchstart', log, false);
document.body.addEventListener('touchmove', log, false);
document.body.addEventListener('touchend', log, false);
Also, the script includes polyfills for document.createTouch
and document.createTouchList
.
How it works
It listens to the mousedown
, mousemove
and mouseup
events, and translates them to touch events. If the mouseevent has the shiftKey
property to true
, it enables multi-touch.
The script also prevents the following mouse events on the page:mousedown
, mouseenter
, mouseleave
, mousemove
, mouseout
, mouseover
and mouseup
.
The script has been tested with the w3c web platform tests and passes all tests, except these;
- assert_true: event is a TouchEvent event expected true got false
- We trigger an event of the type
Event
- assert_equals: touch list is of type TouchList expected “[object TouchList]” but got “[object Array]”
- assert_equals: touch is of type Touch expected “[object Touch]” but got “[object Object]”
Bookmarklet
javascript:!function(a){var b=a.createElement("script");b.onload=function(){TouchEmulator()},b.src="//cdn.rawgit.com/hammerjs/touchemulator/0.0.2/touch-emulator.js",a.body.appendChild(b)}(document);
Download the script from the repo, or just run bower install hammer-touchemulator
.