Web Animations API Tutorial Part 2: The Animation & Timeline Controls

This is Part 2 of an introductory/tutorial series on the Web Animations API coming to browsers. I've updated the series content in June 2016, as Chrome and Firefox have both rolled out major updates (and some small spec changes). If you have thoughts/questions or see that I’ve misinterpreted the spec, please reach out to me on Twitter, @dancwilson.

Now that we understand how to create a basic animation with the Web Animations API, let’s talk about states, controls, callbacks, and timelines.

Animation Play States and Controls

When you call element.animate(), an Animation object (formerly called an AnimationPlayer in the spec) is returned and the animation starts playing. To see the current state of the animation you can check the readonly property playState which will return one of five strings. We can also modify the current state of the animation, by calling one of four methods:

var player = element.animate(/* ... */);
console.log(player.playState); //"running"

player.pause(); //"paused"
player.play();  //"running"
player.cancel(); //"idle"... jump to original state
player.finish(); //"finished"...jump to end state

In addition to running, paused, idle, and finished play states there is a pending state defined that will occur when a play or pause task is pending.

This Walking Circles example shows six circles scaling. You can pause or play each circle to see a portion of the above play states in action.

See the Pen Blob That Walks by Dan Wilson (@danwilson) on CodePen.

Playback Rate

In the previous CodePen example, there is also a “2x” button that you can press to change the playback rate of the animation, switching it to double speed. This is through the read/write playbackRate property.

var player = element.animate(/* ... */);
console.log(player.playbackRate); //1

player.playbackRate = 2; //double speed, can also be decimal to slow it down.

Finish Callback

With CSS transitions, there is an event that typically fires when the transition ends. Similarly, the Animation allows you to specify an onfinish function when the animation either completes or you call the previously discussed finish() method. Note that according to the specification an animation set with an infinite number of iterations cannot be finished, nor can one with a playbackRate of 0. There is also an oncancel handler, and the option of using Promises for when the Animation finishes.

The following example uses onfinish to display some stats once the animation completes (and it also segues nicely to the next discussion on timelines).

See the Pen Timer Countdown by Dan Wilson (@danwilson) on CodePen.

The Timeline

Each Animation exposes two read/write time-related properties - currentTime and startTime. For now, we will focus on the former.

currentTime returns the milliseconds where the animation currently is. The max value will be delay + (duration * iterations), so infinite iterations will not have a max value.

var player = element.animate([
  {opacity: 1}, {opacity: 0}
], {
  duration: 1000,
  delay: 500,
  iterations: 3
});

player.onfinish = function() {
  console.log(player.currentTime); // 3500
};

Playback rate will affect how quickly the timeline continues. If you set a playback rate of 10, your max currentTime remains the same, but you will go through the timeline 10 times faster. This concept is also shown in the earlier Timer Countdown example.

Since currentTime is read/write, we can also use this to jump to a certain point in the timeline. It can also let us synchronize two animations, as shown in the next example.

See the Pen Syncing Timelines - WAAPI by Dan Wilson (@danwilson) on CodePen.

One more option: reverse()

You can also reverse an animation with reverse() which will be very similar to play() (such as it will have the same playState) except it will traverse the timeline in reverse. When an animation finishes the currentTime will be 0.

See the Pen waRKOm by Dan Wilson (@danwilson) on CodePen.

Next Time…

That was a lot of information, but it was still just getting familiar with what is available. We’ll take a look at some more advanced usage next time.

Check out the rest of this series: