6. Drawing with Canvas

In 2004, Apple developed a pixel-based drawing element named canvas for the Mac OS X dashboard that was later employed in the Safari Browser. The HTML5 specification has adopted this element and its associated set of APIs to provide basic drawing functionality. Before the canvas element, browsers required a third-party plug-in to render these basic drawings. Since this is a pixel-based drawing mechanism rather than a vector and layer-based system, the underlying functionality is rudimentary; however, as you will learn in this chapter, it can still provide a means to provide rich displays.

Canvas Overview

At the heart of implementing the canvas are two components: the canvas element in the HTML and the JavaScript to perform operations on the canvas. As with a painter, the canvas is blank until the painter uses brushes, tools, and medium to create the resulting work of art. In the same manner, you program into your JavaScript the motions using canvas shape tools, effects, and transformations. These are then drawn on the canvas, resulting in an updated view of new pixels.

The canvas element gives you a blank surface (thus the name canvas), which you can use to render graphics, images, and text dynamically. The canvas functionality is massive, so we will cover some basics such as drawing shapes and then cover some more complex effects and transformations. However, if you like this type of thing, then we encourage to do further research because we are really only scratching the surface here. We will quickly run through the basics before getting into heavy canvas usage.

Table 6.1 shows the version of each browser that supports the canvas element.

Table 6.1 Canvas Browser Availability

image

Note

