Creating and using the Canvas in HTML 5 and JavaScript

HEALTH WARNING!

We are about to start programming in JavaScript.

At some point your browser will probably ask you a question like the following one…

By allowing your browser to run Java Script you are potentially opening yourself up to serious security vulnerabilities resulting in virus infections.

  1. Only use Java Script from known trusted sources. Dodgy code from dodgy sites may (and probably will) contain malicious code.
  2. Close your browser window after testing a section of code. Navigating to the web after allowing blocked content to run could also open you up to infection.

You have been warned!

Introduction to HTML 5

In the late 1980 early 90s Tim Berners-Lee working in Switzerland devised the first specification for HTML based on SGML. Part of the driving force for this was the feeling that SGML was too complicated to easily share scientific documents across the internet.

A simple HTML document has the following format...

(This should be quite familiar to you!)

When displayed in the browser you will see the following page...

Notice how we use tags to mark up the document (in this case for bold, italics and underlined).

There are however a few problems with the early version of HTML.

1. The tags were defined as part of the language specification. If we wanted to add a new feature to HTML then a new version of the language had to be created.

2. Different browsers added new features to the language in order to compete.

A good example of this is the marquee tag.

In the following document we have created a marquee tag...

The effect that you get is a section of text that moves from one side of the page to the other...

Although we can debate on how effective this feature is the big problem is that it only worked in Internet Explorer. This was a ploy by Microsoft to drive other companies out of the market by having more “cool” features than them. Other companies did the same also in an effort to push Internet Explorer out of the game.

These “browser wars” resulted in multiple versions of HTML appearing specific to different browsers.

This created the possibility that you could navigate to a page and sections of the HTML in that page may not work when viewed in your browser of choice.

In the light of this need for standards Tim Berners-Lee founded the World Wide Web Consortium (W3C) in 1994.

The W3C’s purpose is to devise standards and software related to the World Wide Web.

Some time around 1998 the decided that there was no point extending HTML any further and would concentrate on a few other strands.

XHTML Strict and Transitional

The idea was that a much tighter specification for mark-up would be devised based on XML. XHTML followed many of the rules for XML but came in two versions.

  • XHTML - transitional, which had a slightly more relaxed attitude to the syntax and validation
  • XHTML strict - which tightly followed the XHTML standards and syntax

The W3C hoped that we would all be good boys and girls would adopt the strict version and eventually we would have a world wide web consisting of perfectly validated sites all following the tight syntax of XHTML strict.

Unfortunately the standards were not widely adopted and many people and browsers refused to adopt the new standard. Some people went back to HTML 4 or stopped at XHTML transitional. Some browsers simply didn’t implement the support for XHTML. In spite of this the W3C pressed on with XHTML 2.0.

To make matters worse for the W3C in 2004 (a separate group including Apple, Opera and Mozilla) devised an extension to HTML called Web Forms 2.0.

This went on for some time with the XHTML standards not really being adopted and a parallel project running in competition when in 2006 the W3C changed their mind and around 2007 pretty much abandoned XHTML in favor of HTML 5.

The Role of Java Script

