JavaScript Touch and Gesture Events iPhone and Android
by Michael
There are quite a few sites that describe the touch and gesture events that can be used in the mobile version of WebKit running on iPhone and iPod Touch. There is, however, not so much info with regards to Android. I’ve placed a few links at the bottom of this article that contain information used to compile this brief explanation.
Touch events are a bit like mouse events, but there are some very important differences when it comes to touch vs. mouse:
- A touch is very hard to keep steady whilst a mouse can stay at a fixed position – this means that we go from a touchStart event directly to a touchMove event. Unlike a mouse where a mouseDown event is likely to fire without being followed up by a mouseMove event.
- There is no mouseOver equivalent since a touch can be discontinuous, i.e., we can get from point A to point B without the need of drawing a continuous line between these points.
- A touch is an averaged point taken from the surface area in contact with the pointing device (your finger) translated to pixel coordinates – like finding the centre of a circle. A mouse is very precise and there is no averaging that needs to be done. What I’m trying to say is that a touch is not as accurate as a mouse.
Android and iPhone touch events
Android and iPhone versions of WebKit have some touch events in common:
- touchstart – triggered when a touch is initiated. Mouse equivalent – mouseDown
- touchmove – triggered when a touch moves. Mouse equivalent – mouseMove
- touchend – triggered when a touch ends. Mouse equivalent – mouseUp. This one is a bit special on the iPhone – see below
- touchcancel –
bit of a mysteryUPDATE: this event is triggered when a touch is unexpectedly interrupted, such as an incoming call which causes the browser to lose focus (iOS only) – Thanks to the commenters who posted this information.
Example:
document.addEventListener('touchstart', function(event) { alert(event.touches.length); }, false);
The Event object
As you may have noticed above, the event object contains an array called touches (in Androids case, the event object also containes a touch object – at this stage, touches has always a length of 1 in Android so event.touches[0] === event.touch). The touches array is Apples way of handling multi-touch events – but more on that later.
A touch object contains pretty much the same data as a mouse event such as pageX, pageY etc…
Example:
document.addEventListener('touchmove', function(event) { event.preventDefault(); var touch = event.touches[0]; console.log("Touch x:" + touch.pageX + ", y:" + touch.pageY); }, false);
What about a click?
mouseClick events are triggered after a touchStart, touchEnd event sequence. A reason for mouseClick events not triggering can be that the event propagates further and a touchMove being initiated – this will cancel the mouseClick event sequence.
iPhone Touch and Gesture Events
Apples WebKit implementation has a few things that are different from the Android implementation. The touchEnd event removes the current touch from the event.touches
array. Instead, we have to look inside the event.changedTouches array.
Apples event object for touch events
The event object contains the following arrays:
- touches – contains touch information upon touchStart and touchMove not touchEnd events
- targetTouches – contains information for touches originating from the same target element
- changedTouches – contains touch information upon all touch events
Gesture events
Apple supports gestures which are mult-touch events such as “pinching” and “rotating”:
- gesturestart – triggered when initiating a multi-touch event
- gesturechange – triggered when multiple touches move
- gestureend – triggered when a multi-touch event ends
The event object for gesture events looks very different. It contains scale and rotation values and no touch objects.
Example:
document.addEventListener('gesturechange', function(event) { event.preventDefault(); console.log("Scale: " + event.scale + ", Rotation: " + event.rotation); }, false);
Event table
touch start |
touch move |
touch end |
gesture start |
gesture move |
gesture end |
|
---|---|---|---|---|---|---|
Android | y | y | y | n | n | n |
iPhone | y | y | y | y | y | y |
has event.touches | y | y | y | n | n | n |
(iPhone) has event.scale and event.rotation | n | n | n | y | y | y |
(iPhone) touch in event.touches | y | y | n | – | – | – |
(iPhone) touch in event.changedTouches | y | y | y | – | – | – |
Wow! Thank you so much for this clear post .I m thinking about creating a webmultitouch app for android and iPhone, and this post was just what I needed!
thanks, that's what I need.
touchcancel is for iphone (does not work on my htc desire).
It is when you move your finger down till leaving the touch screen.
This way touchend won’t be triggered, but touchcancel will.
So, usually, for vertical swipe, i always redirect touchcancel event to touch end
Hello,
Good site, for information touch cancel is when the finger is touching out the listening area
Actually touchCancel is not called when the touch leaves the screen/element, but when there is an unexpected interruption, for example when a call comes in (on the phone) or something else happens that would cause the browser (or the app) to lose focus immediately and thus interrupts the current touch event chain. touchCancel is a chance to clean up and one should assume that all touches ended.
Thanks for the info, updated my post.
> Apples WebKit implementation has a few things that are different from the Android
> implementation. The touchEnd event removes the current touch from the event.touches array.
Strange – in latest desktop Chrome with Touch Emulation enabled in developer tools this is also true, the touch that ended is no longer in the touches array. Which makes sense when you think about it – and also goes along with the latest W3c draft, reading:
touches: of type TouchList, readonly
a list of Touches for every point of contact CURRENTLY touching the surface.
I’m confused: it’s from google, it’s webkit based, it’s out there on the market – and has two different implementations. Isn’t this a big overhead to manage two different branches or will this be sync’d (or is already) to the w3c version on upcoming android devices?