For Internet Explorer 8 and older, you will need some third-party help, and that is where explorercanvas (http://code.google.com/p/explorercanvas) comes in. Because you need it for IE8 only, you can put it in conditional statements:

<!--[if lte IE 8]><script src="excanvas.js"></script><![endif]-->


Getting Started

Listing 6.1 has the code needed to get started with the canvas element. If you try this code in a browser, you will not see anything since no JavaScript has been added to actually draw on the canvas. A quick way to verify that the canvas has been rendered by the browser is to add a border to the element using CSS.

Listing 6.1 Setting Up the canvas Element


<!DOCTYPE html>
<html>
<head>
<style>
canvas {
  border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="640" height="480"></canvas>
</body>
</html>


The canvas element has the standard attributes of an HTML element. Minimally, you will need the id, width, and height attributes to be able to reference the canvas from your JavaScript and set the size of the canvas. In addition, the canvas element can be styled like any other element through CSS. In Listing 6.1, a border was applied to allow you to quickly verify that the canvas has been placed on the page and is sized correctly. You could also add a background color or other styles. These styles will appear by default in the canvas because by default the canvas is transparent and will render whatever is below the canvas element. This can be beneficial for overlaying the canvas on other HTML elements so that you can then draw on them.

You will notice in Listing 6.1 that we have included the end tag </canvas> in the HTML. The reason for including the end tag is to provide a fallback container and to be fully compliant with Mozilla because that browser expects fallback content. By having a fallback container, it can then display content between the tags should the canvas element not be supported by the browser. Like with other elements, you could provide an alt attribute to display text content, but if the canvas tag is not supported, then any content held within the opening and closing element tags will be displayed. This can be convenient to display anything from text to images since the canvas drawing will not be displayed.

To draw on the canvas from JavaScript, you first must grab the context of the canvas id you want to draw on. To do this, your script will get the canvas element by id and then use getContext to grab a reference to the canvas element’s two-dimensional context. This context reference provides the link for then changing pixels in the canvas, as shown here:

<canvas id="mycanvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('mycanvas').getContext('2d');
</script>

The getContext method can also be used to verify your JavaScript and determine whether the current browser supports the canvas drawing. A simple check using the canvas element will provide a true value if supported or a false value if not:

var canvas = document.getElementById('mycanvas');
if (mycanvas.getContext) {
   // canvas is supported
  ...

The JavaScript could then take an appropriate path of programming based on whether the browser supports the canvas functionality.

X and Y Coordinates

The last area we need to discuss before jumping into the basic canvas drawing tools is the coordinate system used for drawing on a canvas. Since the canvas is pixel based, an (X,Y) coordinate system is used to determine the particular location or pixel that is being updated. These coordinates are also used with the various tools to reference starting points, end points, and other locations. If you have used tools such as Adobe Photoshop, then using a coordinate-based drawing system will not be anything new to you. The key to the coordinate system is that the (0,0) point is located in the top-left corner of the canvas by default, with the X value increasing as you move left and the Y value increasing as you move down. As an introduction to some of the drawing tools and the canvas grid system, the first recipe in this chapter will lay this grid out for you to see on a canvas.

Beginner Recipe: Laying a Grid on the Canvas

The basis of all drawing using the canvas element is the grid system. However, for all intents and purposes, this grid system is invisible. The canvas element uses the grid system for the basic shape-drawing tools, effects, and transformations. In this recipe, you will use two of the basic shape methods, line and arc, to create a grid on the canvas with small points at the intersection of the vertical and horizontal lines. You will see how important the grid system is in using these basic drawing tools.

The canvas will be defined as being 600 pixels wide and 400 pixels high. At every 100 pixels, a vertical and horizontal line will be drawn creating the grid. To show the coordinates of the intersections, the recipe will use a canvas effect, fillText, that allows the JavaScript to apply text to the canvas element. In the end, you should have the result shown in Figure 6.1.

Figure 6.1 The canvas grid coordinate system drawn by using the line, arc, and fillText methods

image

Let’s make the grid visible now by following these steps and using Listing 6.2:

1. Create a blank HTML page with the html body tags as shown in Listing 6.2, including the canvas opening and closing tags, and fallback text in between.

2. Add the style section with the canvas id style.

3. Add window.addEventListener to launch the showGrid function when the page loads and the canvas and context variable declarations.

4. Add the showGrid function to draw the lines, points, and text on the canvas.

Listing 6.2 Drawing the Canvas Grid


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>6.2 Canvas Grid System</title>
<style>
#canvas {
  border:1px solid #03F;
  background:#CFC;
}
</style>
<script>

// Declare our canvas and context reference variables
var canvas;
var context;

// Lay the grid on to the canvas
function showGrid() {

  // Get references to the canvas and then the drawing context
  canvas = document.getElementById('canvas'),
  context = canvas.getContext('2d');

  // Set line width and color for the grid lines
  context.lineWidth = 1;
  context.strokeStyle = '#999';

  // Set the line spacing for the grid lines
  lineSpacing = 100;

  // Initialize the x and y positions
  var xPos = 0;
  var yPos = 0;

  // determine the number of horizontal and vertical lines on the grid
  var numHorizontalLines = parseInt(canvas.height/lineSpacing);
  var numVerticalLines = parseInt(canvas.width/lineSpacing);

  // Draw the horizontal lines
  for (var i=1; i<=numHorizontalLines;i++) {
    yPos = i*lineSpacing;
    context.moveTo(0,yPos);
    context.lineTo(canvas.width,yPos);
    context.stroke();
  }
  // Draw the vertical lines
  for (var i=1; i<=numVerticalLines;i++) {
    xPos = i*lineSpacing;
    context.moveTo(xPos,0);
    context.lineTo(xPos,canvas.height);
    context.stroke();
  }

  // Add circles and coordinates to the grid intersections
  for (var y=0; y<=numHorizontalLines; y++) {
    for (var x=0; x<=numVerticalLines; x++) {

      // calculate the x and y position
      xPos = x*lineSpacing;
      yPos = y*lineSpacing;

      // if at (0,0) then change color
      if (x==0 && y==0) {
        context.fillStyle='#f00';
      } else {
        context.fillStyle='#000';
      }

      // draw circle at point
      context.beginPath();
      // Draws a circle of radius 5 at the x and y position
      context.arc(xPos,yPos,5,0,Math.PI*2,true);
      context.closePath();
      context.fill();

      // Display the text for the coordinate
      // Check if on last vertical and place text on left
      if (x==numVerticalLines) {
        context.textAlign = 'right';
        xPos -= 5;
      } else {
        context.textAlign = 'left';
        xPos += 5;
      }
      // Check if on bottom horizontal and place text above
      if (y==numHorizontalLines) {
        yPos -= 8;
      } else {
        yPos += 12;
      }
      // Add the text to the canvas
      context.fillText('('+x*lineSpacing+','+y*lineSpacing+')',xPos,yPos);
    }
  }
}

// on page load initialize the bar chart
window.addEventListener('load',showGrid,false);

</script>
</head>
<body>
  <h1>Canvas Grid System</h1>
  <canvas id="canvas" width="600" height="400">
    The Canvas HTML5 element is not supported by your browser.
    Please run this page in a different browser.
  </canvas>
</body>
</html>


We will not go into too much detail here about the actual line, point, or text drawing because these shape-drawing methods and effects will be described later in the chapter. The key here is to understand the process that occurs when you want to draw on a canvas. In this recipe, you have created a canvas element in the HTML, which is 600 pixels wide by 400 pixels high. In addition, the canvas element has been styled to have a border and background color set. When the code is run in your browser, you will see this border and the background color. Since the canvas is transparent by default and the code draws lines, points, and text only on the canvas, the background style color will show through.

When the page loads, the showGrid function will be triggered. The first thing you need to do in the recipe is to get a reference to the canvas element and then get the canvas’s context to be used to draw on. Once you have the context, you can set some basic settings such as the line width with context.lineWidth and the color to be used with context.strokeStyle. Then you set the spacing for your grid lines to 100, set the initial starting coordinate of 0,0, and determine the number of horizontal and vertical lines that will need to be drawn. Using this information, the code then draws all the horizontal lines by moving the position down the canvas every 100 pixels and drawing a line across the canvas. After completing the horizontal lines, the code draws the vertical lines from left to right, drawing each line from the top of the canvas to the bottom of the canvas. Remember that for the y orientation, the top is 0 and increases as you go down.

Once the lines are drawn for the grid, you then want to add the intersection points and their coordinates. To draw the points, you will draw a circle at each point with the arc tool, which you will look at in further detail later in the chapter. At each point, you also display the text of the coordinate with the fillText method. By default, the text will be left and top aligned, which is fine for all the points of the grid, except the right-most column and bottom-most row. If you displayed these points without changing the text alignment, then the text would not be visible because it would be drawn on the context but out of the canvas viewing area. Instead, the code will determine whether the point is in either the last column or the bottom row and modify the alignment for that position.


Note

Since the canvas is based on pixel manipulation, in a two-dimensional world the order in which you draw on the canvas is very important. There is no concept of layers in the Canvas API, so the order in which you build a drawing up will better determine the final product. For example, if you add the text for a signpost to the canvas prior to drawing the sign with a solid background, then your text will be covered up. Instead, you would draw your sign background and then draw your text on top.


You have just drawn your first canvas drawing and at the same time learned how the grid system works with the canvas context. Now let’s look at the basic drawing shapes or methods of the canvas functionality, along with some of the effects that are available.

Canvas Tools

The canvas provides a basic set of tools, as shown next, from which you can create a wide range of simple and complex shapes on the canvas. In this recipe, you will learn briefly about each of these tools and see some quick samples of each tool.

Rectangle: Draws a rectangle at a specific location with a specific width and height

Line: Creates a line from point A to point B

Path: Creates a path using one or more lines or curves

Arc: Creates an arc given particular dimensions and employed to also create circles

Curve: Creates one of two types of curves: Bezier or Quadratic

Beginner Recipe: Making Simple Shapes and Lines

In this recipe, you will draw simple shapes such as a square and triangle and learn how to draw lines and paths.

Drawing and Styling a Rectangle or Square

Using fillRect(pos-x, pos-y, width, height), you can draw a rectangle or square:

canvas.fillRect(0, 0, 100, 100);

This will create a 100 pixel by 100 pixel square and place it in the top-left corner (0,0) of the canvas, as shown in Figure 6.2. By default, the square will be black in color, which is pretty boring, so let’s work on adding some color.

Figure 6.2 A square drawn with canvas

image

On top of the basic toolset provided by canvas, there are a handful of effects that can be used in conjunction with the tools:

Fill: Controls the fill parameters of a shape

Stroke: Controls the stroke of lines used in shapes

Gradient: Allows for the use of either linear or radial fill patterns in shapes

Transparency: Defines the opacity level to either all shapes on the canvas or through fill RGBa values to specific shapes

Shadow: Provides an easy-to-use shadow for applying to individual shapes

Compositing: Masks or clips off areas of the canvas and controls the overall order of the building of shapes on the canvas

You have already briefly seen some of the methods for these effects in this chapter. The following are some of the more common effect methods that are available for shapes:

strokeStyle: Specifies the color or style for lines around shapes

fillStyle: Specifies the color or style used inside shapes

shadowOffsetX/shadowOffsetY: Specifies the distance of the shadow

shadowBlur: Specifies the level of the blurring effect

shadowColor: Specifies the color of the shadow

createLinearGradient: Creates a linear gradient inside the shape

createRadialGradient: Creates a radial gradient inside the shape

So, if you use several of the effects available on the square you drew earlier with fillRect, you can get a rather fetching purple square with a purple shadow (see Listing 6.3). For any of the effects that employ color, such as strokeStyle, fillStyle, and shadowColor, you do not have to use an RGBa format for your colors but can use hex values or HSLa as well. It is important to note, though, that all the styles and effects must be done before using the fillRect method, since the fillRect method is what then tells the canvas context to render the shape, and once rendered, the shape is complete. Since the shape is displayed on the canvas through individual pixels, there is no way to change the shape after drawing it. Instead, you would need to redraw the shape to modify it, as you will learn later in the chapter.

Listing 6.3 Styling the Square


<canvas id="canvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('canvas').getContext('2d'),
  canvas.shadowOffsetX = 10;
  canvas.shadowOffsetY = 10;
  canvas.shadowBlur = 10;
  canvas.shadowColor = 'rgba(200, 0, 200, .3)';
  canvas.fillStyle = 'rgba(200, 0, 200, 1)';
  canvas.fillRect(0, 0, 100, 100);
</script>


With the color code choices available, colors can include the opacity setting, which can be extremely handy for creating the looks of layered images. Listing 6.3 used a semi-transparent shadow RGBa value to get the most desirable shadow effect.

There are two other methods for drawing rectangles: clearRect(pos-x, pos-y, width, height) and strokeRect(pos-x, pos-y, width, height. The clearRect method will clear the pixels in the given rectangle area. This will remove any pixel changes in the area, setting the area back to the default transparent state. As you will learn later in this chapter, using the clearRect method will be extremely helpful in animation and can be used to clear the entire canvas by using the canvas dimensions for the width and height or to clear just a particular area. strokeRect, in combination with lineWidth, will draw a stroke at the coordinates and the width and height you set it. Using a combination of these shapes and effects, as in Listing 6.4, will create an even more unique image.

Listing 6.4 More Styling Options


var canvas = document.getElementById('canvas').getContext('2d'),
canvas.shadowOffsetX = 10;
canvas.shadowOffsetY = 10;
canvas.shadowBlur = 10;
canvas.shadowColor = 'rgba(200, 0, 200, .3)';
canvas.fillStyle = 'rgba(200, 0, 200, 1)';
canvas.strokeStyle = '#09c';
canvas.lineWidth = 5;
canvas.fillRect(0, 0, 100, 100);
canvas.clearRect(25, 25, 50, 50);
canvas.strokeRect(25, 25, 50, 50);


Applying Gradients to Shapes

Another effect you can use with canvas shapes is a gradient. Gradient fills in the canvas can be created either through a linear (createLinearGradient) or radial (createRadialGradient) gradient. To add colors to the gradient, use the addColorStop property. Listing 6.5 creates two rectangles with the two gradient types.

Listing 6.5 Creating Gradients


<canvas id="canvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('canvas').getContext('2d'),
  var grd = canvas.createLinearGradient(0, 200, 200, 0);
  grd.addColorStop(0, '#000'),
  grd.addColorStop(.5, '#ccc'),
  grd.addColorStop(1, '#000'),
  canvas.fillStyle = grd;
  canvas.strokeStyle = '#09c';
  canvas.lineWidth = 5;
  canvas.fillRect(0, 0, 200, 200);
  canvas.closePath();

  var grd = canvas.createRadialGradient(300, 250, 2, 200, 200, 250);
  grd.addColorStop(0, '#000'), // light blue
  grd.addColorStop(1, '#ccc'), // dark blue
  canvas.fillStyle = grd;
  canvas.fillRect(200, 200, 200, 200);
  canvas.closePath();
</script>


Listing 6.5 creates an upper-left rectangle with a linear gradient and a lower-right rectangle with a radial gradient. Both gradient methods employ different parameters to control the behavior of the gradient, as shown here:

createLinearGradient(startX, startY, endX, endY)
createRadialGradient(startX, startY, startRadius, endX, endY, endRadius)

The radial gradient method can get a little complicated, so it is worth playing around with this; try adding various addColorStop to see what happens.

Drawing Lines and Paths

To draw a line using canvas, three methods make up the process:

moveTo(x,y): Moves the current location on the canvas grid to the first point of the line; the line will be drawn from here.

lineTo(x,y): Tells the canvas where the end point will be on the line.

stroke(): Called to have the canvas draw the line. If the stroke style has not been set with the strokeStyle method, then the default color of the line will be black.

In Listing 6.6, you start the line 10 pixels from the top left and, using lineTo, set the end of the line to 10 pixels from the bottom-right corner of the canvas, as shown in Figure 6.3.

Figure 6.3 A line drawn with canvas

image

Listing 6.6 Drawing a Line


<canvas id="canvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('canvas').getContext('2d'),
  canvas.moveTo(10,10);
  canvas.lineTo(630, 470);
  canvas.stroke();
</script>


Remember that the options for the line, such as width and color, must be set prior to calling the stroke method so that the style is rendered properly.

You can use lineTo as many times as you want to draw a variety of shapes by creating a “path” that the line takes. Let’s look at drawing a triangle in Listing 6.7, which uses lineTo three times to draw the three sides of the triangle.

Listing 6.7 Drawing a Triangle


<canvas id="canvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('canvas').getContext('2d'),

  canvas.beginPath();
  canvas.moveTo(10,10);
  canvas.lineTo(630, 470); //diagonal line
  canvas.lineTo(10, 470); //bottom line
  canvas.lineTo(10, 10); //left line
  canvas.closePath();

  canvas.strokeStyle = '#000';
  canvas.lineWidth = 3;

  canvas.fillStyle = '#ccc';
  canvas.fill();

  canvas.stroke();
</script>


To have the lines create one path, you will use two new methods: beginPath and closePath. beginPath tells the canvas that the lines, or curves that come after, belong to one path object that is “closed” when the closePath method is executed. The path of lines or curves can then be treated as one object, similar to a rectangle, and then can be styled similarly.

Previewing the shape using the code in Listing 6.7, you will notice that where the line ends (top-left corner), it is a little rough, because the lines don’t meet smoothly. Well, there is a method for that, lineCap, which accepts a value of butt, round, or square. This will cap the end of the line, but what about the other points of the triangle? You can use the lineJoin method for that, which accepts a value of bevel, miter, or round:

canvas.lineCap = 'round';
canvas.lineJoin = 'round';

Paths can include segments that are created not only from lines but also from curves, as you will see later.

Intermediate Recipe: Drawing Polygons with a Path

In this recipe, you will use the line drawing and path functionality of the Canvas API to draw a regular polygon based on a number of sides and radius provided by the user. Because the polygon is created by employing the path feature, you can then fill in the shape with color. To create the polygon, JavaScript will create a line from and to each vertex of the polygon based on mathematical formulas to determine the coordinates of the vertices. The recipe can be created by following the steps and using the code in Listing 6.8:

1. Create the page in Listing 6.8 with the style and body tags for the canvas.

2. Add the input fields for the number of sides and radius along with the button to trigger the drawing of the polygon.

3. Add the init function, global variables, and load event handler to set the global references to the canvas and context.

4. Add the drawPolygon function, which is the worker function for drawing the actual regular polygon.

Listing 6.8 Drawing Polygons with Paths


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>6.8 Drawing Polygons with Paths</title>
<style>
#canvas {
  border:1px solid #03F;
}
</style>
<script>
// Global variables for the canvas and context
var canvas;
var context;

// initialization function when the page loads
function init() {

  // set the button handler
  var btnDrawPolygon = document.getElementById('drawPolygon'),
  btnDrawPolygon.addEventListener('click',drawPolygon,false);

  // set references to the canvas and context
  canvas = document.getElementById('canvas'),
  context = canvas.getContext('2d'),
}

// function to draw the polygon on the canvas
function drawPolygon() {

  // Retrieve the user input for the polygon
  var numSides = document.getElementById('numSides').value;
  var radius = document.getElementById('radius').value;
  // Get our canvas center point to center the polygon
  var xCenter = parseInt(canvas.width/2);
  var yCenter = parseInt(canvas.height/2);

  // Clear the canvas
  context.clearRect(0,0,canvas.width,canvas.height);

  // Begin our path
  context.beginPath();

  // Map the first vertice to start with
  var xPos = xCenter + radius * Math.cos(2 * Math.PI * 0 / numSides);
  var yPos = yCenter + radius * Math.sin(2 * Math.PI * 0 / numSides);
  context.moveTo(xPos,yPos);

  // Loop through the vertices and map the lines
  for (i = 1; i <= numSides; i++) {

    // Determine the coordinates of the next vertex
    xPos = xCenter + radius * Math.cos(2 * Math.PI * i / numSides);
    yPos = yCenter + radius * Math.sin(2 * Math.PI * i / numSides);

    // Set line to the next vertex
    context.lineTo(xPos,yPos);
  }

  // Close our path of lines
  context.closePath();

  // Set the line properties and draw the lines
  context.lineWidth = 30;
  context.lineJoin = 'round';
  context.stroke();

  // Fill our new polygon
  context.fillStyle = '#00F';
  context.fill();
}

// call the init function on page load
window.addEventListener('load',init,false);

</script>
</head>
<body>
  <h1>Canvas Path Usage:</h1>
  <canvas id="canvas" width="400" height="400">
    The canvas element is not supported in your browser.
  </canvas>
  <br>
  Number of Sides: <input type="number" id="numSides" min="3" step="1" value="7" /><br>
  Radius: <input type="number" id="radius" min="10" step="1" value="150" /><br>
  <button id="drawPolygon">Draw Polygon</button>
</body>
</html>


Upon clicking the Create Polygon button, the drawPolygon function will be called. First, the function retrieves the user inputs for the number of sides and radius for the polygon. Next, the function finds the center point for the canvas to place the polygon in the center of the canvas. Then, you clear the canvas, using the clearRect function, so that you start with a blank canvas each time the user creates a new polygon.

Now that the canvas is set, you begin the path with the beginPath method. Then with some fancy algorithms, you calculate the beginning X,Y coordinate and loop through each vertex using lineTo to create the segments. Once all the line segments have been built, the path is closed with the closePath method. The closePath method joins all the line segments into one path, which you then use to set the line and fill of the polygon, resulting in the polygon being drawn on the canvas, as shown in Figure 6.4.

Figure 6.4 Polygon created with five sides and a radius of 150 via the path functionality

image

Intermediate Recipe: Drawing Arcs and Circles

You are not limited to just straight lines with canvas; you can add curves, too. You start with the arc method, which accepts the following values:

canvas.arc(x, y, radius, startAngle, endAngle, antiClockwise(Boolean));

Let’s look at an example in Listing 6.9, which results in Figure 6.5.

Figure 6.5 An arc drawn with canvas

image

Listing 6.9 Drawing an Arc


<canvas id="canvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('canvas').getContext('2d'),
  canvas.arc(100, 100, 40, 5, 1, true);
  canvas.strokeStyle = '#000';
  canvas.lineWidth = 5;
  canvas.stroke();
</script>


In Listing 6.9, you set the antiClockwise value to true. Try setting it to false and see what is drawn.

To draw a circle, use the arc() method, start the angle with 0, and end it with 2*Math.PI:

canvas.arc(100, 150, 60, 0, 2 * Math.PI, false);
canvas.fillStyle = '#000';
canvas.fill();
canvas.strokeStyle = '#000';
canvas.lineWidth = 2;

Drawing Curves

Two types of curves are available in canvas: quadraticCurveTo and bezierCurveTo. The difference between the two is that quadraticCurveTo has one control point, whereas bezierCurveTo has two. The control points enable you to add curves to lines so you can create more complex shapes:

canvas.quadraticCurveTo(cX, cY, endX, endY);
canvas.bezierCurveTo(c1X, c1Y, c2X, c2Y, endX, endY);

Beginner Recipe: Adding Text

The Canvas API provides two methods for adding text to the canvas: fillText and strokeText. fillText takes a string to display along with the X,Y coordinate to display the text at and creates the text string as filled letters, while the strokeText method takes the same parameters but creates an outline of the text characters:

fillText(text, x, y);

In both cases, the font type, weight, and size can be modified through the font property, and the fill stroke style can be controlled via the fillStyle and strokeStyle canvas properties, as shown in Listing 6.10.

Listing 6.10 Adding Text to the Canvas


<script>
    var canvas = document.getElementById('canvas').getContext('2d'),
    canvas.font = 'bold 80px Tahoma';
    canvas.fillStyle = '#000';
    canvas.fillText('HTML5 Canvas', 10, 100);

    canvas.strokeStyle = '#000';
    canvas.lineWidth = 3;
    canvas.fillStyle = '#ccc';
    canvas.textAlign = 'center';
    canvas.fillText('HTML5 Canvas', 320, 200);
    canvas.strokeText('HTML5 Canvas', 320, 200);
</script>


Listing 6.10 results in Figure 6.6. Notice that in fillText and strokeText, after the string value, are the X and Y coordinates where the text will be drawn. Also, for the second example, the text is aligned to the center, and both fillText and strokeText are used, so if you just wanted a text outline, then remove fillText.

Figure 6.6 Text drawn on the canvas

image

Beginner Recipe: Drawing an Image

One of the more interesting areas of the Canvas API is the inclusion of images. With the drawImage method, you can include an image of your choosing and manipulate the image in multiple ways. The simple example shown in Listing 6.11 loads a PNG image file and results in the display in Figure 6.7.

Figure 6.7 An image drawn onto a canvas (the HTML5 logo is attributed to the W3C, www.w3.org)

image

Listing 6.11 Drawing an Image


<canvas id="canvas" width="640" height="480"></canvas>
<script>
  var canvas = document.getElementById('canvas').getContext('2d'),
  var canvasImage = new Image();

  function drawCanvasImage(){
    canvas.drawImage(canvasImage, 155, 0);
  };

  canvasImage.addEventListener('load',drawCanvasImage,false);

  canvasImage.src = 'images/html5-logo.png';
</script>


The drawImage function has three different formats:

drawImage(image, dx, dy): Displays an image provided in the image URL at the location x and y

drawImage(image, dx, dy, dw, dh): Scales the image based on the display width (dw) and display height (dh)

drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh): Crops a section of the image based on the X,Y coordinate and width and height provided by (sx, sy, sw, and sh)

The basic drawImage method takes the URL of the image and then the x and y position to display the image at. The image is not scaled or cropped in any way. In Listing 6.11, the load event is used to verify that the image has loaded prior to trying to display the image on the canvas. If you pass the image URL directly into the variables, then nothing will display because the image will not have loaded in to the page. So, to confirm that the image has loaded prior to asking the canvas to display the image, you listen for the load image event.

In Figure 6.4, you can see the image just barely fits inside our canvas frame; you can resize the image by using the drawImage method with scaling width and height options:

drawImage(image, x, y, width, height);

In this manner, the script passes in the additional width and height values, such as canvas.drawImage(canvasImage, 50, 50, 150, 211);, which will resize the image to 150 pixels wide by 211 pixels tall and position it 50 pixels from the top and left.

Intermediate Recipe: Cropping an Image

You can also crop the image, by using the third method signature, which includes cropping properties. The cropping properties are the start X and Y positions in the image and the width and height of the cropping frame. It gets a little complicated, so Listing 6.12 has comments next to each value.

Listing 6.12 Cropping an Image


function cropImage(){
  canvas.drawImage(canvasImage,
  0, // position X inside the crop
  0, // position Y inside the crop
  168, // source image width
  236, // source image height
  110, //crop position X
  110, //crop position Y
  250, //crop width
  250 //crop width
  );
);

canvasImage.addEventListener('load',cropImage,false);


In addition to simply drawing the image on the canvas, the API provides a means to use the image to also fill a given shape. Using the createPattern method, you can use an image to fill the background of a shape. First, the image is passed that you want displayed; then a pattern variable is created with the image. Then a shape is drawn, using coordinates and a size. The fill style of the shape is then assigned to the pattern that was created, as shown here:

var canvasImage = new Image();
function createImagePattern(){
  var pattern = canvas.createPattern(canvasImage, 'repeat'),
  canvas.rect(0, 0, 640, 480);
  canvas.fillStyle = pattern;

  canvas.fill();
);
canvasImage.addEventListener('load',createImagePattern,false);

canvasImage.src = 'images/html5-logo.png';

The repeat parameter can have the following values:

repeat: Repeats the pattern horizontally and vertically

repeat-x: Repeats the pattern horizontally

repeat-y: Repeats the pattern vertically

no-repeat: Does not repeat the pattern

Intermediate Recipe: Animating a Sprite Map

Since the drawImage method can be used to crop a source image and draw the resulting subimage onto the canvas, you can use the same effect to animate sprite maps by cycling through the frames of the sprite image. On a set interval, the drawImage method is called to render a new frame of the source image each time, thus creating an animation. In this recipe, you will use a simple sprite map of three frames to animate a recycle icon. Each time the drawImage is called, the frame moves to the next frame. After reaching the last frame, the frame is moved back to the first frame of the source image. To create this example, use the following steps and Listing 6.13:

1. Create the page in Listing 6.13 with the style and body tags for the canvas and including the buttons to start and stop the animation.

2. Add the global variable definitions, init function, and window.addEventHandler event handler.

3. Add the animateSprite function, which draws the cropped image.

4. Add the startAnimation and stopAnimation functions, which are tied to the start and stop animation buttons.

Listing 6.13 Using Image Cropping with Sprite Maps


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>6.13 Sprint Slice Animation</title>
<style>
#canvas {
  /* Place border on our canvas */
  border:1px solid #03F;
}
</style>
<script>
// canvas and context variables for drawing
var canvas;
var context;

// Image holder for our animation
var spriteRecycle = new Image();

// Sprite image frame variables
var sliceX = 0;
var sliceY = 0;
var sliceWidth = 100;
var sliceHeight = 100;

// animation variable
var intervalRef;

// initialize the canvas
function init() {
  // Set the button handlers
  var btnStart = document.getElementById('start'),
  var btnStop = document.getElementById('stop'),
  btnStart.addEventListener('click',startAnimation,false);
  btnStop.addEventListener('click',stopAnimation,false);

  // Retrieve reference to the canvas and context
  canvas = document.getElementById('canvas'),
  context = canvas.getContext('2d'),

  // Assign the source of our image
  spriteRecycle.src = 'recycle_sprite.png';
}

// Animate image based on slice
function animateSprite() {
  // Draw the image based on the current sprite slice
  context.drawImage(spriteRecycle, sliceX, sliceY, sliceWidth, sliceHeight, 0, 0, 100, 100);

  // Increment the slice of the sprite
  sliceX+=100;
  // Reset the slice to the first frame if needed
  if (sliceX>=spriteRecycle.width) {
    sliceX = 0;
  }
}

// Start the animation by setting an interval
function startAnimation() {
  intervalRef = setInterval('animateSprite()',100);
}

// Stop the animation by clearing the interval set
function stopAnimation() {
  clearInterval(intervalRef);
  // erase the canvas with clearRect
  context.clearRect(0,0,100,100);
}

