HTML5 is an emerging standard that is taking over the tried-and-true HTML4 at an increasing rate. HTML5 is a W3C "working draft"—which means that it's still being developed—that contains a rich set of elements and attributes that support the current HTML version 4.01 specification. It also introduces several new elements and attributes that apply to many areas of web page use—audio, video, graphics, data storage, content presentation, and more. This article focuses on the graphics update: the canvas.
The new HTML5 canvas is a native HTML drawing pad that is used with JavaScript code and doesn't use third-party tools. Full HTML5 support is not complete across all web browsers, but within the emerging support, the canvas is already running well on all modern browsers except Windows® Internet Explorer®. Luckily, a solution has emerged to bring Internet Explorer into line.
The canvas element is basically a blank slate until you "paint" something visual on it. Instead of an artist's array of brushes, you have at your disposal different methods to draw on the canvas. You can even create and manipulate animation on the canvas, which is not something you can do with brushes and oils.
This article explores the new HTML5 canvas element. It takes a step-by-step approach from the simple inclusion of the canvas element to advanced JavaScript interaction (the key to animation). Learn to present the canvas on a web page. This article is written for web designers and developers, and although knowledge of JavaScript is not mandatory, it is helpful to understand how the language functions. Knowledge of HTML, however, is key, especially how to create a basic web page.
To view live instances of the examples shown in this article, you need a browser and access to the Internet. All examples are provided on a live website (see Resources).
Determining which browsers support HTML5 and to what extent is a moving target. At the time this article was written, Google Chrome, Apple Safari, and Mozilla Firefox all support most of the new HTML5 elements, and all support the canvas element. Internet Explorer does not support HTML5 in Internet Explorer 7 or 8; Internet Explorer 9 is in beta testing and supports HTML5, though with some problems.
In the meantime, a fix for non-HTML5 versions of Internet Explorer is
available. The basic premise of the fix is to simply create the element
using JavaScript code. For example, you can create a recognizable canvas
tag with the snippet document.createElement('canvas'); however, this does not imply
anything past the element itself. A popular workaround is to include an
entire canvas-based JavaScript library that is supplied by Google called
the ExplorerCanvas—or excanvas, for short. Download and reference it as an external
file, as shown below. (See Resources for links to
more extensive information about excanvas.)
<!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> |
By including excanvas, you provide Internet
Explorer with the canvas and most of its methods.
Because the canvas is nothing more than an HTML tag, it is displayed simply
by its inclusion in the markup. The first example, shown in Figure 1, displays a canvas in its simplest form. It
is visible only because it is given a color scheme via the style attribute and a size via the width and height
attributes.
Figure 1. A blank canvas
The code of this page is short and succinct, as shown in Listing 1.
Listing 1. HTML for a web page with a canvas
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400"
style="background-color:blue;border: 10px yellow solid"></canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
|
The canvas has a width and height of 400 pixels each, along with a yellow border and a blue background. No actual drawing has been put on the canvas; that happens with the JavaScript methods that belong to the canvas.
Table 1 lists several methods that are appended to the context of the canvas.
Table 1. Canvas methods
| Method | Use |
|---|---|
getContext(contextId) | Exposes the API necessary to draw on the canvas. The only
(currently) available contextID is
2d. |
height | Sets the height of the canvas. The default is 150 pixels. |
width | Sets the width of the canvas. The default is 300 pixels. |
createLinearGradient(x1,y1,x2,y2) | Creates a linear gradient. The start coordinate is set with x1,y1 and the end coordinate with x2,y2. |
createRadialGradient(x1,y1,r1,x2,y2,r2) | Creates a radial gradient. The start of the circle begins at
coordinate x1,y1 with a radius r1. The end of the circle is at
coordinate x2,y2 with a radius r2. |
addColorStop(offset, color) | Adds a color stop to a gradient. A color stop is a position in the gradient where a color change occurs. The offset must be between 0 and 1. |
fillStyle | Sets the color used for filling an area—for
example, fillStyle='rgb(255,0,0)'.
|
strokeStyle | Sets the color used for drawing a line—for example,
fillStyle='rgb(255,0,0)'. |
fillRect(x,y,w,h) | Fills a rectangle positioned at x and
y, with a width and height of w and h. |
strokeRect(x,y,w,h) | Draws the outline of a rectangle positioned at x and y, with a width and
height of w and h. |
moveTo(x,y) | Moves the drawing position to coordinate x,y. |
lineTo(x,y) | Draws a line to position to x,y from
the last position at which the drawing method ended. |
Building canvas applications with increased sophistication
This section presents a sequence of examples, each with a bit more functionality.
First, place a set of rectangles on the canvas. Remember that a rectangle is any shape that has four straight sides and right angles, and that a square is a variation of a rectangle. Figure 2 shows a series of rectangles on the canvas, each smaller than the last. Notice that each rectangle has a different color, making each clear and distinct.
Figure 2. A canvas filled with rectangles
Listing 2 shows the code used to create the canvas in
Figure 2. Two lines of code create each rectangle: First, the fillStyle method defines the color using the red,
blue, green (RGB) format for color definition (fillStyle='rgb(255,0,0)). Then, the fillRect method (fillRect(50,50,300,300)) defines the size. The first two
values set the starting coordinates; the last two set the ending
coordinates.
Listing 2. Using JavaScript code to create the context and use various methods
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.onload=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.fillStyle='rgb(0,0,255)';
mycontext.fillRect(0,0,400,400);
mycontext.fillStyle='rgb(255,0,0)';
mycontext.fillRect(50,50,300,300);
mycontext.fillStyle='rgb(0,255,0)';
mycontext.fillRect(100,100,200,200);
mycontext.fillStyle='rgb(100,100,100)';
mycontext.fillRect(125,175,150,25);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
|
To draw on the canvas, access the API that provides the methods by applying
getContext('2d') to the canvas element. The
canvas element is set to a JavaScript variable using this document.getElementById method:
var mycanvas=document.getElementById("myCanvasTag");
|
Then apply getContext to the canvas element
variable, as shown below.
var mycontext=mycanvas.getContext('2d');
|
Once a variable is set to the context, all the methods are ready for use.
The next example shows how to combine two techniques. One is the
overlapping of rectangles, which is done using the fillRect parameters to position the rectangles (see Figure 3).
Figure 3. Applying transparency to rectangles on a canvas
The second technique is the variation of RGB color treatment, which adds
transparency. Instead of using rgb, use rgba. The a indicates
the alpha channel, which manipulates transparency. In the example in
Figure 3, the second rectangle is set to 50% (or .5) transparency, and the
third is set to 25% (or .25). Listing 3 shows the
full markup.
Listing 3. Using transparency
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.onload=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.fillStyle='rgb(0,0,255)';
mycontext.fillRect(30,30,300,300);
mycontext.fillStyle='rgba(0,255,0,0.5)';
mycontext.fillRect(60,60,300,300);
mycontext.fillStyle='rgba(255,0,0,0.25)';
mycontext.fillRect(90,90,300,300);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
|
Gradients—which are coordinated mixes of
color—are native to the canvas through two methods:
createLinearGradient and createRadialGradient. Figure
4 shows a linear gradient. The addColorStop method defines a color and where it becomes
active in the gradient. Since a gradient can have multiple color stops,
this positioning is subjective. The color stop positioning value must be
between 0 and 1, but testing variations and the number of color stops can
yield different results, even if a value (such as .25) remains the same.
In other words, one color stop can have its position as .25, but the
related color can occur a bit off from a quarter of the way through the
imagery based on where you set other color stops. Remember that this is a
new implementation and perhaps still being ironed out. One advantage of
gradients is that they are always attractive, whether or not the code and
the result are perfectly coordinated.
Figure 4. A linear gradient
The gradient in Figure 4 was created with the JavaScript code shown in Listing 4.
Listing 4. Creating a linear gradient
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
var mygradient=mycontext.createLinearGradient(30,30,300,300);
mygradient.addColorStop(0,"#FF0000");
mygradient.addColorStop(1,"#00FF00");
mycontext.fillStyle=mygradient;
mycontext.fillRect(0,0,400,400);
|
Notice that the color stop in Listing 4 is fully implemented as a method of
an on-the-fly gradient created from the method itself. The statement mygradient.addColorStop(0,"#FF0000") shows that
the color stop has both parameters: the position and the color.
Figure 5 shows a radial gradient. The code used to
create this gradient is similar to that in Listing 4, except that the
createRadialGradient method is used instead
of the createLinearGradient method.
Figure 5. A radial gradient
The code used to create the radial gradient in Figure 5 is shown in Listing 5. Notice all five color stops.
Listing 5. Creating a radial gradient
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.onload=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
var mygradient=mycontext.createRadialGradient(300,300,0,300,300,300);
mygradient.addColorStop("0","magenta");
mygradient.addColorStop(".25","blue");
mygradient.addColorStop(".50","green");
mygradient.addColorStop(".75","yellow");
mygradient.addColorStop("1.0","red");
mycontext.fillStyle=mygradient;
mycontext.fillRect(0,0,400,400);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px blue solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
|
A web page can contain multiple canvases, each referenced with its own unique JavaScript context variable. Consequently, each canvas works independently of the others. Figure 6 shows four canvases, each with a different visual.
Figure 6. Multiple canvases on a single web page
Listing 6 shows the code used to create the page in Figure 6. Notice that each canvas has a unique ID and that each context is unique.
Listing 6. Multiple canvases on a single web page
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.onload=function() {
var mycontext1=document.getElementById("myCanvasTag1").getContext('2d');
var mycontext2=document.getElementById("myCanvasTag2").getContext('2d');
var mycontext3=document.getElementById("myCanvasTag3").getContext('2d');
var mycontext4=document.getElementById("myCanvasTag4").getContext('2d');
// gradient 1
var mygradient1=mycontext1.createLinearGradient(30,30,90,90);
mygradient1.addColorStop(0,"#FF0000");
mygradient1.addColorStop(1,"#00FF00");
mycontext1.fillStyle=mygradient1;
mycontext1.fillRect(0,0,100,100);
// gradient 2
var mygradient2=mycontext2.createLinearGradient(30,30,90,90);
mygradient2.addColorStop(1,"#FF0000");
mygradient2.addColorStop(0,"#00FF00");
mycontext2.fillStyle=mygradient2;
mycontext2.fillRect(0,0,100,100);
var mygradient3=mycontext3.createLinearGradient(30,30,90,90);
mygradient3.addColorStop(0,"#0000FF");
mygradient3.addColorStop(.5,"#00FFDD");
mycontext3.fillStyle=mygradient3;
mycontext3.fillRect(0,0,100,100);
var mygradient4=mycontext1.createLinearGradient(30,30,90,90);
mygradient4.addColorStop(0,"#DD33CC");
mygradient4.addColorStop(1,"#EEEEEE");
mycontext4.fillStyle=mygradient4;
mycontext4.fillRect(0,0,100,100);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag1" width="100" height="100" style="border: 10px blue solid">
</canvas>
<canvas id="myCanvasTag2" width="100" height="100" style="border: 10px green solid">
</canvas>
<br />
<canvas id="myCanvasTag3" width="100" height="100" style="border: 10px red solid">
</canvas>
<canvas id="myCanvasTag4" width="100" height="100" style="border: 10px black solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
|
JavaScript events and animation
This article has shown various methods that you can use with the canvas, all of which have created a visual result. Now kick canvas use up a notch with events and animation. JavaScript recognizes many events, including moving or hovering the mouse over a specific web page element. The JavaScript language recognizes many more events; several are used in the example that follows.
The example shown in Figure 7 was created using methods
you've seen in the earlier listings. Now add a few new techniques. The
nose, the eyes, and the circular items and outer boundary of the face are
created with the arc method. The eyelashes are
drawn as lines, and the mouth is created as a bezier curve. Figure 7 also
presents text at the bottom of the canvas that was created using the fillText method.
Figure 7. JavaScript events are used to make a face wink
Listing 7 shows the code used for Figure 7.
Listing 7. Using events to create a wink
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.onload=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
//draw face
mycontext.beginPath();
mycontext.arc(300, 250, 200, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.stroke();
//draw left eye
mycontext.beginPath();
mycontext.arc(220, 150, 30, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(100,100,225)';
mycontext.fill();
//draw left iris
mycontext.beginPath();
mycontext.arc(220, 150, 10, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(0,0,0)';
mycontext.fill();
//draw left eyelid
mycontext.beginPath();
mycontext.arc(220, 150, 30, 0, Math.PI, true);
mycontext.closePath();
mycontext.fillStyle='rgb(200,200,200)';
mycontext.fill();
//draw left eyelashes
mycontext.strokeStyle='rgb(0,0,0)';
lashes(mycontext,198, 170, 193, 185);
lashes(mycontext,208, 177, 204, 193);
lashes(mycontext,220, 180, 220, 195);
lashes(mycontext,232, 177, 236, 193);
lashes(mycontext,242, 170, 247, 185);
mycontext.stroke();
openeye();
//draw right eyelashes
mycontext.strokeStyle='rgb(0,0,0)';
lashes(mycontext, 358, 170, 353, 185);
lashes(mycontext, 368, 177, 364, 193);
lashes(mycontext, 380, 180, 380, 195);
lashes(mycontext, 392, 177, 396, 193);
lashes(mycontext, 402, 170, 407, 185);
mycontext.stroke();
//draw nose
mycontext.beginPath();
mycontext.arc(300, 250, 20, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.stroke();
// draw smile
mycontext.beginPath();
mycontext.lineWidth = 10;
mycontext.moveTo(180, 320);
mycontext.bezierCurveTo(140, 320, 340, 420, 400, 360);
mycontext.closePath();
mycontext.stroke();
//draw message at bottom
mycontext.font="1em sans-serif";
mycontext.fillStyle="rgb(0,0,0)";
mycontext.fillText("Move the mouse over and off the canvas - the face winks!", 10, 480);
}
function lashes(cntx,x1,y1,x2,y2) {
cntx.moveTo(x1,y1);
cntx.lineTo(x2,y2);
}
function closeeye() {
//close right eye
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.beginPath();
mycontext.arc(380, 150, 30, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(200,200,200)';
mycontext.fill();
}
function openeye() {
//open right eye
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.beginPath();
mycontext.arc(380, 150, 30, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(100,100,225)';
mycontext.fill();
//draw right iris
mycontext.beginPath();
mycontext.arc(380, 150, 10, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(0,0,0)';
mycontext.fill();
//draw right eyelid
mycontext.beginPath();
mycontext.arc(380, 150, 30, 0, Math.PI, true);
mycontext.closePath();
mycontext.fillStyle='rgb(200,200,200)';
mycontext.fill();
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="600" height="500" style="border: 5px blue solid"
onmouseover="closeeye()" onmouseout="openeye()"></canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
|
The face in Figure 7 was altered with JavaScript
events. In particular, the onmouseover and
onmouseout events are used to call the
closeeye() and openeye() functions, respectively. These functions are not
methods of the canvas, but are instead standard JavaScript functions. The
connection of the events to the functions is made in the canvas element
itself. The body section of the page is near the bottom of the code in Listing 7, where the canvas is. Within the canvas
tag is
onmouseover="closeeye()" onmouseout="openeye()" |
A new construct appears in the Listing 7
code—the use of beginPath()
and endPath(), which delineate distinct complex
drawing actions. This encasing code draws a particular piece of the image
to stand separate from the other drawing actions.
A few notable items about the code in Listing 7 are listed below:
- When the page opens, the right eye is drawn by a call to the
openeye()function. - Text is written onto the canvas using the
fillTextmethod. - In the
arcmethods,MATH.PI * 2creates a full circle, whereas justMATH.PIcreates a semicircle (for example, the eyelids).
JavaScript packs a powerful programmatic punch. The language can perform quite a bit of manipulation, as shown in Listing 8. The code runs repeatedly, drawing lines on the canvas. The line colors are randomly set.
Listing 8. Using JavaScript to create animation
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px blue solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
<script>
var mycanvas = document.getElementById("myCanvasTag")
var mycontext = mycanvas.getContext('2d');
var x;
var y;
var x2;
var y2;
var r;
var g;
var b;
function line() {
x=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
y=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
x2=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
y2=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
r=Math.floor(Math.random()*255);
g=Math.floor(Math.random()*255);
b=Math.floor(Math.random()*255);
mycontext.moveTo(x, y);
mycontext.lineTo(x2, y2);
mycontext.strokeStyle='rgb(' + r + ',' + g + ',' + b + ')';
mycontext.lineWidth=Math.floor(Math.random()*6);
mycontext.stroke();
mycontext.restore();
}
setInterval(line, 100);
</script>
</body>
</html>
|
Figure 8 shows the animation caught as a snapshot. The code in Listing 8 differs from all the other code examples in this article in that the JavaScript block is placed at the bottom of the page, underneath the canvas element. This ensures that the canvas is already rendered before the code runs.
Figure 8. JavaScript is used to draw endless random lines
HTML5 is poised to change the playing field for web development. The new elements make page layout easier; make local data storage possible through the browser; and have native audio, video, and graphic platforms like the canvas. As browsers update to accommodate more of the new functionality, the nature of the web and the user experience will become more exciting. Great times lie ahead for web development.
Learn
- Find the live demonstrations
of the examples shown in the article.
- WHATWG
is a community of developers working with the W3C to fine-tune HTML5.
- Start
implementing HTML5 today.
- Check out canvas
tutorials and demos from the Mozilla developers.
- PHPGuru.org offers information about using canvas and provides
many great demos and examples.
- See "New to Web
Development" to start learning about dynamic web applications and
more.
- The developerWorks Web development zone
specializes in articles covering various web-based solutions.
- Stay current with developerWorks' IBM technical events and webcasts.
- Watch developerWorks on-demand demos ranging from product installation
and setup for beginners to advanced functionality for experienced
developers.
Get products and technologies
- Download the excanvas.js library for
Internet Explorer.
- Download IBM product
evaluation versions or explore
the online trials in the IBM SOA Sandbox, and get your hands on
application development tools and middleware products from IBM®
DB2®, Lotus®, Rational®,
Tivoli®, and WebSphere®.
Discuss
- Create your My developerWorks profile today and set up a watch list on HTML5. Get connected and stay connected
with the developerWorks community.
- Find other developerWorks members interested in web development.
- Share what you know: Join one of our developerWorks groups focused on web
topics.
- Roland Barcia talks about Web 2.0 and middleware in his blog.
- Follow developerWorks' members' shared bookmarks on web topics.
- Get answers quickly: Visit the Web 2.0 Apps forum.
- Get answers quickly: Visit the Ajax forum.

Ken Bluttman is the author of more than a dozen computer books whose content spans from desktop application development to the latest in web development, design, and architecture. You can reach him at href="kb@kgadesigns.com">kb@kgadesigns.com.



