Skip to main content

Web Animations API

The Web Animations API lets us construct animations and control their playback with JavaScript. A lot of times we use a combination of CSS and JavaScript, but this API allows us to do all of the animation work in JavaScript.

We are going to build a little project for this section.

The HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Web Animations API</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"
integrity="sha512-MV7K8+y+gLIBoVD59lQIYicR65iaqukzvf/nwasF0nqhPay5w/9lJmVM2hMDcnK1OnMGCdVK+iQrJ7lzPJQd1w=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<div class="wrapper">
<div class="controls">
<button id="play"><i class="fa-solid fa-play"></i></button>
<button id="pause"><i class="fa-solid fa-pause"></i></button>
<button id="reverse">
<i class="fa-solid fa-clock-rotate-left"></i>
</button>
<button id="speed-up"><i class="fa-solid fa-plus"></i></button>
<button id="slow-down">Slow Down</button>
</div>
<div id="ball">
<svg
xmlns="http://www.w3.org/2000/svg"
width="194"
height="194"
version="1.1"
>
<circle fill="#000000" cx="97" cy="97" r="97" />
<path
fill="#ffffff"
d="m 94,9.2 a 88,88 0 0 0 -55,21.8 l 27,0 28,-14.4 0,-7.4 z m 6,0 0,7.4 28,14.4 27,0 a 88,88 0 0 0 -55,-21.8 z m -67.2,27.8 a 88,88 0 0 0 -20,34.2 l 16,27.6 23,-3.6 21,-36.2 -8.4,-22 -31.6,0 z m 96.8,0 -8.4,22 21,36.2 23,3.6 15.8,-27.4 a 88,88 0 0 0 -19.8,-34.4 l -31.6,0 z m -50,26 -20.2,35.2 17.8,30.8 39.6,0 17.8,-30.8 -20.2,-35.2 -34.8,0 z m -68.8,16.6 a 88,88 0 0 0 -1.8,17.4 88,88 0 0 0 10.4,41.4 l 7.4,-4.4 -1.4,-29 -14.6,-25.4 z m 172.4,0.2 -14.6,25.2 -1.4,29 7.4,4.4 a 88,88 0 0 0 10.4,-41.4 88,88 0 0 0 -1.8,-17.2 z m -106,57.2 -15.4,19 L 77.2,182.6 a 88,88 0 0 0 19.8,2.4 88,88 0 0 0 19.8,-2.4 l 15.4,-26.6 -15.4,-19 -39.6,0 z m -47.8,2.6 -7,4 A 88,88 0 0 0 68.8,180.4 l -14,-24.6 -25.4,-16.2 z m 135.2,0 -25.4,16.2 -14,24.4 a 88,88 0 0 0 46.4,-36.6 l -7,-4 z"
/>
</svg>
</div>
</div>
</body>
</html>

Here we have some buttons for controlling the animation. I will get to those later. First, we want to focus on making the ball roll. We are using an svg, but you could use anything.

The CSS

Before we do anything with JavaScript, I want to show you how we can do the same animation using just CSS.

body {
background: #000;
color: #fff;
}

html,
body {
height: 100%;
}

.wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}

#ball {
/* animation: roll infinite 3s linear; */
color: white;
width: 25%;
position: absolute;
top: 50%;
left: 50%;
transform-origin: 0 0;
transform: rotate(0) translate3D(-50%, -50%, 0);
backface-visibility: hidden;
will-change: transform, color;
}

path {
fill: currentColor;
}

.controls {
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
}

button {
padding: 10px 20px;
margin: 5px;
background: #333;
color: #fff;
font-size: 18px;
cursor: pointer;
border-radius: 5px;
}

button:hover {
background: blue;
}

/* The Animation */
@keyframes roll {
0% {
transform: rotate(0) translate3D(-50%, -50%, 0);
color: white;
}
30% {
color: blue;
}
100% {
transform: rotate(360deg) translate3D(-50%, -50%, 0);
color: white;
}
}

In the CSS keyframe we are moving the ball by starting at one position and then rotating it 360 degrees. We are also changing the color of the ball at 30% of the animation.

Now, comment out the CSS, because we are going to do the same thing using JavaScript.

The JavaScript

Let's start out by bringing in everything that we need.

  const ball = document.getElementById('ball');
const play = document.getElementById('play');
const pause = document.getElementById('pause');
const reverse = document.getElementById('reverse');
const speedUp = document.getElementById('speed-up');
const slowDown = document.getElementById('slow-down');

Now, we will create a keyframe object. We do this by creating an array of multiple objects. Each object represents a key from the original CSS.

const rollAnimation = [
{ transform: 'rotate(0) translate3D(-50%, -50%, 0)', color: 'white' },
{ color: 'blue', offset: 0.3 },
{ transform: 'rotate(360deg) translate3D(-50%, -50%, 0)', color: 'white' },
];

We can also set the timing in an options object.

const rollOptions = {
duration: 3000,
iterations: Infinity,
};

Now, let's make the element animate.

const roll = ball.animate(rollAnimation, rollOptions);

Now, we get the same animation as we did with CSS. We can also control the animation with JavaScript. Let's add the play and pause button functionality.

play.addEventListener('click', () => roll.play());
pause.addEventListener('click', () => roll.pause());

We can also have it go in reverse.

reverse.addEventListener('click', () => roll.reverse());

If we want to go from reverse to clicking play again and having it move forward, then we have to add the playbackRate to play.

play.addEventListener('click', () => {
roll.playbackRate = 1;
roll.play();
});

Now, it should work.

We can also speed up and slow down the animation using the playbackRate.

speedUp.addEventListener(
'click',
() => (roll.playbackRate = roll.playbackRate * 2)
);

slowDown.addEventListener(
'click',
() => (roll.playbackRate = roll.playbackRate * 0.5)
);

This is a very simple animation, but you can imagine how powerful it can be when you get into some really complex animations.