// call the init function on page load
window.addEventListener('load',init,false);

</script>
</head>
<body>
  <h1>Sprite Map Animation with Canvas</h1>
  <canvas id="canvas" width="100" height="100">
    The Canvas element is not supported in this browser.
  </canvas>
  <br>
  <button id="start">Start</button>
  <button id="stop">Stop</button>
</body>
</html>


After the startAnimation function is called when the user clicks the start button, the function sets an interval for 100 milliseconds to launch the animateSprite function. This is the heart of the animation timing. Each 100 milliseconds, the animateSprite function will be called until the stopAnimation function is called and clears the interval. Each time the animateSprite function is run, a slice of the recycle image will be displayed. The recycle image is 300 pixels wide and contains three slices that are 100 by 100 pixels. After each drawing of the slice, the slice horizontal position is moved 100 pixels to the right, as shown in Figure 6.8. If the slice is already on the last 100 pixels, then the slice is moved back to 0.

Figure 6.8 Slice frames of the sprite image as they are displayed with each cycle

image

Note that you do not have to clear the canvas before each drawImage because the sprite image has an opaque background and you are drawing over the entire 100 by 100 pixel canvas each time.


Note

Even though the canvas element does not support layers in the canvas itself, there is a way you can imitate the functionality of layers. Since the canvas is an element on the page that can be styled and has a transparent background by default, there is nothing preventing developers from having multiple canvas elements defined that are positioned on top of each other. To control the layer position on the page, the z-index style attribute on the element would be used. It would not be too far-fetched to imagine a game that has a background canvas while a character sprite is loaded in a smaller canvas that is positioned on top of the other canvas. If you implement a multiple-canvas page, be cautious of performance issues since references must be kept to the individual canvas elements to use them.


