Partager via


HTML5 / JavaScript Canvas Animation

In this article, I will show how to create a basic animation using JavaScript and the HTML 5 Canvas elements. The animation uses two png images (of concentric circles with transparency) that move within the constrains of the canvas to create a nice pattern effect.

This demo has been primarily built for IE9; it has been tested on other browsers, where some flicker does occur. I intend to discuss eliminating this using double buffering in future articles.

Please click here to view the final result.

image_8_4167CCF5[1]

To start with, create a html page containing the following mark-up (this simply defines a html5 containing a canvas with a background colour set to blue). Note the script block, this is where we will place our JavaScript.

    1: <!DOCTYPE html>
    2: <html>
    3:   <head>
    4:     <title>HTML 5 JS Animation</title>
    5:     <script>   1:     2:     <!-- This is where our JavaScript will go -->   3:     </script>
    6:   </head>
    7:   <body>
    8:     <canvas id="myCanvas" width="500" height="500" style="border: 1px solid #000; background-color: #06D" />
    9:   </body>
   10: </html>

 

I then create a JavaScript “class” called Position that defines the movement of the concentric circles. The start position of the Circles are randomly set (x and y co-ordinates). Movement is based on a random x and y vectors that are reversed when a canvas bound is hit (see the UpdatePosition method). Note that the x and y vectors are multiplied by 4 – this is simply to speed up the animation.

    1: function Postion() 
    2: {
    3:     this.xVector = 0,
    4:     this.yVector = 0,
    5:     this.currentX = 0,
    6:     this.currentY = 0,
    7:     this.xBoundMin = 0,
    8:     this.yBoundMin = 0,
    9:     this.xBoundMax = 500,
   10:     this.yBoundMax = 500,
   11:  
   12:     this.initialize = function () {
   13:         this.xVector = 4 * Math.random();
   14:         this.yVector = 4 * Math.random();
   15:  
   16:         // Random starting positions
   17:         this.currentX = Math.floor(Math.random() * (this.xBoundMax - this.xBoundMin + 1) + this.xBoundMin);
   18:         this.currentY = Math.floor(Math.random() * (this.yBoundMax - this.yBoundMin + 1) + this.yBoundMin);
   19:     }
   20:  
   21:     this.updatePosition = function () 
   22:     {
   23:         this.currentX = this.currentX + this.xVector;
   24:         this.currentY = this.currentY + this.yVector;
   25:  
   26:         if (this.currentX >= this.xBoundMax || this.currentX <= this.xBoundMin) {
   27:             this.xVector = this.xVector * -1;
   28:         }
   29:  
   30:         if (this.currentY >= this.yBoundMax || this.currentY <= this.yBoundMin) {
   31:             this.yVector = this.yVector * -1;
   32:         }
   33:     }
   34: }

Next, define a JavaScript “class” for the concentric circles. This contains an instance of our Position class (to show the images motion) as well as a Draw method, which renders the concentric circle image onto the canvas. Note that as the concentric circle images move from across both the x and the y axis of the canvas, the image needs to be four times the size of the canvas (i.e. so it doesn’t appear to go off-screen). This is why the currentContext.drawImage method contains offsets of 500.

    1: function ConcentricCircle(ctx) 
    2: {
    3:     this.position = new Postion();
    4:     this.drawingContext = ctx;
    5:  
    6:     this.Initialize = function () 
    7:     {
    8:         this.position.Initialize();
    9:     }
   10:  
   11:     this.Draw = function () 
   12:     {
   13:         var img = new Image();
   14:         img.src = 'ConcentricCircles1.png'
   15:  
   16:         var x = Math.round(this.position.currentX);
   17:         var y = Math.round(this.position.currentY);
   18:         var currentContext = this.drawingContext;
   19:  
   20:         img.onload = function () 
   21:         {
   22:             currentContext.drawImage(img, x -500, y -500, 1000, 1000);
   23:         }
   24:  
   25:         this.position.UpdatePosition();
   26:     }
   27: }

I then create a method that is to be called to redraw each frame. This clears the canvas before redrawing the objects in their new position. Finally, I construct the scene by creating two instances of the circle object and setting an interval at which they are redrawn. Note that this interval is set to 40ms (which is 25 frames per second). Note that this code is put in the body.onload method. 

    1: this.window.onload = function () 
    2: {
    3:     var canvas = document.getElementById('myCanvas');
    4:     var context = canvas.getContext('2d');
    5:  
    6:     circle1 = new ConcentricCircle(context);
    7:     circle2 = new ConcentricCircle(context);
    8:     circle1.Initialize();
    9:     circle2.Initialize();
   10:  
   11:     setInterval('DrawScene();', 40);
   12:  
   13:     this.DrawScene = function() 
   14:     {
   15:         context.clearRect(0, 0, 500, 500);
   16:         circle1.Draw();
   17:         circle2.Draw();
   18:     }
   19: }

 

And that’s all we need to do! Remember to refresh the page to restart the animation. Please feel free to get in contact if you have any questions.

Click to view final result

Written by Rob Nowik

Comments

  • Anonymous
    December 30, 2011
    The results look stunning! I'm trying to learn the basics of animation in HTML 5. I'm familiar with animations in WPF (XAML/C#), but this is new to me. Hopefully the learning curve for the transition will not be too bad. Thanks for a terrific post!