Touch Paint(W) Sample Overview

The Touch Paint sample application demonstrates how you can create a simple paint application using the touch events and the Canvas element.

The following figure illustrates the main screens of the Touch Paint.

Figure: Touch Paint screens

Touch Paint screens

The application opens with the main screen where you can see the painting canvas. You can draw on the canvas with your finger.

To change the color or line width, click Options, make your selection, and click OK. To clear the canvas, click Clear.

Source Files

You can create and view the sample application project including the source files in the IDE.

File name Description
config.xml This file contains the application information for the platform to install and launch the application, including the view mode and the icon to be used in the device menu.
css/style.css This file contains the CSS styling for the application UI.
img/ This directory contains the images used to create the user interface.
index.html This is a starting file from which the application starts loading. It contains the layout of the application screens.
js/ This directory contains the application code.
js/app.js This file defines the initialization module.
js/core/ This directory contains the core library.
js/models/options.js This file defines the module providing the functions to change the brush properties.
js/views/ This directory contains the code for handling the UI events for all pages.

Implementation

The init() method initializes the application. The initialization consists of the canvas size calculation and event listener definitions for all UI elements used in the application.

/* main.js */
var canvas = null,
    context = null,
    content = null,
    touches = null,
    drawPath = [],
    strokeColor = '',
    strokeWidth = 5,
    isMoved = false;

function init() 
{
   initCanvas();
   getOptionValues();
   bindEvents();
}

function initCanvas() 
{
   canvas = document.createElement('canvas');
   canvas.width = window.innerWidth;
   canvas.height = window.innerHeight - header.offsetHeight - footer.offsetHeight;
   canvas.setAttribute('id', 'main-canvas');
   content.appendChild(canvas);
   context = canvas.getContext('2d');
}

function getOptionValues() 
{
   strokeWidth = o.getStrokeWidth();
   strokeColor = o.getStrokeColor();
}

function bindEvents() 
{
   addCanvasListeners();
}

function addCanvasListeners() 
{
   canvas.addEventListener('touchstart', onCanvasTouchStart);
   canvas.addEventListener('touchend', onCanvasTouchEnd);
   canvas.addEventListener('touchmove', onCanvasTouchMove);
}

When a touchstart event is triggered, a filled circle is drawn in the initial position. This position is stored in the drawPath array.

/* main.js */
function onCanvasTouchStart(ev) 
{
   var touch = ev.changedTouches[0];

   drawPath[touch.identifier] = touch;

   context.fillStyle = strokeColor;
   context.beginPath();
   context.arc(drawPath[touch.identifier].pageX - canvas.offsetLeft, 
               drawPath[touch.identifier].pageY - canvas.offsetTop - header.offsetHeight,
               strokeWidth / 2, 0, Math.PI * 2, true);
   context.closePath();
   context.fill();
}

When a touchmove event is triggered, the coordinates of the previously triggered touchmove event stored in the changedTouches attribute are saved in the drawPath array and passed as a parameter value of the moveTo() method. The coordinates of the current touchmove event are passed as a parameter value of the lineTo() method and the connected line is created.

/* main.js */
function onCanvasTouchMove(ev) 
{
   var touches = ev.changedTouches,
       touchesLength = touches.length,
       currentDrawPath = null,
       i = 0;

   context.lineWidth = strokeWidth + ADDITIONAL_LINE_WIDTH;
   context.strokeStyle = strokeColor;
   context.lineJoin = 'round';

   for (i = 0; i < touchesLength; i += 1) 
   {
      currentDrawPath = drawPath[touches[i].identifier];
      if (currentDrawPath !== undefined) 
      {
         context.beginPath();
         context.moveTo(currentDrawPath.pageX - canvas.offsetLeft + HALF_PIXEL,
                        currentDrawPath.pageY - canvas.offsetTop + HALF_PIXEL - header.offsetHeight);
         context.lineTo(touches[i].pageX - canvas.offsetLeft + HALF_PIXEL,
                        touches[i].pageY - canvas.offsetTop + HALF_PIXEL - header.offsetHeight);
         context.closePath();
         context.stroke();

         drawPath[touches[i].identifier] = touches[i];
      }
   }
   ev.preventDefault();
}

When a touchend event is triggered, the stored position is deleted.

/* main.js */
function onCanvasTouchEnd(ev) 
{
   var touch = ev.changedTouches[0];

   delete drawPath[touch.identifier];
}