Topic 10: Introduction to Canvas and Event Handling

This topic is only intended for students who are up-to-date. You must complete Topics 1-4, and 6-8,before you attempt this.

Introduction to Canvas

The canvas tag allows you to draw 2D graphics in the browser. It has only been available for the past 10 years or so of web development. It was not available in the first 10 to 15 years of the web; at that time people had to rely on proprietary third-party plugins such as Flash which were awkward to install and keep up to date.

It allows you to draw shapes such as lines, rectangles, circles, polygons and curves - as well as text - within the browser. This opens up a number of possibilities including in-browser drawing applications or even games.

Using the canvas tag

Note that to allow you time to do practical work, I will not go through all of these notes in detail. However they are there for you to read.

How do you create a canvas?

Simply add a <canvas> tag to your HTML and give it an ID, a width and a height (specify the width and height here, and not in the CSS, otherwise the drawing functions will not work correctly) e.g.:

<canvas id='canvas1' width='500' height='500'></canvas>

How do you draw things on a canvas?

You use JavaScript to actually draw on the canvas. Here is a short example which draws a red rectangle. This example only will show the full HTML as well as the JavaScript, but subsequent examples will show the JavaScript only as the HTML remains the same:


<html>
<head>
<script type='text/javascript' src='canvas.js>

</script>
</head>
<body onload='init()'>
<canvas id='canvas1' width='400' height='400'></canvas>
</body>
</html>

JavaScript:
function init()
{
    var canvas = document.getElementById('canvas1');
    var ctx = canvas.getContext('2d');
    ctx.fillStyle = '#ff0000'; // red 
    ctx.fillRect(10,10,100,100);
}
What we do in this script is as follows:
var canvas = document.getElementById('canvas1');
This gets hold of the canvas element using the DOM.
var ctx = canvas.getContext('2d');
This line obtains a drawing context from the canvas. The drawing context is an object we use to draw on the canvas.
ctx.fillStyle = '#ff0000'; // red 
ctx.fillRect(10,10,100,100);
These lines set the fill colour to red and draw a red rectangle at x=10, y=10 of width 100 and height 100 pixels. Here is another example which shows an outline-only, non-filled-in rectangle:
function init()
{
    var canvas = document.getElementById('canvas1');
    var ctx = canvas.getContext('2d');
    ctx.strokeStyle = '#0000ff'; // blue
    ctx.strokeRect(10,10,100,100);
}
Note how this example sets the stroke (i.e. line drawing) colour instead of the fill colour, and draws an outlined rectangle with strokeRect().

Paths (lines and polygons)

We can draw polygons and multi-point lines by creating a path. Here is an example:

function init()
{
    var canvas = document.getElementById('canvas1');
    var ctx = canvas.getContext('2d');
    ctx.strokeStyle = '#0000ff'; // blue
    ctx.beginPath();
    ctx.moveTo(100,100);
    ctx.lineTo(150,100);
    ctx.lineTo(150,150);
    ctx.stroke();
}
Here is an explanation of the new functions:

We could turn it into a polygon, rather than a line, with the addition of the following line immediately before the ctx.stroke():

ctx.closePath();
This line effectively "closes the loop".

We could also draw a filled polygon by substituting ctx.stroke() with ctx.fill().

Text

Here is an example which draws text.

function init()
{
    var canvas = document.getElementById('canvas1');
    var ctx = canvas.getContext('2d');
    ctx.font = '12pt Helvetica';
    ctx.fillText('Hello', 300, 300);
}
This should hopefully be obvious: the font is set to 12pt Helvetica and then the text 'Hello' is drawn at x=300, y=300.

Images

This example draws images. (see here).

function init()
{
    var canvas = document.getElementById('canvas1');
    var ctx = canvas.getContext('2d');
    var image = new Image();
    image.src = "http://server.com/images/hero.png";
    image.addEventListener("load", () => {
        ctx.drawImage(image, 100, 100);
    });
}
Note how we create a new Image object, set its src property to the location of the image on the server, and then draw the image at a given x and y position. Note the image.addEventListener("load", ...) which links to an arrow function which actually draws the image. Why are we doing this? Loading an image from the web might take time, so writing our code this way ensures that the image will only be drawn once it's been loaded.

Circles

We can also draw circles, here is an example:

function init()
{
    var canvas = document.getElementById('canvas1');
    var ctx = canvas.getContext('2d');
    ctx.strokeStyle = '#0000ff'; // blue
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, Math.PI*2, false);
    ctx.stroke();
}
The 6 parameters to arc() need to be explained as many are not obvious. The reason why there are so many is because the function can be used to draw arcs as well as circles. Here is the explanation: Once again we can use fill() to draw a filled circle, or arc, rather than stroke().

Event handling

As we have already seen, event handling is a common technique in client-side web development. An event typically occurs when the user interacts with a page in some way, such as clicking a button or moving the mouse over a div. We have already seen some examples of events with map click events and button click events; indeed events can be classed in the general sense as things that happen outside the main flow of the program, in other words they require asynchronous code. Receiving an AJAX response, or obtaining a GPS signal, are other examples of events. We write callback functions to handle the various types of event; these callback functions are known as event handlers.

The modern way of linking an event to its handler is via the addEventListener() method, which you have already seen. This takes two arguments, the event type and the event handler function. For example:

element.addEventListener("eventtype", eventHandler);
For example, to handle a click event we would say:
element.addEventListener("click", eventHandler);
where eventHandler is a function which runs when the user clicks on the given element.

The event object

In the event handler we need to find out information about the event. Useful information about the event might include:

We can find out all this information via the event object. The event object is a special object automatically sent to an event-handler function by JavaScript as the first argument. Here is an example of how you can use the event object with mouse events:

// init() runs when the page first loads
function init()
{
    // Obtain an element
    var canvas1 = document.getElementById("canvas1");

    // Handle mouse down, mouse move and mouse up events

    // The mouseDownHandler function will handle mouse presses
    canvas1.addEventListener ("mousedown", mouseDownHandler);

    // The mouseMoveHandler function will handle mouse movement
    canvas1.addEventListener ("mousemove", mouseMoveHandler);

    // The mouseUpHandler function will handle mouse release
    canvas1.addEventListener ("mouseup", mouseUpHandler);
}

function mouseDownHandler(e)
{
    console.log(`mouse pressed down at local coordinates: ${e.offsetX}, ${e.offsetY}`);
}

function mouseMoveHandler(e)
{
    console.log(`mouse moved at local coordinates: ${e.offsetX}, ${e.offsetY}`);
}

function mouseUpHandler(e)
{
    console.log(`mouse released at local coordinates: ${e.offsetX}, ${e.offsetY}`);
}

Note how the three event handlers, mouseDown(), mouseMove() and mouseUp() all have one parameter, e, which is the event object. This example uses two properties of the event object, offsetX and offsetY, which represent the current x and y position of the mouse with respect to the element it is currently over (e.g. a canvas).

Other properties of the event object include:

Exercises

Canvas exercises

  1. Create a page with a canvas of width 700, height 500 pixels.
  2. Draw a green filled rectangle with coordinates: top 100, left 100, width 500, height 300.
  3. Write code to draw an image on the canvas at the position that the user clicked the mouse. To do this, write a function to react to the mouseup event. Use this image here.
  4. If you finish, read ahead to this optional further topic covering key events and timers, and attempt the exercises there.