Sei sulla pagina 1di 9

The Developers Guide to HTML5

Canvas
By Malcolm Sheridan
Undoubtedly, the canvas element in HTML5 is the biggest feature that developers will want to use to develop
truly rich web applications without needing to install browser plug-ins like Adobe's Flash player. IE9 was born
at a time when client richness is at the forefront of developers' minds. Modern browsers like Chrome,
Firefox, and Internet Explorer 9 and 10 all support it. But what exactly is the canvas element in HTML5? How
can you use it to create rich web applications?
If you're unfamiliar with HTML5, before diving into this article, try learning more here.

What's the Canvas Element For?


Officially a canvas is "a resolution-dependent bitmap canvas which can be used for rendering graphs, game
graphics, or other visual images on the fly". In layman's terms, the canvas is a new element in HTML5, which
allows you to draw graphics using JavaScript. It can be used to render text, images, graphs, rectangles, lines
gradients and other effects dynamically. Drawing on the canvas is via the canvas 2D API. This API contains a
plethora of functions that give you the power to draw pretty much anything you like on the canvas. Currently,
the canvas supports a 2D surface, not 3D. So what does a canvas look like? Not much. See for yourself.
The code above will render a canvas in the browser, but because the canvas is empty, you wont see
anything. Lets add a border so you can see more clearly. The image below shows the canvas with a black
border.

Figure 1. A Blank Canvas


Not very exciting just yet, but this will change the further you read on! A webpage can multiple canvas
elements. Individualizing each canvas by an id gives you the power to target a specific canvas through
JavaScript. To draw on a canvas, you need to reference the context of the canvas. The context gives you
access to the 2D properties and methods that allow you to draw and manipulate images on a canvas
element. Well dive deeper into the context later.
Every canvas element has x and y coordinates. X being the horizontal coordinate and y being the vertical
coordinate. The following image shows these coordinates on a canvas.

Ill focus more on the context later.

Clarifying the SVG Canvas Relationship


Its important to understand the differences between SVG and canvas elements. SVG is an XML based vector
graphics format. You can add styles to it with CSS and add dynamic behavior to it using the SVG DOM. The
canvas allows you to draw graphics and shapes through JavaScript. It too can be styled and you can add
dynamic behavior to it. Here are some reasons to use the canvas over SVG.
the canvas is faster at drawing complex graphics
you can save images off the canvas whereas you cant using SVG
everything in the canvas is a pixel. On the other hand
The SVG has some advantages too.
its resolution independent so it can scale for different screen resolutions
its xml, so targeting different elements is a breeze
its good at complex animations
So why use one over the other? Well if your website is resolution dependent, highly interactive and you want
vector image editing, choose SVG. On the other hand, if youre developing a game and want to render
graphics really fast, or dont want to deal with XML, choose the canvas. In an ideal world theyd work
together to complement each other.
To get more advanced with choosing between SVG and Canvas, read this blog.

Canvas and Hardware Acceleration


Using canvas is the best way to learn about hardware acceleration on the web. In earlier versions of
browsers, graphics rendering like most compute intensive tasks was handled by the CPU, the central
processing unit. Modern browsers have been innovating in this area by shifting graphic-intensive tasks to the
GPU, the graphics processing unit, to render the graphics and text on a web page using Direct2D and
DirectWrite. The allocation of these tasks to the GPU cores not only accelerates the graphics processing but
also eases the load on the CPU while it takes care of the serial tasks more efficiently.
JavaScript has also been accused of being a processing hog. A good example of this is IE9's JavaScript
engine, Chakra, which takes advantage of multi-processor cores to background compile JavaScript into
machine code for faster processing.
In both cases, the end result is accelerated performance.
I mention this here because if you put accelerated graphics processing together with accelerated Javascript
processing, youve created an ideal environment for getting the most out of HTML5 canvas.
When you send drawing commands to the canvas, the browsers sends them directly to the graphics
hardware without further development on your part. The hardware acceleration works incredibly fast to
deliver real time animations and interactive graphics, without slowing down the surrounding user experience
you're delivering. You can test many different browsers and their support of hardware acceleration here.
There is a liberation here for the creative developer knowing that the visual experiences you can put into
code will be translated and rendered as intended.
All the following ways of working with canvas deliver an enhanced, intensified and more delightful experience
when viewed through a hardware accelerated browser.

Canvas 2D API
The canvas 2D API is an object that allows you to draw and manipulate images and graphics on a canvas
element. To reference the context of the canvas, you call getContext, which is a method on the canvas
element. It has one parameter, which currently is 2d. Heres the snippet of code for referencing the context.
Each canvas has its own context, so if youre page contains multiple canvas elements; you must have a
reference to each individual context that you want to work with.
Aside from getContext, there are plenty of other functions at your disposal in the canvas 2D API. Some of the
notable ones are outlined below.
Transformation Functions
scale - allows you to scale the current context.
rotate - allows you to rotate the x and y coordinates of the current context.
State Functions
save - allows you to save the current state of the context.
restore - allows you to restore the state of the context from a previously saved state.
Text Functions

Text Functions
font - gets or sets the font for the current context.
fillText - renders filled text to the current canvas.
measureText - measures the current width of the specified text.
As you can imagine there are more methods attached to the canvas 2D API. Check out this page for all the
methods that I haven't covered in this section.
The canvas is pretty dull if you dont draw on it, so lets take a look at what you can draw once you have the
context.

Shapes & Colors


Theres an entire group of properties and functions devoted to drawing shapes. Lets begin with rectangles.
Here are the related functions available to draw rectangles.
fillRect(x, y, w, h) - draws the given rectangle onto the canvas, using the current fill style
strokeRect(x, y, w, h) - draws the box that outlines the given rectangle onto the canvas, using the current
stroke style
clearRect(x, y, w, h) - clears all pixels on the canvas in the given rectangle to transparent black
To draw a rectangle, the easiest way is to use fillRect. This draws a rectangle on the canvas using the current
fillStyle. Here's how to create a black rectangle.
This code will render a black rectangle, starting at 5 pixels from the top, 5 pixels from the right, and 145
pixels in width and height. The image below displays the rectangle in the canvas.

If you dont specify a colour, the default colour will always be black. To draw another rectangle on top, call
fillRect again with different parameters. The fillStyle can be any CSS colour, so it can take advantage of the
new opacityproperty in CSS3. The following code draws three rectangles on the canvas, and changes the
colour of the bottom one so its semi transparent.
Heres the result.

Drawing circles is a breeze too. To draw a cirlce, the easiest way is to use arc. This draws a circle on the
canvas using the current fillStyle. The function's definition is below.
arc(x, y, radius, startAngle, endAngle, anticlockwise) - asds points to the subpath such that the arc
described by the circumference of the circle described by the arguments, starting at the given start angle
and ending at the given end angle, going in the given direction, is added to the path
Here's how to create a black circle.

Here's how to create a black circle.


Because arc adds points to the subpath, you must called beginPath first then call fill afterwards. This fills in
the subpaths with the current fillStyle. The image below displays the result.

To draw the outline of a circle, use strokeStyle instead of fillStyle. Then call stroke instead of fill.
Circles dont have to be 360 degrees. To alter the shape, change the start and end radius.
Heres the semi circle.

Moving away from circles and into something more advanced, lets look at drawing Bezier curves. This tough
task is made relatively simple by using the bezierCurveTo function. This adds points to the current subpath
by using the control points that represent a Bzier curve. The parameters for bezierCurveTo are below.
bezierCurveTo (cp1x, cp1y, cp2x, cp2y, x, y) - adds the given point to the current path, connected to the
previous one by a cubic Bzier curve with the given control points
A Bezier curve must include three points. The first two points control the calculation, and the third point is the
ending point for the curve. Heres how to create a simple Bzier curve.
1.
2.
3.
4.
5.

