Creating Web Apps - The Touch API
Written by Mike James   
Monday, 21 January 2013
Article Index
Creating Web Apps - The Touch API
Touch in motion
Touch with color
Complete listing

More than one touch

Now that we have seen the starttouch event working with a single point of contact it is easy to extend the program to handle multiple points of contact.  The touches property is an array of touch objects - one for each point of contact. So all we have to do is add a for loop to process them all in the same way that we processed the first one:

function handleStart(evt) {
 for(var i=0;i<evt.touches.length;i++) {
  var touch = evt.touches[i];
  drawCircle(touch.pageX, touch.pageY,
                       20, "#FF0000", ctx);
 }
}

Now if you run the program you will see that you can make more than one red circle appear with each touch.

You can also use this program to investigate the way that touchstart works if you add a touch point to an existing set. Suppose you have one figure in contact with the screen and hence one red dot, if you move the finger then the red dot stays where it is and no more red dots appear - why would they! If you now touch the screen with another finger then two red dots appear one under the new finger and one under the original finger at its new position.

What this demonstrates is the simple fact that a touchstart event is fired every time a new finger contacts the screen and the list of touch objects includes the details of all of the points of contact even if they existed before the new points of contact.

New touches only

Suppose you only want to deal with new touches that have caused the touchstart event?

The solution is to use the changedTouches property which returns a list of touch objects which correspond to just the new points of contact that triggered this particular touchstart event.

For example to draw a red dot only at the new points of contact the event handier has to be changed to use changedTouches instead of touches.

function handleStart(evt) {
 for(var i=0;i<evt.changedTouches.length;
                                     i++) {
  var touch = evt.changedTouches[i];
  drawCircle(touch.pageX, touch.pageY,
                     20, "#FF0000", ctx); }
}

With this change you can now place one finger on the screen which produces a red dot. When you move this finger to a new location and touch the screen with another finger a red dot now only appears under the "new" finger's location.

There is also a targetTouches property which returns a list of touch objects corresponding to points of contact on the same target element.

Moving Touch

Time to move on to the touchmove event. This is fired when ever a point of contact moves. At what rate the event is fired and hence how accurately you can follow a moving point depends on the device - rate of firing is not part of the standard. This said most devices manage to fire the even around 30 times per second which is enough to follow a point closely.

At this point we need to do some more work to make our touch example work smoothly. The problem is that we are about to make touch contacts that could look like swipes and zooms. If this happens the browser will interpret them as such and will scroll and zoom the view port. To make sure that the browser ignores the touch events that we are handling you ave to add to the page header:

<meta name="viewport"
   content="width=device-width,
   initial-scale=1.0,
   user-scalable=no">

In addition you also need to add to your script:

document.body.addEventListener('touchmove',
    function(event) {
     event.preventDefault();
    }, false);

This stops the touchmove event passing the event onto the browser for default processing.

The touchmove event works in much the same way as the touchstart event - its event object has a touches, currentTouches and so on properties. However before handling all of the points of contact lets go back to an earlier technique of handling just a single point of contact.

 function handleMove(evt){
  var touch=evt.changedTouches[0];
  drawCircle(touch.pageX, touch.pageY,
                       20, "#FF0000", ctx);
}


If you try this out you will discover that you can draw a trail of red dots while moving a single point of contact across the screen.

move

 

You might also be surprised to discover that you can draw two trails of dots at the same time if you have two fingers in contact with the screen.

How can this be?

This is the sort of confusion that arises when working with realtime programming. You may only be processing a single point of contact at a time but if two fingers are moving sometimes the event will return the first finger as changedTouches[0] and some times the second. Also sometimes the first finger isn't moving when the second finger is and so the second figure is processed on its own.

Of course using this approach isn't the best way to work as you are not tracking both fingers as accurately as is possible. If you want to track all points of contact then you need a for loop:

function handleMove(evt) {
 for(var i=0;i<evt.changedTouches.length;
                                    i++){
  var touch = evt.changedTouches[i];
  drawCircle(touch.pageX, touch.pageY,
                     20, "#FF0000", ctx);
 }
}

With this change you should now be able to draw multiple trails all equally smooth.



Last Updated ( Monday, 21 January 2013 )