Click here to Skip to main content
11,428,825 members (63,583 online)
Click here to Skip to main content

Beginner's Guide to HTML5 and CSS3 - Coding Canvas (Part 7 of 12)

, 25 Apr 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
All about learning how to code on HTML5 Canvas. You will be learning the basics about canvas, how to draw shapes, animations etc.

Click on the image to see Canvas Animation

Introduction

In this article we will be learning the below mentioned topics which are related to HTML5 Canvas element.
By the end of this article you should be able fully understand the basics about HTML5 canvas and you should be able to draw some shapes, create some amazing animations etc.


What is canvas?

Creating a canvas

Canvas Coordinates, Paths, Text, Gradients, Images

Drawing onto a canvas with Javascript

Canvas examples

Background

If you are a beginner , it's highly recommended to read through the following articles to understand more about the HTML and CSS.

Beginner's Guide to HTML5 and CSS3 - Writing Your First Code (Series 1 of 12)

Beginner's Guide to HTML5/CSS3 - Styling Your First Web Page (Series 3 of 12)

Beginner's Guide to HTML5 & CSS3 : Laying Out Your First Web Page (Series 4 of 12)

Beginner's Guide to HTML5 & CSS3 - Getting Fancy with HTML5 & CSS3 (Series 5 of 12)


What is canvas ?

The canvas is a resolution dependent bitmap canvas which is used to render graphics, games graphics etc on the fly. Javascript coding is used to draw on canvas. If you ask how does the an empty canvas would look like when it gets rendered on browser? It shows absolutely nothing; Yes with no contents, no borders nothing.

Creating a canvas

The canvas element is defined with <canvas> tag.

Here's an example shows the usage of canvas element.

<canvas id="canvas" width="250" height="100" style="border:1px solid black;">
</canvas> 

The 'id' attribute is used to identify a canvas. Within the javascript code, we can get the canvas by using a javascipt code GetElementById passing in the canvas id.

The width and height attribute of a canvas are optional. If you don't specify the width and height, then by default the canvas gets rendered with 300px * 150px (width * height)

We will learn how to create a canvas and access the same with in the javascript. Here's an example to create a simple canvas.

<html>
  <head>
    <title>Creating Canvas</title>
    <script type="text/javascript">
      function DrawCanvas(){
        var canvas = document.getElementById('canvas'if (canvas.getContext){
          var context = canvas.getContext('2d');
        }
      }
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="DrawCanvas();">
    <canvas id="canvas"></canvas>
  </body>
</html> 

You can see from the above sample, a canvas is defined with a <canvas> tag.

The HTML body has a onload event set to DrawCanvas; hence when the page gets loaded, the DrawCanvas method gets called which draws canvas.

Note – We just don't draw on canvas right now. However we are just putting down the basic skeleton required in working with canvas. With in the DrawCanvas function, we are getting the canvas element by using document.getElementById passing in the canvas 'id' then we get the 2D context so that we can make use of the context in drawing shapes in canvas.

Canvas Coordinates, Paths, Text, Gradients, Images

Let us learn some of the basic concepts of canvas coordinates. The coordinate system in a canvas starts with (0,0) at the upper left of the canvas corner. Along the x axis the value gets increased; The y axis value gets increased towards the bottom edge of the canvas.

Canvas Co-ordinates

Let us draw a filled rectangle at x= 20, y= 20 with a width of 150 and height of 100. The main code which is resposible for drawing a filled rectangle is as below. You can see other codes which are used to draw the horizontal and vertical line and display the co-oridinates.

ctx.fillStyle='#f90';
ctx.fillRect(20,20,150,100); 

 <html>
 <head>
     <title>Text Fill and Alignment</title>   
 </head>
  <body>            
    <canvas id='canvas' width='400' height='400'>
      Canvas not supported
    </canvas>    
    <script>
        var c=document.getElementById("canvas");
        var ctx=c.getContext("2d");
     
        ctx.stokeStyle = "#000000";
        ctx.lineWidth  = 5;
        ctx.beginPath();
      
        ctx.moveTo( 0, 0);
        ctx.lineTo( 300, 0);  
        ctx.fillText("(0,0)",7, 14);  
       
        ctx.moveTo(0,0)
        ctx.lineTo( 0, 250);          
        ctx.fillText("(250,0)",270, 14);  
             
        ctx.stroke();
        ctx.closePath();  
      
        ctx.beginPath();
        ctx.fillStyle='#f90';
        ctx.fillRect(20,20,150,100); 
        ctx.closePath();  
      
        ctx.fillStyle = "#000000";
        ctx.font = 'italic 20pt Calibri';
        ctx.fillText("Filled Rectangle at 20,20",100, 200);
    </script>
  </body>
 </html>


Paths

The paths in a canvas are lines, curves etc. Defining the path in a canvas is like you are trying to draw a picture on canvas by using pencil. We can make use of moveTo() , lineTo() , bezierCurveTo() , quadraticCurveTo() functions to create a path in a canvas.

Note – The path does not get drawn unless a call to stroke method is explicitly made to draw the defined paths.

<html>
 <body>
    <canvas id="canvas" width="578" height="200"></canvas>
    <script>
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      ctx.font="20px Georgia";
      ctx.beginPath();
      ctx.fillText("(100,20)",100, 20);       
      ctx.moveTo(100, 20);
      // line 1         
      ctx.fillText("(200,160)",200, 160); 
      ctx.lineTo(200, 160);
      // quadratic curve
      ctx.fillText("(250,120)",250, 120); 
      ctx.quadraticCurveTo(230, 200, 250, 120);
      // bezier curve
      ctx.fillText("(400,150)",400, 150); 
      ctx.bezierCurveTo(290, ­40, 300, 200, 400, 150);
      // line 2
      ctx.fillText("(500,90)",500, 90); 
      ctx.lineTo(500, 90);
      ctx.lineWidth = 5;
      ctx.strokeStyle = 'orange';
      ctx.stroke();
    </script>
  </body>
</html>  


Path

Let us see the Path methods

fill() -­ The fill method is used to fill the current drawing. If a fill style is set prior to calling fill method, it will fill with the specified color.

stroke() -­ The stroke method is used to draw the path that is being defined.

beginPath() ­- The beginPath is used to begin a path, or resets the current path.

moveTo() - The moveTo function moves the path to the specified point in the canvas.

closePath() ­- The closePath function creates a path from the current point back to the starting point.

lineTo() ­ The lineTo function is used to create a line from that point to the last specified point in the canvas.

clip() ­ The clip function is used to clip a region of any shape and size from the original canvas.

quadraticCurveTo() -­ Used to create a quadratic Bézier curve.

bezierCurveTo() ­- Used to create a cubic Bezier curve.

arc() -­ Used to create an arc/curve. One can create a circle or parts of it.

arcTo() ­ Used to create an arc/curve between two tangents.

IsPointInPath() ­ This function returns true if the specified point is in the current path else it returns false.


We will be seeing more examples of drawing paths shortly. Coming next there are several example which makes use of most of the above defined functions for paths. Also there are dedicated examples for arcs and curves.


Text in Canvas


Texts can be draw on canvas. Unfortunately we can't related the text on canvas to the CSS text content with a box model. With canvas text, there are only limited capabilities like setting font, alignment etc is possible. Unlike CSS styles like floats, margins, padding, word wrapping cannot be set.


Here's how a font can be set

[font style][font weight][font size][font face]

Below are the font properties which can be applied to text on canvas.


font style - ­ normal, italic, oblique, inherit

font weight - ­ normal, bold, bolder, lighter, auto, inherit, 100, 200, 300, 400, 500, 600, 700, 800,900

font size - ­ font size can be set with a valid pixel size e.g 10px etc.

font face ­ - font face family can be arial, cursive, fantasy, monospace, verdana, serif, sans­serif etc.


Note – The default font style is set to normal unless you explicitly state the font style to reflect.

Let us learn with an example on how to set the font for our text in canvas.

<html>
   <body>
    <canvas id="canvas" width="578" height="200"></canvas>
    <script>
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      // Set font face to "sans­serif" , 30px
      ctx.font      = "40px sans­serif";
      ctx.fillStyle = "#f90";
      ctx.fillText("HTML5 Canvas", 50, 50);  
      // Set font face to Calibri with 30pt
      ctx.fillStyle = "black";
      ctx.font = 'italic 30pt Calibri';
      ctx.fillText('CodeProject', 150, 100);    
    </script>
  </body>
</html>



Now we will see how to draw a filled or outlined text on canvas. There are functions such as fillText and strokeText which can be used to create a filled or outlined text.

Note ­ The fillText if set with the fillStyle, will set the text color with the specified fill style.

fillText   (textString, x, y [,maxWidth]);

strokeText (textString, x, y [,maxWidth]);

The parameter x, y represents the location where to draw a text inside the canvas. The maxwidth is optional; if the max width is set and out text grows outside the maximum width, it will get compressed and drawn on the canvas.

Let us take a look into text alignment and see how the fillText, alignment works in real time. The text alignment in a 2D context defines how a text should be aligned horizontally when the text is drawn.

Below are the possible text alignment that one can perform.

start - ­ The text is drawn just after the x position.

left - ­ The text is drawn just after the x position, like start.

center -­ The center of the text is located a the x position.

end - ­ The end of the text is located the x position.

right - ­ The right edge of the text is located the x position, towards end.

Here's an example:

<html>
<head>
     <title>Text Fill and Alignment</title>  
</head>
  <body>           
    <canvas id='canvas' width='400' height='400'>
      Canvas not supported
    </canvas>   
    <script>
        var c=document.getElementById("canvas");
        var ctx=c.getContext("2d");    
        ctx.font      = "16px Verdana";
        ctx.fillStyle = "#000000";
        ctx.textAlign = "center";
        ctx.fillText("Learn(Text Center)", 250, 60);
        ctx.textAlign = "start";
        ctx.fillText("HTML5(Text Start)", 250, 80);
        ctx.textAlign = "end";
        ctx.fillText("CSS3(Text End)", 250, 100);
        ctx.textAlign = "left";
        ctx.fillText("In(Text Left)", 250, 120);
        ctx.textAlign = "right";
        ctx.fillStyle="#f90";
        ctx.fillText("24 Hrs(Text Right)", 250, 140);             
        ctx.strokeText("CodeProject", 250, 20);       
        ctx.closePath();
    </script>
  </body>
</html>



Now let us try to understand the text baseline property of 2D context.

The text baseline determines the y parameter of the fillText or strokeText. When the text gets placed with the baseline, the text placement will be altered according to the textBaseLine property set.

top - Specifies the text is aligned based on the top of the tallest glyph in the text.

hanging - Specifies the text is aligned based on the line the text seems to hang from. It's almost identical to top.

middle - ­ Specifies the text is aligned according to the middle of the text.

bottom - ­ Specifies the text is aligned based on bottom of the glyph in the text.

alphabetic - Specifies the bottom of vertically oriented glyphs.

ideographic ­- Specifies the bottom of horizontally oriented glyphs.

Here's the code shows all possible textBaseLine settings.

<html>
<body>
<canvas id="canvas" width="400" height="150">
   This Browser does not support the HTML5 canvas tag.
</canvas>
<script>
    var c=document.getElementById("canvas");
    var ctx=c.getContext("2d");
    ctx.stokeStyle = "#000000";
    ctx.lineWidth  = 1;
    ctx.beginPath();
    ctx.moveTo(  0, 75);
    ctx.lineTo(500, 75);
    ctx.stroke();
    ctx.closePath();
    ctx.font      = "16px Verdana";
    ctx.fillStyle = "#000000";
    ctx.textBaseline = "top";
    ctx.fillText("top", 0, 75);
    ctx.textBaseline = "hanging";
    ctx.fillText("hanging", 40, 75);
    ctx.textBaseline = "middle";
    ctx.fillText("middle", 120, 75);
    ctx.textBaseline = "alphabetic";
    ctx.fillText("alphabetic", 200, 75);
    ctx.textBaseline = "ideographic";
    ctx.fillText("ideographic", 300, 75);
    ctx.textBaseline = "bottom";
    ctx.fillText("bottom-glyph", 400, 75);
</script>  
</body>
</html> 


Gradients


Gradients are patterns of colors that one can apply to canvas graphics. With gradients you will find variations in colors across the shape with which it's being applied. You will notice the pattern of color changes gradually from one color to another. We will be leaning two types of gradients here. The linear and radial gradient.


Linear Gradient

In case of linear gradient you will notice the color difference either horizontally, vertically or diagonally. A linear gradient is created using createLinearGradient() function. This function takes 4 parameters, x1, y1, x2, y2. The gradients gets extended from x1 , y1 to x2 , y2.

Here's an example of a diagonal gradient.

In the below example you will notice a diagonal gradient is created by setting the x1 = 0, y1 = 0, x2 = canvas.width and y2 = canvas.height.

​<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var ctx = canvas.getContext('2d');

      ctx.rect(0, 0, canvas.width, canvas.height);

      // add linear gradient

      var grid = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);

      // orange

      grid.addColorStop(0, '#f90'// light orange

      grid.addColorStop(1, '#ffcc7f');

      ctx.fillStyle = grid;

      ctx.fill();

    </script>

  </body>

</html>


LinearGradient

The gradient just does not happen by itself. We need to add color stop in order to create the effect. We can call a function addColorStop with two parameters; the first parameter can take a value ranging from 0 to 1. The second parameter takes the color value.

In the above code, we have added two color stops indicating two different colors to be applied to create a gradient.

// orange

grid.addColorStop(0, '#f90'// light orange

grid.addColorStop(1, '#ffcc7f'

Note – In order to create some more gradient color variations you can add more color stops to create the same. However remember the value can range from 0 to 1.

Here's an example which creates a three color stops

var horizontalLinearGradient = context.createLinearGradient(0,0,100,0);

horizontalLinearGradient.addColorStop(0  , 'red');

horizontalLinearGradient.addColorStop(0.5, 'green');

horizontalLinearGradient.addColorStop(1  , 'blue'

The horizontal gradient only can be achieved by varying the x1 and x2 values. The y1 and y2 values will be set to 0.

Example :

var x1 =   0;

var y1 =   0;

var x2 = 200;

var y2 =   0;

var horizontalLinearGradient = context.createLinearGradient(x1, y1, x2, y2);

The vertical gradient only can be achieved by varying the y1 and y2 values. The x1 and x2 values will be set to 0.

var x1 =   0;

var y1 =   0;

var x2 =   0;

var y2 = 200;

var verticalLinearGradient = context.createLinearGradient(x1, y1, x2, y2);


Radial Gradient


With radial gradient, the change in the gradient color happens in a circular pattern. The color gets changed from inside and out.

The radial gradients can be created by using the below mentioned function.

createRadialGradient(x1, y1, r1, x2, y2, r2);

In order to create a radial gradient we need to define two circles. x1, y1 are points defined for the first circle with radius r1. Similarly x2, y2 are points defined for second circle with radius r2.

Here's an example of a radial gradient. You can notice there are two color stops added one with orange and the other one red. The first color stop has the first parameter as 0; which means that the color will start where the first circle starts and the second color stop has the first parameter as 1; which means that the color will start where the second circle starts.

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="canvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('canvas');

      var ctx = canvas.getContext('2d');

      ctx.rect(0, 0, canvas.width, canvas.height);

    
      var x1 = 120;  

      var y1 = 100;  

      var r1 = 30;  


      var x2 = 120;  

      var y2 = 100; 

      var r2 = 100;  

    
      var radialGradient = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);

      radialGradient.addColorStop(0, 'orange');

      radialGradient.addColorStop(1, 'red');

      ctx.fillStyle = radialGradient;

      ctx.fillRect(20,20, 200, 200</script>

  </body>

</html>


RadialGradient

Images on canvas


We will learn how to draw images in canvas. Images can be drawn with the help of a 2D context function named drawImage(). It takes two parameters, the image object and the horizontal (x) and vertical (y) positions where you want the image to be drawn.

In order to draw an image, first we will create an image and wait for it to load until we make a call to drawImage. You will see in this example how to accomplish this.

Here's an example for drawing an image in canvas.

<html>

  <body>

    <canvas id="myCanvas" width="578" height="400"></canvas>

    <script>     

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');

      var imageObj = new Image();


      imageObj.onload = function() {

        context.drawImage(imageObj, 100, 50);

      };     

      imageObj.src = 'http://s.codeproject.com/App_Themes/CodeProject/Img/logo250x135.gif'; 
   </script>

  </body>

</html>


Canvas-Image
Image Pattern in canvas


We can create patterns and use them as a fill style while drawing shapes in canvas. The patterns can be created by making a call to createPattern function. It takes two parameters, an image object and the repeat option as second parameter. The repeat option can be set with one of these values ­ repeat, repeat­x, repeat­y, or no­repeat.

Let us take a look into an example and try to understand how to apply bob image as a pattern.
Note – In order to draw a bob image for our example, I have extracted the bob image from the CodeProject Logo and used an online tool to get base64 encoded image.

In this example, the image object source (src) is set in javascript. We are using repeat as a second parameter which indicates a repeat pattern.

<html>

  <head>

    <style>

      body {

        margin: 0px;

        padding: 0px;

      }

    </style>

  </head>

  <body>

    <canvas id="myCanvas" width="578" height="300"></canvas>

    <script>

      var canvas = document.getElementById('myCanvas');

      var context = canvas.getContext('2d');


      var imageObj = new Image();

      imageObj.onload = function() {

        var pattern = context.createPattern(imageObj, 'repeat');


        context.rect(0, 0, canvas.width, canvas.height);

        context.fillStyle = pattern;

        context.fill();

      };     

  </script>

  </body>

</html>


Canvas-ImagePattern

Drawing onto a canvas with Javascript

Let us learn into how to draw shapes in canvas.


Draw rectangle

The rect() method is used to create a rectangle in HTML5 canvas. Here's an example which create a simple rectangle.

The below example creates a rectangle with 100, 45, 250, 100 (x­coordinate, y­coordinate, width, height). Later we will see how to fill a rectangle with color. Calling stroke method creates an outline around the rectangle.

<html>

  <body>

    <canvas id="canvas" width="600" height="200"></canvas>

    <script>

      var canvas = document.getElementById(canvas'
      var context = canvas.getContext('2d');

      context.beginPath();

      context.rect(100, 45, 250, 100);

      context.fillStyle = 'orange';

      context.fill();

      // stroke with black border

      context.strokeStyle = 'black';

      context.stroke();

      context.closePath();

    </script>

  </body>

</html>


Canvas-Rectangle
Draw Arc

The arc method is used to create circle, semi circle etc. Here's the syntax to draw an arc.

arc(x, y, radius, startAngle, endAngle, anticlockwise)

<html>

  <body>

    <canvas id="canvas" width="578" height="200"></canvas>

    <script>

      var canvas = document.getElementById('canvas');

      var context = canvas.getContext('2d');

      var X = 250;

      var Y = canvas.height / 2;

      var radius = 50;

      context.beginPath();     

      context.arc(X, Y, radius, 0, 2 * Math.PI, false);    

      context.fillStyle = 'orange';

      context.fill();

      context.lineWidth = 2;

      context.strokeStyle = 'black';

      context.stroke();

      context.closePath();     

      context.beginPath();

      context.fillStyle = 'red';

      context.arc(80, 75, 70, 0, Math.PI, true);

      context.fill();

      context.closePath();     

    </script>

  </body>

</html>


Canvas-Arc
Draw Line

Let us see how to draw lines with in the canvas. lineTo(x, y) is used to draw the line from the current position to the position specified by x, y.

Here's the below code sample builds triangles by making use of lineTo and moveTo functions.

<html>

  <body>

  <canvas id="canvas" width="578" height="200"></canvas>

  <script>

    var canvas = document.getElementById('canvas');

    if (canvas.getContext){

    var ctx = canvas.getContext('2d');

    // Filled triangles     

    ctx.beginPath();

    ctx.moveTo(25,25);

    ctx.lineTo(105,25);

    ctx.lineTo(25,105);

    ctx.fillStyle = 'red';

    ctx.fill();

    ctx.beginPath();

    ctx.moveTo(105,25);

    ctx.lineTo(105,105);

    ctx.lineTo(25,105);

    ctx.closePath();

    ctx.fillStyle = 'orange';

    ctx.fill();

  }     

    </script>

  </body>

</html>


Canvas-Line

Draw custom shapes

The custom shapes can be draw by using the combination of the above mentioned methods. But we will be learning some more functions like bezierCurveTo() , quadraticCurveTo() with an example. The bezier curve requires three points. The first two points are control points that are used in the bezier curve calculation; The last point represents the end points of the curve.


cp1x ­ - The x­coordinate of the first Bezier control point.

cp1y ­ - The y­coordinate of the first Bezier control point.

cp2x ­ - The x­coordinate of the second Bezier control point.

cp2y ­ - The y­coordinate of the second Bezier control point.

x ­- The x­coordinate of the ending point.

y ­- The y­coordinate of the ending point.

The quadraticCurveTo() function requires two points. The first point represents the control point used by for the calculation of the quadratic curve. The last points represents the endpoints of the curve.


Canvas-CustomShapes

Transformation in Canvas


Now let us learn some of the transformation functions such as translate(), rotate() and scale() that can be applied for graphics with in the canvas.


Translate

translate method is used to perform translation in canvas. This method is used to move the canvas from it's origin to a different point in the grid.

The translate function takes two parameters the x and y value and it moves the canvas from it's origin to a new position as specified in the x and y parameters.

Note ­ x indicates the horizontal distance to move and y indicates how far to move the grid vertically.

Here's how the translate function is defined.

translate(x, y)

Let us see with an example how the translation works

<html>

<head>
     <title>Translate Demo</title>  
</head>

  <body>

    <canvas id='canvas' width='400' height='400'>
            Canvas not supported
    </canvas>   

    <script>

       var c=document.getElementById("canvas");

       var ctx=c.getContext("2d");

       ctx.fillStyle='orange';

       ctx.fillRect(20,20,150,100); 

       ctx.translate(200,100);

       ctx.fillStyle='red';

       ctx.fillRect(20,20,150,100</script>

  </body>

</html>


Canvas-Translate

Rotate


Let us learn how to rotate a graphics in canvas. The rotate(angle) function is used to rotate the canvas with the specified angle.

Note ­ The rotation center point is always the canvas origin. If you want to change the center point, then you need to apply translate and then rotate.

Let us take a look into an example to see how the rotation works.

1. We draw the first filled rectangle at x = 20, y = 20 with width = 150 and height = 100.

2. Translate the canvas by x = 400, y = 200

3. Rotate the canvas by an angle 40 degrees.

4. Fill rectangle with x = 20, y = 30, width = 100 and height = 100

5. Draw text at x = 150, y = 100, You can notice the text has be rotated.

<html>

<head>

     <title>Rotate Demo</title>  

</head>

  <body>   

    <canvas id='canvas' width='400' height='400'>

      Canvas not supported

    </canvas>   

    <script>

       var c=document.getElementById("canvas");

       var ctx=c.getContext("2d");

       ctx.fillStyle='orange';

       ctx.fillRect(20,20,150,100);

       ctx.translate(400,100);

       ctx.rotate(40);     

       ctx.fillStyle='red';

       ctx.fillRect(20,30,100,100); 

       ctx.fillStyle = '#f90';

       ctx.font = 'italic 30pt Calibri';

       ctx.fillText('CodeProject', 150, 100);   

   </script>

  </body>

</html>


Canvas-Rotate

Scale

Let us learn how we can scale a canvas; either increase or decrease the canvas size. Scale(x, y) – Scale function is used to scale the canvas. It takes two parameters, x and y. The 'x' value represents the units that needs to be scaled horizontally and the 'y' value is used to scaled vertically.

Note – The scale values must be real numbers. The negative values reduce the unit size and positive values increase the unit size. Values of 1.0 leave the units the same size.

Here's an example for scaling.

<html>

<head>
     <title>Scaling Demo</title>  
</head>

  <body>   

    <canvas id='canvas' width='400' height='400'>

      Canvas not supported

    </canvas>   

    <script>

      var c=document.getElementById("canvas");

      var ctx=c.getContext("2d");

      ctx.fillStyle='orange';

      ctx.fillRect(20,20,150,100); 

      ctx.scale(2,2);

      ctx.fillRect(100,10,150,100</script>

  </body>

</html>


Canvas-Scale

Animation in Canvas


Now we will learn how to do some basic animations in canvas. Animations in canvas can be done by drawing shapes and redrawing them over and over with an interval of time to redraw the frames to create an effect and that's how you can see animations. Let us take a took into some basic functions used for animations.


setInterval() -­ The setInterval function is used to perform a timed loop in javascript. We use this function to create animations by redrawing the frames with a specific interval of time. The setInterval method calls a function or it does some expression evaluation at a specified interval of time.

Here's the syntax:

var intervalId = window.setInterval(expression, msec, lang);

The expression is nothing but a code or a function containing javascript logic to be executed at an interval specified in 'msec'.

The lang or language parameter is optional and can be either of the below mentioned values.

Jscript ­ Language is JScript.

javascript ­ Script is JavaScript.

XML ­ Script is XML.

Here's a real world example for setInterval. The DisplayTimer function in this example gets called for every 1000 milli seconds.

​var intervalId = setInterval(function(){DisplayTimer()},1000);

function DisplayTimer()
{

      var date = new Date();

      var time = date.toLocaleTimeString();

      document.getElementById("div").innerHTML=time;
}


clearInterval() – The clearInterval function is used to stop the setInterval callback. It takes a single parameter which is the setInterval Id.

Here's the syntax:

clearInterval(id_of_setinterval)

Example:

​var intervalId = setInterval(function(){DisplayTimer()},1000// Creates a timed loop.

clearInterval(intervalId); // Clears of stops the timed loop.


setTimeout() – The setTimeout function is used to call a function or a code after the specified delay. This function is similar to setInterval , takes two required parameters code and delay. The third parameter lang or language is optional. In Summary, the setTimeout function evaluates a function/code after a specified number of milliseconds has elapsed.

Here's the syntax:

setTimeout(function,milliseconds,lang)

You might ask what is the difference between the setInterval and setTimeout function. Here it is.
The setTimeout and setInterval invoke functions after a delay. The setInterval repeats the invocation periodically, as far as possible. setInterval causes the invocation irrespective of the function it called has broken because of errors. The setTimeout does a periodically invocation but if the program aborts, before the next setTimeout call is reached no additional invocations takes place.

The other difference is although when we specify a delay for the setTimeout, the function won't be called exactly at the specified delay. The setTimeout ensures to call the function only when the previous call to the function has successfully completed it's execution.

Consider an example where you have function with a code to refresh data for every X milliseconds. Say if there's a delay (D milliseconds) because of network slowdown, it might take some time to complete the call and the next time the function is supposed to be called is X + D milliseconds. This is what happens with setTimeout but not with setInterval, as the function will be called exactly at X milliseconds.

In summary if you don't care about the callback has completed or not then you can make use of setInterval or else use setTimeout when you want to make sure the callback has completed get execution and in addition to that, if the function completes successfully (meaning no errors or exceptions) then the further callback happens with setTimeout.

Now comes the interesting part. For animation we will make use of a special function named requestAnimationFrame.

Below are advantages as explained by Paul, the creator of requestAnimationFrame function.

• The browser can optimize the callback, so animations will be smoother.

• Animations in inactive tabs will stop, allowing the CPU to chill.

• More battery­friendly.

Just like the setInterval and setTimeout, the requestAnimationFrame also returns an Id which can be used for stop callback. The requestAnimationFrame is much better than setInteval or setTimeout function as it makes a callback to render new frames at a higher rate. Note – The target is to render 60 frames per second to create smooth animation.

Here's how we use requestAnimationFrame. Note the fallback mechanism which makes use of setTimeout.

window.requestAnimationFrame =    window.requestAnimationFrame

                                   || window.webkitRequestAnimationFrame

                                   || window.msRequestAnimationFrame

                                   || window.amozRequestAnimationFrame

                                   || (function (func){setTimeout(func, 16.666);});

window.requestAnimationFrame(func);

Let us see with a simple example to create animation. In this example, we use a bob image and create a animation by moving the periodically from left to right and then right to left.

Here's the HTML code

​<html>

  <body>

    <canvas id="canvas" width="578" height="400"></canvas>

  </body>

</html>

How are we creating animation ?

All we need is a bob image and a canvas to render the animation. So here's what we do. We are making a call to animate bob with the help of a function AnimateBob(). Here's what happens inside the animate bob function.

1. We are making use of requestAnimationFrame to update frames to redraw by making a call to Animate bob function.

2. Increase the horizontal x values by the speed value. if the x value is <= 0 or >= 400 then default the speed value.

3. Make a call to draw function to draw our Bob image object in canvas.

Below is the javascript code to create animation.

var x =  0;
var y = 25;
var speed = 5;

var canvas  = document.getElementById("canvas");
var context = canvas.getContext("2d");

function AnimateBob() {

  reqAnimFrame = window.mozRequestAnimationFrame    ||

                 window.webkitRequestAnimationFrame ||

                 window.msRequestAnimationFrame  ||

                 window.oRequestAnimationFrame ||

                 (function (func){setTimeout(func, 16.666);});

    reqAnimFrame(AnimateBob);

    x = x + speed;

    if(x <= 0|| x >= 400){

        speed = ­-speed;

    }

    draw();
}

function draw() {

    var imageObj = new Image();

    setBobImage(imageObj);   

    // Clear canvas and re­draw
    context.clearRect(0, 0, canvas.width, canvas.height);

    context.drawImage(imageObj, x, y);   
}

AnimateBob();


Canvas-Bob-Animation

Canvas examples

1. Bob Clock

Let us take a look into our first sample on Bob Clock. This example is all about drawing a clock. We will get started with defined the canvas.

<html>
<head>
    <title>Clock Demo</title>
</head>
<body>
     <img id='ImageElement'/>
     <canvas id='canvas' width='400' height='400'>
         Canvas not supported
     </canvas>
</body>
</html>

First let us define some of the variables required for drawing clock.

var canvas = document.getElementById('canvas'),

context = canvas.getContext('2d'),

ImageElement = document.getElementById('ImageElement'),

bobImage = document.getElementById("bob"),

FONT_HEIGHT = 25,

MARGIN = 35,

HAND_TRUNCATION = canvas.width/25,

HOUR_HAND_TRUNCATION = canvas.width/10,

NUMERAL_SPACING = 20,

RADIUS = canvas.width/2 - MARGIN,

HAND_RADIUS = RADIUS + NUMERAL_SPACING,

loop;

img = document.createElement("img");

In order to draw a clock , we need to draw circle, hands, numbers and then update the clock image. Every time when we are drawing a clock, we need to clear and redraw the clock.

function drawClock() {
   context.clearRect(0,0,canvas.width,canvas.height);
  
   context.save();
       
   context.fillStyle = 'white';
   context.fillRect(0, 0, canvas.width, canvas.height);

   drawCircle();
   drawCenter();
   drawHands();

   context.restore();

   drawNumerals();

   updateClockImage();
}

Let us draw clock circle.

We draw an arc, which creates a circle. Then we apply fill style with a slate color and fill the circle. You will notice another arc, which is also a circle with radius 150. We apply a orange fill style (#f90). The last line of the drawCircle function draws the bob image exactly at the center of the clock.

function drawCircle() { 
   context.beginPath();
   context.arc(canvas.width/2, canvas.height/2, RADIUS, 0, Math.PI*2, true);
   context.fillStyle='#323232';
   context.fill();
   context.closePath();
  
   context.beginPath();
   context.arc(canvas.width/2, canvas.height/2, 150, 0, Math.PI*2, true);
   context.fillStyle='#f90';
   context.fill();
   context.closePath();     
   context.drawImage(img,150,140);
}

Now let us see how to draw clock hands. The below function is dedicated in drawing the hour, minute and second hands. We take the current date and draw all the required hands for our clock.

You will notice the hands are drawn by using the moveTo and lineTo functions and then in the end apply stroke to create the outline.

function drawHand(loc, isHour) {
   var angle = (Math.PI*2) * (loc/60) - Math.PI/2,
       handRadius = isHour ? RADIUS-HAND_TRUNCATION-HOUR_HAND_TRUNCATION 
                           : RADIUS-HAND_TRUNCATION;

   context.moveTo(canvas.width/2, canvas.height/2);
   context.lineTo(canvas.width/2  + Math.cos(angle)*handRadius, 
                  canvas.height/2 + Math.sin(angle)*handRadius);
   context.stroke();
}

function drawHands() {
   var date = new Date,
       hour = date.getHours();
   hour = hour > 12 ? hour - 12 : hour;
   drawHand(hour*5 + (date.getMinutes()/60)*5, true, 0.5);
   drawHand(date.getMinutes(), false, 0.5);
   drawHand(date.getSeconds(), false, 0.2);
}

Now let us see how to draw numbers inside the clock. The below function drawNumerals does out work. We are defining an array of numbers to be drawn i.e 1 to 12. Then we loop through each number and draw inside the clock with the help of fillText method, passing the location where to draw.

function drawNumerals() {
   var numerals = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],
       angle = 0,
       numeralWidth = 0;

   numerals.forEach(function(numeral) {
      angle = Math.PI/6 * (numeral-3);
      numeralWidth = context.measureText(numeral).width;
      context.fillText(numeral, 
         canvas.width/2   + Math.cos(angle)*(HAND_RADIUS - 50) - numeralWidth/2,
         canvas.height/2 + Math.sin(angle)*(HAND_RADIUS - 50) + FONT_HEIGHT/3);
   });
}

In the end we are making a call to update the clock image. We are rendering the canvas content to a image element.

function updateClockImage() {
   dataUrl = canvas.toDataURL();
   ImageElement.src = dataUrl;
}

The last but not the least very important thing that we need to do is to call setInterval with an interval to update clock. We are redrawing the clock with a 1000 milliseconds = 1 second interval.

loop = setInterval(drawClock, 1000);

Here's how the clock will look like.

Try it out

Clock

2. Particle Emitter

Now let us take a look into how to implement a particle emitter in canvas.

Let us define a canvas.

<html>
<head>
    <title>Particle Emitter</title>  
</head>

<body style="background-color:#000000">
    <canvas id="canvas" width="500" height="500"/>
</body>
</html>

Now we will define the javascript variables and get the 2D canvas context.

var points = [], numPoints = 50, i, canvas, context, width, height, gravity = 0.1, emitter;

canvas = document.getElementById('canvas');
width = canvas.width;
height = canvas.height;
context = canvas.getContext("2d");
emitter = {x:width / 2, y:height};

We will make use of setInterval with an interval 800/24 milliseconds to add points and update the canvas.

setInterval(function() {
        addPoint();
        update();
        draw();
    }, 800/24);

In order to make the particle emitter to be emit with different colors, we will be using a random color generator. When ever we make a call to randomColor function, it will return a random color (RGB).

 function randomColor() {
        var r, g, b;
        r = Math.floor(Math.random() * 255);
        g = Math.floor(Math.random() * 255);
        b = Math.floor(Math.random() * 255);
        return "rgb(" + r + "," + g + "," + b + ")";
    }

The key things about the particle emitter is defining the points and then drawing the points with arc and fill the context with the point color. Let us take a look into how to initialize points for our particle emitter program.

 function initPoint(p) {
        p.x = emitter.x;
        p.y = emitter.y;
        p.vx = Math.random() * 4 - 2;
        p.vy = Math.random() * -5 - 4;
        p.radius = Math.random() * 5 + 1;
        p.color = randomColor();
    }

Now we will see how to add and update points. We are creating a new point, initializing the same and hold the points in a points array.

function addPoint() {
        var point;
        if(points.length < numPoints) {
            point = {};
            initPoint(point);
            points.push(point);
        }
    }

Here's the particle points update function. You can notice below, we are updating the particle x and y values.

function update() {
        var i, point, len = points.length;
        for(i = 0; i < len; i += 1) {
            point = points[i];
            point.vy += gravity;
            point.x += point.vx;
            point.y += point.vy;
            if(point.x > width ||
               point.x < 0 ||
               point.y > height ||
               point.y < 0) {
                initPoint(point);
            }
        }
    }

Now we will see how to draw the particles in canvas. We are looping through the points array and then we are drawing a filled arc. The arc start angle is defined as 0 and the end angle when we are specifying as twice the PI value, draws a circle with the points radius.

 function draw() {
        var i, point, len = points.length;
        context.fillStyle = "rgba(0,0,0,0.05)";
        context.fillRect(0, 0, width, height);
        for(i = 0; i < len; i += 1) {
            point = points[i];
            context.fillStyle = point.color;
            context.beginPath();
            context.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);
            context.fill();
        }
    }

Here's how it looks like.

Paticle Emitter

Points of Interest

I had never thought we could do some brilliant and extraordinary things in canvas. Sure there is a great future with canvas based animations, games etc and it would replace third party vendors like Adobe Flash. I'm just amazed about the wonderful capabilities of a canvas.

History

Version 1.0 - Initial Creation of Coding Canvas Article - 04/23/2014.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ranjan.D
Web Developer
United States United States
Profile

Around 10 years of professional software development experience in analysis, design, development, testing and implementation of enterprise web applications for healthcare domain with good exposure to object-oriented design, software architectures, design patterns, test-driven development and agile practices.

In Brief

Analyse and create High Level , Detailed Design documents.
Use UML Modelling and create Use Cases , Class Diagram , Component Model , Deployment Diagram, Sequence Diagram in HLD.

Area of Working : Dedicated to Microsoft .NET Technologies
Experience with : C# , J2EE , J2ME, Windows Phone 8, Windows Store App
Proficient in: C# , XML , XHTML, XML, HTML5, Javascript, Jquery, CSS, SQL, LINQ, EF

Software Development

Database: Microsoft SQL Server, FoxPro
Development Frameworks: Microsoft .NET 1.1, 2.0, 3.5, 4.5
UI: Windows Forms, Windows Presentation Foundation, ASP.NET Web Forms and ASP.NET MVC3, MVC4
Coding: WinForm , Web Development, Windows Phone, WinRT Programming, WCF, WebAPI

Healthcare Domain Experience

CCD, CCR, QRDA, HIE, HL7 V3, Healthcare Interoperability

Education

B.E (Computer Science)

CodeProject Contest So Far:

1. Windows Azure Developer Contest - HealthReunion - A Windows Azure based healthcare product , link - http://www.codeproject.com/Articles/582535/HealthReunion-A-Windows-Azure-based-healthcare-pro

2. DnB Developer Contest - DNB Business Lookup and Analytics , link - http://www.codeproject.com/Articles/618344/DNB-Business-Lookup-and-Analytics

3. Intel Ultrabook Contest - Journey from development, code signing to publishing my App to Intel AppUp , link - http://www.codeproject.com/Articles/517482/Journey-from-development-code-signing-to-publishin

4. Intel App Innovation Contest 2013 - eHealthCare

5. Grand Prize Winner of CodeProject HTML5 &CSS3 Article Contest 2014

6. Grand Prize Winner of CodeProject Android Article Contest 2014

7. Grand Prize Winner of IOT on Azure Contest 2015

Comments and Discussions

 
QuestionExellent Pin
Member 1004637428-Apr-14 12:42
memberMember 1004637428-Apr-14 12:42 
AnswerRe: Exellent Pin
Ranjan.D28-Apr-14 15:51
mvpRanjan.D28-Apr-14 15:51 
GeneralMy vote of 5 Pin
Guruprasad.K.Basavaraju25-Apr-14 15:57
memberGuruprasad.K.Basavaraju25-Apr-14 15:57 
GeneralRe: My vote of 5 Pin
Ranjan.D25-Apr-14 16:22
mvpRanjan.D25-Apr-14 16:22 
GeneralMy Vote 5 Pin
ambilykk25-Apr-14 0:24
memberambilykk25-Apr-14 0:24 
GeneralRe: My Vote 5 Pin
Ranjan.D25-Apr-14 1:25
mvpRanjan.D25-Apr-14 1:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150428.2 | Last Updated 25 Apr 2014
Article Copyright 2014 by Ranjan.D
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid