Archive for ‘HTML5’

June 18, 2012

A simple drawing grid with HTML5 part 4

This week, we will complete the simple drawing grid by adding support for mobile browsers. Support for mobile browsers consists of enabling interaction with the canvas with touch events rather than the mouse events that are currently used.
The first step however is to add some detection for whether or not the client is using a mobile device. There really isn’t a standard way to accomplish this that I am aware of, but we can use a bit of javascript to do the job.

var isMobile = {
    Android: function() {
        return navigator.userAgent.match(/Android/i) ? true : false;
    },
    BlackBerry: function() {
        return navigator.userAgent.match(/BlackBerry/i) ? true : false;
    },
    iOS: function() {
        return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
    },
    Windows: function() {
        return navigator.userAgent.match(/IEMobile/i) ? true : false;
    },
    Any: function() {
        return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
    }
};

This is not a comprehensive detection of all mobile devices, but should cover the most popular ones.

Once we determine if the client is using a mobile browser, we can choose wheter or not to bind mouse events or touch events. This is a simple matter of adding an if condition when the page has been loaded.

if (!isMobile.Any()) {
	alert('not mobile');
	$("#grid").mousedown(function(e) {
		mouseDown = true;
	}).bind('mouseup', function() {
		mouseDown = false;
	}).bind('mouseleave', function() {
		mouseDown = false;
	});
	
	$("#grid").mousemove(function(e) {
		if (mouseDown) {
			drawOnCanvas(e);
		}
	});
} else {
	grid_canvas.addEventListener('touchstart', function(e) {
		mouseDown = true;
	});
	
	grid_canvas.addEventListener('touchend', function(e) {
		mouseDown = false;
	});
	
	grid_canvas.addEventListener('touchmove', function(e) {
		e.preventDefault();
		if (mouseDown) {
			drawOnCanvas(e);
		}
	});
}

You should note that by default, some mobile browsers have the default behavior for ‘ touchmove’ already defined to move the entire browser window. We can disable this by adding the following to the ‘touchmove’ event that is bound to the canvas.

e.preventDefault();

Now that we have detection and handling for mobile browsers, the drawing grid is supported in both mobile and non-mobile web browsers. As an exercise, you may choose to increase the size of the canvas and controls to make it more visible for mobile devices with smaller screens.

The entire source for our completed drawing grid application can be seen by viewing the source of the demo.

June 14, 2012

A simple drawing grid with HTML5 part 3

This is a continuation of our simple drawing grid series. Last week, we ended up with a functional drawing grid with a few expected controls like setting pen size and pen color. While it was functional, it left a lot to be desired from a presentation standpoint. This week, we will work on giving our application a little bit of style with css.
First, we will want to arrange the HTML a bit to support our controls being rendered to the right of the grid rather than below. This could be done with css, but for the purpose of simplicity, we will do it with a good old fashioned table.

<table>
	<tr>
		<td rowspan="2">
			<div id="container">
				<canvas id="grid">
					<p>Your browser does not support HTML5 canvas</p>
				</canvas>
			</div>
			<script type="text/javascript" src="scripts/grid.js"></script>
		</td>
		<td>
			<!-- controls -->
		</td>
	</tr>
</table> 

Instead of using buttons, to improve the appearance, we will use images for some of the controls. For the pen size selection, I chose to use text. For this, you can simply open up your favorite image editor (I chose gimp), select your preferred font, type in your label and save the image. For the other controls, you can simply use google to find images available for free via the creative commons license.
Once you have selected the images, all that is required is to change the input type of the elements from button to image and add a source path. I’ve created an images folder for this purpose, but you can place them anywhere that you choose.

<div><input type="image" src="images/eraser.png" title="erase" onclick="setEraser()" ></div>

If you remember from last week, we were using the mousedown event on any button other than mouse button one to provide the eraser functionality. To make it more intuitive, a control has been added to provide that functionality instead.
The process of choosing colors by defining a button or image input per color as we did last week isn’t very scalable. To solve this problem, we will add a color selector to the the controls section. We’ll discuss the implementation a bit later, but will define the element while working with the html.

