Touch Drawing App using HTML5 Canvas

This HTML5 Sample App uses Canvas to do free style drawing using touch, mouse or device accelerometer. This app can be run on HTML5 supported browser or can be packaged to hybrid application using PhoneGap* or Intel XDK and run on Apple iOS*, Android* and other devices.

SketchPad App screenshot

This app makes use of the jQuery Mobile framework to implement the UI elements which scales consistently on various cross platform devices and web browsers. This post describes how a line is drawn using HTML5 canvas and then explains how jQuery touch and mouse event handlers are used to implement free style drawing using touch and mouse. It also uses the Cordova's accelerometer APIs to implement drawing based on device tilt. The App uses basic CSS manipulation using jQuery for implementing other UI elements like the color palette selection.

The full source for this HTML5 Canvas app is available on github. This github has example sources for creating touch drawing app with:

  • just JavaScript
  • jQuery
  • jQuery + jQuery Mobile for UI
  • canvas drawing using device's accelerometer using Cordova APIs

DEMO


 

Drawing a line using Canvas

The Javascript* code snippet below shows the simplest way to draw a line using canvas.

function drawLine()
{
    var ctx=document.getElementById("canvas").getContext("2d");
    ctx.beginPath(); 
    ctx.moveTo(10,10);
    ctx.lineTo(50,50);
    ctx.lineWidth = 5;
    ctx.strokeStyle = "#00F"; 
    ctx.stroke(); 
}

This basic code is used along with touch and mouse events to make free form drawing possible with touch or using a mouse. The moveTo() and lineTo() methods of getContext("2d") are used to define the starting and ending point of the lines. The lineWidth and strokeStyle properties of getContext("2d") are used to set the line width and the color palette selection in the App. The stroke() method is used to actually draw the line based on the touch or mouse event.


 

Touch Event Drawing

The javascript code snippet below shows the implementation of touch events to draw canvas lines. The jQuery "touchstart" event is used to set the starting point of the line using moveTo() method and the "touchmove" event is used to set the ending point of the line using lineTo() method followed by stroke() method to actually draw the line on the canvas.

$.fn.drawTouch = function() {
    var start = function(e) {
        var touchEvent = e.originalEvent.changedTouches[0];
        ctx.beginPath();  
        ctx.moveTo(touchEvent.pageX, touchEvent.pageY);
    };
    var move = function(e) {
        var touchEvent = e.originalEvent.changedTouches[0];
        e.preventDefault();
        ctx.lineTo(touchEvent.pageX, touchEvent.pageY);
        ctx.stroke();
    };
    $(this).touchstart(start);
    $(this).touchmove(move);
};

 

MSPointer Event Drawing (for Microsoft* IE)

The javascript code snippet below shows the implementation of mspointer events to draw canvas lines. The "MSPointer" events are required for touch to work on Internet Explorer, Window Phone and Windows Surface devices. The jQuery "mspointerdown" event is used to set the starting point of the line using moveTo() method and the "mspintermove" event is used to set the ending point of the line using lineTo() method followed by stroke() method to actually draw the line on the canvas.

$.fn.drawPointer = function() {
        var start = function(e) {
        e = e.originalEvent;
                ctx.beginPath();
                x = e.pageX;
                y = e.pageY-44;
                ctx.moveTo(x,y);
        };
        var move = function(e) {
                e.preventDefault();
        e = e.originalEvent;
                x = e.pageX;
                y = e.pageY-44;
                ctx.lineTo(x,y);
                ctx.stroke();
    };
        $(this).on("MSPointerDown", start);
        $(this).on("MSPointerMove", move);
};

Mouse Event Drawing

The javascript code snippet below shows the implementation of mouse events to draw canvas lines. The jQuery "mousedown" event is used to set the starting point of the line using moveTo() method and the "mousemove" event is used to set the ending point of the line using lineTo() method followed by stroke() method to actually draw the line on the canvas. The "mouseup" event is used to make sure that drawing is only possible when mouse is clicked and moving and not when mouse is just moved on the canvas.

$.fn.drawMouse = function() {
    var clicked = 0;
    var start = function(e) {
        clicked = 1;
        ctx.beginPath();
        ctx.moveTo(e.pageX, e.pageY);
    };
    var move = function(e) {
        if(clicked){
            ctx.lineTo(e.pageX, e.pageY);
            ctx.stroke();
        }
    };
    var stop = function(e) {
        clicked = 0;
    };
    $(this).mousedown(start);
    $(this).mousemove(move);
    $(this).mouseup(stop);
};

Accelerometer Drawing

This app also implements accelerometer to draw lines based on how the device is tilted. The javascript code snippet below shows how the accelerometer is used to implement this. The x and y values returned by the acceleometer is used to draw the line either right/left or up/down. The value is also used to determine the length of line draw which appears to user as the speed at which the line is drawn and is made proportional to the value of accelerometer x/y values. So the line gets drawn faster if the device is tilted more.

// Start checking the accelerometer
function startWatch() {
    // Update acceleration every 1 seconds
    var options = { frequency: 100 };
    watchID = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
}

// Stop checking the accelerometer
function stopWatch() {
    if (watchID) {
        navigator.accelerometer.clearWatch(watchID);
        watchID = null;
    }
}

// onSuccess: draw line based on tilt direction and amount of tilt
function onSuccess(acceleration) {
    // draw based on accelerometer positions
    if(acceleration.x > 2 && Math.abs(acceleration.y) < 2 ){
        if (x < 3){ x = 3; } // stop drawing at edge of canvas
        x = x-Math.abs(acceleration.x); // length of line drawn is made proportional to tilt
        ctx.lineTo(x, y);
        ctx.stroke();
    } else if(acceleration.x < -2 && Math.abs(acceleration.y) < 2){
        if (x > $(window).width() - 3){ x = $(window).width() - 3;}
            x = x+Math.abs(acceleration.x);
            ctx.lineTo(x, y);
            ctx.stroke();
    } else if(acceleration.y > 2 && Math.abs(acceleration.x) < 2){
            if (y > $(window).height() - 93) { y = $(window).height() - 93;}
            y = y+Math.abs(acceleration.y);
            ctx.lineTo(x, y);
            ctx.stroke();
    } else if(acceleration.y < -2 && Math.abs(acceleration.x) < 2){
            if(y < 3) { y = 3;}
            y = y-Math.abs(acceleration.y);
            ctx.lineTo(x, y);
            ctx.stroke();
    }	
}

SketchPad App screenshot

The app also implements the vibrate feature to alert user when the cursor reacher the end of canvas while using the accelerometer to draw, this is implemented by using the navigator.notification.vibrate() call.