Thursday, May 26, 2011
An attempt towards Code Optimization
Saturday, April 9, 2011
Determine if HTML5 Canvas is Empty or has Data
To begin with, I searched if there are any existing solutions and found one which suggests to check every pixel with in the canvas area. Of course this could be a solution, but I was looking for some thing that suits my case better. I am working on a web application having several forms where canvas is used to take signatures either using a stylus/ mouse (as in touch screen laptops) or with finger touch (Iphone/ IPad) events. Also each web page may have up to four canvas boxes. So the method of checking each pixel could increase the processing time for each web page.
Also i was more inclined towards a solution using the properties of canvas or the programming language (in this case ASP .Net) and with less inclination towards the old school method of checking each pixel. One such property is the 'toDataURL', which retrieves the canvas data in string format. This string data can be converted as a byte array and there by we can get the size of the image. But the size of the byte array is not zero, even when the canvas is empty. When the canvas is empty, the default header information adds up to some size. Adding to this problem is the size of this default header is different in different browsers like safari, chrome, opera and firefox.
Initially i thought of checking the default size for each browser and use it to determine if the canvas is empty, but later found that this header size changes for different sizes of canvas and it may change in the later versions of the browsers. Still as of today, all the browsers are yet to comply to all the set standards of HTML5.
Finally, i came up with a solution where the emptiness of the canvas is determined dynamically, by comparing the size of the canvas before writing (during the page-load event) and after writing (when form 'submit' button is pressed). The data-URL of the canvas is retrieved and stored when the canvas is empty (during the page load event) and the data-URL of the canvas is retrieved again when the page is submitted. By checking the difference between the two data-URLs we can determine the status of the canvas.
The sample code below, explains the implementation.
Thus by using the canvas 'toDataURL' property and the page_load events, we could determine if the canvas is empty.
Saturday, March 12, 2011
Drawing board/Scribbling Pad for Tablet PC’s and smart phones
The example in my previous post can be extended to support touch-screen devices by adding the touch events, similar to the existing mouse events. In this post we look into touch events.
The touch events are ‘ontouchstart’, ‘ontouchmove’ and ‘ontouchend’.
‘OnTouchStart’ Event:-
sigCanvas.ontouchstart = function (event) {
event.preventDefault(); // to get rid of the default touch screen scroll action
var sigContext = this.getContext('2d');
var pos = getTouchPositionInElement(this, event); //get touch position on to canvas
sigContext.beginPath();
sigContext.moveTo(pos.x, pos.y);
sigContext.lineTo(pos.x + 0.5, pos.y + 0.5); //puts a dot on screen
sigContext.stroke();
this.down = true;
}
‘OnTouchMove’ Event:-
sigCanvas.ontouchmove = function (event) {
event.preventDefault(); //to get rid of the default touch screen scroll action
if (this.down) {
var sigContext = sigCanvas.getContext('2d');
var pos = getTouchPositionInElement(this, event);
sigContext.lineTo(pos.x, pos.y);
sigContext.closePath();
sigContext.stroke();
sigContext.beginPath();
sigContext.moveTo(pos.x, pos.y)
}
}
‘OnTouchEnd’ Event:-
sigCanvas.onTouchEnd = function (event) {
event.preventDefault(); //to get rid of the default touch screen scroll action
if (this.down) {
var sigContext = sigCanvas.getContext('2d');
var pos = getTouchPositionInElement(this, event);
sigContext.lineTo(pos.x, pos.y);
sigContext.closePath();
sigContext.stroke();
this.down = false;
}
}
Determine the Touch position on the canvas:-
var getTouchPositionInElement = function (element, e) {
var elementPosition = getElementPosition(element); //get canvas position on screen
var touchPosition= getTouchPosition(e); //get touch position on screen
var x = touchPosition.x - elementPosition.x;
var y = touchPosition.y - elementPosition.y;
var position = new Array();
position['x'] = x;
position['y'] = y;
return position; //touch position relative to canvas
}
Determine the canvas position on the screen:-
var getElementPosition = function (element) {
var posX = element.offsetLeft;
var posY = element.offsetTop;
try {
while (element.offsetParent) {
posX += element.offsetParent.offsetLeft;
posY += element.offsetParent.offsetTop;
if (element == document.getElementsByTagName('body')[0]) {
break
}
else {
element = element.offsetParent;
}
}
}
catch (e) {
}
var dims = new Array(0);
dims['x'] = posX;
dims['y'] = posY;
return dims; //return the top left position (co-ordinates) of canvas
}
Determine the touch position on the screen:-
var getTouchPosition = function (e) {
var touch = e.changedTouches[0]; //retrieves figure touch co-ordinates on screen
var touchPosition = new Array();
touchPosition['x'] = touch.pageX;
touchPosition['y'] = touch.pageY;
return touchPosition;
}
When the final application (with both mouse and touch events) is accessed through a mouse/ stylus the ‘mouse events’ are triggered and when accessed on a touch screen device triggers the ‘touch events’.
Saturday, February 19, 2011
Drawing Board/ Scribbling Pad with HTML5 Canvas
Recently, I was assigned with a problem of implementing the cross browser signature functionality. Since there was a need to support some of the major browsers (IE, Safari, FF, Chrome, Opera) and different platforms, there was a need to identify any one feature that works on all browsers. Based on a lead given, I started looking at the canvas feature of HTML5.
But very soon realized Canvas is not supported in IE (or until IE version 8), but soon learnt it will be supported from IE9. Also there are libraries available like “Excanvas” with which the Canvas feature can be supported in earlier versions of IE, except for few limitations.
The signature pad is similar to a drawing board where we can scribble; hence the example below is a drawing application. The languages used are html5 and JavaScript. For the most part the code is self-explanatory and commented at places.
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Canvas Drawing Boardtitle>
<style type="text/css">
.canvasborder {border: 2px solid black;}
style>
<script type="text/javascript" src="Scripts/jquery-1.4.1.js">script>
<script type="text/javascript">
var DrawingBlock = function (element) {
var DrawCanvas = document.getElementById(element); //
var DrawContext = DrawCanvas.getContext('2d');
DrawCanvas.down = false;
//Event is triggered when mouse button is pressed down on canvas
DrawCanvas.onmousedown = function (event) {
var pos = getMousePositionInElement(this, event); //retrieve the mouse position on canvas
DrawContext.beginPath();
DrawContext.moveTo(pos.x, pos.y);
DrawContext.lineTo(pos.x + 0.5, pos.y + 0.5); //put a dot, at the point of mouse down.
DrawCanvas.down = true; // true until the mouse button is pressed down.
}
//Event is triggered when pressed mouse button is released when on canvas
DrawCanvas.onmouseup = function (event) {
if (this.down) {
var pos = getMousePositionInElement(this, event);
DrawContext.lineTo(pos.x, pos.y);
DrawContext.closePath();
DrawContext.stroke();
this.down = false;
}
}
//Event is triggered when mouse is moved over canvas.
DrawCanvas.onmousemove = function (event) {
if (this.down) { //only if mouse button is held down
var pos = getMousePositionInElement(this, event);
DrawContext.lineTo(pos.x, pos.y);
DrawContext.closePath();
DrawContext.stroke();
DrawContext.beginPath();
DrawContext.moveTo(pos.x, pos.y)
}
}
//Return the canvas position on the document.
var getCanvasElementPosition = function (element) {
//Top left corner of the canvas is used as the
//reference to calculate the mouse position
var posX = element.offsetLeft;
var posY = element.offsetTop;
var canvasPos = new Array(0);
canvasPos['x'] = posX;
canvasPos['y'] = posY;
return canvasPos;
}
//Retrieve the mouse position on canvas
var getMousePositionInElement = function (element, event) {
var elementPosition = getCanvasElementPosition(element); //canvas position on the page
var mousePosition = getMousePosition(event); //mouse cordinates on the page.
var x = mousePosition.x - elementPosition.x;
var y = mousePosition.y - elementPosition.y;
var position = new Array(); //mouse position w.r.t canvas
position['x'] = x;
position['y'] = y;
return position;
}
//Retrieve the mouse co-ordinates in the document (web page)
var getMousePosition = function (event) {
var x = event.pageX;
var y = event.pageY;
var mouseposition = new Array();
mouseposition['x'] = x;
mouseposition['y'] = y;
return mouseposition;
}
//tracking the mouse-up event outside canvas (drawing board).
this.setMouseUpButton = function () {
DrawCanvas.down = false;
}
DrawCanvas.onselectstart = function () {
return false;
}
}
var drawingImage;
window.onload = function init() {
drawingImage = new DrawingBlock("DrawingCanvas"); //initialize the canvas element
}
//Event is triggered with mouse button is released in the document (web page).
$(document).mouseup(function (e) {
drawingImage.setMouseUpButton();
});
script>
head>
<body>
<tr>
<canvas id="DrawingCanvas" width="500" height="500" class="canvasborder">canvas>
tr>
<tr>
<td class="bold text">Drawing Boardtd>
tr>
body>
html>
The above code is tested in browsers like, IE 9 (Release Candidate), Safari, Firefox, Chrome and Opera on Windows and Mac platforms.