Animation Loop

Let us suppose that you want to animate a result through time - typically evolving even when the user doesn't interact directly with it. Animation consists in repetitively calling a function that print/compute/draws the currently visualized results. Such repetition is called an animation loop.

Each static view of a single call from an animation loop is called a Frame. The animation loop should be able to update and draw the result at least 25 times per seconds in order to have the feeling of a continuous animation. The number of drawing per seconds is usually called Frames Per Seconds, or fps. A continous animation should therefore run, at least, at 25fps, or in order words, the computation of each frame should not exceed 40ms.

Our screen have typically a refreshing rate of about 60fps. It is therefore useless to draw the results more often.

requestAnimationFrame

JavaScript proposes the built-in function requestAnimationFrame allowing to handle an animation loop in calling itself repetitively.

requestAnimationFrame takes as argument a user defined function. This function is called automatically as soon as the system is ready, and synchronize to the refreshing rate of your system.

Create an empty screen program with the following JS code

requestAnimationFrame( frame )

function frame(currentTime) {
  console.log(currentTime);
  requestAnimationFrame( frame )
}

Example of animation

Consider this simple example of an animation loop generated using requestAnimationFrame.
HTML:
<body>
  <div class="box"></div>
</body>
CSS:
.box {
  position: fixed;
  width: 100px;
  height: 100px;
  background-color: red;
}
JavaScript:
"use strict";

const boxElement = document.querySelector(".box");
let leftPos = 0;

requestAnimationFrame( animationLoop )

// This function is continuously called by requestAnimationFrame
function animationLoop(currentTime) {

  boxElement.style.left = `${leftPos}px`;
  leftPos = leftPos+1;

  if(currentTime>2000) // after the webpage run 2s
  {
    boxElement.style.backgroundColor = "green";
  }
  if(currentTime>4000) // after the webpage run 4s
  {
    boxElement.style.backgroundColor = "yellow";
    boxElement.style.width = "200px";
    boxElement.textContent = "Animated in JavaScript!";
  }

  requestAnimationFrame( animationLoop )
}
Observe the result, and the possibility to generate a time-dependant animation in the animationLoop function.

Interaction and animation

Let us consider we want to model the following behavior, where a disc appears when and where the user click, and then falls down.

[Corresponding Webpage]

Let us first start with a single disc.

Create the following code making a disc appearing at the position of the user click (no animation yet).

HTML
<body>
  <div class="circle"></div>
</body>
CSS
.circle {
  background-color:cyan; 
  width: 100px; 
  height: 100px; 
  position: fixed; 
  border-radius: 50%;
}
JavaScript
const radius = 50;  // Radius of the circle
let y = 0;          // height (/vertical) of the circle within the viewport
let circleElement = document.querySelector('.circle');

main();

function main() {
  document.addEventListener('click', createCircle);
}

function createCircle(event) {
  const x = event.clientX;
  y = event.clientY;
  circleElement.style.top = `${y-radius}px`;
  circleElement.style.left = `${x-radius}px`;
}

Create an animation in making the y value increasing from a constant value at each frame. Then applying this new y value to the style of circleElement. (Note that your disc will instantaneously translate to a new position when the user clicks.)

Extend your code in handling an arbitrary number of discs. A new disc should appear for each user click.

Hints :