Introduction
The
HTML5 specification defines canvas as “The canvas element provides scripts
with a resolution-dependent bitmap canvas, which can be used for rendering graphs,
game graphics, or other visual images on the fly.
In its most basic definition; it’s a square on a web page where, by using javascript
anything you want can be drawn, as an element <canvas> will be show
nothing on the page because it has no content.
Canvas has a lot to it and boasts a number of features including the ability to
draw shapes, create patterns and gradients, colour filling and pixel manipulation
and also allows exporting to static files.
1. Fall Back
Four of the main five browsers support canvas, with IE8 currently not doing so.
IE9 however, does support canvas and it supports the extra feature; hardware accelerated
drawing to the canvas which is something that other browsers currently don’t have,
making IE9 the browser to use when developing and using <canvas>.
Because the <canvas> element is relatively new and is not supported
in some browsers like Internet Explorer versions below IE9, it’s important to have
a fall back option available for when the browser doesn’t support the element. This
can be done by providing alternative content inside the <canvas>
element, the browsers which don’t support the <canvas> element will
just ignore the container and then render the fall back content inside it
Doing
this will of course mean that browsers which do support the <canvas>
element, will just ignore the alternative content and just render the canvas content
as it should be. An example of this would be to supply an alternative image for
the dynamically rendered <canvas> content shown below:
<canvas id="tiger" width="150" height="150">
<img src="images/tiger.png" width="150" height="150" alt=""/>
</canvas>
Scripts can also check also check for support when they execute, this can be performed
by testing for the getContext method, and the following shows how:
var canvas = document.getElementById('tutorial');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
// drawing code here
} else {
// canvas-unsupported code here
}
Required </canvas> tag
In the Apple Safari implementation, <canvas> is an element implemented
in much the same way <img> is; it does not have an end tag. However,
for <canvas> to have widespread use on the web, some facility for
fall back content must be provided. Therefore, Mozilla's implementation requires
an end tag (</canvas>).
If fall back content is not needed, a simple <canvas id="foo" ...> </canvas>
will be fully compatible with both Safari and Mozilla -- Safari will simply ignore
the end tag.
If fall back content is desired, some CSS tricks must be employed to mask the fall
back content from Safari (which should render just the canvas), and also to mask
the CSS tricks themselves from IE (which should render the fall back content).
2. Why use Canvas and not SVG? Consider the Options
Until recently you really couldn’t draw on the web and the web itself didn’t really
provide primitives to actually draw things on the screen and the graphics weren’t
very interactive, they didn’t work well with javascript, the option was to use the
plugins to help you to deploy the fancy things that were needed on the web including
Microsoft’s VMI, flash and Silverlight.
Canvas and SVG embed themselves into the web and are a part of the html mark-up
within the sites that we build.
SVG
SVG (scalable vector graphics) like canvas, exists in the DOM of a page, making
it easy to attach event handlers for interactively and it can easily deal with collision
detection (e.g. in games) and supports animations through javaScript and through
HTML5 are new tags which can be used for drawing, for example to draw a rectangle
you use a rectangle tag:
<svg width="200" height="200">
<rect X="0" y="0" Width="100" height="100"
Fill="blue" stroke="orange"
Stoke-width="5px"
Rx="8" ry="8"
Id="myRect" class="chart" />
</svg>
SVG is a web standard that pre dates HTML5, but HTML5 tells us 'heres how you drop
svg into a normal html page' with html like tags that do drawing right inside html.
They integrate well, they are not just static graphics, we can manipulate, animate
and interact with them. So let’s play with our rectangle in javascript:
var rect = document.getElementById('myRect');//grabs the element
rect.style.fill = 'yellow'; //changes its properties
rect.onclick = function() { alert('hello'); }; //add interaction
Click here to view the example in jsbin.
SVG is higher level and should be used when you want to import and export graphical
assets, you can export to illustrator. SVG is a retains mode API, (both are needed
for different functions), whenever you want to create easy user interfaces because
SVG is a retains mode API it means there is a tree of everything that’s been added
to the screen so it’s easy to do detections and adding events because you can attach
events to something in the tree.
It’s good for interaction and medium animations,
but canvas is lower level and is great when you don’t need the tree and want to
have keyboard interaction, its JS centric and has higher animation involving more
pixel orientation. It’s important to choose both in the right situations.
Canvas
In HTML5, the Canvas API, is like a scriptable image tag, as opposed to SVG which
is a tree format and is delivered in the mark-up, canvas is like an image tag that
javascript can customise;
The basic <canvas> mark-up (with an id) looks like the following:
<canvas id="a"></canvas>
This will have no content and will ‘appear’ as an invisible block of space, to draw
you need to have some drawing context which can be declared using javaScript, and
once this is obtained, the drawing can take place.
<script>
// declare the two variables at once using a comma
var canvas = document.getElementById("a"),
context = canvas.getContext("2d");
// now you're ready to draw
</script>
The 2d drawing API is large and the following code shows how easy it is to create
something simple, two rectangles, one red, one blue with 50% opacity.
<html>
<head>
<script type="application/javascript">
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(10, 10, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect(30, 30, 55, 50);
}
</script>
</head>
<body>
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
It will look like this:
Click here to view the example in jsbin.
Unlike SVG, canvas only supports one primitive shape, rectangles. To give an idea
of the scale of the library, the following are the methods and properties for drawing
just rectangles.
- The
fillStyle property can be a CSS color, pattern or gradient, if
a colour isn’t specified, the default is black. The drawing context remembers its
properties as long as the page is open.
- The
stokeStyle property is like fillStyle, it can be any
colour, gradient or pattern and just allows you to put a stroke around an object.
stokeRect (x, y, width, height) draws a new rectangle with the current
stoke style. stokeRect just draws the edges.
fillRect (x, y, width, height) draws a filled rectangle.
clearRect (x, y , width, height) clears the pixels in the chosen rectangle.
Each <canvas> has a drawing element, which is where the 'creative'
side of thing’s happens, once a <canvas> element has been defined
in the DOM by using document.getElementById() the getContext()
method is called, and the string ‘2d’ is passed through:
var b_canvas = document.getElementById("b");
var b_context = b_canvas.getContext("2d");
b_context.fillRect(50, 25, 150, 100);
Calling the fillRect() method draws the rectangle and fills it with
the current fill style, which colour is black as default. The rectangle is bounded
by its upper-left corner (50, 25), its width (150), and its height (100).
Before it’s possible to understand the drawing possibilities and get going, it’s
important to get to grips with the coordinate space.
Coordinate Space
If the canvas element is specified at 200 pixels wide and 200 pixels high, by default
1 unit in the grid corresponds to 1 pixel on the canvas. The origin of this grid
is positioned in the top left corner (coordinate (0,0)). All elements are placed
relative to this origin. So the position of the top left corner of the blue square
becomes x pixels from the left and y pixels from the top (coordinate (x,y)).
Canvas Coordinates Image
3. Drawing Paths
As discussed earlier, canvas only supports one primitive shape, a rectangle. Anything
else must be drawn by creating and combining paths, with rectangles, there is a
set of functions which draw the rectangle immediately onto the canvas, but to make
shapes using paths, a couple of extra steps are required.
beginPath()-The first step to create a path is calling the beginPath
method. Internally, paths are stored as a list of sub-paths (lines, arcs, etc) which
together form a shape. Every time this method is called, the list is reset and we
can start drawing new shapes.
closePath()- This method tries to close the shape by drawing a straight
line from the current point to the start. If the shape has already been closed or
there's only one point in the list, this function does nothing.
stroke(),fill()- The final step will be calling the stroke and/or fill
methods. Calling one of these will actually draw the shape to the canvas. Stroke
is used to draw an outlined shape, while fill is used to paint a solid shape.
For example, the code needed for drawing a triangle would look like this:
ctx.beginPath();
ctx.moveTo(75,50);
ctx.lineTo(100,75);
ctx.lineTo(100,25);
ctx.fill();
moveTo
One function, which is like lifting a pencil from one spot on a piece of paper and
placing it on another spot, is moveTo. It has two argumeents, x and
y which are the coordinates of the new starting point.
This would typically be used when the canvas is initialised or the beginPath method
is called, or you can use it to draw unconnected paths.
moveTo(x, y)
The following is an example of drawing a smiley face with the moveTo
method, if you remove the moveTo method you will be able to seee the
connecting lines, the help to understand the arc function look below
the example:
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // Mouth (clockwise)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true); // Left eye
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true); // Right eye
ctx.stroke();
It will look like this:
Click here to view the example in jsbin.
lineTo
For drawing straight lines, the lineTo method is used:
lineTo (x, y)
Taking two arguments, x and y, which are the coordinates of the line’s end point,
the starting point depends on the previous drawn paths, which of course can be changed
by the moveTo method.
Arc
For drawing arcs or circles the arc method is used:
arc(x, y, radius, startAngle, endAngle, anticlockwise)
This method takes five parameters: x and y are the coordinates of the circle's center.
Radius is self-explanatory. The startAngle and endAngle
parameters define the start and end points of the arc in radians. The starting and
closing angle are measured from the x axis. The anticlockwise parameter is a Boolean
value which when true draws the arc anticlockwise, otherwise in a clockwise direction.
Angles in the arc function are measured in radians, not degrees. To convert degrees
to radians you can use the following JavaScript expression: var radians = (Math.PI/180)*degrees.
4. Exporting and Saving
Another thing that separates canvas from SVG is the ability to save the created
image as a bitmap. This comes naturally for a <canvas> element because
the element is a bitmap in the first place. The canvas can export its image to a
data URL (e.g. data: image/png.image…). Which may then be rendered in the browser,
and then could be saved. The browser must support PNG images and may have different
support for JPG and GIF. PNG is advantageous because it supports alpha transparency,
so on the canvas where nothing has been drawn, it’ll be transparent.
To get the
data URL, simply call canvas.toDataURL('image/png'). Note that we’re calling toDataURL()
on the <canvas> element, not on the 2D context. This is because
we’re getting all the pixels in the canvas, not just the pixels in a particular
context. So as an example, it’ll make the browser redirect to a PNG version of the
image when a user clicks on the <canvas> element:
canvas.onclick = function () {
window.location = canvas.toDataURL('image/png');
};
5. Conclusion
Personally I think that canvas is one of the most interesting features of HTML5,
offering a huge amount of scope for development and functionality. It's ready to
be used within most modern browsers and gives a huge 2D context API with a wealth
of features allowing the creation of games, interface enhancements and all sorts
of a other things (even fun stuff!).
The Next Step
This tutorial focuses on some of the main areas of the Canvas API and introduces
the elements needed to get going and have a play with it. There’s an awful lot more
including:
- More paths methods and functions.
- Colour manipulation and transparency.
- Gradients, fills and patterns.
- Text
- Pixel Manipulation
- Animations
Be sure to head over to the demos sections to have a look at some examples, and
also there’s plenty of great Canvas resources to get more informed about the API: