Day 1: HTML5 Animation using Canvas

HTML 5 Animations Day 1 Animation using Canvas

Over the next 5 days we’re going to cover many different ways to use HTML5 to generate animations. You will find that HTML5 animation is really reliant on either CSS3 or JavaScript and so a large part of these tutorials will be covering JavaScript and popular JavaScript libraries as well as CSS3 animations.

Day 1: HTML5 Animation using Canvas
One of the biggest changes in HTML5 is the ability to draw on the screen using canvas. Canvas is an html tag similar to div and table. Unlike its predecessors, Canvas contents are rendered with JavaScript. In order to use the Canvas, you’ll need to place the canvas tag somewhere inside your HTML.

  1.   <canvas id="myCanvas" width="600" height="400"></canvas>

Lets start by just simply drawing a circle using Canvas and JavaScript. You can see the sample here

  1. <!DOCTYPE HTML>
  2. <html>
  3.   <head>
  4.     <style>
  5.       body {
  6.         margin: 0px;
  7.         padding: 0px;
  8.       }
  9.       #myCanvas {
  10.         border: 1px solid #000000;
  11.       }
  12.     </style>
  13.     <script>
  14.  
  15.   // declare vars here so they can be accessed globally
  16.      //get context of canvas
  17.      var canvas;
  18.                   var context;
  19.      
  20.      // set circle vars
  21.                var centerX;
  22.                  var centerY;
  23.                   var radius;
  24.  
  25.       window.onload = function() {
  26.         init()
  27.       };
  28.    
  29.    function init() {
  30.     //get element by id
  31.     canvas = document.getElementById("myCanvas");
  32.     // context is like the graphics api for canvas
  33.                    context = canvas.getContext("2d");
  34.      
  35.      // set circle vars
  36.                centerX = canvas.width / 2;
  37.                 centerY = canvas.height / 2;
  38.                 radius = 20;
  39.  
  40.              drawCircle()
  41.  
  42.    }
  43.    
  44.    function drawCircle() {
  45.    // console.log("drawCircle")
  46.   context.beginPath();
  47.                context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
  48.                context.fillStyle = "#FF0099";
  49.                context.fill();
  50.                context.lineWidth = .5;
  51.                 context.strokeStyle = "black";
  52.                 context.stroke();
  53.    }
  54.  
  55.     </script>
  56.   </head>
  57.   <body>
  58.     <canvas id="myCanvas" width="600" height="400"></canvas>
  59.   </body>
  60. </html>

After we have created a canvas tagLine 61 and set the property id to “myCanvas”, its time to write some JavaScript inside our script tags.

The first thing we want to do is set up our variables. Online 17 we declare the canvas variable and on line 18 we declare the context (think of this as the graphics engine).

It is important that we don’t run any JavaScript functions until the page is loaded. So on line 25 we call an init() function when the page loads.

  1.   window.onload = function() {
  2.         init()
  3.       };

Online 30 , inside the init() function we set our variables.
line 33 here we access the dom by its label “myCanvas” that we declare on line 61 . Once we have the dom we can access the graphics api by using the getContext(“2d”) method.

Also inside the init we call a function to drawCircle() which starts on line 44

Inside the drawCircle() function on line 47 we use the context to draw an arc. The properties of the arc are starting x, starting y, the circles radius, the start angle , end angle and whether or not to go clockwise.

  1. context.arc(x, y, radius, startAngle, endAngle, anticlockwise)

Fig1
If you preview the HTML code above you will see a magenta Circle in the middle of the canvas.

Making the Ball Move Using JavaScript

In HTML5 using canvas we wont move the same object across the stage like Flash but rather we are actually going to redraw the canvas repeatedly clearing our canvas in between redrawing our circle but moving it slightly each time. This will give the illusion of the object moving.

Let’s take a look at the code. You can see the example here.

  1. <!DOCTYPE HTML>
  2. <html>
  3.   <head>
  4.     <style>
  5.       body {
  6.         margin: 0px;
  7.         padding: 0px;
  8.       }
  9.       #myCanvas {
  10.         border: 1px solid #000000;
  11.       }
  12.     </style>
  13.     <script>
  14.  
  15.   // declare vars here so they can be accessed globally
  16.      //get context of canvas
  17.      var canvas;
  18.            var context;
  19.      
  20.      // set circle vars
  21.          var cx;
  22.            var cy;
  23.            var cr;
  24.      
  25.      // set direction & speed vars
  26.      var dx;
  27.      var dy;
  28.      
  29.      // set scene size
  30.      var canvasWidth;
  31.      var canvasHeight;
  32.  
  33.       window.onload = function() {
  34.    
  35.         init()
  36.       };
  37.    
  38.    function init() {
  39.    
  40.     //get element by id
  41.     canvas = document.getElementById("myCanvas");
  42.     // context is like the graphics api in flash
  43.           context = canvas.getContext("2d");
  44.    
  45.     // set h/w
  46.     canvasWidth = canvas.width;
  47.     canvasHeight = canvas.height;
  48.      
  49.      // set circle vars
  50.         cx = canvasWidth / 2;
  51.           cy = 0;
  52.           cr = 10;
  53.    
  54.     // set dirction and vel
  55.     dx = 1;
  56.     dy = 1;
  57.    
  58.    return setInterval(renderScene, 10)
  59.  
  60.    }
  61.    
  62.    function clearScene() {
  63.     context.clearRect(0,0,canvasWidth, canvasHeight)
  64.    }
  65.    
  66.    function renderScene() {
  67.     clearScene();
  68.     drawCircle(cx, cy, cr)
  69.    
  70.     if(cy + dy > canvasHeight) {
  71.      console.log("hit bottom")
  72.      cy = 0;
  73.     }
  74.    
  75.     cy += dy;
  76.    }
  77.    
  78.    function drawCircle(cx, cy, cr) {
  79.    // console.log("drawCircle")
  80.   context.beginPath();
  81.         context.arc(cx, cy, cr, 0, 2 * Math.PI, false);
  82.         context.fillStyle = "#FF0099";
  83.         context.fill();
  84.         context.lineWidth = .5;
  85.         context.strokeStyle = "black";
  86.         context.stroke();
  87.    }
  88.  
  89.     </script>
  90.   </head>
  91.   <body>
  92.     <canvas id="myCanvas" width="600" height="400"></canvas>
  93.   </body>
  94. </html>

as you can see we’ve created a few extra variables in the script, notably cx, cy, cr, dx and dy

I’m simply using cx, cy and cr to hold the positions of the circle and its radius. dx and dy will represent direction, speed or movement, however you want to think of it. We will increase the current position of the circle after each time its drawn, clearing the canvas in between renderings.

The biggest difference in the init() function is the addition of the setInterval() function. Here we call renderScene() every 10th of a second.

renderScene() is where we draw our art. Think of it as a graphics rendering function. It will clear the scene, render the scene and repeat as long as its called.

renderScene() also contains some logic to stop the “movement” when the ball “hits” a certain spot.

When you run the code above in your browser you will see a magenta ball falling to the bottom of the canvas area, then it will start at the top again.

Thats pretty cool, but what about multiple objects moving independently? Well, thats where things get a bit more complicated but still fairly easy to accomplish.

Object Oriented JavaScript Animation

We’re going to need to create a class or a blueprint for multiple objects where we can store individual properties for each object and use prototyping to attach public methods to them. Basically we’re going to need to use Object Oriented Programming in Javascript to accomplish this. I’m not going to get into OOP in this tutorial but will explain briefly what I’m doing below

Lets take a look at the code below. You can see the sample here.

  1.    <!DOCTYPE HTML>
  2. <html>
  3.   <head>
  4.     <style>
  5.       body {
  6.         margin: 0px;
  7.         padding: 0px;
  8.       }
  9.       #myCanvas {
  10.         border: 1px solid #000000;
  11.       }
  12.     </style>
  13.     <script>
  14.  
  15.   // declare vars here so they can be accessed globally
  16.      //get context of canvas
  17.      var canvas;
  18.            var context;
  19.      // make an array to hold the circles
  20.      var circles;
  21.      // canvas size
  22.      var canvasWidth;
  23.      var canvasHeight;
  24.      // num of circles you want
  25.      var numCircles;
  26.      
  27.      // circle position and radius
  28.      var cx;
  29.      var cy;
  30.      var cr;
  31.      
  32.      // circle trig properties
  33.      var dx;
  34.      var dy;
  35.      var speed;
  36.  
  37.       window.onload = function() {
  38.    
  39.         init();
  40.       };
  41.    
  42.    function init() {
  43.     console.log("init")
  44.     //get element by id
  45.     canvas = document.getElementById("myCanvas");
  46.     // context is like the graphics api in flash
  47.                  context = canvas.getContext("2d");
  48.    
  49.     canvasWidth = canvas.width;
  50.     canvasHeight = canvas.height;
  51.    
  52.     numCircles = 5;
  53.    
  54.     speed = 1;
  55.     dx = speed;
  56.     dy = speed;
  57.    
  58.     cx = Math.round(Math.random() * canvasWidth);
  59.     cy = 0;
  60.     cr = 10;
  61.    
  62.    
  63.     // set array
  64.     circles = new Array();
  65.    
  66.     drawCircles();
  67.  
  68.    }
  69.    
  70.    function Circle(context, radius, speed, width, xPos, yPos) {
  71.    this.context = context;
  72.    this.radius = radius;
  73.    this.speed = speed;
  74.    this.width = width;
  75.    this.xpos = xPos;
  76.    this.ypos = yPos;
  77.    
  78.    //speed
  79.    this.dx = 0;
  80.    this.dy = 1;
  81.    
  82.    }
  83.    
  84.    // takes the place of rendering the stage
  85.    Circle.prototype.update = function() {
  86.      
  87.    this.dy += 1;
  88.    this.ypos += this.dy;
  89.    if (this.dy > 5) {
  90.     console.log('max accel')
  91.     this.dy = 5;
  92.    }
  93.    
  94.    if (this.ypos > canvasHeight) {
  95.     this.ypos = 0;
  96.    }
  97.    
  98.  
  99.    this.context.beginPath();
  100.    this.context.arc(this.xpos, this.ypos, this.radius, 0, 2 * Math.PI, false);
  101.    this.context.closePath();
  102.    
  103.     this.context.fillStyle = "#FF0099";
  104.                   this.context.fill();
  105.                   this.context.lineWidth = .5;
  106.                   this.context.strokeStyle = "black";
  107.                   this.context.stroke();
  108.    
  109.    }
  110.    
  111.    function clearScene() {
  112.     context.clearRect(0,0,canvasWidth, canvasHeight)
  113.    }
  114.    
  115.    function renderCanvas() {
  116.     // clear last scene
  117.     clearScene();
  118.     // access each circle and fire method update
  119.     for (var i = 0; i < circles.length; i++) {
  120.      var currentCircle = circles[i];
  121.      currentCircle.update();
  122.     }
  123.    }
  124.    
  125.    function drawCircles() {
  126.     for (var i = 0; i < numCircles; i++) {
  127.               var randyX = Math.round(Math.random() * canvasWidth);
  128.             var randyY = Math.round(Math.random() * canvasHeight);
  129.        var circle = new Circle(context, cr, speed, 20, randyX, randyY); //context, radius, speed, size, xPos, yPos
  130.        circles.push(circle);
  131.    
  132.     }
  133.     //trace teh array
  134.     console.log(circles);
  135.     //set up timer to fire functino
  136.    setInterval(renderCanvas, 50);
  137.    
  138.    }
  139.  
  140.     </script>
  141.   </head>
  142.   <body>
  143.     <canvas id="myCanvas" width="600" height="400"></canvas>
  144.   </body>
  145. </html>

Fig1
If we run this code in the browser you’ll see many circles being generated all around the canvas, and then they are animated independently of each other and reset their position when they hit the bottom of the canvas area.

Lets take a look at the code. The first thing you’ll notice in the code is we’ve changed some variables. We removed cx, cy, dx and dy because those properties will be local to the individual circles now.

We’ve added numCircles, the amount of circles you would like to animate, speed, and circles, an array to hold all the circles.

our init() function is similar but now we are populating numCircles, speed and the circle radius (cr). We’ll call a function to draw the circles drawCircles() on line 66.

The drawCircles() function is where we start to see some OOP. Here we’re going to create a new class called Circle and pass it parameters. The params are notably a random x number based on the width of the stage and a random y number based on the height of the stage. In Javascript you create objects by using functions. On line 70 you see function Circle(). This acts as a Constructor. We take the params we pass and make them into public properties on lines 71-80 we set the velocity in the y direction. Finally (back in the drawCircles() function) on line 130 we push the instance of circle into the circles array. The last thing we do in the drawCircles() function is on Line 136 we use setInterval to fire off the renderCanvas function just like we did in the previous animation.

Line 115 The renderCanvas() function behaves a little differently this time. This time we’re not going to draw the circle here, but rather we’re going to loop thru the array of circles and have them call a public method called update(). This is where the prototype comes in. Again, this isn’t the best practice for OOP but in a pinch for a quick animation, it works. We’re going to set up the public method using prototype on line 85. Inside the update function we’re going to set the velocity on line 87 increasing it slightly until it hits 5. we’ll use the dy property as a basis to increase the ypos and we’ll look for when that passes the bottom of the stage (line 94) and we’ll reset it to the top and randomly pick a new xpos (line 95).

So now you have multiple objects moving independently. The nice thing about this animation is it will run in just about every browser for both desktop and mobile devices.

JavaScript is an important part of canvas animations and hopefully this tutorial has helped you get a good start.

Posted on July 2, 2012 at 9:21 pm by Runtime · Permalink
In: HTML5, JavaScript, OOP, Tutorial, animation · Tagged with: , ,

Leave a Reply

You must be logged in to post a comment.