Exploring the Web Animations API

The Web Animations API provides a single interface for CSS and SVG animations. It aims to make things easier by providing better performance, more control over timing and playback and a flexible and unified javaScript programming interface. I gave it a spin and tried to make some simple animations with it.

The first one is a ball that rolls from left to right. Because of it’s simplicity it is a good candidate for a CSS keyframe animation. The second animation involves movement in both horizontal and vertical directions along a curved path to create the illusion of a bouncing ball. For this one we will use a motionpath animation to move the ball along an svg-style path and combine it with a keyframe animation to make the ball spin.

Both animations will use the same markup that consists of the object that will be animated together with a list of buttons to control the playback of the animation.


<div class="animation-wrapper">
    <span id="ball-container">
        <img src="https://webdesigner-webdeveloper.com/chris-des-dev/wp-content/uploads/2015/01/ball.svg" id="ball" alt="" />
    </span>
</div>

<ul class="controls" id="controls">
    <li><button id="keyframe-start">start Keyframe</button></li>
    <li><button id="motionpath-start">start Motionpath</button></li>
    <li><button id="pause">pause</button></li>
    <li><button id="cancel">stop</button></li>
    <li><button id="play">resume</button></li>
    <li><button id="reverse">reverse</button></li>
</ul>


A keyframe animation

Moving the ball in one direction is straightforward. We can use a keyframe animation and specify values for the position at the beginning and endpoint of the animation using a CSS transform. Making the ball spin involves the same technique so that’s pretty easy. For these two effects we will create two separate animation objects.

The challenge lies in combining the animations in a way so that they will play at the same time. At the time of writing it’s not possible to assign multiple animations to the same HTML element and animate them in parallel. As a workaround we place the image inside a wrapper element. The moving animation is assigned to the wrapper element and the spinning animation is assigned to the image. By combining the two animation objects in a animationGroup we can play them in parallel. If you want to play the animations after each other you can use a animationSequence object instead.


var Animations = {},
    player,
    controls = document.getElementById('controls');

// The elements we will use for our animations
Animations.targets = {
    path: document.getElementById('path'),
    ballContainer: document.getElementById('ball-container'),
    ball: document.getElementById('ball')
};

// Move the ball container from left to right
Animations.keyframeMove = new Animation(Animations.targets.ballContainer, [
    {offset: 0, transform: 'translate(0,0)'},
    {offset: 1, transform: 'translate(600,0)'}], {
    duration: 2000
});

// Spin the ball
Animations.keyframeSpinRoll = new Animation(Animations.targets.ball, [
    {transform: 'rotate(950deg)'}], {
    duration: 2000
});

// Combine the animations for moving and spinning in an animation group
Animations.animationGroupRoll = new AnimationGroup([
    Animations.keyframeMove,
    Animations.keyframeSpinRoll], {
        easing: 'ease-out'
});

A motionpath animation

For this animation we can follow the same workflow as the previous one. So we’ll create two animation effects and combine them in a group. One defines the path along which the ball will move as an SVG-style path and another makes the ball spin with a CSS transform. To play the two animations in parallel we again combine them in a animationGroup.


// Move the ball container along an svg style path
Animations.motionpathBounce = new Animation(Animations.targets.ballContainer,
    new MotionPathEffect("M25,25 " +
        "a150,100 0 0,1 300,0 " +
        "a75,50 0 0,1 150,0 " +
        "a35,20 0 0,1 70,0 " +
        "a2,1 0 0,1 35,0 " +
        "h45"), {
        duration: 2500
});

// Spin the ball
Animations.keyframeSpinBounce = new Animation(Animations.targets.ball, [
    {transform: 'rotate(950deg)'}], {
    duration: 2500
});

// Combine the animations for moving and spinning in an animation group
Animations.animationGroupBounce = new AnimationGroup([
    Animations.motionpathBounce,
    Animations.keyframeSpinBounce], {
    easing: 'ease-out'
});

Hooking up the animation controls

To actually play the animation we have to construct an animationPlayer object. We do this by calling the play method of the document’s timeline object. When the play method gets called, the animation gets tied to it’s own timeline which allows us to control the timing of the animation. The animationPlayer provides methods to reverse, stop, pause and resume the animation.


controls.addEventListener('click', function(event) {
  if (event.target) {
    var targetElement = event.target;

    switch (targetElement.id) {
      case 'keyframe-start':
        player = document.timeline.play(Animations.animationGroupRoll);
        break;
      case 'motionpath-start':
        player = document.timeline.play(Animations.animationGroupBounce);
        break;
      case 'pause':
        player.pause();
        break;
      case 'cancel':
        player.cancel();
        break;
      case 'play':
        player.play();
        break;
      case 'reverse':
        player.reverse();
    }
  }
});

The API is currently not or not fully supported by most browsers but with a polyfill we can make it work in all modern browsers.

More information

0 comments

  1. Šime Vidas

    21-01-2015

    I’m looking at the spec, it looks like motion path animation effects (i.e. the MotionPathEffect constructor) have been removed in favor of Adobe-proposed “Motion Path Module” which defines this effect using a CSS motion-path property.

  2. 主流动画实现方式总结 – Benjamin

    25-01-2015

    […] Exploring the Web Animations API […]

  3. Wer

    19-02-2015

    Hi,
    Thanks for that.

    According to https://github.com/web-animations/web-animations-js, MotionPathEffect is not supportet at the moment.

    web-animations-next.min.js does not include the MotionPathEffect and gives error:
    “Uncaught ReferenceError: MotionPathEffect is not defined”.

    I see you use webanimationpost.min.js, but it has faults, especially when using AnimationSequence in more complex animations.

    Any suggestions? Perhaps you know of a temporary solution for MotionPathEffect only?

    Thanks,
    Wer

  4. Christian van Deursen

    19-02-2015

    Hi Wer,
    For this post I used the legacy webanimations polyfill. This version did support MotionPath so I used it to try out the API. It is recommended to use the ‘web-animations-next’ polyfill. According to https://github.com/web-animations/web-animations-next support for MotionPath is planned so I think we will have to be patient..

  5. sahar

    05-04-2015

    tank you

Comments are closed.