Since HTML 5 is looking more and more the future of interface development (not just for multimedia and not just for the web we are going to have to move with the times. The down side is that if we want to do any multimedia in HTML 5 we are going to have to learn JavaScript.

The Structure of HTML 5

As seen above a simple HTML document has the following format...

The following is a blank HTML 5 document…

If you are familiar with XHTML you will notice that the doc type (at the top is much simpler). This line of code must be present to tell the browser to translate the page as an HTML 5 document and not HTML or XHTML. The simpler doc type is one clue as to the direction taken with HTML 5 the idea is to make it a bit simpler for non technical people to use.

Creating Your Storyboard

The first step in designing this multimedia content is to plan it on a storyboard.

Here is the storyboard for our first animation in JavaScript.

For the next step in this exercise you will need to create a new C# web site in Visual Studio. In this case we will call it SpaceLander.

Create a new HTML 5 document

Name the new page Default.html

Take a look at basic page structure

<!DOCTYPEhtml

htmlxmlns="

head

metacharset="utf-8"/>

title</title

</head

body

</body

</html

The next step is to create the canvas object. This is the area we define on the web page where our animation will appear.

<!DOCTYPEhtml

htmlxmlns="

head

metacharset="utf-8"/>

title</title

</head

body

canvasid="canvas"width="400"height="400"</canvas

</body

</html

Next we want to style the page to make it more interesting to look at. To do this we will create an external style sheet.

Now select the style sheet from the list of available entries…

Modify the style sheet like so…

body {

background-color: rgb(176,176,176);

}

#canvas

{

background-color: rgb(255,255,255);

}

To link the style sheet to the page add the following line of HTML…

<!DOCTYPEhtml

htmlxmlns="

head

metacharset="utf-8"/>

title</title

linkrel="stylesheet"href="StyleSheet.css"/>

</head

body

canvasid="canvas"width="400"height="400"</canvas

</body

</html

To view the page in the browser press F5 as you would for any other Visual Studio project.

You should be able to see the canvas drawing area against the grey web page background…

The next step is to create the area in the page where we will write our script. To do this we need to mark up the page so that it knows that a specific section is code not HTML…

<!DOCTYPEhtml

htmlxmlns="

head

metacharset="utf-8"/>

title</title

linkrel="stylesheet"href="StyleSheet.css"/>

</head

body

canvasid="canvas"width="400"height="400"</canvas

script

</script

</body

</html

Events in JavaScript are a very similar concept to events in ASP.NET. (We will explore eventsin more detail later on.)

We write sections of code acting as event handlers to process certain events when they happen to the interface.

One important event in JavaScript is the load event.

This event runs as soon as the page is loaded in the browser.

The following code adds the handler for the load event…

<!DOCTYPEhtml

htmlxmlns="

head

metacharset="utf-8"/>

title</title

linkrel="stylesheet"href="StyleSheet.css"/>

</head

body

canvasid="canvas"width="400"height="400"</canvas

script

//this function will always be executed when the page loads

window.onload = function ()

{

//our code here

}

</script

</body

</html

We will now create two important objects to allow us to control what is on the canvas

The canvas is not automatically available to the code that we write. To access the canvas in the code we need to attach an object called the context. This object allows us to draw on the canvas.

To get at the canvas we create an object based on it and then associate a context to the canvas like so...

<!DOCTYPEhtml

htmlxmlns="

head

metacharset="utf-8"/>

title</title

linkrel="stylesheet"href="StyleSheet.css"/>

</head

body

canvasid="canvas"width="400"height="400"</canvas

script

//this function will always be executed when the page loads

window.onload = function ()

{

//our code here

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d');

}

</script

</body

</html

Canvas is linked to the HTML 5 tags via

document.getElementById('canvas')

getElementByID tells the code to link to a section of HTML 5 we want to do something with i.e….

('canvas')

Which is the ID of the section of HTML 5 specified when we created that mark-up

canvasid="canvas"width="400"height="400"</canvas

This canvas object allows us access to the HTML 5 canvas area.

Problem – the canvas has no drawing facilities built into it. Before we may do any drawing we need access to the context. The context may be 2D or 3D. The context gives us access to the full set of drawing tools (API – Applications Programmers Interface) In this case we need access to the 2D drawing context…

context = canvas.getContext('2d')

Having gained access to the context via the variable “context” we now have access to the 2D drawing API.

In JavaScript we will use vector drawing to create a simple square.

Vector drawing is based on drawing shapes by means of using coordinates strokes and fills.

Planning out your first Shape

The first step is to plan out the shape on paper. (Honestly this really makes life a lot simpler as our designs get more complicated.)

Using a page of graph paper we shall plan out a 30px (pixel) by 30px square

Notice that the canvas starts at zero not one!

The coordinates follow standard x, y coordinates.

So to draw a square we need to draw lines like so…

It is a good idea to use a ruler (and a pencil in case you make a mistake!)

(Note at this stage we have only created three sides of the square we shall see why in a moment.)

So to draw the square we need to start at position 0,0. Draw a line to 29,0, then 29,29 and then 0,29.

Writing your First JavaScript

The JavaScript to do this look like this…

script

//this function will always be executed when the page loads

window.onload = function ()

{

//our code here

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d')

//start the line (path)

context.beginPath();

//set the start coordinates

context.moveTo(0, 0);

//draw the top line

context.lineTo(29, 0);

//draw the right side

context.lineTo(29, 29);

//draw the bottom line

context.lineTo(0, 29);

//go ahead and draw the line

context.stroke();

}

</script

To draw a line we create a “path” which is a line passing through a set of coordinates.

The first step is to begin the path using beginPath. Next we tell the line where it is starting from (moveTo) and then we send the path to different coordinates to get the shape that we are after. The last step is to actually draw the line using the “stroke” method. (Think of the stroke of a pen or a brush!)

If you try the code above you will get something like this…

Not quite the square we are after but we are getting there.

The last step is to finish the left hand side of the square.

We could do this by one of two approaches.

We could add an extra lineTo to finish off the square. Or we could close the path using closePath. In this case we will do the latter…

//this function will always be executed when the page loads

window.onload = function ()

{

//our code here

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d')

//start the line (path)

context.beginPath();

//set the start coordinates

context.moveTo(0, 0);

//draw the top line

context.lineTo(29, 0);

//draw the right side

context.lineTo(29, 29);

//draw the bottom line

context.lineTo(0, 29);

//close the path

context.closePath();

//go ahead and draw the line

context.stroke();

}

The advantage of closing the path is that we may also use fill method to make the insides of the shape have a colour.

window.onload = function ()

{

//our code here

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d')

//start the line (path)

context.beginPath();

//set the start coordinates

context.moveTo(0, 0);

//draw the top line

context.lineTo(29, 0);

//draw the right side

context.lineTo(29, 29);

//draw the bottom line

context.lineTo(0, 29);

//close the path

context.closePath();

//fill the shape

context.fill();

//go ahead and draw the line

context.stroke();

}

You should get something like this…

This is all very nice but would it be good if we set up some actual animation!

In this first example we will create animation in a slightly rubbish manner.

Once we have got things working we will have a go at refining what we are doing so that it fits in with good OO programming practice and hopefully makes our life simpler in the long run.

Creating Basic Animation – Frames and Sprites

The steps to creating animation in JavaScript in simple terms are as follows.

  1. We draw a frame
  2. We calculate the new position of sprites in the animation to create a new frame
  3. We repeat step one

We are using the word sprite to refer to “things” in the animation. In the above example our sprite is the square we have just drawn.

In calculating the position of sprites in the animation we may take into account a number of factors

Sprites might chase or run away from other sprites

Sprites might for example bounce off the side of the canvas area

A canon ball sprite might follow an arc.

Pressing the keys on the keyboard or moving the mouse might make the sprite do something.

There are lots of options / combinations to the above.

The first thing we want to do is try and get the square we have drawn above moving.

To do this we will need to change the structure of our code.

To keep re-drawing frames we need to first create a function that draws our box like so…

window.onload = function ()

{

//our code here

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d')

draw();

function draw()

{

//start the line (path)

context.beginPath();

//set the start coordinates

context.moveTo(0, 0);

//draw the top line

context.lineTo(29, 0);

//draw the right side

context.lineTo(29, 29);

//draw the bottom line

context.lineTo(0, 29);

//close the path

context.closePath();

//fill the shape

context.fill();

//go ahead and draw the line

context.stroke();

}

}

To make sure that it works we need to make sure that there is a suitable call to the function draw()

(In JavaScript we are able to create functions inside of other functions.)

This means that the variables canvas and context having been declared in the page’s load event are in the same scope as the function “draw”.

Run the code and everything should work as before.

That gives us part of the three step process…

  1. We draw a frame
  2. We calculate the new position of sprites in the animation to create a new frame
  3. We repeat step one

That is some of step one completed in that we can draw our sprite!

The next step is to create a function that calculates the new position of the sprite and draws the sprite in its new position.

Create a new function called drawFrame like so adding the call to draw()…

//this function will always be executed when the page loads

window.onload = function ()

{

//create a reference to the canvas

var canvas = document.getElementById('canvas'),

//access the 2D drawing API

context = canvas.getContext('2d')

function drawFrame()

{

//draw the sprite

draw();

}

//this function draws our sprite

function draw()

{

//start the line (path)

context.beginPath();

//set the start coordinates

context.moveTo(0, 0);

//draw the top line

context.lineTo(29, 0);

//draw the right side

context.lineTo(29, 29);

//draw the bottom line

context.lineTo(0, 29);

//close the path

context.closePath();

//fill the shape

context.fill();

//go ahead and draw the line

context.stroke();

}

}

Run the program to see what happens. You should see nothing.

Why is this?

The problem is that we are not making a call to the new function in the page’s load event.

To fix this add a line of code like this to call the new function…

//this function will always be executed when the page loads

window.onload = function ()

{

//create a reference to the canvas

var canvas = document.getElementById('canvas'),

//access the 2D drawing API

context = canvas.getContext('2d')

//call the drawFrame function

drawFrame();

function drawFrame()

{

//draw the sprite

draw();

}

//this function draws our sprite

function draw()

{

//start the line (path)

context.beginPath();

//set the start coordinates

context.moveTo(0, 0);

//draw the top line

context.lineTo(29, 0);

//draw the right side

context.lineTo(29, 29);

//draw the bottom line

context.lineTo(0, 29);

//close the path

context.closePath();

//fill the shape

context.fill();

//go ahead and draw the line

context.stroke();

}

}

Ok now what?

Getting things moving

So far in drawing the square we are hard coding the coordinates into the function.

//set the start coordinates