Canvas Transformations

In addition to the canvas tools and effects that are available, a handful of transformation tools are available for use. The following are the three transformation tools available:

rotate(angle): Rotates the underlying context grid of the canvas so that anything added to the rotated context appears rotated to the user. The angle is in radians and is measured clockwise.

scale(x, y): Allows the developer to control the scale for the x and y units. The scale method takes the x unit scale and y unit scale as parameters.

transform: This transformation provides the developer with access directly into the transformation matrix.

Three methods are associated with the canvas that assist in performing a transformation. The translate(x, y) canvas method allows you to move the point of origin of the canvas to a new location. So, if you called translate(100,100), the new origin point would be shifted 100 pixels down and 100 pixels to the right and become your new point of origin. This is extremely important with transformations such as rotation, because the point of origin is the point around which the rotation is performed. There are two ways to return the point of origin to the original location. The first is to simply use the translate method again to return the location in the opposite directions. The second and preferred method is to use the save and restore canvas methods.

The save and restore methods allow you to save the current context prior to any transformation and then restore the context to the saved version at a later time. We will use this pattern along with the rotate method in various recipes to demonstrate transformations with canvas. The rotate method takes a number of radians to rotate the canvas orientation. To convert angle degrees to radians, use the following formula:

Angle in Radians = angle in degrees * Pi / 180