<input type="color" id="colorpicker" name="colorpicker" /> 

Now that we have all of the controls defined, the html table should look similar to the following.

<td rowspan="2">
	<div id="container">
		<canvas id="grid">
			<p>Your browser does not support HTML5 canvas</p>
		</canvas>
	</div>
	<script type="text/javascript" src="scripts/grid.js"></script>
</td>
<td>
	<div><input type="image" src="images/smallPen.png" title="small pen" onclick="setPenSize(2)" ></div>
	<div><input type="image" src="images/mediumPen.png" title="medium pen" onclick="setPenSize(4)" ></div>
	<div><input type="image" src="images/largePen.png" title="large pen" onclick="setPenSize(8)" ></div>
	<div><input type="image" src="images/eraser.png" title="erase" onclick="setEraser()" ></div>
	<div><input type="image" src="images/trash.png" title="clear" onclick="initCanvas()" ></div>
	<input type="color" id="colorpicker" name="colorpicker" />
</td> 

Last week, our canvas used a blue background color so that it was clearly visible on the page. To improve the appearance, we will use a white background and use css to define a border. To do this, create a folder called css and an empty text file within it named grid.css. Then simply use the following to create a nice border around the canvas

#container {
	width: 400px; margin: 0px 12px 24px 12px;		
	box-shadow: 0px 5px 25px #343434;
	-moz-box-shadow: 0px 5px 25px #343434;
	-webkit-box-shadow: 0px 5px 25px #343434;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px; 
	border-radius: 10px;
}

Next, add a reference to the css script in the head section of the page.

<link rel="stylesheet" href="css/grid.css" type="text/css">

The last step is to implement the color picker functionality. Rather than re-inventing this functionality, we will use the fantastic color picker called Spectrum from Brian Gridstead. After evaluating several freely available color picker controls, Spectrum proved to be far and away the easiest to implement, most compatible with all of the major browsers, and feature complete.
The first step in implementing Spectrum is to download spectrum.js and spectrum.css. I’ve placed them in the scripts folder and the css folder respectively. Once the files are in place, add them to the page.

<script src="scripts/spectrum.js" type="text/javascript"></script>
<link rel='stylesheet' href='css/spectrum.css' type="text/css">	

And finally, bind the extension to the “colorpicker” element that we defined earlier while creating the controls section. To do this, simply add the following to grid.js .ready function.

$("#colorpicker").spectrum({
	color: "#0000ff",
	change: function(color) {
		penColor = color.toHexString();
	},
	show: function(color) {
		erase = false;
	}
});

As you can see, the change event of the color picker sets our pen color and the show event disables the erase functionality. Be sure to spend some time reviewing the excellent documentation provided on the Spectrum website to learn more about all of the options available with the extension.
For now, we have completed our face lift for the drawing application. The full source code is available via the demo.

June 5, 2012

A simple drawing grid with HTML5 part 2

Last week we created a full page drawing surface with HTML5 canvas. This week we will add a few simple controls to allow for the user to clear the surface, set drawing colors, and choose different sizes for the ‘pen’. Next week, we will finish the simple drawing application with a bit of css styling.
To make room for some controls, the drawing surface will no longer encompass the entire page. Instead of a fixed width, we will still scale the size by a factor of one half x and y.

var viewWidth = window.innerWidth * 0.5;
var viewHeight = window.innerHeight * 0.5;

If you remember last week, we relied on window events for clearing and initializing the canvas. Since we will be adding a button for clearing the canvas, the window events are no longer required. Instead, we will initialize the canvas when the page has been loaded.

$(document).ready(function() {
	
	initCanvas();

	$("#grid").mousedown(function(e) {
		mouseDown = true;
		mouseButton = e.which;
	}).bind('mouseup', function() {
		mouseDown = false;
	}).bind('mouseleave', function() {
		mouseDown = false;
	});
	
	$("#grid").mousemove(function(e) {
		if (mouseDown) {
			var x = Math.floor((e.pageX-xOffset) / penWeight);
			var y = Math.floor((e.pageY-yOffset) / penWeight);
			if (x != lastX || y != lastY) {
				lastX = x;
				lastY = y;
				ctx.fillStyle = mouseButton == 1 ? penColor : backgroundColor;
				ctx.fillRect(x*penWeight, y*penWeight, penWeight, penWeight);
			}
		}
	});
});

