Animation controlled by JavaScript

a sliding block controlled by mouse

Introduction

Nowadays, more and more animation is applied on Front-end. It’s interesting to understand how JavaScript controls the animation.

In this article, I will talk about:

  • what is the animation in the browser

Animation in browser

Animation is a method in which frames are manipulated to appear as moving images. In browser, we can write a function to move images, and call this function repeatedly to achieve animation.

There are 3 ways.

setInterval : It can repeatedly call a function or executes a code snippet, with a fixed time delay between each call.

Usually, the browser shows 60 frames per second. Therefore the interval is set as 16ms (16ms * 60 = 960 < 1000ms).

let timerId = setInterval(() => alert('tick'), 16);

setTimeout : a better way to achieve animation. It’s more flexible.

let timerId = setTimeout(function tick() {   
alert('tick');
timerId = setTimeout(tick, 16);
}, 16);

There are 2 advantages of setTimeout :

  1. Delay (16ms) can be controlled dynamically.

To control the delay:

let delay = 16;
let timerId = setTimeout(function tick() {
alert('tick');
if (some-condition) delay += 16; // delay is updated
timerId = setTimeout(tick, delay);
}, delay);

setInterval fixes the interval as 16ms, regardless the time of executing the function. That means the real time between two function is less than 16ms. However, setTimeout ensures the interval is exactly 16ms.

(more details is presented here)

requestAnimationFrame: this function calculates the interval between frames automatically. I will use this one in this article.

let tick = () => { requestAnimationFrame(tick) };cancelAnimationFrame(tick); // cancel the tick animation

Timeline

Timeline is the class which controls the animation. Its attributes are:

  • tick & tickHandler : the functions which trigger the animation

These attributes must be private. We don’t want they are changed by outside accidentally. Unfortunately, JavaScript doesn’t have the private keyword. But, we can useSymbol to create a private key since Symbol is unique. Even if two Symbol have the same name, they are different. For exemple, we create a private animations :

const ANIMATIONS = Symbol('animations');export class Timeline { 
constructor() { this[ANIMATIONS] = new Set(); }
}

Timeline has several methods:

  • start : start the timeline, and start the animation.

It’s easy to cancel the animation. Since I use requireAnimationFrame :

this[TICK_HANDLER] = requestAnimationFrame(this[TICK]);
cancelAnimationFrame(this[TICK_HANDLER]);

The tricky part is to start one. The tick function deals with it.

First, it marks the start time as now. Then, for each animation, we need to calculate the time of animation:

  • If the animation is registered before the timeline start, then the time of animation is now — timelineStart

Next, the pausedTime and animation delay should be removed.

Finally, this time is passed to the animation, and animation is executed.

Animation

In browser, the animation is created by CSS. In the exemple, sliding block controlled by mouse, the animation is controlled by transform

transform: translateX(20px)

That means move the block 20px right.

We need to create an Animation class. It receives the time of animation, and calculates the position of the block. The method receive(time) works on this.

Before presenting receive method, let’s see the attributes of Animation.

  • object & property : the CSS property of HTML element we want to control. In this example, it’s transform

Well, receive(time) calculates the range of animation by endValue - startValue , and the progress of animation by timingFn(time/duration) . The template accept startValue + range * progress , and returns the position.

Timeline control

Since Timeline and Animation have been created, animation can be controlled now.

First, let’s set a simple HTML, create a block.

Next, in JavaScript file, I created a timeline and an animation. then, I bound it with mouseover and mouseout event. Finally, I launched the timeline and add the animation to it.

In fact, the timing function is Cubic Bezier Curve, and I used the existed codes.

Conclusion

In this article, I presented how to control the animation using JavaScript. The main idea is create a timeline, which can maintain several animation, and the animation can modify the CSS of HTML element. The most important part of this little project is how to calculate the position of HTML element with the animation time.

If you want to try it, don’t forget pack the files. You may need following setup.

npm initnpm install --save-dev webpack webpack-cli webpack-dev-servernpm install --save-dev babel-loader @babel/core @babel/preset-env

and, the webpack configuration:

Finally, run webpack serve , enjoy :)

Developper in Paris, interested in Big Front-end, Full Stack, Explainable AI. Try to introduce AI into Full Stack workflow

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store