Through the use of transformations such as the rotate and scale methods, you can use the canvas to create interesting animations, as shown in the next recipe.


Note

As with any base set of API calls that lend themselves to enlarged and repetitive functionality, such as drawing squares, circles, and so on, from the base components, extended libraries of calls have been created by various developers. In turn, many of these libraries have been productized and can provide a basis for enveloping the canvas functionality in simpler calls. In addition, the libraries have typically extended the functionality, making more complex features easier to employ. Some libraries that you may want to check out include netron, canvas toolkit, EaselJS, jCanvaScript, and gury. As the HTML5 canvas gains in popularity, we are sure that the number and breadth of libraries will continue to increase.


Advanced Recipe: Animating an Image

In this recipe, you will use two steps to “roll” a gear across the canvas from left to right. The first step will be to move the image by redrawing the image on a given interval to the right. The second step will be to rotate the image a certain number of degrees each time you move the image. As shown earlier, the rotate effect is used to rotate the context of the drawing. In this example, you will save the default canvas context and then rotate the context, draw the image, and finally restore the context. In this manner and with the combination of these methods, the code in Listing 6.14 will create the illusion that the gear image is rolling across the screen.

1. Create the page in Listing 6.14 with the style and body tags for the canvas.

2. Add the global variable definitions, init function, and window.addEventListener event handler.

3. Add the moveGear function, which rotates, moves, and draws the gear image.

Listing 6.14 Moving and Rotating an Image


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>6.14 Moving Gear</title>
<style>
#canvas {
  /* apply a simple border to the canvas */
  border:1px solid #03F;
}
</style>
<script>

// canvas and context reference variables for drawing
var canvas;
var context;

// the gear image reference
var gear = new Image();

// the current x position of the image
var xpos;

// The animation variables
var stepCounter;  // counter for the current step
var stepDegrees;  // how much to rotate each step
var stepDistance; // how far to move image each step
var stepSpeed;    // how fast to rotate and move the image
var stepsFullRevolution;  // how many steps in a full rotation

// initialize the board width and height
function init() {
  canvas = document.getElementById('canvas'),
  context = canvas.getContext('2d'),
  // Initialize our step counter for the rotation
  stepCounter = 0;
  stepDegrees = 2;
  stepDistance = 2;
  stepSpeed = 5;
  stepsFullRevolution = parseInt(360 / stepDegrees);

  // Add the image load event listener
  gear.addEventListener('load',initGear,false);

  // Set the gear source image
  gear.src = 'gear.png';
}