context.lineWidth = 20;
context.beginPath();
context.moveTo(5, 50);
context.bezierCurveTo(30, 30, 130, 530, 200, 100);
context.stroke();

The image below is whats drawn in the canvas.

Bzier curves give you a great amount of power to draw with. Heres an advanced example of drawing a
smiley face on a canvas.
The image below displays the smiley face.

To complement the shapes capable on the canvas, you can also mix up the colours either by a solid colour,
outline, gradient or pattern. Ive used fillStyle mostly in the previous examples. This function fills the
background of the context with a solid colour. This can be a multitude of colours. The following example will
randomise the background colour of the canvas and produces a rainbow effect.
The effect can be seen in the image below.

If you don't want solid colours, you can use strokeStyle and strokeRect to draw the outline of a rectangle.
Another feature of canvas gives to the ability to create gradients. The related function for this are below.
addColorStop(offset, color) - adds a colour stop with the given color to the gradient at the given offset. 0.0
is the offset at one end of the gradient, 1.0 is the offset at the opposite end
createLinearGradient(x0, y0, x1, y1) - returns a CanvasGradient object that represents a linear gradient that
paints along the line given by the coordinates
createRadialGradient(x0, y0, r0, x1, y1, r1) - returns a CanvasGradient object that represents a radial
gradient that paints along the cone given by the circles represented by the coordinares
A linear gradient can be created by calling createLinearGradient. To add colour to the gradient you call
addColorStop. Calling this adds the specified colour at the x and y coordinates. The following example
demonstrates a simple linear gradient.
The gradients can be seen below.

There's a lot more on gradients that I haven't covered. For the full picture you should check out the W3C

website here.

Lines, Text & Shadows


When youre drawing lines, think of paths. Each canvas has a path. Defining a path is like drawing a line. Any
line is possible. Just like writing, you need to define a path, and then fill the path in. Here are some of the
related properties and functions for drawing lines.
lineWidth [ = value ] - returns the current line width. Can be set, to change the line width
lineCap [ = value ] - returns the current line cap style. Can be set, to change the line cap style. The possible
line cap styles are butt, round, and square
lineJoin [ = value ] - returns the current line join style. Can be set, to change the line join style. The possible
line join styles are bevel, round, and miter
To draw lines you call moveTo and lineTo. These function accept x and y parameters which tell it exactly
where you want to draw the line. You can also specify the width of the line by settings the lineWidth. Once
you've defined the line, you need to call stroke to draw the line.
The following example demonstrates how to draw a series of lines, starting from thick to small.
The result is below.

To add some pizzazz to the lines, you can also change what's known as the cap, or the end shape of the line
by setting the lineCap property. To create a rounded edge, I can set the lineCap to round.
Doing that to the example draws the rounded lines.

As well as lines, text is simple to draw on a canvas element. Unlike text on a web page, there's no box model,
which means the CSS that you're familiar with is not available. But you do have options. Some of the related
properties and functions for drawing text are below.

font [ = value ] - returns the current font settings. Can be set, to change the font. The syntax is the same as
for the CSS 'font' property
textAlign [ = value ] - returns the current text alignment settings. Can be set, to change the alignment. The
possible values are start, end, left, right, and center
textBaseline [ = value ] - returns the current baseline alignment settings. Can be set, to change the baseline
alignment
fillText(text, x, y [, maxWidth ] ) - fills the text at the given position
strokeText(text, x, y [, maxWidth ] ) - strokes the text at the given position
To print some plain text use fillText. I'm setting the font size and type by using the font property.
Here's the result.

To create transparent text, set the fillStyle.


And the result.

Adding effects like shadows is a piece of cake too. The following code uses the shadow drawing objects to
create the shadow.

The shadow can be customised to create any angle or shadow colour you like. I've only demoed a small
fraction of what you can do with text on the canvas. For more information on this, check out the Text
sectionon W3C.

Images & Video


