Professional Documents
Culture Documents
Using Touch Events With The HTML5 Canvas
Using Touch Events With The HTML5 Canvas
Canvas
by Ben Centra
December 5, 2014
in Code
The HTML5 canvas element has been around for a while now, and it’s great for
lots of things: drawing, games, user input, and more. It’s also fairly easy to use,
and its API is similar to other drawing APIs out there. What’s not so easy is
getting the canvas to work with both mouse and touch events, a requirement for
mobile-friendly applications.
Partially as a joke I wanted to add an “e-signature” feature to a friend’s project.
Since it was meant to be mobile-friendly, it was time to use the canvas with
touch support! Here’s how it was done:
You can check out the final demo here and view the code here.
Canvas Setup
Canvas setup is easy enough:
<canvas id="sig-canvas" width="320" height="160">
Get a better browser, bro.
</canvas>
// Set up the canvas
var canvas = document.getElementById("sig-canvas");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "#222222";
ctx.lineWith = 2;
Mouse Input
In order to draw a signature, I needed to capture user input on the canvas.
Starting with mouse input, I handled these three mouse events:
Drawing
Now that I knew the state of the mouse, I could start drawing to the canvas. To
make it happen smoothly and efficiently, I took advantage of the browser
method requestAnimationFrame. I used a handy function that determines the
appropriate method of getting the window’s animation frame or, failing that,
falling back on a simple timeout loop:
// Get a regular interval for drawing to the screen
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimaitonFrame ||
function (callback) {
window.setTimeout(callback, 1000/60);
};
})();
To actually do the drawing, I set up a draw loop. I created
a renderCanvas() function for drawing the signature, connecting the previous
and current mouse positions with a line (if drawing is enabled). By hooking into
the window’s animation frame and running that function in a loop, I got a fully
interactive signature field!
// Draw to the canvas
function renderCanvas() {
if (drawing) {
ctx.moveTo(lastPos.x, lastPos.y);
ctx.lineTo(mousePos.x, mousePos.y);
ctx.stroke();
lastPos = mousePos;
}
}
Touch Input
Since the project to which I was supposedly contributing was a modern web app,
I needed to support smartphones and tablets. This meant adding touch controls
to supplement the mouse controls. Keeping it simple, I only used one touch at a
time (sorry, multitouch). For starters, I utilized three touch event counterparts
to the mouse events from earlier:
Because I wanted to play around with event dispatching, I used these touch
events to trigger their mouse event counterparts and do the appropriate
conversions (touch position to mouse position, etc).
// Set up touch events for mobile, etc
canvas.addEventListener("touchstart", function (e) {
mousePos = getTouchPos(canvas, e);
var touch = e.touches[0];
var mouseEvent = new MouseEvent("mousedown", {
clientX: touch.clientX,
clientY: touch.clientY
});
canvas.dispatchEvent(mouseEvent);
}, false);
canvas.addEventListener("touchend", function (e) {
var mouseEvent = new MouseEvent("mouseup", {});
canvas.dispatchEvent(mouseEvent);
}, false);
canvas.addEventListener("touchmove", function (e) {
var touch = e.touches[0];
var mouseEvent = new MouseEvent("mousemove", {
clientX: touch.clientX,
clientY: touch.clientY
});
canvas.dispatchEvent(mouseEvent);
}, false);