The one important change to this scripting is that we have added a bind for the ‘mouseleave’ event. This is required since the canvas no longer covers the entire page.
The canvas initialization scripting should be separated as it also provides the functionality of clearing the canvas by clicking on a button.

<input type="button" value="Clear" onclick="initCanvas()" >
initCanvas = function() {
    grid_canvas.setAttribute("width", viewWidth);
    grid_canvas.setAttribute("height", viewHeight);
    grid_canvas.style.top = 0;
    grid_canvas.style.left = 0;
	
	ctx.clearRect(0,0,viewWidth,viewHeight);
	ctx.fillStyle = backgroundColor;
	ctx.fillRect(0,0,viewWidth,viewHeight);	
};

Similarly, some buttons will be added to allow the user to specify the drawing color and drawing size.

<input type="button" value="Red Pen" onclick="setPenColor('rgb(255,0,0)')" >
<input type="button" value="Small Pen" onclick="setPenSize(2)" >
setPenColor = function(rgb) {
	penColor = rgb;
};

setPenSize = function(size) {
	penWeight = size;
}

So now we have a more useful drawing application that gives that provides some expected functionality. The results will still be fairly primitive, but we will work on improving the presentation next week with some css styling.

The complete source can be found by viewing the source of the demo.

Tags: ,
May 29, 2012

A simple drawing grid with HTML 5

This week, we will build a simple drawing grid using HTML5 and javascript. In the coming weeks we will transform this simple example into a fully functional drawing application. For this demo, the entire browser window will be a canvas and resizing or reloading the window will clear it.
The first step is to define our canvas and add some css that will set the size of the canvas to the size of the browser window.

<!DOCTYPE HTML>
<html>
	<style type="text/css">
	html, body { width: 100%; height: 100%; margin: 0px; }
	</style>
	<body>
		<canvas id="grid">
			<p>Your browser does not support HTML5 canvas</p>
		</canvas>
	</body>
</html>

This is all that is required to create a canvas that consumes the entire browser window. The next step is to add javascript to the page so we can have an interactive drawing surface. We will be using jquery and loading a script named grid.js; which will perform the canvas updates.

<!DOCTYPE HTML>
<html>
	<head>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
	</head>
	<style type="text/css">
	html, body { width: 100%; height: 100%; margin: 0px;  }
	</style>
	<body>
		<canvas id="grid">
			<p>Your browser does not support HTML5 canvas</p>
		</canvas>
		<script type="text/javascript" src="scripts/grid.js"></script>
	</body>
</html>

The next step is to create a folder named “scripts” and within it create a text file called grid.js using your favorite editor. The grid.js script will be responsible for all of the canvas updating. For starters, we will need to define the callbacks for window events in order to initialize the canvas data. “window.onresize” will be used so that the canvas can be cleared when the window is resized.

window.onload = window.onresize = function() {
	var grid_canvas = document.getElementById("grid");
	var ctx = grid_canvas.getContext("2d");
	var viewWidth = window.innerWidth;
	var viewHeight = window.innerHeight;
	var backgroundColor = "rgb(0,0,255)";

	grid_canvas.style.position = "fixed";
	grid_canvas.setAttribute("width", viewWidth);
	grid_canvas.setAttribute("height", viewHeight);
	grid_canvas.style.top = 0;
	grid_canvas.style.left = 0;

	ctx.clearRect(0,0,viewWidth,viewHeight);
	ctx.fillStyle = backgroundColor;
	ctx.fillRect(0,0,viewWidth,viewHeight);	
}

At this point, the canvas is created, but isn’t very interesting. To draw on the canvas, we will rely on mouse events. In this demo, holding down the left mouse button and dragging will fill in cells of the grid that the mouse is hovering over. Holding any other mouse button down and dragging will be used for an “erase” function. It’s not actually erasing, but coloring the cells in with the defined background color. The following should be added to the window event callback defined above.