// When the image is loaded then start the animation
function initGear(){
  // set the initial X position to just off left of canvas
  xpos = -(gear.width/2);
  // call the animation function
  moveGear();
};

// Function to remove old cog image and draw new image
function moveGear() {

  // Clear the old cog off the canvas
  context.clearRect(0, 0, canvas.width, canvas.height);

  // Save the present canvas context so we can return
  context.save();

  // Increment the position
  xpos += stepDistance;

  // Move our 0,0 point to the new position of the cog
  context.translate(xpos,canvas.height-(gear.width/2));

  // Rotate the context and thus our cog
  context.rotate(Math.PI * stepDegrees * stepCounter / 180);

  // Draw the newly rotated image
  context.drawImage(gear, -(gear.width/2), -(gear.height/2), gear.width, gear.height);

  // Restore the context to the original orientation
  context.restore();
  // Check if the cog has left the canvas on the right
  if ((xpos-(gear.width/2)) < canvas.width) {

    // Increment the stepCounter and check if completed full revolution
    stepCounter++;
    if (stepCounter>=(stepsFullRevolution-1)) {
      stepCounter=0;
    }

    // cog is still showing - keep moving
    setTimeout('moveGear()',stepSpeed);
  }
}

// call the init function on page load
window.addEventListener('load',init,false);

</script>
</head>
<body>
  <h1>The Rolling Cog</h1>
  <canvas id="canvas" width="600" height="100">
    The Canvas element is not supported in this browser.
  </canvas>
</body>
</html>


When the moveGear function is called after the image is loaded, the first action performed by the code is to clear the canvas by calling clearRect. You need to do this or else “remnants” of the prior image drawn will remain on the canvas. Next, the script saves the current context, increments the horizontal position, and then positions the origin to the new position with the translate function. Then the script rotates the image based on the new origin by the stepDegrees set previously with the rotate method. Next the image is drawn, and you restore the context orientation thereafter for the next drawing function.

After drawing the gear image at the new position and angle, you check to see whether the image has moved past the right edge of the canvas by comparing the horizontal position and the canvas width. If it has moved past the edge, then you stop the animation. However, if the image is still in view on the canvas, then the script increments the step counter and sets the next timeout to kick off the moveGear function again.

Any of the animation settings can be adjusted by changing the animation variables in the top of the script. Figure 6.9 shows different stages of the image in the canvas.

Figure 6.9 Slice frames of the sprite image as they are displayed with each cycle

image

Note

You can interact with the canvas, whether to play a game or move a shape, by catching mouse events such as mouseover and click. The coordinates provided by the event can be mapped through the offset X and Y coordinates to the location of the canvas on the page. For example, if the X,Y from the mouse click event is 150,200 and the canvas offset is 100 for the x and 100 for the y, then the coordinate for the mouse click in the canvas is 50,100. Knowing this coordinate in the canvas grid, you can then determine whether it occurred on a particular shape that was drawn on the canvas.


Advanced Recipe: Animating a Vertical Bar Chart

In this last recipe of the chapter, you will take the tools of canvas along with some effects and transformations to create a vertical bar chart from a set of sample JSON data. When the chart loads, the vertical bars will grow to their defined values based on some animation settings that have been defined such as the speed and distance to grow each column. Figure 6.10 shows the output with sample data after the animation of the bars has completed. To create this recipe, follow these steps and the code in Listing 6.15:

1. Create the page in Listing 6.15 with the style and body tags for the canvas, which has the id of graph.

2. Add the global variable definitions including the chartData JSON object, initGraph function, and window.addEventListener event handler.

3. Add the initSettings function, which sets all the properties of the graph including the number of bars and size of the bars.

4. Add the drawAxis function, which will add the x- and y-axis lines, the data marks on the axis, and the titles.

5. Add the growBars function, which is the function to animate the growth of the vertical bars to their proper height.

6. Add the drawBar helper function, which performs the actual drawing of the bar on the canvas.

Figure 6.10 The completed vertical bar chart with sample data

image

Listing 6.16 Creating an Animated Vertical Bar Chart


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>6.16 Growing Bar Chart</title>
<style>
#graph {
  /* outline our canvas */
  border:1px solid #03F;
}
</style>
<script>

// Canvas and drawing context variables
var canvas;
var context;

// Chart settings
var chartMargin;
var chartAxisSpace;
var chartWidth;
var chartHeight;

// bar variables
var numBars = 0;       // total number of bars
var barMargin = 20;    // margin between bars
var barWidth = 0;      // bar width
var maxValue = 0;      // maximum data value for the bars

// number of y-axis labels
var numYLabels;

// bar animation variables
var idxStep;
var numSteps;
var growSpeed;

// Chart JSON sample data
var chartData = {'bars':[
  {'title':'Year 1','value':'7'},
  {'title':'Year 2','value':'12'},
  {'title':'Year 3','value':'20'},
  {'title':'Year 4','value':'33'},
  {'title':'Year 5','value':'55'},
  {'title':'Year 6','value':'93'},
  {'title':'Year 7','value':'156'}
]}

// initialize the board width and height
function initGraph() {

  // get reference to canvas and drawing context
  canvas = document.getElementById('graph'),
  context = canvas.getContext('2d'),

  initSettings(); // initialize the chart settings
  drawAxis(); // draw the chart axis and labels
  growBars(); // animate the bars into the chart
}

function initSettings() {

  // set our chart settings
  chartMargin = 20; // margin around entire canvas
  chartAxisSpace = 50; // area for the x- and y-axes
  // set the chart drawing area
  chartHeight = canvas.height-chartAxisSpace-2*chartMargin;
  chartWidth = canvas.width-chartAxisSpace-2*chartMargin;

  // set the number of labels to use for the y-axis
  numYLabels = 8;

  // set the number of bars based on the chartData
  numBars = chartData.bars.length;
  // find our max data value to scale the graph
  for (var i=0; i < numBars; i++) {
    if (chartData.bars[i].value > maxValue) {
      maxValue = parseInt(chartData.bars[i].value);
    }
  }

  // determine the width of each bar
  barWidth = (chartWidth / numBars)-barMargin;

  // initialize animation variables
  idxStep = 0;
  numSteps = 100;
  growSpeed = 6;
}