Well when you're working with the canvas, it's possible to work with images and videos too. The obvious
question is why not just use a standard <img> element? Well the big advantage is your image can be part of
a much bigger and complex image thanks to all the wizardry you can create with the canvas element. There's
one main function for working with images and videos, and that's drawImage. The following piece of code
references the sheep image and draws that on the canvas.
That code draws the sheep on the canvas.

The image can now be rotated, flipped, faded in and out or simply spun around now that it's drawn on the
canvas.
Videos follow a similar path. First you need to use the HTML5 video element. As you can imagine, there's a
tonne of functionality attached to this element, so before we begin, you should read up about it here. The

tonne of functionality attached to this element, so before we begin, you should read up about it here. The
video element on its own is not that interesting. The element itself contains a controls attribute, which
determines if the browser should display the standard set of video controls, and loop which tells the browser
if the video is recursive. Inside the video element you specify three children, each with the same video, but
with different formats. Nothing new here, but when you team the video element with the canvas, well you can
come up with some amazing things.
Ill first add the canvas and video HTML.
Not much is happening here. The video will play inside the video tag, but Im going draw the video on the
canvas and position the video centrally on the canvas. The result is awesome. Heres the code.
The trick to making this work is to recursively draw the video on the canvas, otherwise itll only be drawn
once, and that would look pretty awful. This is why setInterval is called when the page loads. The live video
can be seen here.

Transformations & Animations


Transformations and animations are possible with the canvas element. Here are some of the related
properties and functions for performing transformations.
scale(x, y) - changes the transformation matrix to apply a scaling transformation with the given
characteristics
rotate(angle) - changes the transformation matrix to apply a rotation transformation with the given
characteristics
translate(x, y) - changes the transformation matrix to apply a translation transformation with the given
characteristics
transform(m11, m12, m21, m22, dx, dy) - changes the transformation matrix to apply the matrix given by
the arguments
setTransform(m11, m12, m21, m22, dx, dy) - changes the transformation matrix to the matrix given by the
arguments.
Transformations and animations can work separately, but when you combine them, as Ill demonstrate now,
can make powerful visual statements. Lets start with rotation. To rotate the context, pass in an angle and it
will rotate on the canvas. The following example demonstrates draws a rectangle every 250 milliseconds and
each rectangle is rotated, so the effect is like a spinning wheel. The colour is randomized as well to produce
a brilliant effect.
The image below displays the result.

The still image does this demonstration no favours, so to see the animation working you can go here.
Scaling canvas elements is easy too. Ill stick with the previous demo, except for rotating; Ill scale out each
rectangle ever second. Heres the code.
The image below displays the result.

Again the image will not show the animation, so to see the animation working you can go here. As you can
imagine this is just a starting point for transformations and animations. For a complex animation, you can
take a look at Brilliant Lines, which was created by the W3C group. That can be found here. For more
information on transformations, you should go here.

Working with the Mouse


As you may have guessed, working with the mouse is also possible. Just like any element on a webpage, you
can return the x and y coordinates of the mouse by querying the pageX and pageY properties of the
element. To track the mouse over a canvas, here's the snippet of code.
In the code above, I've attached an event to capture the mouse movement, so when it moves, the x and y
coordinates are printed to the webpage. Nice and simple. For something a little more advanced, I wanted to
make like canvas act like a piece of paper, so it gives you the ability to draw on it. Well the code to do this is
not too complex. Here's the entire code.
Thanks to JavaScript, I can easily extend the canvas element and add some custom event handlers for
handling the mouse movement. A live version of this can be seen here. Go ahead, try it out: sketch
something.
And thats the beauty of the canvas element: there is so much you can try out.
That was a whirlwind tour, and I hope its made you keen to work with the canvas element, knowing that these
extraordinary effects are totally achievable in IE9 now.
Want to learn more? Try these links:
HTML5 Canvas Developer Guide on MSDN
How to Choose Between Canvas and SVG to Create Web Graphics
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET and regular presenter at conferences and user
groups throughout Australia. Being an ASP.NET Insider, his focus is on web technologies and has been for the
past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with
JavaScript.

Potrebbero piacerti anche