Many times, there are various interactions that take place in a web app based on mouse movement, clicking, dragging, etc. With a mouse, this is fairly simple, as there is a single point, and events like mousedown, mouseup, and mousemove can be used to discover the state of the mouse at any given time.
On mobile browsers, however, it's a different story. Most phones support at least some kind of multi-touch, and the mousedown and mouseup events are not fired (there is, after all, no button). In addition, mousemove will only be applicable when dragging. Instead, mobile browsers dispatch touchstart, touchmove, and touchend events. Moreover, these events keep track of all touch points, not just the first or last one, and as such make handling them a bit more difficult.
For the purposes of an application that only requires tracking clicks and drags, it is more convenient to translate these touch events into mouse events without having code duplication. This can be accomplished quickly in several steps. First, we want to ignore events with more than one touch point, as this is used by many mobile browsers to zoom and/or scroll. Then, we want to get the information from the touch event and simulate a mouse event using that data. And finally, we dispatch the simulated event and prevent the default response to the touch event.
In code, it looks like this (replace element with whatever element you want the listener on):
And a closure-compiled version:
I hope you find this useful in any mobile web apps you're making. However, this will only track one touch point, so if you require more control over multi-touch features, I recommend checking out this guide. Though the title suggests that this is iPhone-only, it also applies to the default browser on Android, as it fires the same touch events.
On mobile browsers, however, it's a different story. Most phones support at least some kind of multi-touch, and the mousedown and mouseup events are not fired (there is, after all, no button). In addition, mousemove will only be applicable when dragging. Instead, mobile browsers dispatch touchstart, touchmove, and touchend events. Moreover, these events keep track of all touch points, not just the first or last one, and as such make handling them a bit more difficult.
For the purposes of an application that only requires tracking clicks and drags, it is more convenient to translate these touch events into mouse events without having code duplication. This can be accomplished quickly in several steps. First, we want to ignore events with more than one touch point, as this is used by many mobile browsers to zoom and/or scroll. Then, we want to get the information from the touch event and simulate a mouse event using that data. And finally, we dispatch the simulated event and prevent the default response to the touch event.
In code, it looks like this (replace element with whatever element you want the listener on):
var touchToMouse = function(event) { if (event.touches.length > 1) return; //allow default multi-touch gestures to work var touch = event.changedTouches[0]; var type = ""; switch (event.type) { case "touchstart": type = "mousedown"; break; case "touchmove": type="mousemove"; break; case "touchend": type="mouseup"; break; default: return; } // https://developer.mozilla.org/en/DOM/event.initMouseEvent for API var simulatedEvent = document.createEvent("MouseEvent"); simulatedEvent.initMouseEvent(type, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); touch.target.dispatchEvent(simulatedEvent); event.preventDefault(); }; element.ontouchstart = touchToMouse; element.ontouchmove = touchToMouse; element.ontouchend = touchToMouse;
And a closure-compiled version:
var touchToMouse=function(b){if(!(b.touches.length>1)){var a=b.changedTouches[0],c="";switch(b.type){case "touchstart":c="mousedown";break;case "touchmove":c="mousemove";break;case "touchend":c="mouseup";break;default:return}var d=document.createEvent("MouseEvent");d.initMouseEvent(c,true,true,window,1,a.screenX,a.screenY,a.clientX,a.clientY,false,false,false,false,0,null);a.target.dispatchEvent(d);b.preventDefault()}}; element.ontouchstart=touchToMouse; element.ontouchmove=touchToMouse; element.ontouchend=touchToMouse;
I hope you find this useful in any mobile web apps you're making. However, this will only track one touch point, so if you require more control over multi-touch features, I recommend checking out this guide. Though the title suggests that this is iPhone-only, it also applies to the default browser on Android, as it fires the same touch events.
I've had success with this code, except when the drawing canvas is in a page loaded in a iFrame. Touch events are not translated into mouse events. Any ideas?
ReplyDelete