Latest specification at http://w3c.github.io/web-animations/.
Four animation-related specifications already exist on the web platform: CSS Transitions,
CSS Animations, SVG Animations / SMIL, and requestAnimationFrame()
. However:
requestAnimationFrame()
is not a declarative approach - it requires the use
of the main thread, and will therefore jank if the main thread is busy.Web Animations is a new specification for animated content on the web. It's being developed as a W3C specification as part of the CSS and SVG working groups. It aims to address the deficiencies inherent in these four specifications. Web Animations also aims to replace the underlying implementations of CSS Transitions, CSS Animations and SVG Animations, so that:
Here's a simple example of an animation that scales and changes the opacity of
a <div>
over 0.5 seconds. The animation alternates producing a pulsing effect.
<div class="pulse" style="width:150px;">Hello world!</div>
<script>
var elem = document.querySelector('.pulse');
var player = document.timeline.play(new Animation(elem, [
{opacity: "0.5", transform: "scale(0.5)"},
{opacity: "1.0", transform: "scale(1)"}
],
{
direction: "alternate", duration: 500, iterations: Infinity
}));
</script>
The Web Animations model is a description of an engine for animation content on the web. The engine is sufficiently powerful to support CSS Transitions, CSS Animations and SVG Animations.
Web Animations also exposes a JS API to the model. This API defines a number of new interfaces that are exposed to JavaScript. We'll go through some of the more important ones here: Animations, AnimationEffects, TimingDictionaries, TimingGroups, and AnimationPlayers.
An Animation
object defines a single animation effect that applies to a single element target. For example:
var animation = new Animation(targetElement,
[{left: '0px'}, {left: '100px'}], 2000);
Here, the target element's "left" CSS property is modified smoothly from 0px
to 100px
over 2 seconds.
An AnimationEffect
object controls which CSS properties and SVG attributes are
modified by an animation, and the values that those properties and attributes
vary between. AnimationEffect objects also control whether the effect replaces
or adds to the underlying value.
There are three major kinds of effects: KeyframeEffect
, MotionPathEffect
, and EffectCallback
.
A KeyframeEffect
controls one or more properties/attributes by linearly
interpolating values between specified keyframes. KeyframeEffects are usually
defined by specifying the keyframe offset and the property-value pair in a
dictionary:
[
{offset: 0.2, left: "35px"},
{offset: 0.6, left: "50px"},
{offset: 0.9, left: "70px"},
]
If the offset is not specified, keyframes are evenly distributed at offsets between 0 and 1.
[{left: "35px"}, {left: "50px"}, {left: "70px"}]
See the specification for the details of the keyframe distribution procedure, and how KeyframeEffects are evaluated at offsets outside those specified by the keyframes.
A MotionPathEffect
allows elements to be animated along SVG-style paths. For example:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<path id=path d="M 100,100 a 75,75 0 1,0 150,0 a 75,75 0 1,0 -150,0"/>
</defs>
</svg>
<script>
var animFunc = new MotionPathEffect(document.querySelector('#path').pathSegList);
var animation = new Animation(targetElement, animFunc, 2000);
</script>
An EffectCallback
allows animations to generate call-outs to JavaScript
rather than manipulating properties directly. Please see the
specification for more details on this
feature.
Two different types of TimingGroups (AnimationGroup
and AnimationSequence
) allow animations to be synchronized and sequenced.
To play a list of animations in parallel:
var animationGroup = new AnimationGroup([new Animation(...), new Animation(...)]);
To play a list in sequence:
var animationSequence = new AnimationSequence([new Animation(...), new Animation(...)]);
Because Animation
, AnimationGroup
, AnimationSequence
are all TimedItems, groups can be nested:
var animationGroup = new AnimationGroup([
new AnimationSequence([
new Animation(...),
new Animation(...),
]),
new Animation(...)
]);
Groups also take an optional TimingDictionary parameter (see below), which among other things allows iteration and timing functions to apply at the group level:
var animationGroup = new AnimationGroup([new Animation(...), new Animation(...)], {iterations: 4});
TimingDictionaries are used to control the internal timing of an animation (players control how an animation progresses relative to document time). TimingDictionaries have several properties that can be tweaked:
The values provided within TimingDictionaries combine with the animation hierarchy to generate concrete start and end values for animation iterations, animation backwards fills, and animation forwards fills. There are a few simple rules which govern this:
fill: 'backwards'
) or last parent iteration (for fill: 'forwards'
)duration
values for TimingGroups are generated based on the calculated durations of the child animations.The following example illustrates these rules:
var animationGroup = new AnimationGroup([
new AnimationSequence([
new Animation(..., {duration: 3000}),
new Animation(..., {duration: 5000, fill: 'both'})
], {duration: 6000, delay: 3000, fill: 'none'}),
new Animation(..., {duration: 8000, fill: 'forwards'})
], {iterations: 2, fill: 'forwards'});
In this example:
AnimationSequence
has an explicit duration
of 6 seconds, and so the
second child animation will only play for the first 3 of its 5 second durationAnimationGroup
has no explicit duration, and will be provided with a
calculated duration of the max (duration + delay
) of its children - in this case 9 seconds.fill: "both"
is specified for the second Animation
within the AnimationSequence
, the AnimationSequence
itself has a fill
of "none". Hence, as the animation ends right at the end of the AnimationSequence
, the animation will only fill backwards, and only up until the boundary of the AnimationSequence
(i.e. 3 seconds after the start of the AnimationGroup
).Animation
inside the AnimationGroup
and the AnimationGroup
are both fill: "forwards"
. Therefore the animation will fill forward in two places:
AnimationGroup
starts until the second iteration of the AnimationGroup
starts (i.e. for 1 second)AnimationGroup
starts, extending forward indefinitely.In order to play an Animation
or TimingGroup
, an AnimationPlayer
must be constructed:
var player = document.timeline.play(myAnimation);
AnimationPlayers provide complete control the start time and current playback head of their attached animation. However, players can't modify any internal details of an animation.
AnimationPlayers can be used to pause, seek, reverse, or modify the playback rate of an animation.
document.timeline.currentTime
is a timeline's global time. It gives the number
of seconds since the document fired its load event.
Include web-animations.js
in your project:
<script src="web-animations-js/web-animations.js"></script>
In order to work in as many browsers as feasible, we have decided to take the following approach to prefix handling:
the polyfill will automatically detect the correctly prefixed name to use when writing animated properties back to the platform.
where possible, the polyfill will only accept unprefixed versions of experimental features. For example:
var animation = new Animation(elem, {"transform": "translate(100px, 100px)"}, 2000);
will work in all browsers that implement a conforming version of transform
, but
var animation = new Animation(elem, {"-webkit-transform": "translate(100px, 100px)"}, 2000);
will not work anywhere.
When the polyfill requires features to implement functionality that is not inherently specified using those
features (for example, CSS calc()
is required in order to implement merging between lengths with different units)
then the polyfill will provide a console warning in browsers where these features are absent.
For running tests or building minified files, consult the tooling information.
When we make a potentially breaking change to the polyfill's API surface (like a rename) we'll continue supporting the old version, deprecated, for three months and ensure that there are console warnings that a change is pending. After three months, the old version of the API surface (e.g. the old version of a function name) will be removed. If you see deprecation warnings you can't avoid it by not updating.
We also announce anything that isn't a bug fix on [email protected] (https://groups.google.com/forum/#!forum/web-animations-changes).