function drawAxis() {
  // Set line width for the axis lines
  context.lineWidth = 2;

  // draw y-axis - from lower left to upper left
  context.moveTo(chartMargin+chartAxisSpace,chartHeight+chartMargin);
  context.lineTo(chartMargin+chartAxisSpace, chartMargin);
  context.stroke();

  // draw X axis - from lower left to lower right
  context.moveTo(chartMargin+chartAxisSpace, chartMargin+chartHeight);
  context.lineTo(chartMargin+chartAxisSpace+chartWidth, chartMargin+chartHeight);
  context.stroke();

  // Set the line width back to 1 pixel
  context.lineWidth = 1;

  // Add data marks to the y-axis
  var markerAmount = parseInt(maxValue / numYLabels);
  context.textAlign = 'right';
  context.fillStyle = '#000';
  // Loop through and add the markers to the y-axis
  for (var i=0; i <= numYLabels; i++) {
    // Determine the label and X and Y points
    markerLabel = i*markerAmount;
    markerXPos = chartMargin + chartAxisSpace - 5;
    markerYPos = chartMargin + (chartHeight – ((i*markerAmount*chartHeight)/maxValue));

    // Add the text marker at the positions determined
    context.fillText(markerLabel, markerXPos, markerYPos, chartAxisSpace);
  }
  // Add labels for each bar based on the chart data
  context.textAlign = 'center';
  // loop through each bar and add the title
  for (var i=0; i<numBars; i++) {
    // determine the X and Y positions for the marker
    markerXPos = chartMargin+chartAxisSpace + barMargin + (i * (barWidth+barMargin)) + (.5*barWidth);
    markerYPos = chartMargin+chartHeight + 10;

    // Add the text under the bottom of the bar
    context.fillText(chartData.bars[i].title, markerXPos, markerYPos, barWidth);
  }

  // Add y-axis title
  // Save the present context
  context.save();
  // Move the 0,0 point to the y-axis title point
  context.translate(chartMargin+10,chartHeight/2);
  // Rotate the current drawing context counter-clockwise 90 degrees
  context.rotate(Math.PI*-90 / 180);
  // Add our text title
  context.fillText('Sales (in 000s)',0,0);
  // Restore the context drawing orientation
  context.restore();

  // Add X Axis Title
  context.fillText('Year Out',chartMargin+chartAxisSpace+(chartWidth/2),chartMargin+chartHeight +40);
}

// Animation function to grow the bars vertically
// Called on a timeout based on number of steps
function growBars() {

  // Declare our bar x,y, and h
  // barWidth is predetermined above
  var barStartX = 0;
  var barStartY = 0;
  var barHeight = 0;

  // bar value variable from the data set
  var barValue = 0;

  // Loop through the bars and draw each based on step
  for (var i=0; i < numBars; i++) {
    // get the bar value
    barValue = parseInt(chartData.bars[i].value);

    // calculate the bar height, starting x and y points
    barHeight = (barValue * chartHeight / maxValue) / numSteps * idxStep;
    barStartX = chartMargin + chartAxisSpace + (i * (barWidth + barMargin)) + barMargin;
    barStartY = chartMargin + (chartHeight-barHeight);

    // call the helper function to draw the bar
    drawBar(barStartX, barStartY, barWidth, barHeight);
  }

  // Grow the bars more if they have not finished growing
  if (idxStep<numSteps) {
    idxStep++;
    setTimeout('growBars()',growSpeed);
  }
}

// helper function to draw a bar based on dimensions passed
//could pass in context along with other params to customize
function drawBar(barX, barY, barW, barH) {
  // Create rectangle with fill
  context.fillStyle = '#00c';
  context.fillRect(barX, barY, barW, barH);

  // Add shadow to bar
  context.shadowOffsetX = 3;
  context.shadowOffsetY = -3;
  context.shadowBlur = 3;
  context.shadowColor = 'rgba(200, 200, 200, .3)';

  // Add line border on the bar
  context.strokeStyle = '#000';
  context.lineWidth = 1;
  context.strokeRect(barX, barY, barW, barH);
}

// on page load initialize the bar chart
window.addEventListener('load',initGraph,false);

</script>
</head>
<body>
  <h1>Growing Bar Chart</h1>
  <canvas id="graph" width="600" height="400">
    This browser does not support the canvas element.
  </canvas>
</body>
</html>


When the page is loaded, the initGraph function will be called, which will in turn call the initSettings function, which will set all the settings of the graph. Next, the initGraph will call the drawAxis method. The drawAxis function will draw two lines for the x-axis and y-axis. Then the function will add the data marks to the y-axis based on the number of marking you set in the initialization. For the x-axis, you use the title property of the JSON chart data for each bar. Notice that you align the text for each bar on the center of the bar. Lastly, the function adds the y-axis title, which is rotated 90 degrees counterclockwise, and the x-axis.

Next, the initGraph function calls the growBars function. The growBars function is the heart of the simple animation and increments the animation step to determine on a percentage level how much to grow each bar based on the end bar value from the chartData. In this manner, the function grows each bar proportionally each time the growBars function executes. After calculating the new dimensions for each bar, the growBars function will call the helper function drawBar with the bar dimensions to actually draw the bar on the canvas. Once the growBars function has looped through all the bars of the graph, the function then checks to see whether this step was the last step in the animation. If there are more steps, then the function sets a timeout to call the growBars function again after incrementing the step index. Figure 6.11 shows how the bar chart grows through this animation.

Figure 6.11 Growth of the bar chart columns

image

To change the speed or growth rate of the bars, all you need to do is change the numSteps and growSpeed variables in the initSettings function.


Tip

Creating animated and even interactive charts with the HTML5 canvas is quite simple, as you saw in this last recipe. If you want to see the endless possibilities of using the HTML5 canvas for creating charts ranging from basic line graphs to complicated rose charts, you will want to check out the RGraph JavaScript and HTML5 canvas chart library at www.rgraph.net. The developers of the library have performed the heavy lifting, and as long as you follow the license agreement, you can incorporate it into your own projects if desired. In either case, the library demonstrates the potential of using the canvas with JavaScript.


Summary

In this chapter, you learned about the Canvas API. The Canvas API has a tremendous amount to offer for drawing capabilities above and beyond what has been described. However, with these basics, you now have the tools to explore more advanced methods and topics of the Canvas API. We encourage you to push its limits and let your artistic creativity flow.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset