This is a port of the simple bouncing ball simulation to JavaScript on the HTML5 canvas. You can view the result here.
The HTML5 code
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Bouncing ball</title> <style> body{background-color: #666;} #canvas {background-color: #ccc;} </style> </head> <body> <canvas id="canvas" width="700" height="500"></canvas> <script src= "bouncing_ball.js"></script> </body> </html>
Nothing complicated here, assuming you’re familiar with basic HTML markup. Note the ridiculously simple HTML5 doctype, and the inclusion of a canvas element, on which we’ll draw the animation. We’ve placed the JavaScript code in the file bouncing_ball.js, and it looks like this:
The JavaScript code
// initialise canvas and context var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); // physical variables var g = 0.1; // gravity var fac = 0.8; // velocity reduction factor per bounce var radius = 20; // ball radius var color = "#0000ff"; // ball color // initialise position and velocity of ball var x = 50; var y = 50; var vx = 2; var vy = 0; // ensure that code does not run before page has loaded window.onload = init; function init() { // set up a timer setInterval(update, 1000/60); // 60 frames per second }; function update() { // update velocity vy += g; // gravity // update position x += vx; y += vy; // handle bouncing if (y > canvas.height - radius){ y = canvas.height - radius; vy *= -fac; } // wrap around if (x > canvas.width + radius){ x = -radius; } // update the ball drawBall(); }; function drawBall() { with (context){ clearRect(0, 0, canvas.width, canvas.height); // clear canvas fillStyle = color; beginPath(); arc(x, y, radius, 0, 2*Math.PI, true); closePath(); fill(); }; };
The code should be self-explanatory, but here is a quick rundown. The first two lines make the canvas element accessible to the JavaScript code by means of the DOM getElementById() method and then specifies the 2D drawing API of canvas using its getContext() method.
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d');
The next 4 lines of code set the values of the acceleration of the ball (due to gravity), the velocity reduction factor each time it bounces, the radius and color of the ball. Next follow 4 more lines that set the initial position and velocity of the ball.
The next 4 lines set up the animation to get the action going.
window.onload = init; function init() { setInterval(update, 1000/60); };
The window.onload function ensures that the init() function is called only when the document has fully loaded. The init() function does just one thing: it calls the setInterval method, which is essentially a timer that repeatedly fires the function specified as the first argument (here it’s update) after an interval specified in milliseconds as the second argument (here it’s 1000/60, or approximately 16.7 milliseconds – 60 being the frame rate per second).
The update() function, which is called 60 times per second, looks like this:
function update() { vy += g; x += vx; y += vy; if (y > canvas.height - radius){ y = canvas.height - radius; vy *= -fac; } if (x > canvas.width + radius){ x = -radius; } drawBall(); };
The first line increments the vertical velocity by applying the acceleration due to gravity, followed by two lines that update the position of the ball by the current values of the velocity components. Next, the two if blocks of logic handle the bouncing (by reversing the vertical velocity and reducing its magnitude on each bounce) and wraps the ball around when it leaves the canvas so that it reappears from the other side. Finally, the drawBall() method is called. It looks like this:
function drawBall() { with (context){ clearRect(0, 0, canvas.width, canvas.height); fillStyle = color; beginPath(); arc(x, y, radius, 0, 2*Math.PI, true); closePath(); fill(); }; };
This code uses methods of the 2D drawing API to first clear the canvas, then draw a filled circle using the arc() method. Recall that this is done at each time step – the animation takes place by wiping the canvas clean and redrawing the ball in a slightly different position every time step.
That’s it – not very hard, is it? There are endless ways of enhancing the realism by introducing more and more physics effects such as friction, wind and so on. We’ll look at some of these effects in future posts.