Back to Home

JavaScript animations

JavaScript animations can handle things that CSS can’t. For instance, moving along a complex path, with a timing function different from Bezier curves, or an animation on a canvas.

Using setInterval

An animation can be implemented as a sequence of frames – usually small changes to HTML/CSS properties. For instance, changing style.left from 0px to 100px moves the element. And if we increase it in setInterval, changing by 2px with a tiny delay, like 50 times per second, then it looks smooth. That’s the same principle as in the cinema: 24 frames per second is enough to make it look smooth. The pseudo-code can look like this: More complete example of the animation: Click for the demo: [codetabs height=200 src=“move”]

Using requestAnimationFrame

Let’s imagine we have several animations running simultaneously. If we run them separately, then even though each one has setInterval(…, 20), then the browser would have to repaint much more often than every 20ms. That’s because they have different starting time, so “every 20ms” differs between different animations. The intervals are not aligned. So we’ll have several independent runs within 20ms. In other words, this: …Is lighter than three independent calls: These several independent redraws should be grouped together, to make the redraw easier for the browser and hence load less CPU load and look smoother. There’s one more thing to keep in mind. Sometimes CPU is overloaded, or there are other reasons to redraw less often (like when the browser tab is hidden), so we really shouldn’t run it every 20ms. But how do we know about that in JavaScript? There’s a specification Animation timing that provides the function requestAnimationFrame. It addresses all these issues and even more. The syntax: That schedules the callback function to run in the closest time when the browser wants to do animation. If we do changes in elements in callback then they will be grouped together with other requestAnimationFrame callbacks and with CSS animations. So there will be one geometry recalculation and repaint instead of many. The returned value requestId can be used to cancel the call: The callback gets one argument – the time passed from the beginning of the page load in milliseconds. This time can also be obtained by calling performance.now(). Usually callback runs very soon, unless the CPU is overloaded or the laptop battery is almost discharged, or there’s another reason. The code below shows the time between first 10 runs for requestAnimationFrame. Usually it’s 10-20ms:

Structured animation

duration

Total time of animation. Like, 1000. timing(timeFraction)

Timing function, like CSS-property transition-timing-function that gets the fraction of time that passed (0 at start, 1 at the end) and returns the animation completion (like y on the Bezier curve). For instance, a linear function means that the animation goes on uniformly with the same speed:


function linear(timeFraction) {
return timeFraction;
Its graph: That’s just like transition-timing-function: linear. There are more interesting variants shown below. draw(progress)

The function that takes the animation completion state and draws it. The value progress=0 denotes the beginning animation state, and progress=1 – the end state. This is that function that actually draws out the animation. It can move the element:

function draw(progress) {
train.style.left = progress + 'px';

…Or do anything else, we can animate anything, in any way. Let’s animate the element width from 0 to 100% using our function. Click on the element for the demo: [codetabs height=60 src=“width”] The code for it: Unlike CSS animation, we can make any timing function and any drawing function here. The timing function is not limited by Bezier curves. And draw can go beyond properties, create new elements for like fireworks animation or something.

Timing functions

We saw the simplest, linear timing function above. Let’s see more of them. We’ll try movement animations with different timing functions to see how they work.

Power of n

If we want to speed up the animation, we can use progress in the power n. For instance, a parabolic curve: The graph: See in action (click to activate): [iframe height=40 src=“quad” link] …Or the cubic curve or even greater n. Increasing the power makes it speed up faster. Here’s the graph for progress in the power 5: In action: [iframe height=40 src=“quint” link]

The arc

Function: The graph: [iframe height=40 src=“circ” link]

Back: bow shooting

This function does the “bow shooting”. First we “pull the bowstring”, and then “shoot”. Unlike previous functions, it depends on an additional parameter x, the “elasticity coefficient”. The distance of “bowstring pulling” is defined by it. The code: The graph for x = 1.5: For animation we use it with a specific value of x. Example for x = 1.5: [iframe height=40 src=“back” link]

Bounce

Imagine we are dropping a ball. It falls down, then bounces back a few times and stops. The bounce function does the same, but in the reverse order: “bouncing” starts immediately. It uses few special coefficients for that: In action: [iframe height=40 src=“bounce” link]

Elastic animation

One more “elastic” function that accepts an additional parameter x for the “initial range”. The graph for x=1.5: In action for x=1.5: [iframe height=40 src=“elastic” link]

Reversal: ease*

So we have a collection of timing functions. Their direct application is called “easeIn”. Sometimes we need to show the animation in the reverse order. That’s done with the “easeOut” transform.

easeOut

In the “easeOut” mode the timing function is put into a wrapper timingEaseOut: In other words, we have a “transform” function makeEaseOut that takes a “regular” timing function and returns the wrapper around it: For instance, we can take the bounce function described above and apply it: Then the bounce will be not in the beginning, but at the end of the animation. Looks even better: [codetabs src=“bounce-easeout”] Here we can see how the transform changes the behavior of the function: If there’s an animation effect in the beginning, like bouncing – it will be shown at the end. In the graph above the regular bounce has the red color, and the easeOut bounce is blue.

let timer = setInterval(function() {
  if (animation complete) clearInterval(timer);
  else increase style.left by 2px
}, 20); // change by 2px every 20ms, about 50 frames per second
Example:

Follow the lesson from Microsoft Web-Dev-For-Beginners course

Tags: javascript