Touch events have been around for some time now, and I feel they are not being used enough on mobile versions of sites. From swiping to scrolling to manipulating DOM elements, they are incredibly easy to implement and can definitely take us away from the traditional route of just vertical scrolling and button clicks that we default to today.
In this post, I'll cover the entire process, from creating the required event listeners to capturing multiple touch points on an element.
The touch API overview
Touch events on your browser act essentially like mouse events do, with the difference that certain devices will allow for multiple touch points. Each finger on the screen will essentially represent its own Touch object and will maintain it's own status and coordinates relative to the viewport. Each touch object contains the following list of properties.
Note, however, that some of the properties are dependant on the hardware being used. For example, if there is no pressure-sensitivity sensor on your device, then its value will remain as Nan. The same goes for the radius, which essentially is the size of the hitbox that you'll be targeting. The 2 properties that I will mainly cover however are the changedTouches property and the touches property. Both of which are returned in the event argument for mouse events.
The changedTouches collection is based on the event that is currently being triggered.
- For the touchstart event, it is a list of the touch points that became active with the current event.
- For the touchmove event, it is a list of the touch points that have changed since the last event.
- For the touchend event, it is a list of the touch points that have been removed from the surface (that is, the set of touch points corresponding to fingers no longer touching the surface).
The touches collection returns a list of Touch points that have been active since the first touch point. Meaning that if you remove a touch point from the screen, it will still be available in the touches collection for future use.
Those are the primary properties that we will use in the examples going forward. Essentially, we just want to know where we are touching and when we have stopped.
Adding the event listeners
You can add touch events to any DOM elements on your page.
var el = document.getElementById("id");
el.addEventListener("touchstart", handleStart, false);
el.addEventListener("touchend", handleEnd, false);
el.addEventListener("touchcancel", handleCancel, false);
el.addEventListener("touchmove", handleMove, false)
A touchstart event occurs when the screen detects a new touch point. If you touch the screen with multiple fingers, then you would end up with multiple touchstart events triggering. In the following example, I will add a new class to remove the box-shadow on touchStart, giving it a physical button look and feel.
var target = ev.target;
document.getElementById('touchstatus1').innerHTML = '<span>touch start</span>';
d('touchstatus2').innerHTML = ' ';
This event gets triggered when a touch point is no longer being held. If multiple touch points are registered at once, then each one would have its own touchEnd event fired as soon as that point is de-selected.
var target = ev.target;
document.getElementById('touchstatus2').innerHTML = '<span>touch end</span>';
d('touchstatus1').innerHTML = ' ';
The cancel event is useful if there any resources that you might want to clear in case something interrupts the touch process. For example, if an alert box appears in between touch start and touch end, you'll want to handle that transition gracefully. Also, if your finger happens to leave the current detectable area then a cancel event will be triggered too.
Touchmove acts much like the mousemove event handler. It will track each touch points movement across the screen and return the X and Y coordinates of each touch-point.
touches = ev.changedTouches;
d('touchstatus3').innerHTML = 'X: ' + touches.clientX;
d('touchstatus4').innerHTML = 'Y: ' + touches.clientY;
Touch any point in the following box and move it around to see its coordinates.
Notice in the example above that I only referenced the first item in the changedTouches collection. For the touchStart event, this will be the current touch point that you are on.
Multiple touch points
The following example iterates through the changedTouches collection, and displays basic information for each of the points. After each point is ended the div corresponding to it will be cleared from the DOM. Try touching and untouching in different orders in order to see how the changedTouches collection maintains state.
var parent = d('touchpoints');
temp = ev;
var touch = ev.changedTouches;
var div = c('div');
div.className = 'touchpoint';
div.id = 'touchpoint' + touch.identifier;
div.innerHTML = '<div>ID: ' + touch.identifier + '</div>';
div.innerHTML += '<div>X: ' + touch.clientX + '</div>';
div.innerHTML += '<div>Y: ' + touch.clientY + '</div>';
If you are going to be adding a ev.preventDefault() call to your touchstart event, it is important to realize that actions, such as clicking on a link, will not , function. So it would be best to either only prevent default on touchMove or on the actual elements that you are trying to target which are not a parent of any links.