Section 22.5. Graphics in a canvas


22.5. Graphics in a <canvas>

The next stop in our tour of client-side vector-graphics technologies is the <canvas> tag. This nonstandard HTML element is explicitly designed for client-side vector graphics. It has no appearance of its own but exposes a drawing API to client-side JavaScript so that scripts can draw anything they want into a canvas. The <canvas> tag was introduced by Apple in the Safari 1.3 web browser. (The reason for this radical extension to HTML is that the HTML rendering capability of Safari is also used by the Dashboard component of the Mac OS X desktop, and Apple wanted a way to support scripted graphics in Dashboard.)

Firefox 1.5 and Opera 9 have followed Safari's lead. Both browsers also support the <canvas> tag. You can even use the <canvas> tag in IE, with open source JavaScript code (initially from Google) that builds canvas compatibility on top of IE's VML support. (see http://excanvas.sourceforge.net). Standardization efforts for the <canvas> tag are underway by an informal consortium of web browser manufacturers, and a preliminary specification can be found at http://www.whatwg.org/specs/web-apps/current-work.

An important difference between the <canvas> tag and SVG and VML is that <canvas> has a JavaScript-based drawing API while SVG and VML describe a drawing with an XML document. These two approaches are functionally equivalent: either one can be simulated with the other. On the surface, they are quite different, however, and each has its strengths and weaknesses. An SVG drawing, for example, is easily edited by removing elements from its description. To remove an element from the same graphic in a <canvas> tag, it is often necessary to erase the drawing and redraw it from scratch. Since the Canvas drawing API is JavaScript-based and relatively compact (unlike the SVG and VML grammars), it is documented in this book. See Canvas, CanvasRenderingContext2D, and related entries in Part IV.

Most of the Canvas drawing API is defined not on the <canvas> element itself but instead on a "drawing context" object obtained with the getContext( ) method of the canvas.[*] This script draws a small red square and blue circle and is typical for drawing to a canvas:

[*] This method requires a single argument that must be the string "2d" and returns a drawing context that implements a two-dimensional API. In the future, if the <canvas> tag is extended to support 3D drawing, the getContext( ) method will presumably allow you to pass the string "3d".

 <head> <script> window.onload = function( ) {  // Do the drawing when the document loads     var canvas = document.getElementById("square");  // Get canvas element     var context = canvas.getContext("2d");           // Get 2D drawing context     context.fillStyle = "#f00";                      // Set fill color to red     context.fillRect(0,0,10,10);                     // Fill a square     canvas = document.getElementById("circle");      // New canvas element     context = canvas.getContext("2d");               // Get its context     context.fillStyle = "#00f";                      // Set blue fill color     context.beginPath( );                             // Begin a shape     // Add a complete circle of radius 5 centered at (5,5) to the shape     context.arc(5, 5, 5, 0, 2*Math.PI, true);     context.fill( );                                  // Fill the shape } </script> </head> </body> This is a red square: <canvas  width=10 height=10></canvas>. This is a blue circle: <canvas  width=10 height=10></canvas>. 

In previous sections, you've seen that SVG and VML describe complex shapes as a "path" of lines and curves that can be drawn or filled. The Canvas API also uses the notion of a path. But instead of describing a path as a string of letters and numbers, a path is defined by a series of method calls, such as the beginPath( ) and arc( ) invocations in the example. Once a path is defined, other methods, such as fill( ), operate on that path. Various properties of the drawing context, such as fillStyle, specify how these operations are performed.

One reason the Canvas API can be so compact is that it does not provide any support for drawing text. To incorporate text into a <canvas> graphic, you must either draw it yourself, incorporate it with bitmap images, or overlay HTML text on top of the <canvas> with CSS positioning.

Example 22-11 shows how to draw pie charts using a canvas. Much of the code in this example will be familiar from the SVG and VML examples. The new code in the example is the Canvas API, and you can look up those methods in Part IV.

Example 22-11. Drawing a pie chart in a <canvas> tag

 <html> <head> <script> // Create and return a new canvas tag with the specified id and size. // Note that this method does not add the canvas to the document function makeCanvas(id, width, height) {     var canvas = document.createElement("canvas");     canvas.id = id;     canvas.width = width;     canvas.height = height;     return canvas; } /**  * Draw a pie chart in the canvas specified by element or id.  * Data is an array of numbers: each number represents a wedge of the chart.  * The pie chart is centered at (cx, cy) and has radius r.  * The colors of the wedges are HTML color strings in the colors[] array.  * A legend appears at (lx,ly) to associate the labels in the labels[]  * array with each of the colors.  */ function pieChart(canvas, data, cx, cy, r, colors, labels, lx, ly) {     // Get the canvas if specified by id     if (typeof canvas == "string") canvas = document.getElementById(canvas);     // We draw with the canvas's drawing context     var g = canvas.getContext("2d");     // All the lines we draw are 2-pixel-wide black lines     g.lineWidth = 2;     g.strokeStyle = "black";     // Total the data values     var total = 0;     for(var i = 0; i < data.length; i++) total += data[i];     // And compute the angle (in radians) for each one     var angles = []     for(var i = 0; i < data.length; i++) angles[i] = data[i]/total*Math.PI*2;     // Now, loop through the wedges of the pie     startangle = -Math.PI/2;  // Start at 12 o'clock instead of 3 o'clock     for(var i = 0; i < data.length; i++) {         // This is the angle where the wedge ends         var endangle = startangle + angles[i];         // Draw a wedge         g.beginPath( );              // Start a new shape         g.moveTo(cx,cy);            // Move to center         // Line to startangle point and arc to endangle         g.arc(cx,cy,r,startangle, endangle, false);         g.closePath( );              // Back to center and end shape         g.fillStyle = colors[i];       // Set wedge color         g.fill( );                   // Fill the wedge         g.stroke( );                 // Outline ("stroke") the wedge         // The next wedge starts where this one ends.         startangle = endangle;         // Draw the rectangle in the legend for this wedge         g.fillRect(lx, ly+30*i, 20, 20);         g.strokeRect(lx, ly+30*i, 20, 20);         // And put a label next to the rectangle.         // The Canvas API does not support text, so we just do         // ordinary html text here. We use CSS positioning to put the text         // in the right spot on top of the Canvas element. This would be         // a little cleaner if the canvas tag itself were absolutely positioned         var label = document.createElement("div");         label.style.position = "absolute";         label.style.left = (canvas.offsetLeft + lx+30)+"px";         label.style.top = (canvas.offsetTop+ly+30*i-4) + "px";         label.style.fontFamily = "sans-serif";         label.style.fontSize = "16px";         label.appendChild(document.createTextNode(labels[i]));         document.body.appendChild(label);     } } function init( ) {     // Create a canvas element     var canvas = makeCanvas("canvas", 600, 400);     // Add it to the document     document.body.appendChild(canvas);     // And draw a pie chart in it     pieChart("canvas", [12, 23, 34, 45], 200, 200, 150,              ["red", "blue", "yellow", "green"],              ["North", "South", "East", "West"],              400, 100); } </script> </head> <body onload="init( )"> </html> 




JavaScript. The Definitive Guide
JavaScript: The Definitive Guide
ISBN: 0596101996
EAN: 2147483647
Year: 2004
Pages: 767

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net