var xOffset = $("#grid").offset().left;
var yOffset = $("#grid").offset().top;
var mouseDown = false;
var mouseButton = 0;
var penColor = "rgb(255,255,255)";
var penWeight = 5;

$("#grid").mousedown(function(e) {
	mouseDown = true;
	mouseButton = e.which;
}).bind('mouseup', function() {
	mouseDown = false;
});

$("#grid").mousemove(function(e) {
	if (mouseDown) {
		var x = Math.floor((e.pageX-xOffset) / penWeight);
		var y = Math.floor((e.pageY-yOffset) / penWeight);

		ctx.fillStyle = mouseButton == 1 ? penColor : backgroundColor;
		ctx.fillRect(x*penWeight, y*penWeight, penWeight, penWeight);
	}
});

Loading the page now should result in a functional drawing application. Changing the “penWeight” variable will alter the cell sizes on the hidden grid. As a small optimization, you may consider storing the last cell that was drawn to and skipping a redraw (included in the source example) if the user is still moving with the cell. At smaller cell sizes, this becomes less important.

The demo for the grid can be found here.

February 28, 2012

Creating an HTML5 Timer, part 2

Last week, we created a generic timer using canvas and the setInterval function. This week, we will add some audio elements and stylize the application using CSS3.  This timer is going to have an optional ticking sound for each second that elapses and an alarm sound when it has expired.

Adding sounds in HTML5 is done by defining elements with the <audio> tag. We’ll need to define a couple of them for our sounds without the controls attribute.

 

<audio id=”clockTick” preload=”auto”>

<source src=”audio/tick.mp3″ type=”audio/mpeg” />

<source src=”audio/tick.wav” type=”audio/wav” />

audio tag not supported.

</audio>

<audio id=”alarm” preload=”auto”>

<source src=”audio/alarm.mp3″ type=”audio/mpeg” />

<source src=”audio/alarm.wav” type=”audio/wav” />

</audio>

 

Next we’ll add a helper function to play the sounds.

 

function playSoundById(elementId) {

document.getElementById(elementId).play();

}

 

Since the ticking sound is optional, users will be able to turn it off with a button that toggles.

 

<div><input id=”muteButton” type=button value=”Mute” style=”width:97px; font-weight:bold” onClick=”muteClock()” ></div>

 

function muteClock() {

clockMuted = !clockMuted;

if (clockMuted == true) {

muteButton.value = “Un-Mute”;

return;

}

muteButton.value = “Mute”;

}

 

The last step for the sounds is to make calls to the helper function that we created. The ticking sound should be called from inside the setInterval function and the alarm sound will be called from inside the finish() function.

 

if (!clockMuted) {

playSoundById(‘clockTick’);

}

playSoundById(‘alarm’);

 

Last week, we built the interface using a simple html table.  This week, we have removed the table and now rely on CSS to position the elements. This gives us a bit more flexibility for the positioning of elements as well as the styling.

 

<div id=”container”>

<section id=”displaySection”>

<div class=”time”>

<input id=”elapsedTime” value=”0:00:00″ readonly=”readonly”>

</div>

<div id=”clock”>

<canvas id=”canvas” width=”100″ height=”100″>

Your browser does not support the canvas tag

</canvas>

<div class=”controls”>

<div><input name=”starter” type=button value=”Start” style=”width:97px; font-weight:bold” onClick=”startClock()” ></div>

<div><input name=”pauser” type=button value=”Pause” style=”width:97px; font-weight:bold” onClick=”pauseClock()” ></div>

<div><input name=”resetter” type=button value=”Reset” style=”width:97px; font-weight:bold” onClick=”resetClock()” ></div>

<div><input id=”muteButton” type=button value=”Mute” style=”width:97px; font-weight:bold” onClick=”muteClock()” ></div>

</div>

</div>

</section>

<section id=”settingSection”>

<div class=”settings”>

<input id=”hours” placeholder=”hh” type=”number” value=”” onkeypress=”validate(event)” />

<input id=”minutes” placeholder=”mm” type=”number” value=”” onkeypress=”validate(event)” />

<input id=”seconds” placeholder=”ss” type=”number” value=”” onkeypress=”validate(event)” />

</div>

</section>

</div>

 

And with a bit of CSS, our timer looks like the following.

You can see the CSS for our timer by viewing the source of the demo, although I would encourage you to experiment with some different styles of your own.

Tags:
February 21, 2012

Creating an HTML 5 Timer, part 1

This week, we will be creating a functional timer using HTML 5 timer elements. For visualization, we will use the canvas element to visualize time elapsed as well as an overlay that displays a message when the time has expired.

As a first step, we will craft the HTML for the interface. At the top of the page, we will display elapsed time followed by a canvas element the represents the elapsed time.

<input id=”elapsedTime” value=”0:00:00″ readonly=”readonly” style=”border:none; vertical-align:middle text-align:center; width:120px; font-size:32px; font-weight:bold” >

<td>

<div id=”container”>

<canvas id=”canvas” width=”100″ height=”100″>

Your browser does not support the canvas tag

</canvas>

<div id=”timesUp” style=”position:absolute; top:95px; left:12px; color:red”></div>

</div>

</td>

You will notice that the canvas and has been wrapped in a container that includes the another div. This extra div will be used for an overlay message to be displayed when the time has expired.

Next, we’ll add some input boxes so users can specify hours, minutes, and seconds as well as some buttons for starting, stopping, and resetting the timer.

<td>

<input id=”hours” type=”text” value=”” style=”width:26px” onkeypress=”validate(event)” />

<input id=”minutes” type=”text” value=”” style=”width:26px” onkeypress=”validate(event)” />

<input id=”seconds” type=”text” value=”” style=”width:26px” onkeypress=”validate(event)” />

</td>

<td>

<input name=”starter” type=button value=”Start” style=”width:97px; font-weight:bold” onClick=”startClock()” >

</td>

<td>

<input name=”pauser” type=button value=”Pause” style=”width:97px; font-weight:bold” onClick=”pauseClock()” >

</td>

<td>

<input name=”resetter” type=button value=”Reset” style=”width:97px; font-weight:bold” onClick=”resetClock()” >

</td>

In our input boxes for hours, minutes, and seconds, we want to limit the input to integers. To do this, we’ll use the validate event and regular expressions.

function validate(evt) {

var theEvent = evt || window.event;

var key = theEvent.keyCode || theEvent.which;

key = String.fromCharCode( key );

var regex = /[0-9]|\./;

if( !regex.test(key) ) {

theEvent.returnValue = false;

if(theEvent.preventDefault) theEvent.preventDefault();

}

}

Now we will need to create the script that drives the timer. When the page is loaded, we will need to initialize some variables and render our canvas element.

var interval = 1000;

var limit = 0;

var canvas, ctx, size, startAngle, wedgeSize, fillClr, elapsed, intervalId, timerElement;

var hh=0, mm=0, ss=0;

var hInput, mInput, sInput, overlay;

$(document).ready(function() {

canvas = $(“#canvas”)[0];

ctx = canvas.getContext(‘2d’);

size = Math.min(canvas.width, canvas.height);

startAngle = -Math.PI/2;

timerElement = document.getElementById(‘elapsedTime’);

hInput = document.getElementById(‘hours’);

mInput = document.getElementById(‘minutes’);

sInput = document.getElementById(‘seconds’);

overlay = document.getElementById(‘timesUp’);

initClock();

});

Notice the initClock function that is called. We don’t have that yet, so let’s create it. This function will be responsible for resetting variables as well as drawing the initial canvas element.

function initClock() {

timerElement.value = “0:00:00”;

overlay.innerHTML = “”;

elapsed = 0;

wedgeSize = (interval / limit) * Math.PI * 2;

fillClr = “#fff8dc”;

var bgClr = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

bgClr.addColorStop( 0, “#000000” );

bgClr.addColorStop( 1, “#999999” );

fillClr = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

fillClr.addColorStop( 0, “#AAAAAA” );

fillClr.addColorStop( 1, “#EEEEEE” );

var drawX = drawY = radius = size / 2;

var circle = canvas.getContext(“2d”);

circle.globalAlpha = 1;

circle.beginPath();

circle.arc(drawX, drawY, radius, 0, Math.PI * 2, true);

circle.fillStyle = bgClr;

circle.fill();

circle.lineWidth = 0.25;

circle.strokeStyle = “#000000”;

circle.stroke();

}

At this point, all that is left to do is to plug in the buttons that we defined earlier. So let’s start with getting the timer running. This function will parse the user input for hours, minutes, and seconds and kick off the timer using HTML5’s setInterval function. The setInterval function will repeatedly be called until it is cleared, so we can take advantage of this to advance our visual representations.

function startClock() {

limit = (parseInt(hInput.value == “” ? “0” : hInput.value) * 3600)

+ (parseInt(mInput.value == “” ? “0” : mInput.value) * 60)

+ parseInt(sInput.value == “” ? “0” : sInput.value);

limit *= 1000;

intervalId = setInterval(function () {

elapsed = elapsed + interval;

wedgeSize = (elapsed / limit) * Math.PI * 2;

updateTime();

var drawX = drawY = radius = size / 2;

var endAngle = startAngle + wedgeSize;

var wedge = canvas.getContext(“2d”);

wedge.beginPath();

wedge.moveTo(drawX, drawY);

wedge.arc(drawX, drawY, radius, startAngle, endAngle, false);

wedge.closePath();

wedge.fillStyle = fillClr;

wedge.fill();

wedge.lineWidth = 0.25;

wedge.strokeStyle = “#eeeeee”;

wedge.stroke();

if (elapsed >= limit) {

clearInterval(intervalId);

finish();

}

}, interval);

}

You should notice a call to an updateTime() function. We’ll need to create this function as it is responsible for the text display of elapsed time.

function updateTime() {

var s,m;

ss += 1;

s = ss < 10 ? ‘0’ + ss : ss;

if (ss > 59) {

ss = 0;

s = ’00’;

mm += 1;

}

m = mm < 10 ? ‘0’ + mm : mm;

if (mm > 59) {

mm = 0;

m = ’00’;

hh += 1;

}

timerElement.value = hh + ‘:’ + m + ‘:’ + s;

}

Once the elapsed time has reached the limit, clearInterval () is called as well as a finish().  The finish() function is something we will need to create. Its purpose for now is to display some text in the overlay.

function finish(){

overlay.innerHTML = “Time is up!”;

}

Since we want our users to be able to pause the timer, we can attach the clearInterval() function to the Pause button.

function pauseClock() {

clearInterval(intervalId);

}

Finally, we will need to create a function for the Reset button. This function will stop the clock, zero out the elapsed time, and re-initialize the canvas.

function resetClock() {

pauseClock();

elapsed = hh = mm = ss = 0;

initClock();

}

You can see the demo in action here. Next week we will add a bit a polish to the interface as well as add some audio indicators for interval updates and an alarm when the time limit is hit.

February 14, 2012

Multiple View Models with Knockout

In a recent project, I was required to create a form for user input in a web page. Each section of the form is distinct and serves a unique purpose, so I chose to use a tabbed layout . The order in which the forms are completed was not a strict requirement, so some visual indication of which sections were completed was also a requirement.

I decided to use Knockout js for the data binding to take advantage its easy data bindings as well as the ko.computed method to determine which sections are complete.  While creating a design for this, it became apparent that each section (tab) should be its own view model. The problem was that there really isn’t any documentation on how to create multiple view models on a single page. There is an obscure reference deep in the Knockout js documentation that does not clearly explain how to do it.

After a bit of googling, I could not find any clear instructions on how to solve the problem; only some single line answers. After getting small hints from several google search results and some trial and error, I was able to come up with a clean solution.

The solution is actually quite simple, but I thought I would share it with since having a clear example would have saved me a lot of time.

The first thing to do is to create your sections on the page with a unique id.

<section class="tab" id="firstSection">
	<h1>First Section</h1>
	<p>First Name: <strong data-bind="text: name"></strong></p>
	<p>First name: <input data-bind="value: name" /></p>

</section>

<section class="tab" id="secondSection">
	<h1>Second Section</h1>
	<p>Second Name: <strong data-bind="text: name"></strong></p>
	<p>Second name: <input data-bind="value: name" /></p>	
</section>

One thing you may notice about this example is that it is using the same variable name called “name” in each section. This is one of the benefits of using multiple view models since those variables are only accessible in the scope of the view model.

Second, you will need to define your view models. There is nothing special about how these are defined for this particular solution.

function firstViewModel() {
	var self = this;
	self.name = ko.observable("Enter Name");			
};

function secondViewModel() {
	var self = this;
	self.name = ko.observable("Enter Name");	
};

Lastly, you will need to apply the bindings for the view models and assign them to the previously defined sections.

ko.applyBindings(new firstViewModel, $("#firstSection")[0]);
ko.applyBindings(new secondViewModel, $("#secondSection")[0]);

Take note of the second parameter passed to the applyBindings method as it does the magic of isolating the view model to a specific element on the page.  I am not sure why this isn’t clearly documented anywhere, but hopefully this post proves useful to anyone that is looking to add support for multiple view models on a single page.

A working demo can be found here

January 31, 2012

Creating a simple pie chart with HTML5 Canvas Part 3

Over the last two weeks, we have created a simple pie chart and then added some functionality. This week we will focus on some design aspects to improve the presentation of the chart.

While contrasting colors for each slice of the pie can be used for a clear distinction between slices, using a border for each one generally looks nicer. This is easily accomplished using the .stroke method.

 

ctx.lineWidth = 1;

ctx.strokeStyle = “#fff”;

ctx.stroke();

 

Another simple way to improve the appearance of the chart is to add some color gradient for each slice. Using color gradients will give the chart a more modern look and are extremely simple to add. The first step is to define the gradient as follows.

 

var gradient = ctx.createLinearGradient( 0, 0, canvas.width, canvas.height );

gradient.addColorStop( 0, “#ddd” );

gradient.addColorStop( 1, colors[i] );

 

Once the gradient is defined, we can set it as the fillStyle for the context and call the fill method.

 

ctx.fillStyle = gradient;

ctx.fill();

 

Last week we added rendering of the pie slice values at the bottom of the screen. While that does the job of giving the user information about the slice, it forces them to look away from the chart. To improve on that, we will have the value of the slice be rendered at the position of the mouse. The effect will be that the value follows the user as they hover over the slices.

 

ctx.fillStyle = ‘#fff’;

ctx.font = ‘bold 10px verdana’;

ctx.fillText(pieData[slice][‘value’], x, y, 20);

 

While adding these improvements may seem trivial, they are worth mentioning due to the fact that they transform what was a simple and dull chart into one that is more functional, intuitive, and professional.

For the full source and a working demo, please follow the link below.

 http://yojimbocorp.com/demos/pieChart3.html

January 24, 2012

Creating a simple pie chart with HTML5 Canvas Part 2

Last week we created a pie chart using HTML5’s Canvas element. This week we will utilize jQuery to add some simple functionality.  For this exercise, we want to be able to visualize the exact values of each slice of the pie when the user positions the mouse over them. To do this, we will use the .mousemove event from jQuery to update text on the page.

The first step is to include jQuery.

 

<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js”></script&gt;

 

Next, we will need to refactor the script from last week a bit in order to reference it from the mousemove event. To do this, we will create an array to store the data for each slice.

 

var pieData = [];

for(var i in data) {

                pieData[i] = [];

                pieData[i][‘value’] = data[i];

                pieData[i][‘startAngle’] = 2 * Math.PI * lastPosition;

                pieData[i][‘endAngle’] = 2 * Math.PI * (lastPosition + (data[i]/total));

                lastPosition += data[i]/total;

}

 

Now that the data is stored a bit differently than last week, we will need to update the script that renders the pie chart. Specifically, we will change the ctx.arc call to reference the data we just stored in the pieData array.

 

for(var i = 0; i < data.length; i++)

{

                ctx.beginPath();

                ctx.moveTo(center[0],center[1]);

                ctx.arc(center[0],center[1],radius,pieData[i][‘startAngle’],pieData[i][‘endAngle’],false);

                ctx.lineTo(center[0],center[1]);

                ctx.closePath();

                ctx.fillStyle = colors[i];

                ctx.fill();

}

 

Next we will add some text to the page that will be used to display the value of the pie chart that the user is currently hovering over with the mouse.

 

<div>

        Hover over a slice

</div>

 

Now that we have a placeholder for the text, we can add the mousemove event that will first evaluate whether the user is within the radius of the chart and then do a bit of math to determine which slice the mouse is over.

 

$(“#canvas”).mousemove(function(e) {

                var x = Math.floor((e.pageX-$(“#canvas”).offset().left));

                var y = Math.floor((e.pageY-$(“#canvas”).offset().top));

                var fromCenterX = x – center[0];

                var fromCenterY = y – center[1];

                var fromCenter = Math.sqrt(Math.pow(Math.abs(fromCenterX), 2) + Math.pow(Math.abs(fromCenterY), 2 ));

 

                if (fromCenter <= radius) {

                                var angle = Math.atan2(fromCenterY, fromCenterX);

                                if (angle < 0) angle = 2 * Math.PI + angle; // normalize

 

                                for (var slice in pieData) {

                                                if (angle >= pieData[slice][‘startAngle’] && angle <= pieData[slice][‘endAngle’]) {

                                                                $(“div.sliceValue”).text(“The value for the slice is ” + pieData[slice][‘value’]);

                                                                return;

                                                }

                                }

                }

});

 

If all went well, you should now have a working demo. If not, you can view the source of the working demo linked below.

 

http://yojimbocorp.com/demos/pieChart2.html

January 17, 2012

Creating a simple pie chart with HTML5 Canvas

This week we take a look at how to use the HTML5 canvas element to create a simple pie chart. To begin, we need to define the element using the canvas tag. Please note the id, height, and width are required.

<canvas id=”canvas” width=”400″ height=”300″></canvas>

In order to interact with this canvas through Java script, we will need to first get the element by Id and then create a context.


<script type="text/javascript">

var canvas = document.getElementById(‘canvas’);

var ctx = canvas.getContext(“2d”);

</script>

These two steps are essentially all that is required to start drawing to the canvas. For this example, we will be drawing a simple pie chart, so let’s add some data. We’ll use some hard coded values for data in the interest of simplicity.

 

var data = [75,68,32,95,20,51];

var colors = [“#7E3817”, “#C35817”, “#EE9A4D”, “#A0C544”, “#348017”, “#307D7E”];

var center = [canvas.width / 2, canvas.height / 2];

var radius = Math.min(canvas.width, canvas.height) / 2;

var lastPosition = 0, total = 0;

 

Next we will need to get the total value of all the data being represented in the pie chart. This is required in order to scale the size of each slice correctly. To do this, we simply need to loop through the data array and add each value into the ‘total’ variable defined above.

 

for(var i in data) { total += data[i]; }

 

And finally, we are ready start using canvas to draw each slice of the pie. To do this, we will loop through the data array again and call the canvas methods to create and fill the shapes.

 

for (var i = 0; i < data.length; i++) {

ctx.fillStyle = colors[i];

ctx.beginPath();

ctx.moveTo(center[0],center[1]);

ctx.arc(center[0],center[1],radius,lastPosition,lastPosition+(Math.PI*2*(data[i]/total)),false);

ctx.lineTo(center[0],center[1]);

ctx.fill();

lastPosition += Math.PI*2*(data[i]/total);

}

 

Loading the page in an HTML5 enabled browser should result in our chart being rendered as follows.

 

pie_chart

 

Next week we will take a look at adding labels to the chart as well as adding some user interaction with animation.