Introduction
In this article, I will try to show one of the basic complex animations of Canvas
and Web Worker in HTML5.
We are going to draw a square and animate it around the center of canvas
. The square will make double rotation: around a circle (clockwise) and around itself (counterclockwise).
Because the user could modify the radius of the circle and the size of the square, we will create a worker to work in the background. Otherwise the JavaScript will keep forever the application threat if the user enters a bad input.
Using the Code
We start with the HTML markup. Since the Canvas
element and the Worker are not supported in the previous version of HTML, the following declaration is the one we need.
<!DOCTYPE html>
After we declare the canvas
:
<canvas id="canvas" height="400" width="400"></canvas>
We need an “Id
” because we will access it in JavaScript.
Then we need fields to allow users to interact. To keep thing simple, we create a table with one row only and three columns as follows:
<table id="table">
<tr id="table_row">
<td>
<label for="tcircle">
Circle radius</label><br />
<input type="text" id="tcircle" class="textbox" />
</td>
<td>
<label for="tsquare">
Square size</label><br />
<input type="text" id="tsquare" class="textbox" />
</td>
<td>
<input type="hidden" id="hidden" value="34,21" onchange="valueChanged()"/>
<br />
<input type="button" value="Apply" id="btn" />
</td>
</tr>
</table>
Now since our user interface is ready, let us move to JavaScript to perform drawing on the canvas
.
We start by defining two global variables:
var canvas;
var context;
The first is the canvas
and the second is the context
on which we will be working on.
Let us create our first function which draws a circle. It takes one parameter: the radius of the circle. Here is the function:
function draw_circle(radius) {
context.beginPath();
context.arc(0, 0, radius, 0, 2 * Math.PI, true);
context.closePath();
context.stroke();
}
Here is the square function:
function draw_square(size) {
var angle = 0;
var r = size / Math.SQRT2;
context.beginPath();
context.moveTo(r * Math.cos(angle), r * Math.sin(angle));
var gama = Math.PI / 2;
for (var i = 1; i < 4; i++) {
angle += gama;
context.lineTo(r * Math.cos(angle), r * Math.sin(angle));
}
context.closePath();
context.fillStyle = "#00ff00";
context.fill();
}
Because we draw, clear the context
and draw again, we need one clear
function.
function clear() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
The function to call when the page loads is:
function init() {
canvas = document.getElementById("canvas");
if (canvas && canvas.getContext) {
context = canvas.getContext("2d");
return setInterval(draw, 10);
}
else {
alert("Canvas is not supported!");
}
}
Now is our draw
function.
First, let us create three others global variables for angles.
var beta = 0;
var alpha = 0;
var theta = .01 * Math.PI;
Now here is the draw function:
function draw() {
clear();
var R = 30;
var S = 20;
alpha += theta;
context.save();
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(alpha);
draw_circle(R);
beta -= 3 * theta;
context.save();
context.translate(R, 0);
context.rotate(beta);
draw_square(S);
context.restore();
context.restore();
}
We finish the draw and animation. Now let us allow interaction.
We start by creating our worker. It just takes the values of the two text boxes and converts them into one string
.
function applyValues(radius, size) {
return radius + "," + size;
}
this.onmessage = function (event) {
var data = event.data;
postMessage(applyValues(data.radius, data.size));
};
To finish, in the HTML markup in the script
section, we perform the following task with some basic security and information to display to the user.
<script>
function getWebWorkerSupport() {
return (typeof (Worker) !== "undefined") ? true : false;
}
if (getWebWorkerSupport() == true) {
var radius, size, message;
worker = new Worker("scripts/worker.js");
worker.onmessage = function (event) {
document.getElementById("hidden").value = event.data;
};
document.getElementById("btn").onclick = function () {
radius = document.getElementById("tcircle").value;
size = document.getElementById("tsquare").value;
var canvas = document.getElementById("canvas");
if (!isNaN(radius) && !isNaN(size)) {
radius = parseInt(radius);
size = parseInt(size);
if (radius >= size / Math.SQRT2) {
if ((radius + (size / Math.SQRT2)) < 200) {
message = { 'radius': radius, 'size': size };
worker.postMessage(message);
}
else {
alert("The summation of the radius and the half of the
hypotenuse must not be greater than 200 pixels");
}
}
else {
alert("The radius must be greater the size/sqrt(2)!");
}
}
else {
alert("Numerics type are needed!");
}
}
}
</script>
The event that wires up when the value of the hidden field changed is:
function valueChanged() {
return document.getElementById("hidden").value;
}
The hidden field is there just to update when drawing.
It is all. Thank you.
History
- 11th May, 2011: Initial version