How to draw animated circles in HTML5 canvas

This post explains the steps required to draw circles and apply simple animations with collision detection.

Step 1 - Draw Circle

In this step, we will learn how to draw a circle in canvas using arc() method as explained below.

We have used beginPath() method to begin our path and called arc() method to add the circle operation. In the end, we have used stroke() method to draw all the accumulated operations. In our case, we have only added a single circle to the path.

Method Signature - arc(x, y, radius, startAngle, endAngle, anticlockwise)

Method Parameters -

x - The x-coordinate of the center of Circle

y - The y-coordinate of the center of Circle

radius - The radius of the Circle

startAngle - Starting position of the Arc

endAngle - Starting position of the Arc

anticlockwise - Flag to change circle direction

// Single Circle - Get Canvas element by Id var canvas1 = document.getElementById( "canvas1" );

// Set Canvas dimensions canvas1.width = 200; canvas1.height = 200;

// Get drawing context var c1 = canvas1.getContext( '2d' );

// Begin Path c1.beginPath();



// Arc Operation c1.arc( 50, 50, 30, 0, Math.PI * 2, false );



// Fill Stroke c1.stroke();

The above code draws a Circle by considering x-axis from left to right and y-axis from top to bottom as shown below.

Step 2 - Draw multiple circles

In this step, we will draw multiple circles by using a simple iteration using for loop. We have also used Math.random() method to get a different value of x and y coordinate to randomize the position of circles.

// Multiple Circle - Get Canvas element by Id var canvas2 = document.getElementById("canvas2");

// Set Canvas dimensions canvas2.width = 200; canvas2.height = 200;

// Get drawing context var c2 = canvas2.getContext('2d');

// Iterate to draw 4 circles for( var i = 0; i < 4; i++ ) { // Generate x and y values between 0 to 140 considering 30 pt radius var x = 30 + Math.random() * 140; var y = 30 + Math.random() * 140;

// Begin Path c2.beginPath();



// Arc Operation c2.arc( x, y, 30, 0, Math.PI * 2, false );

// Fill Stroke

c2.stroke(); }

Step 3 - Animate one circle

To animate the circle we have used requestAnimationFrame( functionName ) method. We have used dx and dy to control change in circle motion in x and y-direction respectively.

To move the circle, we are incrementing change in x and y value by 1. We have used dx and dy to control the animation speed of the Circle. If x and y values grow beyond 50 to 150 range, we have reversed the change by making dx and dy value negative and vice versa. The function clearRect() is used to clear the drawings made on Canvas in previous iterations.

// Single Animated Circle - Get Canvas element by Id var canvas3 = document.getElementById("canvas3");

// Set Canvas dimensions canvas3.width = 200; canvas3.height = 200;

// Get drawing context var c3 = canvas3.getContext( '2d' );

// Radius var radius = 50;

// Starting Position var x = radius + Math.random() * ( 200 - radius * 2 ); var y = radius + Math.random() * ( 200 - radius * 2 );



// Speed in x and y direction var dx = (Math.random() - 0.5) * 2; var dy = (Math.random() - 0.5) * 2; function animate3() {

requestAnimationFrame( animate3 );

c3.clearRect( 0, 0 , 200, 200 ); if( x + radius > 200 || x - radius < 0 ) { dx = -dx; } if( y + radius > 200 || y - radius < 0 ) { dy = -dy; } x += dx; y += dy; c3.beginPath(); c3.arc( x, y, 50, 0, Math.PI * 2, false ); c3.stroke(); }

// Animate the Circle animate3();

The above-mentioned code adds an animated circle within the canvas boundaries as shown below:

Step 4 - Animate multiple circles

In order to draw and animate multiple circles, we have used circle class having draw and update function to preserve the location of each circle. The draw function is used to draw the circle and update function is used to control circle motion.

Similar to step 3, we will iterate and make multiple circles using circle class objects. We have used the function animate4() having for loop as our render or animation loop to iterate all circle objects and call the update method to change circle position.

// Multiple Animated Circle - Get Canvas element by Id

var canvas4 = document.getElementById( "canvas4" );



// Set Canvas dimensions

canvas4.width = 200;

canvas4.height = 200;



// Get drawing context

var c4 = canvas4.getContext( '2d' );



// The Circle class

function Circle( x, y, dx, dy, radius ) {



this.x = x;

this.y = y;

this.dx = dx;

this.dy = dy;



this.radius = radius;



this.draw = function() {



c4.beginPath();



c4.arc( this.x, this.y, this.radius, 0, Math.PI * 2, false );



c4.strokeStyle = "blue";



c4.stroke();

}



this.update = function() {



if( this.x + this.radius > 200 || this.x - this.radius < 0 ) {



this.dx = -this.dx;

}



if( this.y + this.radius > 200 || this.y - this.radius < 0 ) {



this.dy = -this.dy;

}



this.x += this.dx;

this.y += this.dy;



this.draw();

}

}



var circles = [];



// Radius

var radius = 50;



for( var i = 0; i < 5; i++ ) {



// Starting Position

var x = Math.random() * ( 200 - radius * 2 ) + radius;

var y = Math.random() * ( 200 - radius * 2) + radius;



// Speed in x and y direction

var dx = ( Math.random() - 0.5 ) * 2;

var dy = ( Math.random() - 0.5 ) * 2;



circles.push( new Circle( x, y, dx, dy, radius ) );

}



function animate4() {



requestAnimationFrame( animate4 );



c4.clearRect( 0, 0, 200, 200 );



for( var r = 0; r < 5; r++ ) {



circles[ r ].update();

}

}



animate4();



The animated circles with default stroke will look similar to the output as shown below:

Step 5 - Add colors to Animated Circles

In this step, we will use a different color for each circle to have minor variation by adding the color property to Circle class.

// Multiple Colored Animated Circle - Get Canvas element by Id

var canvas5 = document.getElementById( "canvas5" );



// Set Canvas dimensions

canvas5.width = 200;

canvas5.height = 200;



// Get drawing context

var c5 = canvas5.getContext( '2d' );



// The Circle class

function ColoredCircle( x, y, dx, dy, radius, color ) {



this.x = x;

this.y = y;

this.dx = dx;

this.dy = dy;



this.radius = radius;

this.color = color;



this.draw = function() {



c5.beginPath();



c5.arc( this.x, this.y, this.radius, 0, Math.PI * 2, false );



c5.strokeStyle = this.color;



c5.stroke();

}



this.update = function() {



if( this.x + this.radius > 200 || this.x - this.radius < 0 ) {



this.dx = -this.dx;

}



if( this.y + this.radius > 200 || this.y - this.radius < 0 ) {



this.dy = -this.dy;

}



this.x += this.dx;

this.y += this.dy;



this.draw();

}

}



var coloredCircles = [];



var circleColors = [ 'red', 'green', 'blue', 'yellow', 'orange' ];



// Radius

var radius = 50;



for( var i = 0; i < 5; i++ ) {



// Starting Position

var x = Math.random() * ( 200 - radius * 2 ) + radius;

var y = Math.random() * ( 200 - radius * 2) + radius;



// Speed in x and y direction

var dx = ( Math.random() - 0.5 ) * 2;

var dy = ( Math.random() - 0.5 ) * 2;



// Color

var color = circleColors[ i ];



coloredCircles.push( new ColoredCircle( x, y, dx, dy, radius, color ) );

}



function animate5() {



requestAnimationFrame( animate5 );



c5.clearRect( 0, 0, 200, 200 );



for( var r = 0; r < 5; r++ ) {



coloredCircles[ r ].update();

}

}



animate5();