Using JQuery Mobile with the HTML5 canvas element to listen for touch events on the iPad and Android browsers

Post to Twitter

Lately I’ve been messing around with JQuery Mobile, the HTML5 canvas element as well as my Droid X and iPad 2. The nice thing is JQuery Mobile supports numerous touch events and makes life a lot easier. In fact, JQuery Mobile ensures your web app will work on both mobile and desktop/laptop browsers as well. Sadly you just can’t expect a JavaScript onclick event to work on a mobile device as it does on the desktop/laptop browser. Read on for more information and a sample web app.


Note: The following code and commentary by me should not be taken as the gospel truth, there are several things I’m doing to get this all working that could (should) be changed to be better. If you have questions make sure to utilize the JQuery Mobile Forum. This code was tested against JQuery Mobile alpha release 4 and might break in the future pending changes to the JQuery Mobile code base. Most important, this code should be considered nothing more than an experiment.

First off I wanted to use the orientationchange event in JQuery Mobile. I wasn’t actually able to get this working perfectly on both mobile and desktop/laptop browsers and I’m still not sure what the problem was so I simply bound to the window.resize event – which from my understanding and reading is where JQuery Mobile ultimately binds to as well for the orientationchange event on non-touch based devices as quoted by their documentation:

Note that we currently bind to the resize event when orientationChange is not natively supported.

$(window).resize(function() { resizeCanvas() });

I’ve found the best way to avoid all the scaling/resizing issues with the Canvas is to simply remove it when the browser window or orientation is changed and then redraw so that is exactly what I did:

var w = window.innerWidth / 1.2;
var h = window.innerHeight / 1.2;
var canvasString = '<canvas id="mainCanvas" width="' + w + '" height="' + h + '">Canvas is not supported</canvas>';

$('#contentholder').empty();
$(canvasString).appendTo('#contentholder');

Using the JQuery Mobile tap event I can then draw a simple square and the coordinates of the touch (or mouse click in the case of of desktop/laptop browser). The touch events in JQuery Mobile are currently as follows:

tap – Triggers after a quick, complete touch event.
taphold – Triggers after a held complete touch event (close to one second).
swipe – Triggers when a horizontal drag of 30px or more (and less than 20px vertically) occurs within 1 second duration.
swipeleft – Triggers when a swipe event occurred moving in the left direction.
swiperight – Triggers when a swipe event occurred moving in the right direction.

The final code looks like this:

<!DOCTYPE html> 
<html lang="en">
    <head>
    <title>iOS/Android Canvas</title>
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" />
	<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
	<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script>
         <script>
            $(function() {
                var canvasContext;
                resizeCanvas();
                $(window).resize(function() { resizeCanvas() });
                 
                function resizeCanvas()
                {
					var w = window.innerWidth / 1.2;
					var h = window.innerHeight / 1.2;
					var canvasString = '<canvas id="mainCanvas" width="' + w + '" height="' + h + '">Canvas is not supported</canvas>';
					
					$('#contentholder').empty();
					$(canvasString).appendTo('#contentholder');
					canvasContext = $('#mainCanvas').get(0).getContext('2d'); 
										
					$('#mainCanvas').bind('tap', function(event){
						touchX = event.pageX;
						touchY = event.pageY;
						canvasContext.fillStyle="#0f0";
						canvasContext.fillRect(touchX - 75, touchY - 50, 50, 50);

						canvasContext.font = "20pt Arial";				
						canvasContext.fillText("X: " + touchX + " Y: " + touchY, touchX, touchY);
					});
                }				
            });
            </script>
    <style>
      #mainCanvas
      {
        background-color: #000;
        border: solid 3px #0F0;
      }
      body
      {
        background: #000;
      }
      #contentholder
      {
        width: 99%;
        height: 99%;
        margin: 0 auto;
        text-align: center;
      }
     </style>
    </head>
 
    <body>
	<div  data-role="page"> 
		<div data-role="header">Header</div> 
		<div data-role="content"><div id="contentholder"></div></div> 
		<div data-role="footer">Footer</div> 
	</div>
    </body>
</html>

You can try the example out here.

Here is a screenshot from Chrome and the iPad 2:

Note: I’ve only tested the code on Google Chrome, the Droid X (Android), iPad 2 (iOS) and a MacBook Pro with OS X. One thing to keep in mind that I noticed is that the interpretations of the touch coordinates seem to differ on all the devices/browsers so you might need to play with that part.

Post to Twitter

This entry was posted in HTML5, JavaScript, Mobile. Bookmark the permalink.

3 Responses to Using JQuery Mobile with the HTML5 canvas element to listen for touch events on the iPad and Android browsers

  1. Pingback: Creating a real-time games or web apps with HTML5 Canvas, JQuery and the Union Platform | Giant Flying Saucer

  2. Atul Vaidya says:

    This code still works with JQM RC2. Just a couple of questions

    a. You do not explicitly code the mousedown event and yet it works on desktop browsers. Is JQM taking care of this in the background?

    b. Why the /1.2? Is it just a fudge factor or is there a reasoning behind it?

  3. Chad Lung says:

    @Atul,

    a. Its been a while since I wrote this but I believe the “tap” is something JQM will ensure works on desktops and browsers
    b. 1.2 was a measurement that worked for the demo I did. Might not be accurate for other things – you would need to play with this and research what would be best.

Comments are closed.