Create great graphics with the HTML5 canvas

New features help you create from simple figures to awesome animation

Enhance your web pages with canvas, a simple HTML5 element that packs a punch. Entice visitors to your site over and over again by taking advantage of its flexibility and variety.

Ken Bluttman, Web Developer, Freelance Consultant

Ken BluttmanKen 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.



08 February 2011

Also available in Chinese Japanese

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.

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See HTML5 fundamentals

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).

Browser support

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.


Creating your first canvas

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
A canvas that is blank but visible because of the background style

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.

Canvas methods

Table 1 lists several methods that are appended to the context of the canvas.

Table 1. Canvas methods
MethodUse
getContext(contextId)Exposes the API necessary to draw on the canvas. The only (currently) available contextID is 2d.
heightSets the height of the canvas. The default is 150 pixels.
widthSets 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.
fillStyleSets the color used for filling an area—for example, fillStyle='rgb(255,0,0)'.
strokeStyleSets 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.

A deeper visual experience

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
The canvas is filled with multi-color 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
Setting transparency to objects on the 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
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
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>

Multiple canvases

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
Mulitple canvases

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.

Incorporating events

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
A winking face

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 fillText method.
  • In the arc methods, MATH.PI * 2 creates a full circle, whereas just MATH.PI creates a semicircle (for example, the eyelids).

Animation

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
Animation on a canvas

Summary

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.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=623407
ArticleTitle=Create great graphics with the HTML5 canvas
publish-date=02082011