This specification defines a model for synchronization and timing of changes to the presentation of a Web page. This specification also defines an application programming interface for interacting with this model and it is expected that further specifications will define declarative means for exposing these features.

Introduction

Web Animations defines a model for supporting animation and synchronization on the Web platform. It is intended that other specifications will build on this model and expose its features through declarative means. In addition, this specification also defines a programming interface to the model that may be implemented by user agents that provide support for scripting.

Use cases

The Web Animations model aims at two broad areas of application:

User interface effects

Animation can be used to give visual clues and feedback to make a user interface more readily comprehensible.

For example, a user action results in a table row being removed to represent an item being removed from a shopping cart. In such a case, fading the row to transparent and then shifting the subsequent rows up to fill the space over a few hundred milliseconds provides the user with clear feedback as to the results of their action as opposed to instantly removing the row from the DOM.

To support this scenario not only are the animated effects of fading and shifting required, but so is synchronization, both between the animations, and between animations and scripted actions (removing the table row from the DOM after the animations have completed).

Storytelling and visualisation

Another type of animation uses the animated effect to convey a story or represent some information. Unlike user interface effects which are largely a presentational adjunct to the content, these animations form an essential part of the content presented to the user.

For example, in an animated cartoon two cats fly through space to another planet leaving a rainbow trail behind them. After arriving at the planet a change of scene occurs and the user should decide whether or not the cats enter a magic mountain by selecting one of two preset destinations in the scene.

This scenario requires the following features:

• animated effects for moving characters along a path as well as warping a path (the rainbow trail),
• synchronization that allows some actions to happen simultaneously (the two cats moving) and others in sequence (the change of scene),
• play control to allow rewinding the cartoon, or changing its playback rate to accommodate particular learning or accessibility needs,
• the ability to trigger animations in response to user input

Similar use cases in this category include visualising physical phenomena such as spring motion for educational purposes, or visualising data such as the prevalence of a disease over a geographical space over a year whereby animation is used to present the time-based component of the data.

Relationship to other specifications

CSS Transitions [[CSS3-TRANSITIONS]], CSS Animations [[CSS3-ANIMATIONS]], and SVG [[SVG11]] all provide mechanisms that generate animated content on a Web page. Although the three specifications provide many similar features, they are described in different terms. This specification proposes an abstract animation model that encompasses the common features of all three specifications. This model is backwards-compatible with the current behavior of these specifications such that they can be defined in terms of this model without any observable change.

The animation features in SVG 1.1 are defined in terms of SMIL Animation [[SMIL-ANIMATION]]. It is intended that by defining SVG's animation features in terms of the Web Animations model, the dependency between SVG and SMIL Animation can be removed.

The programming interface component of this specification makes some additions to interfaces defined in HTML5 [[HTML5]].

Overview of this specification

This specification begins by defining an abstract model for animation. This is followed by a programming interface defined in terms of the abstract model. The programming interface is defined in terms of the abstract model and is only relevant to user agents that provide scripting support.

Web Animations model overview

At a glance, the Web Animations model consists of two largely independent pieces, a timing model and an animation model. The role of these pieces is as follows:

Timing model
Takes a moment in time and converts it to a proportional distance within a single iteration of an animation called the time fraction. An iteration index is also generated for animations that vary as they repeat.
Animation model
Takes the time fractions and iteration indices produced by the timing model and converts them into a series of values to apply to the target properties and attributes.

Graphically, this flow can be represented as follows:

Overview of the operation of the Web Animations model.
The current time is input to the timing model which produces a time fraction and an iteration index.
These parameters are used as input to the animation model which produces the values to apply.

For example, consider an animation that:

• starts after 3 seconds,
• runs twice,
• takes 2 seconds every time, and
• changes the width of a rectangle from 50 pixels to 100 pixels.

The first three points apply to the timing model. At a time of 6 seconds, it will calculate that the animation should be half-way through its second iteration and produces the result 0.5. The animation model then uses that information to calculate a width for the rectangle of 75.

This specification begins with the timing model and then proceeds to the animation model.

Timing model

This section describes and defines the behavior of the Web Animations timing model. Timing events, however, which are also a feature of the timing model, are described separately in .

The timing model at a glance

Two features characterise the Web Animations timing model: it is stateless and it is hierarchical.

Stateless

The Web Animations timing model operates by taking an input time and producing an output time fraction. Since the output is based solely on the input time and is independent of previous inputs, the model may be described as stateless. This gives the model the following properties:

Frame-rate independent
Since the output is independent of previous inputs, the rate at which the model is sampled will not affect its progress. Provided the input times are proportional to the progress of real-world time, animations will progress at an identical rate regardless of the capabilities of the device running them.
Direction-agnostic
Since the sequence of inputs is insignificant, the model is directionless. This means that the model can be sampled in reverse or even in a backwards and forwards pattern without requiring any specialized handling.
Constant-time seeking
Since each input is independent of the previous input, the processing required to perform a seek operation, even far into the future, is at least potentially constant.

There are a few exceptions to the stateless behavior of the timing model.

Firstly, timing events are fired when, for example, one sample falls on the opposite side of an animation's interval boundary to the previous sample. This is certainly stative behavior. However, events should be considered as a layer added on top of the core timing model. When no event listeners are registered processing of events can be ignored.

Another exception to this stateless behavior is that a number of methods defined in the programming interface to the model provide play control such as pausing an item. These methods are defined in terms of the time at which they are called and are therefore stative. These methods are provided primarily for convenience and are not part of the core timing model but, like events, are layered on top.

Similarly, the bounding behavior of players means that dynamic changes to the end time of the media (source content) of a player may produce a different result depending on when the change occurs. This behavior is somewhat unfortunate but has been deemed intuitive and consistent with HTML. As a result, the model is can only truly be described as stateless in the absence of dynamic changes to its timing properties.

Finally, each time the model is sampled, it can be considered to establish a temporary state. While this temporary state affects the values returned from the programming interface, it has no influence on the subsequent samples and hence does not conflict with the stateless qualities described above.

Hierarchical

The other characteristic feature of the Web Animations timing model is that time is inherited. Time begins with a monotonically increasing time source and cascades down a number of steps to each animation. At each step, time may be shifted backwards and forwards, scaled, reversed, paused, and repeated.

A hierarchy of timing nodes. Each node in the tree derives its time from its parent node. At the root of the tree is the global clock.

A consequence of this hierarchical arrangement is that complex animation arrangements can be reversed, scheduled, accelerated and so on as a whole unit since the manipulations applied to the parent cascade down to its descendants. Furthermore, since time has a common source, it is easy to synchronize animations.

Timing model concepts

In Web Animations timing is based on a hierarchy of time relationships between timing nodes. Parent nodes provide timing information to their child nodes in the form of time values. A time value is a real number which nominally represents a number of seconds from some moment. The connection between time values and wall-clock seconds may be obscured by any number of transformations applied to the value as it passes through the time hierarchy.

In the future we may have timelines that are based on UI gestures in which case the connection between time values and seconds will be weakened even further.

Periodically, the user agent will trigger an update to the timing model in a process called sampling. On each sample the time values of each timing node are updated.

A more precise definition of when the model is updated when scripting is involved is provided in .

The global clock

At the root of the Web Animations timing hierarchy is the global clock.

The global clock is a source of monotonically increasing time values unaffected by adjustments to the system clock. The time values produced by the global clock represent wall-clock seconds from an unspecified historical moment. Because the zero time of the global clock is not specified, the absolute values of the time values produced by the global clock are not significant, only their rate of change.

Note that the global clock is not exposed in the programming interface and nor is it expected to be exposed by markup. As a result the moment from which global clock time values are measured, that is, the zero time of the clock, is allowed to be implementation-dependent. One user agent may measure the number of seconds since the the user agent was loaded whilst another may use the time when the device was started. Both approaches are acceptable and produce no observable difference in the output of the model.

Timelines

A timeline provides a source of time values for the purpose of synchronization.

Typically, a timeline is tied to the global clock such that its absolute time is calculated as a fixed offset from the time of the global clock. This offset is established by designating some moment as the timeline's zero time and recording the time value of the global clock at that moment. At subsequent moments, the time value of the timeline is calculated as the difference between the current time value of the global clock and the value recorded at the zero time.

Note that we anticipate that other types of timelines may be introduced in the future that are not tied to the global clock. For example, a timeline whose time values correspond to UI gestures.

Since a timeline may be defined relative to a moment that has yet to occur, it may not always be able to return a meaningful time value. A timeline is considered to be not started when it is in such a state that it cannot produce a time value.

The document timeline

Each document has a timeline called the document timeline whose time value at a given moment is calculated as a fixed offset from the global clock such that its zero time corresponds to the moment immediately prior to dispatching the load event of the document. Prior to this moment, the document timeline is not started.

For documents that support the concept of current document readiness, this is the moment after the current document readiness has changed to "complete" but before dispatching the load event. For user agents that support Navigation Timing [[NAVIGATION-TIMING]], this occurs between the domComplete and loadEventStart timings.

This is not correct. We need a means to start animations prior to document load.

Since the document timeline is tied to the global clock by a fixed offset, time values reported by the document timeline increase monotonically. Furthermore, since no scaling is applied, these time values are proportional to wall-clock seconds.

Players

The children of a timeline are called players. A player takes a timed item which is a static description of some timed behavior and binds it to a timeline so that it runs. A player also allows run-time control of the connection between the timed item and its timeline by providing pausing, seeking, and speed control. The relationship between a player and a timed item is analogous to that of a DVD player and a DVD.

A player connects a single timed item, called its source content, to a timeline and provides playback control.

A player records the time value of its timeline at which its source content is scheduled to begin as the player start time.

When a player is created, it is assigned a globally unique sequence number called the player sequence number. This number is used to resolve the sort order of players that have the same start time for a variety of situations such as combining animations, queuing events, and returning the list of current players.

The current time of a player

Players provide a time value to their source content called the player's current time.

The calculation of the current time is as follows:

```current time = (timeline time - player start time) * playback rate - time lag```

Where:

If the timeline with which the player is associated is not started then the current time is `null`.

It is often useful to manipulate the current time of a player even when its associated timeline is not started, for example, to pre-seek a player. For this purpose, we define the effective current time of a player as the result of evaluating the current time as above but substituting the effective timeline time for the timeline time.

The procedure for performing manual updates to the current time is defined in .

Seeking, pausing and bounding

Seeking, pausing and bounding a player are closely related and are described here together.

Introduction to seeking

Changing the current playback position of a player can be used to rewind its source content to its start point, fast-forward to a point in the future, or to provide ad-hoc synchronization between timed items.

However, in Web Animations, the start time of a player has special significance in determining the priority of animations (see ) and so we cannot simply adjust the start time. Instead, an additional offset is introduced called the time lag that further offsets a player's current time from its timeline. The effect of the time lag when seeking is illustrated below.

At time t, a seek is performed on the player changing its current time from 1.5s to 2s.
As a result, the time lag is set to -0.5s.
Note that the start time indicated by a red star does not change.

It is possible to seek a player even if its timeline is not started. Once the timeline begins, the player will begin playback from the seeked time.

Introduction to pausing

Pausing can be used to temporarily suspend a player. Like seeking, pausing effectively causes the current time of a player to be offset from its timeline by means of setting the time lag.

The effect of pausing on a player's time lag is illustrated below.

The effect of pausing a player.
Whether pausing before or after a player's start time the duration of the interval during which the player was paused is added to the player's time lag whilst the start time remains unaffected.

Bounding the current time

Players in the real world such as DVD players or cassette players typically continue playing until they reach the end of their media at which point they stop. If such players are able to play in reverse, they typically stop playing when they reach the beginning of their media. In order to emulate this behavior and to provide some consistency with HTML's media elements [[HTML5]], the current time of Web Animations' players do not progress beyond the end time of their source content or play backwards past time zero. This is called bounding.

It is possible, however, to seek the current time of a player to a time outside this range. When doing so, the current time will not progress but the player will act as if it had been paused.

This allows, for example, seeking the current time of a player with no source content to 5s. If source content with an end time later than 5s is later associated with the player, playback will begin from the 5s mark.

Similar behavior to the above scenarios may be arise when the length of a player's source content changes.

Limiting the current time to this range acts like a sort of automatic pausing and is accomplished using the same machinery as pausing such as the time lag and pause start time.

Seeking, pausing and bounding properties

Players track three properties related to seeking, pausing and bounding.

time lag
The offset from a player's scheduled current time as defined by its start time, and its actual current time after accounting for the effects of seeking, pausing, and bounding. The time lag is initially zero and is updated as per the definition in .
paused state
A boolean value that is true if the player is currently paused. The paused state is initially false.
pause start time
The effective current time to maintain while the player is paused or effectively paused due to bounding behavior. Null when neither of these conditions apply. The pause start time is initially null.

A number of calculations for performing seeking, pausing and bounding are defined to operate even when the associated timeline is not started. For such situations we define the effective timeline time as the current time value of the timeline associated with a player unless the timeline is not started, in which case the effective timeline time is zero.

Calculating the time lag

The time lag value is both a stored and a calculated value. When a player is paused or bounded, the value is calculated from the pause start time. When a player is not paused or bounded, the stored value is used. The stored value is initially zero, and is updated when the player is unpaused, seeked, or becomes no longer bounded.

The value of time lag at a given moment is calculated as follows:

1. Let the pause time lag be the result of evaluating ```(effective timeline time - start time) * playback rate - pause start time```.
2. Let the unbounded current time be the result of evaluating the current time using the stored value for the time lag.
3. Let the source content end be the end time of the player's source content. If the player has no source content, let the source content end be zero.
4. The time lag is then calculated using the first matching condition from below:
If the paused state is true,
Return the pause time lag.
If the unbounded current time < zero,
1. If the pause start time is null, let the pause start time be zero.
2. Return the result of evaluating the pause time lag using the possibly updated pause start time.
If the unbounded current timesource content end,
1. If the pause start time is null, let the pause start time be source content end.
2. Return the result of evaluating the pause time lag using the possibly updated pause start time.
Otherwise,
1. If the pause start time is not null, set the stored value of the time lag to the pause time lag.
2. Let the pause start time be null.
3. Return the stored value of the time lag.

This procedure needs verification. It is highly likely to be wrong.

Updating the paused state

The procedure for updating the paused state is as follows:

1. Let new value be the new paused state to set.
2. If new value equals the current paused state, return.
3. The next step depends on the current paused state as follows,
If paused state is true,
1. Set the stored value of time lag to the current calculated value of time lag as defined in .
2. Set the pause start time to null.
Otherwise,
Record the current value of the effective current time as pause start time.
4. Update paused state to new value.

Performing a seek

Seeking is the process of updating a player's current time to a desired value. It is achieved using the following procedure:

1. Let seek time be the desired time value for the player's current time.
2. The steps for adjusting the current time depend on the paused state as follows:
If the paused state is true,
Set pause start time to seek time.
If the paused state is false,
Set the stored value for the time lag to the result of evaluating ```(effective timeline time - start time) * playback rate - seek time```.

The timing events queued when a seek is performed are described in .

Bounded players

A player is said to be bounded when the paused state is false but the pause start time is set (not null).

Speed control

The rate of play of a player can be controlled by setting its playback rate. For example, setting a playback rate of 2 will cause the player's current time to increase at twice the rate of its timeline. Similarly, a playback rate of -1 will cause the player's current time to decrease at the same rate as the time values from its timeline increase.

Note that timed items also have a playback rate associated with them that behaves differently to that defined here.

Players have a playback rate that provides a scaling factor from the rate of change of the associated timeline's time values to the player's current time. The playback rate is initially 1.

Setting a player's playback rate to zero effectively pauses the player but without affecting the player's paused state.

Updating the playback rate

Changes to the playback rate trigger a compensatory seek so that that the player's current time is unaffected by the change to the playback rate.

The procedure is as follows:

1. Let previous time be the value of the effective current time before updating the playback rate.
2. Update the playback rate to the new value.
3. Seek to previous time using the procedure defined in .

Timed items

A timed item is an abstract term referring to a node in the timing hierarchy.

Relationship between timed items and players

The source content of a player, if set, is a type of timed item. The source content of a player is said to be directly associated with that player.

Timed items can be combined together into a hierarchy using timing groups (see ). Only the root timed item of such a hierarchy can be directly associated with a player. If a timed item that has a parent timing group is designated as the source content of a player, the timed item is removed from its parent timing group before being associated with the player.

A timed item is associated with a player if it is directly associated with a player or if it has an ancestor timing group that is directly associated with a player. At a given moment, a timed item can be associated with at most one player.

A timed item, item, is associated with a timeline, timeline, if item is associated with a player which, in turn, is associated with timeline.

Types of timed items

This specification defines two types of timed item:

All types of timed item define a number of common properties which are described in the following sections.

The active interval

The period that a timed item is scheduled to run is called its active interval. Each timed item has only one such interval.

The lower bound of the active interval is determined by the start time of the timed item but may be shifted by a start delay on the timed item.

The upper bound of the interval is determined by the active duration.

The relationship between the start time, start delay, and active duration is illustrated below.

Examples of the effect of the start delay on the endpoints of the active interval.
(a) A timed item with no delay; the start time and beginning of the active interval are coincident.
(b) A timed item with a positive delay; the beginning of the active interval is deferred by the delay.
(c) A timed item with a negative delay; the beginning of the active interval is brought forward by the delay.

Timed items define an active interval which is the period of time during which the item is scheduled to produce its effect with the exception of fill modes which apply outside the active interval.

The lower bound of the active interval is defined by the combination of the timed item's start time and start delay

A timed item's start time is the moment at which the parent timing group, if any, has scheduled the timed item to begin. It is expressed in inherited time. In most cases, including the case when the timed item has no parent timing group, the start time is zero. The singular exception is sequence timing groups which set the start times of their children as described in .

In addition to the start time, a timed item also has a start delay which is an offset from the start time. Unlike the start time which is determined by the parent timing group, the start delay is a property of the timed item itself.

The lower bound of the active interval of a timed item, expressed in inherited time space, is the sum of the start time and the start delay.

These definitions are incorporated in the calculation of the local time (see ) and active time.

The length of the active interval is called the active duration, the calculation of which is defined in .

Local time and inherited time

In Web Animations all times are relative to some point of reference. These different points of reference produce different time spaces.

This can be compared to coordinate spaces as used in computer graphics. The zero time of a time space is analogous to the origin of a coordinate space.

Just as with coordinate spaces, time spaces can also be nested. Timing groups typically perform some transformations on the time values they receive from their parent or player before passing on the transformed time values to their children. Child timed items then operate within that transformed time space.

Children take the transformed time values from their parent—called the inherited time— and add their start time to establish their own local time space as illustrated below.

Inherited time and local time.
At time t, the inherited time is 2.5.
For timed item (a) which has a start time of 1, the local time is 1.5.
For timed item (b) which has a start time of 1 and a start delay of 1, the local time is also 1.5 since local time is based on a timed item's start time only, and not on its start delay.

For a timed item, the inherited time at a given moment is based on the first matching condition from the following:

If the timed item has a parent timing group,
the inherited time is the parent timing group's current transformed time.
If the timed item is directly associated with a player,
the inherited time is the current time of the player.
Otherwise,
the inherited time is `null`.

The local time of a timed item is the timed item's inherited time minus its start time. If the inherited time is `null` then the local time is also `null`.

Timed item phases and states

At a given moment, a timed item may be in one of three possible phases. If a timed item has a `null` local time it will not be in any phase.

The different phases are illustrated below.

An example of the different phases and states used to describe a timed item.

The phases are as follows:

before phase
The timed item's local time falls before the item's active interval.
active phase
The timed item's local time falls inside the item's active interval.
after phase
The timed item's local time falls after the item's active interval.

In addition to these phases, a timed item may also be described as being in one of several overlapping states. These states are only established for the duration of a single sample and are primarily a convenience for describing stative parts of the model such as event dispatch.

These states and their useage within the model are summarised as follows:

in play

Corresponds to a timed item whose active time is changing on each sample. This occurs when the timed item and all its ancestors are in the active phase. Animations only “move” when they are in play.

It is possible for a timed item to be in the active phase but not in play. For example, if a timed item has a parent timing group that causes the timed item's active interval to be clipped and both parent and child apply the same fill mode, the child timed item may be effectively be snapshotted within the active phase despite no longer being in play.

Transitions to and from the in play state trigger timing events as defined in .

current

Corresponds to a timed item that is either in play or may become in play in the future. This will be the case if the timed item is in play or in its before phase, or it has an ancestor for which this is true thereby opening up the possibility that this timed item might play again (e.g. due to repeating).

This state is used in the programming interface to identify all animations and players that are likely to be of interest.

Furthermore, the current state provides an important definition for managing the amount of memory required by implementations. Assuming a monotonically increasing timeline an implementation can safely discard all timed items that are not current and not referenced elsewhere provided they take care to preserve any fill values. This is because such timed items will no longer have any dynamic effect.

in effect
Corresponds to a timed item that has a resolved active time. This occurs when either the timed item is in its active phase or outside the active interval but at a time where the item's fill mode (see ) causes its active time to be resolved. Only in effect animations apply a result to their target.

The normative definition of each of these states follows.

A timed item is in the before phase if the timed item's local time is not `null` and is less than the item's start delay.

A timed item is in the active phase if all of the following conditions are met:

1. the timed item's local time is not `null`, and
2. the timed item's local time is greater than or equal to its start delay, and
3. the timed item's local time is less than the sum of its start delay and active duration.

A timed item is in the after phase if the timed item's local time is not `null` and is greater than or equal to the sum of its start delay and active duration.

A timed item is in play if all of the following conditions are met:

1. the timed item is in the active phase, and
2. the timed item has a parent timing group that is in play or else is directly associated with a player that is not bounded.

A timed item is current if it any of the following conditions is true:

A timed item is in effect if its active time as calculated according to the procedure in is not `null`.

Fill behavior

The effect of a timed item when it is not in play is determined by its fill mode.

The possible fill modes are:

• none,
• forwards,
• backwards, and
• both.

The normative definition of these modes is incorporated in the calculation of the active time in .

Fill modes

The effect of each fill mode is as follows:

none
The timed item has no effect when it is not in play.
forwards
When the timed item is in the after phase, or when the timed item is in the active phase but an ancestor is in its after phase, the timed item will produce the same transformed time value as the last moment it is scheduled to be in play. For all other times that the timed item is not in play, it will have no effect.
backwards
When the timed item is in the before phase, or when the timed item is in the active phase but an ancestor is in its before phase, the timed item will produce the same transformed time value as the earliest moment that it is scheduled to be in play. For all other times that the timed item is not in play, it will have no effect.
both
When the timed item or an ancestor is in its before phase, backwards fill behavior is used. When the timed item or an ancestor is in its after phase, forwards fill behavior is used.

Some examples of the these fill modes are illustrated below.

Examples of various fill modes and the states produced.
(a) fill mode ‘none’. The timed item has no effect outside its active interval.
(b) fill mode ‘forwards’. After the active interval has finished, the timed value continues to maintain a fill value.
(c) fill mode ‘backwards’. The timed item produces a fill value until the start of the active interval.
(d) fill mode ‘both’. Both before and after the active interval the timed item produces a fill value.

Note that setting a fill mode has no bearing on the endpoints of the active interval. However, the fill mode does have an effect on various other properties of the timing model since the active time of a timed item is only defined (that is, not `null`) inside the active interval or when a fill is applied.

Currently timing functions that generate results outside the range [0, 1] will behave unexpectedly when applied to animation groups, as children will increase iterations or enter into fill mode rather than continuing to extrapolate along their defined behavior (which is what they would do if the timing function applied to them directly).

To fix this it is possible we will wish to introduce 'overflow' fill modes that respond to time values larger than or smaller than the active time range by extrapolating rather than filling.

Repeating

Iteration intervals

It is possible to specify that a timed item should repeat a fixed number of times or indefinitely. This repetition occurs within the active interval. The span of time during which a single repetition takes place is called an iteration interval.

Unlike the active interval, a timed item can have multiple iteration intervals although typically only the interval corresponding to the current iteration is of interest.

The length of a single iteration is called the iteration duration. The initial iteration duration of a timed item is simply its intrinsic iteration duration.

The intrinsic iteration duration of a timed item is zero, however some specific types of timed item such as timing groups override this behavior and provide an alternative intrinsic duration (see and ).

The iteration duration of a timed item may be set by the author to represent a value other than the intrinsic iteration duration.

Comparing the iteration duration and the active duration we have:

Iteration duration
The time taken for a single iteration of the timed item to complete.
Active duration
The time taken for the entire timed item to complete, including repetitions. This may be longer or shorter than the iteration duration.

The relationship between the iteration duration and active duration is illustrated below.

A comparison of the iteration duration and active duration of a timed item with an iteration count of 2.5. Note that the iteration duration for the final iteration does not change, it is simply cut-off by the active duration.

Controlling iteration

The number of times a timed item repeats is called its iteration count. The iteration count is a real number greater than or equal to zero. The iteration count may also be positive infinity to represent that the timed item repeats indefinitely.

In addition to the iteration count, timed items also have an iteration start property which specifies an offset into the series of iterations at which the timed item should begin. The iteration start is a finite real number greater than or equal to zero.

The behavior of these parameters is defined in the calculations in .

The effect of the iteration count and iteration start parameters is illustrated below.

The effect of the iteration count and iteration start parameters.
In the first case the iteration count is 2.5 resulting in the third iteration being cut-off half way through its iteration interval.
The second case is the same but with an iteration start of 0.5. This causes the timed item to begin half way through the first iteration.

Unlike the iteration count parameter, the iteration start parameter does not effect the length of the active duration.

Note that values of iteration start greater than or equal to one are generally not useful unless used in combination with an animation effect that has an accumulation operation property of sum.

Iteration time space

We have already encountered different time spaces in describing local time and inherited time (see ). Repetition introduces yet another time space: the iteration time space.

Iteration time space is a time space whose zero time is the beginning of a timed item's current iteration.

Within the Web Animations model we also refer to active time which is a time relative to the beginning of the active interval. This time space, however, is internal to the model and not exposed in the script interface or in markup.

These time spaces are illustrated below.

A comparison of item time, active time, and iteration time for an animation with a iteration duration of 1s and an iteration count of 2.5.

Note that while the time spaces themselves are not bounded, Web Animations defines active time and iteration time such that they are clamped to a set range as shown in the diagram. For example, whilst a time of -1 second is a valid time in active time space, the procedure for calculating the active time defined in will never return a negative value.

In addition to these time spaces we can also refer to the document time space which is time space of the time values of the document timeline of the active document.

Interval timing

When a timed item repeats we must define the behavior at the iteration boundaries. For this and indeed for all interval-timing, Web Animations uses an endpoint-exclusive timing model. This means that whilst the begin time of an interval is included in the interval, the end time time is not. In interval notation this can written `[begin, end)`. This model provides sensible behavior when intervals are repeated and sequenced since there is no overlap between the intervals.

In the examples below, for the repeated item, at local time 1s, the iteration time is 0. For the sequenced items, at inherited time 1s, only item B will be in play; there is no overlap.

Illustration of end-point exclusive timing. For both repeated and sequenced timed items there is no overlap at the boundaries between intervals.

An exception to this behavior is that when performing a fill, if the fill begins at an interval endpoint, the endpoint is used. This behavior falls out of the algorithm given in and is illustrated below.

After one iteration, the iteration time is 0, but after two iterations (and thereonwards), the iteration time is equal to the iteration duration due to the special behavior defined when a timed item fills.

Timed item speed control

Like players, timed items also have a playback rate parameter. The playback rate of a timed item is a finite real number that acts as a multiplier when calculating the timed item's transformed time from its local time.

The effect of setting the playback rate of a timed item differs from the setting the playback rate on a player. Its behavior is defined in the timing calculations given in .

In summary, the behavior of the playback rate of a timed item is as follows:

Core timed item calculations

Overview

At the core of the Web Animations timing model is the process that takes an inherited time value and converts it to an iteration time.

Following this further transformations are applied before resulting at a final transformed time.

The first step in this process is to calculate the bounds of the active interval which is determined by the active duration.

This process is illustrated below.

Calculation of the active duration is based on multiplying the iteration duration by the iteration count and then dividing by the playback rate.

The process for calculating the active duration is normatively defined in .

Having established the active duration, the process for transforming a timed item's inherited time into its transformed time is illustrated below.

An overview of timing model calculations.
(1) The inherited time is converted into a local time by incorporating the start time.
(2) The local time is converted into an active time by incorporating the start delay.
(3) The playback rate and iteration start properties are applied to the active time to produce the scaled active time.
(4) The scaled active time is then converted to an offset within a single iteration: the iteration time.
(5) The iteration time is converted into a directed time by incorporating the playback direction.
(6) Finally, a timing function is applied to the directed time to produce the transformed time.

The first step, calculating the local time is described in . Steps 2 to 4 in the diagram are described in the following sections. Steps 5 and 6 are described in and respectively.

Calculating the active duration

In order to calculate the active duration we first define the repeated duration as follows:

repeated duration = ```iteration duration × iteration count```

If either the iteration duration or iteration count are zero, the repeated duration is zero.

This clarification is needed since the result of infinity multiplied by zero is undefined according to IEEE 754-2008.

The active duration is calculated according to the following steps:

1. If the playback rate is zero, return `Infinity`.
2. Otherwise, return ```repeated duration / abs(playback rate)```.

Transforming the local time

Calculating the active time

The active time is based on the local time and start delay. However, it is only defined when the timed item should produce an output and hence depends on its fill mode and phase as well as the phase of its parent timing group, if any, as follows,

If the timed item is in the before phase,
The result depends on the fill mode as follows.
If the fill mode is backwards or both,
Return zero.
Otherwise,
Return `null`.
If the timed item is in the active phase,
The result depends on the first matching condition from the following,
If the timed item has a parent timing group and that parent timing group is in the before phase, and the fill mode of this timed item is none or forwards,
Return `null`.
If the timed item has a parent timing group and that parent timing group is in the after phase, and the fill mode of this timed item is none or backwards,
Return `null`.
Otherwise,
Return `local time - start delay`.
If the timed item is in the after phase,
The result depends on the fill mode as follows.
If the fill mode is forwards or both,
Return the active duration.
Otherwise,
Return `null`.
Otherwise (the local time is `null`),
Return `null`.

Calculating the scaled active time

Before the active time can be converted to an iteration time we must factor in the timed item's playback rate and iteration start. The result is called the scaled active time.

In order to calculate the scaled active time we first define the start offset as follows:

start offset = ```iteration start × iteration duration```

If the iteration start is zero, the start offset is zero.

This clarification is needed since the iteration duration may be infinity and the result of infinity multiplied by zero is undefined according to IEEE 754-2008.

The scaled active time is calculated according to the following steps:

1. If the active time is `null`, return `null`.
2. Return the scaled active time based on the playback rate as follows,
If the playback rate is less than zero,
Return ```(active time - active duration) × playback rate + start offset```.
If the playback rate is zero,
Return start offset.
Otherwise,
Return ```active time × playback rate + start offset```.

Calculating the iteration time

The iteration time is calculated according to the following steps:

1. If the scaled active time is `null`, return `null`.
2. If the iteration duration is zero, return zero.
3. If ```scaled active time - start offset``` is equal to the repeated duration, and iteration count is not zero, and ```(iteration count + iteration start) % 1``` is zero, return the iteration duration.
4. Otherwise, return ```scaled active time % iteration duration```.

Calculating the current iteration

The current iteration can be calculated using the following steps:

1. If the scaled active time is `null`, return `null`.
2. If the scaled active time is zero, return zero.
3. If the iteration duration is zero, return `floor(iteration start + iteration count)`.
4. If the iteration time equals the iteration duration, return ```iteration start + iteration count - 1```.
5. Return ```floor(scaled active time / iteration duration)```.

If the iteration duration is infinite, the result of ```floor(scaled active time / iteration duration)``` will be zero as defined by IEEE 754-2008.

Direction control

Timed items may also be configured to run iterations in alternative directions using direction control. For this purpose, timed items have a playback direction parameter which takes one of the following values:

• normal,
• reverse,
• alternate, or
• alternate-reverse.

The semantics of these values are incorporated into the calculation of the directed time which follows.

A non-normative definition of these values is as follows:

normal
All iterations are played as specified.
reverse
All iterations are played in the reverse direction from the way they are specified.
alternate
Even iterations are played as specified, odd iterations are played in the reverse direction from the way they are specified.
alternate-reverse
Even iterations are played in the reverse direction from the way they are specified, odd iterations are played as specified.

Calculating the directed time

The directed time is calculated from the iteration time using the following steps:

1. If the iteration time is `null`, return `null`.
2. Calculate the current direction using the first matching condition from the following list:
If playback direction is `normal`,
Let the current direction be forwards.
If playback direction is `reverse`,
Let the current direction be reverse.
Otherwise,
1. Let d be the current iteration.
2. If playback direction is `alternate-reverse` increment d by 1.
3. There used to be a step here which seemed to be adding special handling for filling when the item ends on a repeat boundary but it seems like that is taken care of by the calcuation of iteration time and current iteration. Is anything actually needed here?

4. If `d % 2 == 0`, let the current direction be forwards, otherwise let the current direction be reverse.
3. If the current direction is forwards then return the iteration time.

Otherwise, return the iteration duration - iteration time.

Time transformations

Scaling the time

It is often desirable to control the rate at which a timed item progresses. For example, easing the rate of animation can create a sense of momentum and produce a more natural effect. Conversely, in other situations such as when modelling a discrete change, a smooth transition is undesirable and instead it is necessary for the timed item to progress in a series of distinct steps.

For such situations Web Animations provides timing functions that scale the progress of a timed item.

Timing functions take an input time fraction and produce a scaled output time fraction.

Example of a timing function that produces a ease-in effect. Given an input timing fraction of 0.7, the timing function scales the value to produce an output time fraction of 0.52.
By applying this timing function, time will appear to progress more slowly at first but then gradually progress more quickly.

Timing functions are applied to an iteration of a timed item.

Timing functions

A timing function takes an input time fraction in the range [0, 1] and produces an output time fraction whose range is unbounded (i.e. positive and negative infinity are permitted).

Timed items have one timing function associated with them. The default timing function is the linear timing function whose output is identical to its input. The linear timing function can be represented by the string “linear”.

The range of timing functions that may be applied to a given timed item depends on the type of the timed item.

Currently, the set of timing functions allowed on a timing group is not restricted. This has raised concern about complexity of implementation and also complexity of behavior with regards to fill modes and events. As a result, allowing the full set of timing functions on timing groups is considered at risk.

Alternatives are to either restrict timing functions on timing groups to the linear timing function or to a set of “simple” timing functions that have properties that alleviate some of the concerns with the more complex timing functions.

Scaling using a cubic Bézier curve

A common method of producing easing effects is to use a cubic Bézier curve to scale the time. The endpoints of the curve are fixed at (0, 0) and (1, 1) while two control points P1 and P2 define the shape of the curve. Provided the x values of P1 and P2 lie within the range [0, 1] such a curve produces a function that is used to map input times (the x values) onto output times (the y values). This arrangement is illustrated below.

A cubic Bézier curve used as a timing function.
The shape of the curve is determined by the location of the control points P1 and P2.
Input time fractions serve as x values of the curve, whilst the y values are the output time fractions.

Some example cubic Bézier timing functions are illustrated below.

The timing functions produced by each of the keyword values associated with cubic Bézier timing functions accepted by the `Timing.easing` member from the script interface.

A cubic Bézier timing function is a type of timing function defined by four real numbers that specify the two control points, P1 and P2, of a cubic Bézier curve whose end points are fixed at (0, 0) and (1, 1). The x coordinates of P1 and P2 are restricted to the range [0, 1].

The evaluation of this curve is covered in many sources such as [[FUND-COMP-GRAPHICS]].

A cubic Bézier timing function may be specified as a string using the following syntax (using notation from [[!CSS3-VALUES]]):

<cubic-bezier-timing-function> = ease | ease-in | ease-out | ease-in-out | cubic-bezier(<number> <number> <number> <number>)

The meaning of each value is as follows:

ease
Equivalent to cubic-bezier(0.25, 0.1, 0.25, 1).
ease-in
Equivalent to cubic-bezier(0.42, 0, 1, 1).
ease-out
Equivalent to cubic-bezier(0, 0, 0.58, 1).
ease-in-out
Equivalent to cubic-bezier(0.42, 0, 0.58, 1).
cubic-bezier(<number> <number> <number> <number>)
Specifies a cubic Bézier timing function. The four numbers specify points P1 and P2 of the curve as (x1, y1, x2, y2). Both x values must be in the range [0, 1] or the definition is invalid.

It has been proposed to extend `cubic-bezier` to allow multiple segments, using syntax such as the following:

```            `cubic-bezier( [ <number>{6} ; ]* <number>{4} )`
```

(i.e. the curve starts at (0, 0); each segment is defined by six numbers where the start point is the end of the previous segment and the numbers define the two control points and the end point. The last segment is defined by four numbers since the end point is fixed at (1, 1).)

This would provide a simpler and more compact syntax for tools trying to map arbitrary curves (e.g. bounce functions) to timing functions than trying to construct the corresponding chained timing function.

Timing in discrete steps

It is possible to scale a timed item's timing so that the timed item occurs in a series of discrete steps using a stepping function.

Some example step timing functions are illustrated below.

Example step timing functions. In each case the domain is the input time fraction whilst the range represents the output time fraction produced by the step function.
The first row shows the function for each transition point when only one step is specified whilst the second row shows the same for three steps.

A step timing function is a type of timing function that divides the input time into a specified number of intervals that are equal in duration. The output time, starting at zero, rises by an amount equal to the interval duration once during each interval at the transition point which may be either the start, midpoint, or end of the interval.

In keeping with Web Animation's model for endpoint exclusive interval timing (see ), the output time at the transition point is the time after applying the increase (i.e. the top of the step).

A step timing function may be specified as a string using the following syntax:

<step-timing-function> = step-start | step-middle | step-end | steps(<integer>[, [ start | middle | end ] ]?)

The meaning of each value is as follows:

step-start
Equivalent to steps(1, start);
step-middle
Equivalent to steps(1, middle);
step-end
Equivalent to steps(1, end);
steps(<integer>[, [ start | middle | end ] ]?)
Specifies a step timing function. The first parameter specifies the number of intervals in the function. It must be a positive integer (greater than 0). The second parameter, which is optional, specifies the point at which the change of values occur within the interval. If the second parameter is omitted, it is given the value end.

Paced timing

Insert a nice diagram showing how this works

A paced timing function scales the input time such that the resulting time values cause a referenced property that is animated by a specified animation effect, referred to as the paced effect, to change at a constant rate over the period of time for which the paced timing function applies.

A paced timing function may be specified as a string using the following syntax:

<paced-timing-function> = paced({ident})

The `{ident}` argument is an identifier [[!CSS3-VALUES]] representing the property name of the referenced property of the paced timing function.

For example, `paced(transform)` would indicate that the time should be scaled such that changes to the transform property occur at a constant rate.

The paced effect is the animation effect specified on the same timed item where the paced timing function is applied. As a result, paced timing functions can only be used on animations and not other types of timed items.

If any of the following conditions is true, the linear timing function is used for the purpose of timing model calculations:

Evaluating a paced timing function

The result of evaluating a paced timing function at input time is calculated as follows:

1. Let length list be a sequence of length values calculated using the rules defined in for the referenced property between each pair of keyframes that refers to the referenced property in a keyframe animation effect, or between each path segment in a motion path animation effect.

Need to confirm this approach is actually backwards-compatible with SVG with regards to motion-path behavior.

2. If the number of items in length list is 1 or less let the output of the timing function be input time and terminate these steps.
3. Let total length be the sum of values in length list.
4. If total length is zero let the output of the timing function be input time and terminate these steps.
5. Let distance be `input time × total length`.
6. Let current position be 0.
7. Let current distance be 0.
8. Let current length be the first value in length list.
9. While distance > ```current distance + current length```, perform the following steps:
1. Increment current position by 1.
2. Increase current distance by current length.
3. Let current length be the value at position current position in length list.
10. The output of the paced timing function is the result of evaluating: ```current distance / total length + (distance - current distance) / current length```

Is this algorithm necessary? Would a prose description suffice?

Calculating the length between two property values

The length between any two property values depends on the type of values as follows:

For numeric values,
length is defined as the absolute value of the difference between two values.

Need to explain how this applies to length values.

For colors,
length is defined as the result of evaluating the following expression
$\sqrt{{\left(\mathrm{ra}-\mathrm{rb}\right)}^{2}+{\left(\mathrm{ga}-\mathrm{gb}\right)}^{2}+{\left(\mathrm{ba}-\mathrm{bb}\right)}^{2}+255×255×{\left(\mathrm{aa}-\mathrm{ab}\right)}^{2}}$
`sqrt((ra - rb)^2 + (ga - gb)^2 + (ba - bb)^2 + 255*255*(aa - ab)^2)`

where the colors between which the length is to be measured are `rgba(ra, ga, ba, aa)` and `rgba(rb, gb, bb, ab)` respectively.

For transform values,

The definition of length for transform values depends on whether adjacent keyframe values of the transform property have matching first components. If the components are translate functions, then euclidean distance between the two translation vectors is used. If the components are scale functions, then the absolute difference between the average scale values is used. If the components are rotate functions, then the absolute difference between rotation angles is used.

If the components match but are not scale, rotate or translate functions, then the linear timing function is used for the purpose of timing model calculations.

If the components do not match, then interpolation between the components will require matrix decomposition. In this case the length is calculated using the euclidean distance between the translate components of the decomposed matrices.

Need a reference for euclidean distance.

This only refers to keyframe values. Need to explain what to do for paths.

Timing function chains

Timing function chains allow combining a series of timing functions in succession.

For example, an ease-in-out timing function followed by an ease-in timing function would produce the following combined timing function.

A timing function chain consisting of an ease-in-out cubic Bézier timing function followed by an ease-in cubic Bézier timing function.

A timing function chain is a type of timing function made up of an ordered list of one or more other timing functions not including another timing function chain where each element in the list is used to produce the scaled output for some non-overlapping segment of the timing function chain's input range.

A timing function chain may be specified as a string using the following syntax:

<timing-function-chain> = <primitive-timing-function>+

The timing function position list

It is possible to control the relative length of each link in the timing function chain by specifying positions for each timing function. For example, stretching the ease-in-out timing function to occupy three-quarters of the time would produce the following result.

A timing function chain with positions specified.

Often when animating keyframe animation effects or motion path animation effects it is useful to have the timing functions line up with the keyframes or path segments. Users of the model may provide this facility using the procedures defined in .

For example, a keyframe animation effect with frames at offsets 0, 0.75, and 1 and corresponding color values of red, blue, green might appear as follows with and without aligning the timing functions in the chain with the keyframes:

A comparison of distributing timing functions evenly across the interval or aligning them with keyframes.

This alignment is particularly useful with step timing functions because, unlike a regular step timing function, it can be used to achieve discrete changes regardless of the position of the keyframes.

By using step timing functions in a timing function chain and aligning the functions with the keyframes of an keyframe animation effect it is possible to produce discrete jumps in values regardless of the positioning of the keyframes.

When using alignment if the number of timing functions does not match the number of keyframes, the last timing function is repeated meaning that the above example can be achieved by simply specifying “step-end” once.

The mapping of the input range of a timing function chain's input range to the individual timing functions in the chain is determined by the timing function position list.

The timing function position list is:

• a sequence of floating-point values
• of length equal to the number of functions in the timing function chain plus 1
• whose values are in the range [0, 1],
• whose first and last values are 0 and 1 respectively, and
• whose values are sorted in ascending order.

Normalizing a timing function position list

Since a timing function position list may not always be provided or may not fit the format described above, the following procedures may be applied by users of the model to produce a suitable timing function position list given the following inputs:

• a timing function chain, chain, and
• either:
• a spacing mode of “distribute” or “align”; or
• a list of positions, input positions.

The specific steps for generating the normalized timing function position list is based on these inputs as follows.

The procedure when spacing mode is “distribute” or when one of the other procedures cannot be applied is called distribute spacing and is defined as follows:

1. Let length be the number of items in chain plus 1.
2. The normalized timing function position list is a list of floating point numbers of length length such that the value of the element at index n, with indices beginning at zero, is equal to ```n × 1 ÷ (length - 1)```.

The procedure when spacing mode is “align” depends on the timed item to which chain is being applied as follows:

If chain is being applied to an animation with an associated keyframe animation effect,

The normalized timing function position list is a list of numbers corresponding to the keyframe offsets of the keyframe animation effect's list of keyframes.

Note that this refers to the keyframe offset values after applying any procedures needed to fill in missing inputs such as .

If chain is being applied to an animation with an associated motion path animation effect,

The normalized timing function position list is a list of numbers where each value is the result of traversing the path elements in the motion path animation effect in order and calculating the ratio of the path length at the end of the path element and the total path length.

Path elements that correspond to moveto elements other than the initial moveto element that starts the path are skipped and do not generate values in the timing function position list.

Otherwise,
Use distribute spacing.

The procedure when a list of input positions is provided is as follows:

1. If any of the following conditions are true, use distribute spacing and terminate these steps:
• input positions is empty.
• input positions is not sorted in ascending order.
• The first and last values of input positions are not 0 and 1 respectively.

An implication of the above two conditions is that no values outside the range [0, 1] are allowed. If we allow keyframe offsets outside [0, 1] we will need to allow timing function offsets outside that range too for consistency.

2. The normalized timing function position list is simply input positions.

Note that even applying the above procedures, the normalized timing function position list may not be suitable since it may not be of the required length (as defined in ). Any difference in lengths is accommodated for by adjusting the timing function chain as follows:

1. Let positions length be the length of the normalized timing function position list.
2. Let functions length be the number of timing functions in timing function chain.
If positions length is greater than `functions length + 1`,
The normalized timing function chain is created by extending the list by duplicating the last timing function in the list until it is of length `positions length - 1`.
If positions length is less than `functions length + 1`,
The normalized timing function chain is created by truncating the timing function chain to length `positions length - 1`.
Otherwise,
The normalized timing function chain is simply the input timing function chain.

The behavior of duplicating the last timing function is useful for achieving an effect similar to SVG's “discrete” animation. For example,

```                trafficLight.animate(
[ { fill: 'red' }, { fill: 'orange' }, { fill: 'green' } ],
{ duration: 2,
easing: 'step-end',
easingTimes: 'align',
fill: 'forwards' }
);
```

If you want to do something that's truly similar to SVG and doesn't relying on fill forwards, i.e. it actually distributes the time evenly among the values over the length of the active interval, you currently need to duplicate one of the values. For example,

```                // Each color gets 1s of air time and then the effect is cleared
trafficLight.animate(
[ { fill: 'red' }, { fill: 'orange' },
{ fill: 'green' }, { fill: 'green' } ],
{ duration: 3,
easing: 'step-end',
easingTimes: 'align' }
);
```

If that is a common pattern we may need to investigate a “discrete” timing function that replicates SVG's behavior natively.

Evaluating a timing function chain

The following steps are used to evaluate a timing function chain at input time fraction x.

1. Let start index be the index of the last value in the timing function position list that is less than or equal to x when iterating from the start of timing function position list to the end.
2. If the value at start index in timing function position list is equal to one, decrement start index by one.
3. Let xstart be the value in the timing function position list at start index.
4. Let xend be the value in the timing function position list at ```start index + 1```.
5. Let f be the timing function in the timing function chain at start index.
6. Calculate the local input time fraction ```xlocal = (x - xstart) ÷ (xend - xstart)```
7. Calculate the local output time fraction ```ylocal = f(xlocal)```
8. The result of evaluating the timing function chain is then ```xstart + ylocal × (xend - xstart)```.

Calculating the transformed time

The transformed time is calculated from the directed time using the following steps:

1. If the directed time is `null`, return `null`.
2. Let iteration fraction be the result of evaluating ```directed time / iteration duration``` unless iteration duration is zero, in which case let iteration fraction be zero.
3. Let scaled fraction be the result of evaluating the timed item's timing function with iteration fraction as the input time fraction.
4. Return the result of evaluating ```scaled fraction × iteration duration```. If the scaled fraction is zero, let the result be zero.

This clarification is needed since the iteration duration may be infinity and the result of infinity multiplied by zero is undefined according to IEEE 754-2008.

Grouping and synchronization

While it is possible to set the timing properties of timed items individually, it is often useful to synchronize timed items so that they share common timing properties and maintain their temporal relationship. This is achieved using a timing group.

A simple example is illustrated below.

Using groups to share common timing properties.
(a) Shows setting a delay of 5 seconds on individual animations.
(b) Produces the same effect by setting the delay on the group.

When a timing group is directly associated with a player, the timed items associated with the timing group can be seeked, paused, and stopped as a unit.

A timing group is a type of timed item that contains an ordered sequence of zero or more timed items known as child timed items.

At a given moment, a timed item may be a child timed item of at most one timing group known as the parent timing group. The parent timing group cannot be the same timed item as the child timed item itself.

By nesting timing groups it is possible to create hierarchical tree structures. The following terms are used to describe the parts and properties of such structures and are defined in [[!DOM4]]:

Note that in applying these definitions to timed items, the term parent refers exclusively to a parent timing group and does not include the player which with a timed item may be directly associated despite the fact that conceptually the player acts as a parent time source.

The temporal relationship between a child timed item and its parent timing group is incorporated in the definition of inherited time (see ).

Relationship of group time to child time

The timing of the children of a timing group is based on the timing of the group. Specifically, times for the children are based on the parent's transformed time. With regards to repetition, this means the children operate inside an iteration of the parent.

For example, if a timing group has an iteration count of 2, then the children of of the group will all play twice since they effectively play inside the group's iterations.

Since children of an timing group base their timing on the group's transformed time, when the group repeats, the children play again.

Note that even in this case, the child timed items still have only one active interval. However, as a result of the parent's timing, the active interval is played twice.

If an iteration count is specified for the children of a group as well as for the group itself, the effect is as if the iteration count of the group was multiplied with the iteration count of the children.

Specifying an iteration count of 2 on an timing group and an iteration count of 3 on one of its children results in that child playing 6 times.

A further result of the children of a timing group basing their timing on the group's transformed time is that they cannot animate outside of the group's active interval. This is because the transformed time of a group will not change outside its active interval. This allows groups to clip the playback of their children.

In the first instance, a timed item has a negative delay and an infinite iteration count.
However, when a similar timed item is placed inside a timing group with a specified iteration duration it has the effect of clipping the child timed item's active interval.

Some further consequences of timing group children basing their timing on their parent group's transformed time are:

Types of timing groups

Timing groups can be used to provide different kinds of synchronization behavior for their children. For example, one type of timing group runs its children in parallel, whilst another type runs the children in sequence.

Compare the two arrangements illustrated below:

Two types of timing groups.
(a) is a parallel timing group where all the children run simultaneously.
(b) is a sequence timing group where the children run in turn.

Timing groups can also contain other timing groups which allows for more sophisticated synchronization. An example is illustrated below.

A sequence timing group that contains a parallel timing group as a child.
The parallel timing group waits for the previous child of the sequence timing group to finish, and then the children of the parallel timing group play simultaneously. After they have finished the next child of the sequence timing group plays.

Web Animations defines two types of timing groups.

Parallel timing groups
Children of the group play simultaneously. The start time of each child coincides with the beginning of the group's iteration interval.
Sequence timing groups
Children of the group play in turn beginning with the first child and proceeding to the last. The start time of each child is set to the end of the active interval of the previous sibling.

Parallel timing groups

A parallel timing group is a type of timing group that schedules its child timed items such that they play simultaneously.

The start time of children of a parallel timing group

The start time of a child timed item of a parallel timing group is zero.

The intrinsic iteration duration of a parallel timing group

The intrinsic iteration duration of a parallel timing group is based on the time when the last child timed item completes its active interval and is calculated using the following procedure.

1. Define the end time of a timed item as :

end time = ```start time + start delay + active duration```
2. The intrinsic iteration duration depends on the number of child timed items as follows,

If the group has no child timed items,
the intrinsic iteration duration is zero.
Otherwise,
1. Let maximum end time be the maximum value after calculating the end time of each child timed item in the group.
2. The intrinsic iteration duration is the result of evaluating ```max(0, maximum end time)```.

Note that for children of a parallel timing group, the start time will always be zero but it is included in the definition of end time here since the end time is also used to define the intrinsic iteration duration of a sequence timing group (see ).

Sequence timing groups

A sequence timing group is a type of timing group that schedules its child timed items such that they play in turn following their order in the group. This ordering is achieved by adjusting the start time of each child timed item in the group.

The start time of children of a sequence timing group

The start time of a child timed item of a sequence timing group is the end time of the child's previous sibling. If the child has no previous sibling the start time is zero.

When the active duration is positive infinity the behavior for calculating the end time of an timed item and the start time of subsequent children follows the usual behavior defined by IEEE 754-2008. As a result, if any of the children of a sequence timing group has an infinite active duration, any children that occur later in the sequence will not play.

Similarly, the above definition does not restrict start times to positive values and hence some children may not play due to a negative start delay on children that occur earlier in the group since their active interval may end before the group's start time.

Need to define if events fire in this case.

Because the start of the active interval is based on the sum of a timed item's start time and start delay, the active intervals of children of a sequence timing group need not run in strict sequence but can be shifted back and forth by using the start delay as shown in the following diagram.

A negative start delay can be used to cause the active interval of two children to overlap. Note that the start delay affects the start time of subsequent children in the group.

The intrinsic iteration duration of a sequence timing group

The intrinsic iteration duration of a sequence timing group is equivalent to the start time of a hypothetical child timed item appended to the group's children calculated according to the definition in unless that produces a negative value, in which case the intrinsic iteration duration is zero.

As a result, if the sequence timing group has no child timed items the intrinsic iteration duration will be zero.

Animations

Animations are a kind of timed item that apply an animation effect to an element or pseudo-element such as `::before` and `::first-line` [[!SELECT]] referred to as the target element.

Calculating the time fraction

Before passing the transformed time of an animation to its animation effect it is converted to a time fraction. The time fraction of a timed item is calculated according to the following steps:

If the iteration duration is zero,

the time fraction is as follows,

If local time < start delay,
Return the result of recalculating the transformed time using an iteration duration of 1.
Otherwise,
1. Let normalized active duration be the result of recalculating the active duration using an iteration duration of 1.
2. Return the result of recalculating the transformed time using a local time of ```start delay + normalized active duration``` and an iteration duration of 1.
Otherwise,
Return transformed time / iteration duration unless transformed time is `null`, in which case return `null`.

Since timing functions are allowed to produce output times outside the range [0, 1] it is possible that the value calculated for a time fraction also lies outside this range.

Animation model

The Web Animations animation model takes the time fractions and current iteration values produced by the timing model for a given animation and applies it as the input to the animation's animation effect.

The output of each animation effect is then combined with other animation effects using an animation stack before being applied to the target properties (see ).

Animation effects

An animation effect takes a time fraction and a current iteration value and uses them to calculate an intermediate animation value for its target properties. Each animation may have at most one animation effect associated with it.

Since the result of an animation effect is based on the time fraction and current iteration value, it is updated whenever the timing model is sampled. Note that changes to the timing model caused by using the programming interface do not cause the animation model (and hence animation effects) to be updated as described in .

Target properties

Each animation effect can have zero or more associated target properties. Not all properties may be animated by an animation effect. Properties that may be animated by an animation effect are defined as animatable. The set of animatable properties is is defined in .

An animation effect that targets a property that is not animatable will have no effect on the property. However, an animation that applies such an animation effect will still exhibit the usual behavior for a timed item such as firing timing events and occupying time in a sequence timing group.

Target property types

The specific operations involved in animating a target property differ based on the property type. For example, the specific procedure for animating a property that specifies a color will differ from a property that specifies a length. Each animatable property defines one or more property types to use when animating.

In order to produce a smooth change between property values, a procedure for interpolation is required. A given property type is interpolable if there is a procedure defined to interpolate between two values of that type.

In order to support accumulation and additive composition, a procedure for addition is required. A given property type is additive if there is a procedure defined to add two values of that type.

An initial list of property types and their procedures for interpolation and addition is given in . In addition to this initial list, specifications that define CSS properties may provide additional property types to define the procedures for interpolation and addition of the values of those properties.

Intermediate animation values

Given a time fraction, a current iteration, and an underlying value, an animation effect produces an intermediate animation value for each animatable target property. Before being applied to the target properties, these intermediate animation values are composed together using the process defined in .

The use of the term 'value' here is misleading, as the output of the effect stage can not be resolved to a concrete value until it is composited with an underlying value. This takes place in the compositing stage, when the animation stack is resolved. It is therfore more accurate to describe the output of the effect stage as a set of values and corresponding composition operations, which are used to modify an underlying value. The same is true of the unaccumulated animation value.

Use of this more precise terminology will also allow the algorithm for accumulation to be specified more precisely.

An intermediate animation value is established by first calculating an unaccumulated animation value and then applying accumulation behavior.

Unaccumulated animation values

The unaccumulated animation value is the result of evaluating an animation effect for a given target property, time fraction and underlying value independent of the current iteration. The procedure for calculating this value depends on the specific type of animation effect and is defined subsequently (see and ).

Accumulating animation values

Animation effects may be defined such that as the animation that is applying them is repeated, the intermediate animation value builds on the value produced by previous iterations. This behavior is called accumulation.

The accumulation behavior of an animation effect is specified by the animation effect's accumulation operation property. The accumulation operation property takes one of the following two values.

sum

The intermediate animation value produced by the animation effect for a given property is the sum of the unaccumulated animation value for the given time fraction and the final intermediate animation value of the previous iteration (i.e. the result of evaluating the intermediate animation value with a time fraction of 1, and a current iteration of ```current iteration - 1```).

If the current iteration is zero, the intermediate animation value is just the unaccumulated animation value.

none
The intermediate animation value for the animation effect is just the unaccumulated animation value.

Accumulation behavior is only applied for target properties that are additive. For target properties whose values are not additive, an accumulation operation of none is used.

Accumulation behavior is only applied for keyframe animation effects when the composition operation is uniform across all keyframes. For keyframe animation effects where the composition operation varies, an accumulation operation of none is used.

The definition of accumulation here needs review. The intention is to provide compatible behavior with SVG but also needs to account for the possibility of timing functions whose final output value is not 1 (if we allow that), and possible differences in the way composition is defined.

Combining animations

After calculating the intermediate animation values for an animation effect they are applied to the animation effect's target properties.

Since it is possible for multiple in effect animations to target the same property it is often necessary to combine the results of several animation effects together. This process is called compositing and is based on establishing an animation stack for each property targetted by an in effect animation effect.

After compositing the results of animation effects together, the composited result is combined with other styles applied to the target property.

An overview of this arrangement is illustrated below:

Overview of the application of intermediate animation values to their target properties.
The results of animation effects targetting the same property are composited together using an animation stack.
The result of this composition is written to an override stylesheet that is more important than other stylesheets but less than any `!important` rules.

For the first part of this operation—combining intermediate animation values that target the same property— it is necessary to determine both how the animation effects associated with the animations are combined with one another, as well as the order in which they are applied, that is, their relative priority.

The matter of how intermediate animation values are combined is governed by any composition operations associated with the corresponding animation effects.

The relative priority of intermediate animation values is determined by an animation stack established for each animated property.

The animation stack

Associated with each property targetted by one or more animation effects is an animation stack that establishes the relative priority of the animation effects.

The relative priority of any two animation effects, A and B, within an animation stack is established by comparing the properties of the animations applying A and B as follows:

1. Let the associated player of an animation effect be the player associated with the animation that is applying the animation effect to the property with which this animation stack is associated.
2. Sort A and B by applying the following conditions in turn until the order is resolved,
1. Sort A and B using any custom animation priority specified for A and B so that lower priorities sort first.
2. Sort A and B by the player start time of the associated player of each of A and B so that earlier times sort first.
3. Sort by the player sequence number so that lower sequence numbers sort first.
4. Sort A and B in tree order.

Animation effects that sort earlier have lower priority.

The custom animation priority

Each animation effect has an associated numeric custom animation priority that is used to provide high-level control of animation priority for specifications layered on top of Web Animations. The initial value of the custom animation priority is zero.

Note that the custom animation priority is primarily intended to be used to prioritize animation effects at a high-level, such as to prioritize animations by type. For example, it can be used to ensure that CSS Animations always override CSS Transitions.

It is possible to control animation priority at a lower-level by setting the player start time appropriately, (possibly after making compensatory adjustments to the start delay of the source content) or influencing the player sequence number by controlling when players are created.

Calculating the result of an animation stack

In order to calculate the final value of an animation stack, the intermediate animation values of each animation effect in the stack are combined in order of priority from lowest to highest priority.

Each step in the process of evaluating an animation stack takes an underlying value as input. The initial underlying value is the base value of the target property as defined in .

For each animation effect in the stack, the appropriate intermediate animation value from the animation effect is combined with the underlying value to produce a new value. This resulting value becomes the underlying value for combining the next animation effect in the stack.

The final value of an animation stack, called the composited value, is simply the result of combining the intermediate animation value of the final (highest priority) animation effect in the stack with the underlying value at that point.

Animation composition

The specific operation used to combine an intermediate animation value with an underlying value is determined by the animation effect that produced the intermediate animation value and is called the composition operation.

This specification defines two common composition operations as follows:

replace
The result of compositing the intermediate animation value with the underlying value is simply the intermediate animation value.

The intermediate animation value is added to the underlying value. For property types where addition is defined such that it is not commutative, the order of the operands is ```underlying value + intermediate animation value```.

If intermediate animation value and underlying value are not of the same property type, or if they are of the same property type but that property type is not additive, replace behavior is applied.

Combining with other styles: the override stylesheet

Applying a composited value to a property depends on establishing an override stylesheet.

The override stylesheet contains composited animation values and acts with a higher priority than all other stylesheets. However, `!important` rules from all other stylesheets act with a higher priority than the override stylesheet. The override stylesheet is regenerated each time the animation model is updated (see ).

The composited value calculated for a property is applied using the following process.

1. Calculate the base value of the property as the value generated for that property by computing the used value [[!CSS21]] for that property in the absence of the override stylesheet.
2. Establish the animation stack for the property (see ).
3. Calculate the composited value of the animation stack passing in the base value of the property as the initial underlying value (see ).
4. Insert the composited value into the override stylesheet.

Keyframe animation effects

A keyframe animation effect is an animation effect that produces intermediate animation values for its target properties by interpolating between a series of property values positioned at fractional offsets.

Each set of property values indexed by a positional offset is called a keyframe.

The positional offset of a keyframe is a value in the range [0, 1]. The list of keyframes for a keyframe animation effect is sorted in ascending order by the positional offset of each keyframe.

Unlike CSS syntax, timing functions are not directly associated with a keyframe. Rather, this is achieved by setting a timing function chain.

If, due to a timing function specified on the timed item from which the time fraction is derived, the time fraction lies outside the range [0, 1], the specified keyframe property values are extrapolated to cover the extended range.

The behavior when keyframes overlap or have unsupported values is defined in .

Each keyframe animation effect has an associated composition operation that specifies how it is combined with other animation effects in the animation stack.

Furthermore, each keyframe may also have an associated composition operation that is applied to all values specified in that keyframe. If no composition operation is specified for a keyframe, the composition operation specified for the keyframe animation effect is used.

The unaccumulated animation value of a keyframe animation effect

The unaccumulated animation value of a single property referenced by a keyframe animation effect as one of its target properties, for a given time fraction and underlying value is calculated as follows.

1. Let target property be the property for which the unaccumulated animation value is to be calculated.
2. If target property is not animatable abort the procedure since the effect cannot be applied.
3. Let time fraction be the time fraction for which the unaccumulated animation value is to be calculated.
4. Let underlying value be the current underlying value.
5. Define the neutral value for composition as a value which, when combined with an underlying value using the add composition operation, produces the underlying value.

Note that this definition does not require determining a suitable zero value for each possible property type. This behavior could be realized, for example, by use of a sentinel value.

6. Let property-specific keyframes be a copy of the list of keyframes specified on the effect.
7. Remove any keyframes from property-specific keyframes that do not have a property value for target property.
8. If property-specific keyframes is empty, return underlying value.
9. If there is no keyframe with a positional offset of 0, create a new keyframe with a positional offset of 0, a property value set to the neutral value for composition, and a composition operation of add, and add it to the beginning of property-specific keyframes.
10. Similarly, if there is no keyframe with a positional offset of 1, create a new keyframe with a positional offset of 1, a property value set to the neutral value for composition, and a composition operation of add, and append it to the end of property-specific keyframes.
11. Iterate over each keyframe in property-specific keyframes and for each keyframe, if:
perform the following steps:
1. Let value to add be the property value of target property specified on keyframe.
2. If the property type of underlying value and value to add is the same and is additive, set the property value of target property for keyframe to ```underlying value + value to add```.
12. If time fraction < 0 and there is more than one keyframe in property-specific keyframes with a positional offset of 0, return the property value for target property of the first keyframe in property-specific keyframes.
13. If time fraction ≥ 1 and there is more than one keyframe in property-specific keyframes with a positional offset of 1, return the property value for target property of the last keyframe in property-specific keyframes.
14. Let start keyframe be the last keyframe in property-specific keyframes whose positional offset is less than or equal to time fraction and less than 1. If there is no such keyframe (because, for example, the time fraction is negative), let start keyframe be the last keyframe whose positional offset is 0.
15. Let end keyframe be the next keyframe in property-specific keyframes after start keyframe.
16. Let start offset be the positional offset of start keyframe.
17. Let end offset be the offset of end keyframe.
18. Let interval distance be the result of evaluating ```(time fraction - start offset) / (end offset - start offset)```
19. Return the result of interpolating between the property values defined for start keyframe and end keyframe using the procedure defined for their property type with interval distance as the interpolation parameter.

Note that this procedure assumes the following about the list of keyframes specified on the effect:

• Each keyframe has a specified positional offset in the range [0, 1].
• The list of keyframes is sorted in ascending order by positional offset.
• Each specified property value is a valid and supported value.
• For a given property, there is a most one specified property value on each keyframe.

It is the responsibility of the user of the model (for example, a declarative markup or programming interface) to ensure these conditions are met.

Note that this procedure permits overlapping keyframes. The behavior is that at the point of overlap the output value jumps to the value of last defined keyframe at that offset. For overlapping frames at 0 or 1, the output value for time fractions less than 0 or greater than or equal to 1 is the value of the first keyframe or the last keyframe in keyframes respectively.

In the presence of certain timing functions, the input time fraction to an animation effect is not limited to the range [0, 1]. Currently, however, keyframe offsets are limited to the range [0, 1] and property values are simply extrapolated for input time fractions outside this range. We are considering removing this restriction for the following reasons.

We are considering removing the restriction since cases exist where it is useful to be able to specify non-linear changes in property values at time fractions outside the range [0, 1].

While this effect could be achieved by careful modification of the timing function, this approach is complex and breaks the model's separation of timing concerns from animation effects. An example is an animation which is subject to an 'overshoot' timing function and which has an effect that sweeps through a non-linear color space.

Procedure for evenly distributing keyframes

Whilst the Web Animations model assumes a sorted list of keyframes with specified positional offsets in the range [0, 1] many users of the model require a facility for automatically distributing keyframes when positional offsets are not provided. A procedure for evenly distributing keyframes with unspecified positional offsets is provided below.

Given a list of keyframes whose positional offets are either a real number in the range [0, 1] or unspecified, we define such as list as loosely sorted by offset if, for each keyframe in the list that has a specified offset, the offset is greater than or equal to the offset of the previous keyframe in the list with a specified offset, if any.

Given a list of keyframes, initial keyframe list, that is loosely sorted by offset we can evenly distribute the keyframes with unspecified positional offsets between those frames with specified offsets using the following procedure:

1. Let distributed keyframes be a copy of initial keyframe list.
2. If distributed keyframes contains more than one keyframe and the positional offset of the first keyframe in distributed keyframes is unspecified, set the positional offset of the first keyframe in distributed keyframes to 0.
3. If the positional offset of the last keyframe in distributed keyframes is unspecified, set its positional offset to 1.
4. Set the offset of all keyframes in distributed keyframes without a specified positional offset as follows. For a keyframe, k, without a specified offset, if:
• a is the positional offset of the last keyframe with a specified offset appearing in distributed keyframes before k,
• b is the positional offset of the first keyframe with a specified offset appearing in distributed keyframes after k,
• n is the number of keyframes between a and b, and
• i is the index of k among the keyframes between a and b such that the first keyframe has index 1 and the last keyframe has index n;

then the offset of k is ```a + (b - a) * i / (n + 1)```

5. Return distributed keyframes.

Motion path animation effects

A motion path animation effect is an animation effect that produces transform unaccumulated animation values such that a target element follows a specified geometric curve commonly referred to as a “motion path”.

The path of a motion path animation effect is provided by an SVG Path, as defined in SVG [[!SVG11]]. A path consists of a list of path elements.

The automatic rotation flag of a motion path animation effect, if set, specifies that the unaccumulated animation value generated by the motion path animation effect produces a rotation that matches the directional tangent vector of the path.

The rotation angle parameter of a motion path animation effect specifies a constant rotation that applies to the target transform in addition to any rotation generated by setting the automatic rotation flag.

Each motion path animation effect has an associated composition operation that specifies whether the unaccumulated animation values generated by the effect replace the underlying value or add to it.

The unaccumulated animation value of a motion path animation effect

The unaccumulated animation value of a motion path animation effect for a given time fraction and underlying value is given by the following process:

1. Determine the current path element and element fraction for the given time fraction using the procedure defined in .
2. Calculate the rotation value for the current path element and element fraction using the process defined in .
3. Calculate the translation value for the current path element and element fraction using the process defined in .
4. Let the transform value be the result of combining the rotation value and translation value by constructing a transform list consisting of the translation value followed by the rotation value.
5. The unaccumulated animation value of the motion path animation effect depends on the value of its composition operation as follows,
If the composition operation of this motion path animation effect is replace,
the unaccumulated animation value of the effect is transform value.
Otherwise,
the unaccumulated animation value of the effect is the result of adding transform value to the underlying value according to the process defined in .

Determining the current path element and element fraction

Each element in the path (excluding moveto elements) is allocated an equally sized non-overlapping segment, with segments collectively partitioning the range [0, 1].

The current path element is the path element corresponding to a given time fraction.

The element fraction represents the offset into the current path element at the given time fraction.

The current path element and element fraction for a given time fraction, progress, are determined by following the steps corresponding to the first matching condition from below:

If progress is greater than or equal to 1,
the current path element is the last element in the path, and the element fraction is 1.
If progress is less than 0,
the current path element is the first element in the path, and the element fraction is 0.
Otherwise,
1. Let effective element list be a clone of the list of path elements with all moveto elements removed.
2. Let time index be progress multiplied by the number of elements in effective element list.
3. Let current element be the element in the effective element list at the index given by `floor(progress)`.
4. Let element fraction be the value given by ```progress - floor(progress) ```.

Calculating the rotation value of a motion path animation effect

For a given path element and element fraction, the rotation value at that point is calculated according to the steps corresponding to the first matching condition from below:

If the automatic rotation flag is not set,
the rotation value of the given path element is the rotation angle.
Otherwise,
the rotation value of the current element is the sum of:

For continuous path elements (all elements except moveto), the angle of the tangent vector for the purpose of these calculations is defined to be an integer multiple of 2π different from the value given by standard mathematical formulae for tangents to curves in 2 dimensional space.

What does “different from” mean here?

For moveto path elements, which are discontinuous, the angle of the tangent vector for the purpose of these calculations is always an integer multiple of 2π.

Any multiple?

At non-smooth junction points, the angle of the tangent vector for the purpose of these calculations is determined by the tangent to the curve after the junction.

The initial value of the angle of the tangent vector is computed using the first element of the curve, and is always in the range [0, 2π).

Single continuous path elements must never produce tangent vector angles that are discontinuous over their defined region. This implies that a single unique solution is available for all points on continuous path elements.

When computing angles after discontinuous or non-smooth jumps, multiple possible solutions may be available. These solutions will differ by integer multiples of 2π. In such cases the solution that lies closest to the previous tangent angle is used.

Please see for a non-normative treatment of this topic.

Calculating the translation value of a motion path animation effect

For a given path element and element fraction, the translation value is determined using the following procedure:

1. Let length be the length of the given path element.

Need a reference to how this is calculated even if it's just a pointer to SVG (which says pretty much nothing).

2. Let element distance be the result of evaluating `element fraction × length`.
3. Let point be the unique point along the current element which is element distance along the path from the start of the path.

What is the significance of “unique point” here?

4. The translation value is the translation transform that transforms the point at the start of the path to point.

The length of a path element is determined, where possible, via closed-form solutions. For some path elements (e.g. beziers) a closed-form solution is not generally possible, and approximations should be used.

The length of a moveto element is always 0.

Please see for a full non-normative treatment of this topic.

Need to describe how transform-origin is applied.

Animatable properties

CSS Properties

Unless specified otherwise, all CSS properties are animatable. Examples of properties which are explicitly marked as not animatable are those defined in [[CSS3-TRANSITIONS]] and [[CSS3-ANIMATIONS]].

[[CSS3-TRANSITIONS]] requires future CSS specifications to provide an ‘Animatable:’ line for each newly defined property. This line defines how animation occurs. ‘Animatable: none’ in this regard merely means that a property is not continuously animatable, that is, not interpolable.

This also applies to CSS properties defined in SVG [[SVG11]] which are likewise animatable except where explicitly noted otherwise.

SVG Attributes

There are a number of SVG attributes which do not map to CSS properties but which are nevertheless animatable. The procedures for animating these attributes are defined in a forthcoming SVG Animation specification.

Animation of property types

The specific procedures for interpolation and addition of animation values for common CSS value types are defined below.

For a given pair of animation values, the procedures depend on the types of the two values. If there is no set of procedures matching the particular types of the two values, the default procedures defined in is used.

In CSS transitions the interpolation procedure is determined by the property, not the specific values. Do we really want to define this in terms of the values in question? That seems to remove flexibility to make different properties with the same value types interpolate differently or turn off additive behavior on a per-property basis.

For each set of procedures, a common notation is used. For interpolation,

• Vres is the result of the interpolation operation,
• p is the interpolation parameter, and
• Vstart and Vend are the animation values representing the start and end of the interpolation interval respectively.

• Vres is the result of the addition operation,
• Va and Vb are the two animation values to be added.

When an addition procedure is not commutative, Va represents the first term of the operation and Vb represents the second.

In some cases the mechanism by which interpolation and addition is achieved differs from that defined in [[CSS3-TRANSITIONS]]. However, the observable results of these operations should be identical.

For example, in [[CSS3-TRANSITIONS]] length values are always converted to computed style pixel lengths and interpolated as numbers, whereas in this specification interpolation between different length units is defined using calc expressions.

Animation of like types

When the types being interpolated or animated equal the following specific procedures are used.

Note that in all cases, if the result of the addition is specified by a calc expression and the units of Va and Vb are related by a constant scalar multiple then the result of the calc expression is evaluated as defined in [[CSS3-VALUES]] before being returned.

What does “being returned” mean here?

For example, the CSS ‘px’ unit is related to the CSS ‘in’ unit by a constant scalar multiple of 96 (i.e. 96px = 1in). On the other hand, the CSS ‘em’ unit is not related to the ‘in’ unit by a constant scalar multiple.

The <integer>, <number> and <percentage> types

Interpolation is calculated as defined in [[CSS3-TRANSITIONS]].

This is weird: we partly redefine what is already described in [[CSS3-TRANSITIONS]] and party reuse its definitions. We should either redefine everything here, or simply extend what is there.

Addition is calculated as Vres = Va + Vb.

The <length>, <angle>, <time> and <frequency> types

Interpolation is calculated as Vres = (1 - p) * Vstart + p * V end.

Addition is calculated as Vres = calc(V a + Vb).

The <resolution> type

Do we want to interpolate this?

Interpolation is calculated as Vres = (1 - p) * Vstart + p * Vend.

Addition is calculated as Vres = calc(Va + Vb).

The <color> type

Interpolation is calculated as defined in [[CSS3-TRANSITIONS]].

Addition is performed on each RGBA color component in premultiplied space, clamping so it is within the range specified in [[CSS3-COLOR]].

What we do for addition depends on why we're adding. As defined here, the result will tend to saturate to opaque white.
Do we clamp upon each addition, or wait until the end? Does it make a difference if we never actually subtract?

The <image> type

Interpolation is performed using the cross-fade() function as defined in [[CSS4-IMAGES]]:

Vres = cross-fade(p, Vstart , Vend).

Addition is defined as the composition of Va over Vb, with Va and Vb aligned at their top left corners. The height and width of the result is the maximum of the heights and widths of Va and Vb. Any result pixels outside the bounds of Va or Vb are defined to be rgba(0, 0, 0, 0).

Probably need to spell out that “over” here refers to the Porter-Duff operator of that name (if, indeed, that is what it means here).
This does not match the saturating behavior defined for addition of colors.

The <position> type

Before interpolation or addition, any shorthand is expanded as described in [[CSS21]] to include both horizontal and vertical positions. Keywords are converted to their equivalent percentage values as described in [[CSS21]].

Interpolation or addition is performed on each provided value in accordance with its type.

The <transform-function> type

Interpolation is calculated as defined in [[CSS3-TRANSFORMS]].

Addition is calculated as an accumulation as defined in [[CSS3-TRANSFORMS]].

Animation of non-matching primitive types

In general, non-matching primitive types cannot be interpolated or added. Non-matching primitive types may only be interpolated or added if the property value they are defined on allows both those types, for example <length> and <percent>. In these cases, the CSS calc() function as defined in [[CSS3-VALUES]] is used.

For interpolation:

Vres = calc((1 - p) * Vstart + p * Vend).

Vres = calc(Va + Vb).

Animation of keywords and primitive types

If keyword value is be defined as equivalent to a primitive type, either directly, or via some intermediate calculation, the equivalent primitive type is be used, and interpolation and addition calculated are defined in or .

In the case that a keyword maps onto a finite ordered list of values with a determinable spacing between them, then a step-wise interpolation is used. For example, the font-weight property accepts an ordered list of values from 100 to 900 in steps of 100. The interpolation in this case is defined as ((1 - p) * Vstart + p * Vend), rounded to the nearest member of the list. Addition in this case is defined as (Va + Vb), clamped to remain within the specifed list of values.

In all other cases, the keyword value is not interpolable. Result of add is the right hand side.

Animation of shorthand properties

Shorthand properties are animated as defined in [[CSS3-TRANSITIONS]].

We probably should just duplicate that text here. For example, it's not obvious from that sentence how addition works since transitions has not concept of addition.

Animation of CSS calc expressions

For interpolation:

Vres = calc((1 - p) * Vstart + p * Vend).

Vres = calc(Va + Vb).

Animation of transform lists

Interpolation of CSS and SVG transform lists is performed as defined in [[CSS3-TRANSFORMS]]

Addition of CSS and SVG transform lists is performed by appending Vb to Va.

Default animation procedures

In the case that no specific set of procedures matches the pair of animation values, the following default procedures are used.

Note that the neutral value for composition does not match any value type and thus all calculations involving the neutral value for composition will use the default algorithms.

Given the output p of a timing function, the result Vres of interpolating between two values, Vstart and Vend is given by

If 0 ≤ p < 0.5
Vres = Vstart
Otherwise,
Vres = Vend
Note that interpolation is never performed on invalid values.

Addition is between two values Va and Vb. The result Vres is given by

Vres = Vb
unless Vb is the neutral value for composition, in which case
Vres = Va

Custom effects

In some situations the animation effects provided by Web Animations may be insufficient. For example, the animation effects defined here are only able to target certain CSS properties. They are unable, therefore, to modify the `currentScale` property of an SVG element to smoothly zoom the viewport without affecting the document content.

In such cases, where the provided animation effects do not provide needed functionality, an effect defined by script may be used. Such custom effects receive a time fraction and current iteration from the timing model and are responsible for producing an effect corresponding to the specified time.

Using an effect defined in script it is possible to animate not only otherwise un-animatable attributes and properties, but potentially anything that is accessible via script, including even producing audio or creating vibrations.

For example, using a custom effect that draws to a `canvas` element, it is possible to produce a complex animated effect featuring patterns that may be difficult to create using CSS or SVG. Compared to using the WindowAnimationTiming interface, this approach ensures the animation is frame-rate independent and can be paused, reversed, eased with timing effects, accelerated, synchronized with other animations, and be controlled in the same manner as any other Web Animations animation without any additional programming.

A custom effect is an author-defined programming callback that is passed timing information whenever a sample is performed.

Execution order of custom effects

Since custom effects, unlike animation effects, are not limited to a single target property, the steps for assessing their order of execution differs from animation effects.

Custom effects are executed after all animation effects have completed and applied their result to their targets (see ).

Need to define this more precisely. Are styles flushed? Presumably they are. Can we suspend reflow for the duration of executing the script-based animation effects and just do it once afterwards?

Within the set of custom effects, the order of execution is initially the same as that defined for animation effects in . However, custom effects may also override this ordering through a priority property associated with the effect. This priority property, if defined, specifies the order in which the callbacks are executed such that the callback of the custom effect with the least priority is executed first.

In deciding which of two custom effects, A and B, should be executed first, the following rules are applied.

1. Sort A and B based on their priority properties such that lower priorities are sorted first. If either does not have a defined priority, then treat the priority as being zero for the purposes of sorting.
2. If A and B have the same priority, sort A and B using the procedure defined for sorting animation effects in .

Items sorted earlier are executed before those sorted later.

Timing events

Possibly move this section into .

The current event model has two undesirable consequences:

• There are two different modes in which events are dispatched: seeked mode and regular mode. Some applications will need to provide different handling based on the mode which complicates handling. Other applications will simply assume seeked mode behavior since the mode can change based on parameters outside the application's control (such as being switched to a background tab causing the refresh rate to drop and the maximum event threshold to be exceeded).
• Uneased timing can cause events to be reordered with respect to how they are visually percieved and can also cause events to be delivered with timestamps in the future.

One alternative under consideration is as follows:

• Primitive onstart / onend events that fire only when an animation first starts playing and last stops playing.
• An onchange event that fires when the play state (e.g. current iteration, fill state, etc.) of an Animation changes, and provides a summary only of ther changes since the last sample. No more than one event is generated per animation per sample.
• The list of actual changes associated with a change event would be lazily generated since this could be costly to generate for large sample intervals.

Another possibility is that rather that switching to seeked event dispatch when there are many events to dispatch due to delays between samples, to instead ignore the delay (as is required for SVG). This would make seeked event dispatch predictable. This approach, however, does not address the issues regarding uneased timing.

As timed items play they report changes to their status through timing events.

Timing events are a property of the Web Animations timing model. As a result they are dispatched even for animations that do not have an associated animation effect, for animations whose target element is not rendered because it or a parent element has display property of none, and for timed items that perform no animation such as timing groups.

Relationship to CSS and SVG events

CSS defines `AnimationEvent`s and `TransitionEvent`s and SVG defines `TimeEvent`s. The proposal here is to dispatch TimingEvents in parallel to these events.

A key difference is that the target of a TimingEvent is a TimedItem and not content. This model leaves firing of events at content up to the declarative mapping onto the model (e.g. CSS or SVG). This approach makes the Web Animations model more self-contained whilst permitting different mappings for different markup. For example, CSS fires events at the target element whilst SVG fires events at the element that generated the animation.

Types of timing events

timingstart

Occurs at the moment when a timed item enters its active interval (from either direction).

Note that if the parent timing group starts a new iteration, this is treated as if this element momentarily exited its active interval (producing a new timingend event), and entered it again (producing a new timingstart event).

• Bubbles: yes
• Cancelable: no
• Context Info: localTime, documentTime, iterationIndex, seeked
timingiteration

Occurs at the moment when a repeating timed item's current iteration changes value excluding changes to and from `null`.

Note that if the parent timing group starts a new iteration, this is treated as if this element momentarily exited its active interval (causing the current iteration to become `null`), and entered it again (producing a new value for current iteration) and hence producing no timingiteration event since the only changes to current iteration are to and from `null`.

• Bubbles: yes
• Cancelable: no
• Context Info: localTime, documentTime, iterationIndex, seeked
timingend

Occurs at the moment when a timed item leaves its active interval (from either direction).

• Bubbles: yes
• Cancelable: no
• Context Info: localTime, documentTime, iterationIndex, seeked
timingcancel

Occurs when a timed item loses its association with a player.

• Bubbles: yes
• Cancelable: no
• Context Info: None

Can we rename these to just start, iteration, end, and cancel? They are only fired at timed items, never DOM nodes, so they won't clash with other events. Is that enough or do the names need to be globally unique?

Uneased timing

Timing events in Web Animations rely on a mode of operating the timing model that does not apply timing functions called uneased timing. There are two reasons for this:

An analogue is a graphics editing program where the user can apply a blur filter to a geometric shape. The graphics program may draw a selection box around the bounding box of the geometric shape ignoring the fact that the blur stretches (infinitely) beyond the selection box.

Furthermore, since fill modes affect the calculation of times in ways that obscure the boundaries of the active interval they are also ignored when operating in uneased time.

The uneased timing of a timed item refers to performing any of the calculations defined for the timed item with the following exceptions:

For example, the uneased inherited time of a timed item is calculated using the regular definition of inherited time after applying the two modifications to the timing of the item and its ancestors noted above.

Normally the time value used as input to a child timed item of a timing group is the group's transformed time. However, since uneased timing does not apply timing functions, we refer to uneased child time which is equivalent to both uneased transformed time and uneased directed time.

Inverse timing calculations

For times calculated using uneased timing it is possible to perform the reverse operation to, for example, convert times from a child timed item to that of its its parent timing group or timeline.

Calculating the uneased local time from uneased child time of a given timed item requires recording the iteration index that corresponds to the uneased child time and is calculated as follows.

1. Let item be the timed item for which the uneased local time is to be calculated.
2. Let child time be the uneased child time to be converted.
3. Let iteration index be the value of current iteration corresponding to child time.
4. Calculate the current direction of item using the procedure defined in substituting iteration index for the current iteration.
5. Let the uneased iteration time be the result corresponding to the first matching condition from below.

If the current direction is forwards,
child time
Otherwise,
`iteration duration - child time`
6. Let the uneased scaled active time be the result corresponding to the first matching condition from below.

If iteration duration is zero,
zero
If uneased iteration time equals iteration duration,
`repeated duration * start offset`
Otherwise,
```iteration index * iteration duration + uneased iteration time```
7. Let the uneased active time be the result corresponding to the first matching condition from below.

If the playback rate is zero,
positive infinity unless scaled active time is zero, in which case the active time is zero
If the playback rate is positive,
```(uneased scaled active time - start offset) / playback rate```
Otherwise,
```(uneased scaled active time - start offset) / playback rate + active duration```
8. Return ```uneased active time + start delay```.

Note that the above procedure is only defined when the uneased child time is defined, that is, not `null`.

The uneased inherited time from uneased local time is simply the sum of the uneased local time and the timed item's start time.

The timeline time from the current time of a player is calculated as follows.

```timeline time = (current time + time lag) / playback rate + start time```

If the player's playback rate is zero, the timeline time is undefined. The handling of an undefined value depends on the context in which it is used. Typically, a current time value for the timeline is available and this is used in place of the undefined value.

Provided that the current iteration values used when calculating the uneased local time are recorded, it is possible, by applying the above definitions in succession, to calculate the time value of a timeline corresponding to the uneased local time of a timed item associated with that timeline.

Event parameters

The event local time is the uneased local time of the timed item that generated event at the moment the event is scheduled to occur. This time is constrained by the timing of the parent timing group's iteration interval such that when converted to an uneased iteration time in the parent's iteration time space (see ) it lies within the range 0 ≤ uneased iteration timeiteration duration (of the parent).

The event timeline time is the result of converting the event local time into the time space of the timeline that sampled the timed item. If is calculated using the procedures defined in .

The event iteration index is the value of the timed item's current iteration and moment the event is scheduled to occur.

The seeked dispatch flag is a boolean value set to `true` if this event was generated as a result of applying seeked event dispatch.

Propagation path

The propagation path for a timing event generated by item, is simply item itself.

Note that unlike `AnimationEvent`s and `TransitionEvent`s in CSS, and `TimeEvent`s in SVG, all of which target an Element; the target of a timing event is a timed item.

Sequence of events

The sequence in which timing events are queued is as follows:

1. timingcancel events are queued first. The sequence within timingcancel events is as follows:
1. Events generated by a timed item associated with a player that was created earlier precede events generated by a timed item associated with a player created later.
2. Events generated by the same player are queued in the order that the unattached timed items that generated the events appear in the player's queue of unattached timed items (see ).
2. All other events are ordered by event timeline time with earlier times preceding later times in the queue.
3. For events with the same event timeline time, the following rules are applied in succession until the order in the queue is resolved,
1. timingstart events of parents precede all events generated by children.
2. timingiteration events of parents precede all events generated by children during the iteration corresponding to the timingiteration event's event iteration index.
3. timingend events of parents follow all events generated by children.

In effect, child timed items operate inside an iteration of their parent timing group and hence events generated by children are wrapped by their parents' events.

4. For events generated by different timed items, timingend events precede timingstart events which precede timingiteration events.

Note that sorting end events before start events is consistent with the end-point exclusive nature of intervals (see ). When animation A ends at the same time as animation B begins, we can imagine that animation A ends an infinitely short amount of time before animation B begins such that there is no overlap.

5. For events generated by the same timed items, timingstart events precede timingiteration events which precede timingend events.
6. For events generated by timed items with a common ancestor timing group, events are ordered based on a tree order traversal of the descendents of the ancestor timing group.
7. Events generated by a timed item associated with a player that was created earlier precede events generated by a timed item associated with a player created later.

Event dispatch

Events are queued when either of the following occurs:

In the former case—when a timeline is sampled—since Web Animations put no requirements on the time between successive samples, it is often the case that the moment when a change in state that should produce an event is scheduled to occur does not line up with a sample.

As such, except for the specific circumstances mentioned in following sections, the events that should be queued when sampling a timeline includes all events scheduled to occur in the interval since the previous sample time up to and including the current timeline time.

Note that when a player is first sampled, it will employ seeked event dispatch as described in after which point the previous sample time for that player will be resolved. As a result, there is never an occasion where the previous sample time is used and yet is undefined.

For the latter case—when a player is seeked—the behavior is defined in .

Make sure we update the previous sample time for a seek/etc.

Note that provides non-normative algorithms that incorporate the behavior defined in this section as well as .

Seeked event dispatch

Under some circumstances the usual behavior of dispatching all events scheduled between two times is not appropriate either because it would produce such a large number of events that performance may be adversely affected, or because it would produce counter-intuitive results in the circumstances. In such situations, an alternative form of event dispatch called seeked event dispatch is used.

Seeked event dispatch is a mode of event dispatch that produces at most one timing event per timed item by comparing whether the timed item was in play or not at some initial moment and at some final moment.

To facilitate this, each timed item has an associated previous play state property that initially has the value not playing.

For a given timed item the events queued as a result of performing seeked event dispatch at uneased local time t is as follows:

1. Let timeline time be the time value of the timeline with which the timed item is associated. The procedures for calculating the timeline time from a timed item's uneased local time or the current time of a player are defined in .
2. Let iteration index be the result of calculating the current iteration at t.
3. Let timeline time be the time value of the timeline with which the timed item is associated. The procedures for calculating the timeline time from a timed item's uneased local time or the current time of a player are defined in .
4. Let current play state be playing if the timed item is in play at t, and not playing otherwise.
5. The events to be queued depend on comparing the current play state and the timed item's previous play state as follows.
If the timed item's previous play state is playing and current play state is not playing,
Queue a new timingend event with parameters:
If the timed item's previous play state is not playing and current play state is playing,
Queue a new timingstart event with parameters:
6. Let the timed item's previous play state be current play state.

For timing groups, this procedure is applied recursively to all child timed items. The resulting events are sorted using the sequence defined in .

Note that seeked event dispatch is only defined for timed items associated with a player. Timed items not associated with a player dispatch timingcancel events as defined in .

Event dispatch and seeking a player

When a seek is performed on a player (see ) seeked event dispatch is applied.

Prior to performing the seek, the previous play state of each timed item that is either the source content of the player or a descendent of the source content is updated to reflect whether the timed item is in play or not at the moment prior to performing the seek.

If the time adjusted flag of the player has been set, no update of the previous play state of the source content and its descendants is performed.

The timeline time used in the seeked event dispatch procedure is simply the seek time.

After completing the seek, the previous sample time of the player is updated to reflect the seek time and the time adjusted flag, if set, is cleared.

Suppressing events during seeking is necessary to provide performant seeking. It is also arguably the more intuitive behavior as, for example, when rewinding a cartoon one probably does not expect a bucketload of events to arrive as a result of traversing backwards over each timed item.

Apart from seeking a player, making adjustments to the arrangement or timing of a player's source content can also cause the timed items' local time to jump. Like seeking, in such circumstances it is often not sensible to dispatch all the intermediate events but rather to employ seeked event dispatch.

The range of circumstances where this behavior is necessary is quite broad when we consider the interdependencies in the timing of timed items. For example,

As such, even small changes to the timing of a timed item can have knock-on effects that affect all other timed items associated with the same player possibly causing their local time to jump. As a result, seeked event dispatch is employed for the source content of a player and all its descendents whenever any change is made to the timing or arrangement of any of those timed items.

Associated with each player is a time adjusted flag that is initially `false`.

The time adjusted flag is set to `true` whenever any of the following actions is performed on any of the timed items associated with the player.

The time adjusted flag is cleared after events are queued for the given player.

When queuing events for a player, if the time adjusted flag of the player is set, seeked event dispatch is used for all timed items associated with the player.

Event dispatch and unattached timed items

The timingcancel event may not be necessary.

It was introduced since in some situations it is useful to distinguish between an animation completing normally (timingend—in which case actions that are scheduled to occur at the end of the animation should be performed) and being prematurely terminated (timingcancel—in which case such actions will generally not be performed).

Currently the only way to prematurely end a timed item is to manually disassociate it from any player which seems too rare to warrant a special event. If players could be cancelled or stopped in some way then this event may make more sense.

Note that the touchcancel event is conceptually similar and may be an argument in favor of keeping this event.

A timed item that is not associated with a player is an unattached timed item.

Each time an operation is performed that causes a timed item that was associated with a player to become an unattached timed item it is appended to the end of a queue of unattached timed items associated with the player.

Should an unattached timed item later become associated with a player it is removed from any queue of unattached timed items it may be present in. As a result a timed item will only ever appear in at most one queue of unattached times and never twice in the same queue.

When events are queued as a result of sampling, the following steps are performed for all timed items in the queue of unattached items for each player that is sampled.

1. If the previous play state of the timed item is playing,
1. Queue a new timingcancel event with all parameters set to `null`.
2. Set the previous play state to not playing.
2. Remove the timed item from the queue of unattached timed items.

Note that timingcancel events are not dispatched when seeking a player. As a result it is possible, using the script interface to make a batch of changes to the arrangement of timed items including seeking and provided all timed items are associated with a player when the script block completes no timingcancel events will be dispatched.

Event dispatch and extended delays

In some circumstances, when events are queued during a sample, the number of events generated may be excessive. This can happen, for example, if the user agent dramatically reduces the sample rate for a background application to conserve battery, or if the device is activated after being in a sleep state for an extended period of time.

In such situations, requiring the user agent to dispatch all timing events scheduled in the interim period would result in a significant drop in performance and in extreme circumstances may render the user agent temporarily unusable whilst it catches up on event processing.

In order to ensure a good user experience even in such circumstances a user agent may switch to seeked event dispatch to alleviate the burden of dispatching excessive events.

If, whilst sampling a timeline, more than 30 events are queued, the user agent MAY employ seeked event dispatch for all timed items associated with the timeline.

30 is somewhat arbitrary. Need feedback both from implementations (on the most constrained device, when does this start being burdensome?) and authoring (what is the minimum guarantee necessary to cover most regular content?)

The SVG bindings may add additional requirements here so that when a protracted delay may make resolving syncbase dependencies in the interim period difficult to achieve without adversely impacting performance, a seek is performed.

Script interface

In addition to the abstract model described above, Web Animations also defines a programming interface to the model. This interface can be used to inspect and extend animations produced by declarative means or for directly producing animations when a procedural approach is more suitable.

The `Timeline` interface

Timelines, including the document timeline are represented in the Web Animations API by the Timeline interface.

Returns the time value for this timeline or `null` if this timeline is not started.

For a document timeline this will never be negative and represents the number of seconds since the document with which this timeline is associated was ready to fire its load event.

Player play()

Creates a new Player object associated with this timeline that is scheduled to start at `currentTime`.

The `timeline` attribute of the newly-created Player object will be set to this object.

Similarly, the `startTime` attribute will be set to the value of this object's `currentTime` attribute at the moment the method was called, or, if `currentTime` is `null`, zero.

The setting of the `source` attribute is described below under the description of the source parameter.

The `currentTime` attribute of the Player object is a calculated value described in .

The `playbackRate` and `paused` attributes take on their default values as described in the definitions of the playback rate and paused state properties of player objects.

optional TimedItem? source = null

The source content to assign to the newly-created Player object.

The `source` attribute of the created Player is set by following the procedure defined for updating that attribute. As a result, if source is already associated with a `player`, it will be disassociated first before being associated with the new Player object.

We will likely change this interface to the following format:

```                Promise play(optional TimedItem? source = null);
Player  playNow(optional TimedItem? source = null);
```

Under this arrangement `play` would begin at the next possible moment whilst attempting to ensure that the animation begins from the first frame. This allows implementations to make adjustments for vsync or overhead in triggering the animation in another process.

The `play` callback passes the created Player as the argument to the Promise's fulfill callback.

`playNow` matches the existing definition of the function and causes the start time of the player to be set to this timeline's `currentTime` even though this may cause the first part of the animation to be dropped.

sequence<Player> getCurrentPlayers()

Returns the set of Player objects associated with this timeline that have associated source content which is current.

The returned list is sorted in increasing order by player sequence number.

double? toTimelineTime (double otherTime, Timeline other)

Returns the time value, otherTime, from another Timeline also tied to the global clock, other, converted to a time value relative to this timeline's zero time.

Returns `null` if:

Note that unlike `currentTime`, this method may return a negative time value if otherTime occurred prior to this timeline's zero time.

Furthermore, negative values for otherTime are also allowed.

If this timeline records the time value of the global clock at its zero time as global clock offset, and so does other as other global clock offset, then the result of this method is simply:

```other global clock offset + otherTime - global clock offset```

Exceptions:

DOMException of type `InvalidNodeTypeError`
Raised if other is a timeline that is not tied to the global clock.

The reason for choosing `InvalidNodeTypeError` here is that DOM4 describes it as meaning, "The supplied node is incorrect or has an incorrect ancestor for this operation." In this case the error is because other does not have the global clock as an ancestor so it seems appropriate.

double? toTimelineTime (Event event)

Returns the number of seconds between when event was fired and this timeline's zero time.

Since the `timeStamp` attribute of the `Event` interface specified in [[DOM-LEVEL-3-EVENTS]] is not guaranteed to be monotonically increasing, implementations SHOULD record alongside each event the time value of the global clock when the event is dispatched so that it can be converted to an accurate time value here.

Unlike `currentTime`, this method may return a negative time value if the event was fired prior to this timeline's zero time.

Returns `null` if this timeline is not started.

This might be deferred to a later version.

The `Player` interface

Players are represented in the Web Animations API by the Player interface.

attribute TimedItem? source

The source content associated with this player.

A player can only be associated with at most one timed item, and likewise, a timed item can only be associated with at most one player. In order to maintain these invariants, on setting this value, the following procedure is performed:

1. Let old value be the current value of the `source` attribute.
2. Let new value be the value to set.
3. If new value is the same object as old value, return.
4. If old value is not `null`, disassociate old value from this player.
5. If new value is not `null`, perform the steps associated with the first matching condition of the following:
If new value has no parent group and is associated with a player,
disassociate new value from its player.
If new value has a parent group,
remove new value from its parent group by calling `new value.remove()`.
Otherwise,
do nothing.
6. Associate new value with this player.
7. Set the `source` attribute to new value.
The timeline associated with this player.
attribute double startTime
The start time of this player.
attribute double currentTime
The effective current time of this player. Setting this attribute follows the procedure defined in .
The time lag of this player which represents the number of seconds the `currentTime` has been delayed due to pausing and seeking. Negative values indicate the player has been advanced ahead of its scheduled time by seeking.
attribute double playbackRate
The playback rate of this player. Setting this attribute follows the procedure defined in .
The paused state of this player.

Returns true if this player is not bounded which occurs when the player is waiting to start, has reached the end of its source content, or has been seeked to a time outside the range `[0, source.endTime]`.

This may be true even while `paused` is also true.

Is this the most useful behavior? Making `playing == !paused && !bounded` is perhaps more intuitive but when `paused` is true and `currentTime` is zero you can't tell if the player is ready to play (but paused), or waiting to play.

void cancel()
Set `source` to null and clears all effects associated with the previous source content.
We need to make sure, for example, that any custom effects get called with a null sample time so they can remove their effects. This applies to manually setting to `source` to null as well so we should define this behavior there.
void finish()

Seeks the player to the end of the source content in the current direction as follows:

If player playback rate < zero,
Seek the player so its current time is zero.
If player playback rate equals zero,
Do nothing.
If player playback rate > zero,
Seek the player so its current time is equal to the end time of the source content or zero if there is no source content associated with this player..

Exceptions:

DOMException of type `InvalidStateError`
Raised if the end time of this player's source content is infinity and the player playback rate is > zero.
void play()

Unpauses the player and rewinds if it has finished playing using the following procedure:

1. Set the paused state of the player to false using the procedure defined in .
2. If source content is associated with the player, adjust the current time of the player as follows:
If current time < zero or current timesource content's end time; and player playback rate > zero,
Seek to time zero.
If current time < zero or current timesource content's end time; and player playback rate < zero,
Seek to the source content's end time.
Otherwise,
Do nothing.

Should this return a Promise that is resolved when `playing` becomes false?

void pause()
Set the paused state of this player to true using the procedure defined in .
void reverse()

Inverts the playback rate of this player and seeks to the start of the source media if it has finished playing in the reversed direction using the following procedure. evt.

1. If the player playback rate is zero, abort these steps.
2. If source content is associated with the player, adjust the current time of the player as follows:
If current timesource content's end time and the player playback rate > zero,
Seek to the source content's end time.
If the current time < zero and the player playback rate < zero,
Seek to time zero.
Otherwise,
Do nothing.
3. Set the player playback rate to ```-player playback rate``` following the steps in .
4. Set the paused state of the player to false.

Is this unpausing behavior correct?

The `TimedItem` interface

Timed items are represented in the Web Animations API by the TimedItem interface.

// Playback state

The local time of this timed item.

`localTime` will be `null` if this timed item is not associated with a player or if it has a parent timing group that is not in effect.

The current iteration index beginning with zero for the first iteration.
// Specified timing

Returns the input timing properties for this timed item.

Should we make this writeable? Then you could do:

```                animA.specified = animB.specified;
```

Doing so would probably also involve defining `Timing.clone` and a constructor for Timing.

Representing these parameters has been a particularly contentious topic.

The current arrangement:

• requires defining both a Timing interface and a TimingInput dictionary type which increases the API surface area somewhat
• means that setting the value occurs at a different place (`anim.specified.duration`) to reading the value (typically, `anim.duration`)
• opens up questions about whether Timing objects should be share-able or not
• uses a union of a string and a double to represent a duration which opens up questions about whether strings such as `"3s"` should be allowed (and allowing them makes walking the tree more complex).

However, it separates "specified" timing from "computed" timing which some consider advantageous.

The only situation where calculated values and input values differ is for `duration` and `activeDuration`.

One alternative that has been proposed is to introduce a `Duration` interface as follows:

```interface TimedItem : EventTarget {
// Timing
attribute double   delay;
attribute FillMode fill;
attribute Duration duration;
attribute Duration activeDuration;
attribute double   playbackRate;
// ...

// Scheduled time
};

interface Duration {
double    sec;
DOMString string;
}
```

Usage is as follows:

``` var specifiedDur  = anim.duration.string; // "auto"
var calculatedDur = anim.duration.sec; // 5

// Update duration to 3s
anim.duration.sec = 3;
// anim.duration.string -> "3s"

// Update duration to 3s (alt.)
anim.duration.string = "3s";
// anim.duration.sec -> 3

// Reset to auto
anim.duration.string = "auto";
// anim.duration.sec -> 5
```

Your feedback is most welcome at public-fx@w3.org, subject [web-animations] ….

// Calculated timing

The start time of this timed item in seconds. This is the time at which the parent timing group, if any, has scheduled this child to run within its transformed time space, that is, the timed item's inherited time space.

The start of the active interval is based on the sum of the start time and start delay.

The iteration duration of this timed item.

Unlike the `duration` attribute of the Timing interface or TimingInput dictionary, this attribute returns the calculated value of the iteration duration. If `specified.duration` is the string `auto` or any unsupported value, this attribute will return the current calculated value of the intrinsic iteration duration.

This value may be changed by setting the `duration` attribute of the `specified` member of this interface.

The active duration of this timed item.

As with `duration`, this attribute returns the calculated value of the active duration. If `specified.activeDuration` is the string `auto` or any unsupported value, this is the result of evaluating the active duration using the procedure defined in . Otherwise, it is the value specified for `specified.activeDuration`.

This value may be changed by setting the `activeDuration` attribute of the `specified` member of this interface.

The upper bound of the active interval expressed in seconds in inherited time space.

`endTime` is calculated as ```start time + start delay + activeDuration```

Note that while the `endTime` is read-only, it can be set indirectly as follows:

```                // Set endTime to 't'
var t = 6;
timing.specified.activeDuration =
t - anim.startTime - anim.specified.delay;
```
// Timing hierarchy

The parent timing group of this timed item or `null` if this timed item does not have a parent timing group.

Should this be `parentGroup`?
The previous sibling of this timed item.
The next sibling of this timed item.
void before (TimedItem... items)

Inserts items before this timed item.

1. If there is no parent timing group, terminate these steps.
2. If any of the timed items in items is an inclusive ancestor of this timed item throw a `HierarchyRequestError` exception and terminate these steps.
3. Insert items before this timed item.

Note that this definition precludes the following usage since `item` is an inclusive ancestor of itself:

```                item.before(item); // throws HierarchyRequestError
```
void after (TimedItem... items)

Inserts items after this timed item.

1. If there is no parent timing group, terminate these steps.
2. If any of the timed items in items is an inclusive ancestor of this timed item throw a `HierarchyRequestError` exception and terminate these steps.
3. Let reference child be the next sibling of this timed item not in items.
4. Insert items before reference child.
void replace (TimedItem... items)

Replaces this TimedItem with the passed in items.

1. If there is no parent timing group, terminate these steps.
2. If any of the timed items in items is an inclusive ancestor of the parent timing group throw a `HierarchyRequestError` exception and terminate these steps.
3. Let reference child be the next sibling of this timed item not in items.
4. Remove this timed item from its parent timing group.
5. Insert items before reference child.
void remove ()
Removes this timed item from its parent timing group or player.
// Associated player

The player with which this timed item is associated, if any. This object can be used to perform play control such as pausing or rewinding on this timed item and all other timed items in the same hierarchy.

This will be `null` if this timed item is not associated with a player.

// Event callbacks
attribute EventHandler onstart
The event handler for the timingstart event.
attribute EventHandler oniteration
The event handler for the timingiteration event.
attribute EventHandler onend
The event handler for the timingend event.
attribute EventHandler oncancel
The event handler for the timingcancel event.

Note that the EventHandler callback interface type is defined in [[!HTML5]].

The `Timing` interface

Timing parameters for a TimedItem are collected together under the Timing type.

attribute double delay

The start delay which represents the number of seconds from a timed item's start time to the start of the active interval.

attribute FillMode fill

The fill mode as specified by one of the FillMode enumeration values.

When performing timing calculations the special value auto is expanded to one of the fill modes recognized by the timing model as follows,

If the timed item to which the fill mode is being is applied is an animation,
Use none as the fill mode.
Otherwise,
Use both as the fill mode.
attribute double iterationStart

The timed item's iteration start property.

A finite real number greater than or equal to zero representing the number of iterations into the timed item at which to begin. For example, a value of 0.5 would cause the timed item to begin half-way through the first iteration.

Values less than zero are clamped to zero for the purpose of timing model calculations.

Note that the value of `iterations` is effectively added to the `iterationStart` such that a timed item with an `iterationStart` of ‘0.5’ and `iterations` of ‘2’ would still repeat twice however it would begin and end half-way through the timed item's iteration interval.

Setting the `iterationStart` to a value greater than or equal to one is typically only useful in combination with an animation effect that has an `accumulate` property of ‘accumulate’.

attribute unrestricted double iterations

The timed item's iteration count property.

A real number greater than or equal to zero (including positive infinity) representing the number of times to repeat the timed item.

Values less than zero are treated as the value 1.0 for the purpose of timing model calculations.

attribute (unrestricted double or DOMString) duration

The iteration duration which is a real number greater than or equal to zero (including positive infinity) representing the time taken to complete a single iteration of the timed item.

The string value `auto` is used to indicate that the iteration duration reflects the timed item's intrinsic iteration duration.

Real numbers less than zero and strings other than the value lowercase value `auto` are treated the same as `auto` for the purpose of timing model calculations.

attribute (unrestricted double or DOMString) activeDuration

The active duration of this timed item, that is, the length of its active interval.

The string value `auto` is used to indicate that the active duration is calculated using the procedure defined in . Otherwise, if a real number greater than or equal to zero (including positive infinity) is specified, that procedure is ignored and the value provided here is used for all timing model calculations that refer to the active duration.

Real numbers less than zero and strings other than the value lowercase value `auto` are treated the same as `auto` for the purpose of timing model calculations.

Should we allow strings such as `"3s"` here? i.e. a CSS <time>. It might be useful for readability but introduces complexity when handling this member (need to test the type, then possibly parse the string). It also introduces the issue of whether we should parse a full clock value.

attribute double playbackRate

The timed item's playback rate property.

This is a multiplier applied to the local time potentially causing the item to run at a different rate to its natural speed.

attribute PlaybackDirection direction

The playback direction of the timed item as specified by one of the PlaybackDirection enumeration values.

attribute DOMString easing

The timing function used to scale the time to produce easing effects.

The syntax of the string is defined by the <timing-function-chain> production. Unrecognized string values or values that correspond to a timing function that is not supported for the type of timed item to which this property is applied are treated as if the `linear` keyword was specified for the purpose of timing model calculations.

In future we may extend this so that it is possible to query the individual functions in the string. It may be possible to do this by extending this attribute using some stringifier magic, or else we could just add `easingList` similar to HTML's `classList`.
EasingTimesInput getEasingTimes()

Returns the input for the timing function position list as established by calling `setEasingTimes` on this object.

void setEasingTimes(EasingTimesInput easingTimes)

Sets the value of the timing function position list.

The input is normalized using the procedures defined in including making adjustments to the timing function chain as necessary. Note that the results of this normalization are not exposed through the API.

The `TimingInput` dictionary

The TimingInput dictionary is used as a convenience for specifying the timing properties of a TimedItem in bulk.

double delay = 0

The specified start delay.

See the description of the `delay` attribute on the Timing interface.

FillMode fill = "auto"

The fill mode as specified by one of the FillMode enumeration values.

double iterationStart = 0.0

The timed item's iteration start property.

See the description of the `iterationStart` attribute on the Timing interface.

unrestricted double iterations = 1.0

The timed item's iteration count property.

See the description of the `iterations` attribute on the Timing interface.

(unrestricted double or DOMString) duration = "auto"

The iteration duration of the timed item.

See the description of the `duration` attribute on the Timing interface.

(unrestricted double or DOMString) activeDuration = "auto"

The active duration of the timed item.

See the description of the `activeDuration` attribute on the Timing interface.

double playbackRate = 1.0

The timed item's playback rate property.

See the description of the `playbackRate` attribute on the Timing interface.

PlaybackDirection direction = "normal"

The playback direction of the timed item.

See the description of the `direction` attribute on the Timing interface.

DOMString easing = "linear"

The timing function used to scale the time to produce easing effects.

See the description of the `easing` attribute on the Timing interface.

EasingTimesInput easingTimes = "distribute"

Specifies the values of timing function positions list.

See the description of the `getEasingTimes` method on the Timing interface.

The `FillMode` enumeration

none
No fill.
forwards
Fill forwards.
backwards
Fill backwards.
both
Fill backwards and forwards.
auto
Fill backwards and forwards when applied to a TimingGroup and no fill when applied to an Animation.

The `PlaybackDirection` enumeration

normal
All iterations are played as specified.
reverse
All iterations are played in the reverse direction from the way they are specified.
alternate
Even iterations are played as specified, odd iterations are played in the reverse direction from the way they are specified.
alternate-reverse
Even iterations are played in the reverse direction from the way they are specified, odd iterations are played as specified.

The `EasingTimesInput` typedef

For simplicity, throughout this specification EasingTimesInput is used to represent either a list of values corresponding to a timing function position list or a SpacingMode from which a timing function position list may be synthesized according to the procedure in .

If we later extend easing times to allow controlling the output ranges (i.e. a y value as well), we could achieve that by making the type ```(SpacingMode or sequence<double> or sequence<DOMPoint>)``` or something of that sort.

That would be backwards-compatible but would make it hard to write code that falls back gracefully. An alternative would be to simply add `getEasingPoints` etc.

The `SpacingMode` enumeration

This enumeration specifies values corresponding to the spacing mode input to the procedure defined in .

distribute
Corresponds to a spacing mode of “distribute”.
align
Corresponds to a spacing mode of “align”.

The `TimingGroup` interface

The different types of timing groups defined by Web Animations share a common TimingGroup interface as defined below.

The list of child timed items in the group.
The first child of this timing group.
The last child of this timing group.
void prepend (TimedItem... items)
1. If any of the timed items in items is an inclusive ancestor of this timed item throw a `HierarchyRequestError` exception and terminate these steps.
2. Insert items before the first child.
void append (TimedItem... items)
1. If any of the timed items in items is an inclusive ancestor of this timed item throw a `HierarchyRequestError` exception and terminate these steps.
2. Insert items before `null`.

Common definitions for manipulating hierarchies

The next sibling of item not included in a set of timed items, items is determined using the following steps:

1. Let context item be item.
2. While the next sibling of context item is not `null` perform the following steps:
1. Let context item be the next sibling of context item.
2. If context item is not in items return context item and terminate these steps.
3. Return `null`.

To remove an item from its parent timing group or player, perform the steps corresponding to the first matching condition from below, if any:

If item has a parent timing group,
Remove item from the parent timing group's list of child timed items.
If item is directly associated with a player,
Disassociate item from the player.

To insert a series of zero or more timed items, items, to parent's list of child timed items before reference child perform the following steps for each item in items:

1. Remove item from its parent.
2. Insert item to parent's list of child timed items before reference child.

The `TimedItemList` interface

A list of timed items may be represented by a TimedItemList.

The `TimedItemList` interface supports indexed properties with indices in the range 0 ≤ index < `length`.

The only reason this interface exists is to provide a familiar experience for authors familiar with DOM interfaces where child nodes are accessed via a `children` member.

The number of timed items in the list.
getter TimedItem? item(unsigned long index)

Returns the timed item at `index`. If `index` is greater than or equal to `length` returns `null`.

The `ParGroup` interface

Parallel timing groups are represented by the `ParGroup` interface.

Some feedback indicates this naming is less than obvious. The precedent is `<par>` from SMIL but would `ParallelGroup` or `Parallel` be better? Likewise for SeqGroup.

Constructor ()

Creates a new ParGroup object using the following procedure:

1. Create a new ParGroup object, group.
2. Set timing input as follows,
If timing is a TimingInput object,
Let timing input refer to timing.
If timing is a `double`,
Let timing input be a new TimingInput object with all members set to their default values and `duration` set to timing.
Otherwise (timing is undefined),
Let timing input be a new TimingInput object with all members set to their default values.
3. Set `group.specified` to a new Timing object whose attributes are assigned the value of the member of the same name on timing input except for the `easingTimes` attribute whose value is assigned by calling `setEasingTimes` on timing input with the value of `easingTimes` as the parameter value.

The above two steps are identical with the constructor for Animation and should be factored out somewhere.

4. Add children to the group by calling ```group.splice(0, 0, children)```.

Note that since Timing objects have the same member names as TimingInput dictionaries, it is also possible to pass the `specified` member of another TimedItem as the timing parameter.

Doing so will cause the Timing object to be treated as a TimingInput dictionary and thus it will effectively be cloned, not shared.

sequence<TimedItem>? children

A sequence of timed items to add as children of this group.

These children are appended in sequence using the same semantics as the `TimingGroup.append` method.

optional (unrestricted double or TimingInput) timing

The timing properties or iteration duration of the new timing group.

ParGroup clone ()

Creates a deep copy of this ParGroup object using the following procedure.

1. Let source be this ParGroup object, the object to be cloned.
2. Let cloned timing be a new TimingInput object whose members are assigned the value of the attribute with the same name on `source.specified`.
3. Let cloned children be an empty sequence of TimedItem objects.
4. For each child in `source.children`, append the result of calling `child.clone()` to cloned children.
5. Return a new ParGroup object created by calling the ParGroup constructor with parameters ```ParGroup(cloned children, cloned timing)```.

The `SeqGroup` interface

Sequence timing groups are represented by the `SeqGroup` interface.

Constructor (sequence<TimedItem>? children, optional (unrestricted double or TimingInput) timing)
The meaning and handling of each of the parameters in this constructor is identical to the constructor for ParGroup.
SeqGroup clone ()

Creates a deep copy of this SeqGroup object using the same procedure as defined for ParGroup.clone except that a new SeqGroup object is created instead of a ParGroup.

The `Animation` interface

Animations are represented by the `Animation` interface.

Constructor ()

Creates a new Animation object using the following procedure:

1. Create a new Animation object, animation.
2. Set timing input as follows,
If timing is a TimingInput object,
Let timing input refer to timing.
If timing is a `double`,
Let timing input be a new TimingInput object with all members set to their default values and `duration` set to timing.
Otherwise (timing is undefined),
Let timing input be a new TimingInput object with all members set to their default values.
3. Set `animation.specified` to a new Timing object whose attributes are assigned the value of the member of the same name on timing input except for the `easingTimes` attribute whose value is assigned by calling `setEasingTimes` on timing input with the value of `easingTimes` as the parameter value.
4. Assign the animation effect based on the type of effect as follows,
If effect is an AnimationEffect object or a CustomEffect object,
Assign `animation.effect` to effect.
If effect is a OneOrMoreKeyframes,
Set `animation.effect` to a new KeyframeEffect object constructed by passing effect as the frames parameter and with the other parameters set to their default values.
Otherwise,
Set `animation.effect` to `null`.

Examples of the usage of this constructor are given in .

Note that as with the constructor for TimingGroups it is possible to pass in a Timing object here (e.g. the `specified` member of another TimedItem) in which case it will be cloned.

AnimationTarget? element
The target element or target pseudo-element. This may be `null` for animations that do not target a specific element.
(AnimationEffect or CustomEffect or OneOrMoreKeyframes)? effect
The animation effect used to set the `effect` attribute of the newly-created Animation object.

If this parameter is an AnimationEffect object or CustomEffect object, it will shared with any other Animation objects referring to the same AnimationEffect or CustomEffect object. It will not be copied.

If this parameter of type OneOrMoreKeyframes, the animation effect of the newly-created Animation will be a newly-created KeyframeEffect object initialized by using this object as the list of keyframes and with all other parameters set to their default values.

If this parameter is `null`, the newly-created Animation will also have a `null` animation effect.

optional (unrestricted double or TimingInput) timing

The timing properties or iteration duration of the new animation.

attribute (AnimationEffect or CustomEffect)? effect

The animation effect or custom effect to apply. May be `null` in which case the animation will produce no noticeable effect other than dispatching events (see ).

The element or pseudo-element being animated by this object. This may be `null` for animations that do not target a specific element such as an animation that produces a sound using an audio API.

Note that in a future version, AnimationTarget may be extended to allow targetting, for example, a sequence of elements. Therefore, code that is intended to be used with arbitrary Animation objects should test the concrete type of `target` before using it and not assume that it refers to an Element.

If SVG is extended to allow multiple targets (using, e.g., `select="rect"`) then it might be most natural to represent that in the API by allowing the `target` to refer to multiple elements. It's something that deserves attention for version 1.

Animation clone ()

Creates a copy of this Animation object using the following procedure.

1. Let source be the Animation object to clone, that is, this object.
2. Let cloned timing be a new TimingInput object whose members are assigned the value of the attribute with the same name on `source.specified`.
3. The AnimationEffect is cloned depending on the type of `source.effect` as follows,
If `source.effect` is an Animation object,
Let cloned effect be the result of calling `source.effect.clone()`.
If `source.effect` is a CustomEffect object,
If `source.effect` has a method called `clone` let cloned effect be the result of calling that method, otherwise let cloned effect be `source.effect`.
Otherwise,
Let cloned effect be `null`.
4. Return a new Animation object created by calling the Animation constructor with parameters ```Animation(source.target, cloned effect, cloned timing)```.

Creating a new `Animation` object

The Animation constructor offers a number of approaches to creating a new Animation object. At its simplest, an Animation object that changes the ‘left’ property of elem to 100 over three seconds can be achieved as follows:

```var anim = new Animation(elem, { left: '100px' }, 3);
```

The second parameter, representing the animation effect, may specify multiple properties, an AnimationEffect object, or even a callback object.

```// Specify multiple properties at once
var animA = new Animation(elem, { left: '100px', top: '300px' }, 3);

// Specify multiple frames
var animB = new Animation(elem, [ { left: '100px' }, { left: '300px' } ], 3);

// Share the animation effect of another animation
var animC = new Animation(elem, animB.effect, 3);

// Supply a specialized animation effect
var animD =
new Animation(elem, new MotionPathEffect("M100 250C100 50 400 50 400 250"), 3);

// Supply a custom script-based animation effect
var animE = new Animation(elem,
{
sample: function(time) {
if (time !== null) {
document.documentElement.currentScale = 1.0 + time * 2.0;
} else {
document.documentElement.currentScale = 1.0;
}
}
}, 3);
```

The third parameter representing the animation's timing, may simply be a number representing the iteration duration as above, or, to specify further timing properties such as the playback rate, a TimingInput object can be used as follows:

```var anim =
new Animation(elem, { left: '100px' }, { duration: 3, playbackRate: 2 });
```

It is also possible to omit the timing parameter altogether in which case default timing values will be used. Since the intrinsic iteration duration of an animation is zero, and the default `fill` when constructing an Animation is forwards, it is possible to create animations that simply set a property without any interpolation as follows,

```new Animation(elem, { display: 'none' });
```

This is particularly useful in combination with other animations or timed items. For example, fading an element before switching ‘display’ to ‘none’ can be achieved as follows,

```new SeqGroup(
[
new Animation(elem, { opacity: '0%' }, 1),
new Animation(elem, { display: 'none' })
]
);
```

Having created an Animation, it can be played using `document.timeline.play(anim)`. For simple effects, the `Element.animate` shortcut is more convenient since it performs this last step automatically. For example,

```elem.animate({ left: '100px' }, 3);
```

The `PseudoElementReference` interface

We should replace this with the `PseudoElement` from the ED of CSSOM unless it gets dropped.

Since animations may also target pseudo-elements, Web Animations API introduces the PseudoElementReference interface to represent such targets.

Constructor (Element element, DOMString pseudoElement)
Creates a new pseudo-element reference using element as the subject and pseudoElement as the pseudo-element to match (e.g. ‘`::first-line`’).
attribute Element element
The element used as the subject for matching a pseudo-element.

Exceptions:

DOMException of type `NoModificationAllowedError`
Raised on setting if this object is a readonly object.
attribute DOMString pseudoElement
The pseudo-element including the initial colon(s). For example, ‘`::after`’.

Exceptions:

DOMException of type `NoModificationAllowedError`
Raised on setting if this object is a readonly object.

The `AnimationTarget` typedef

For simplicity, throughout this specification AnimationTarget is used wherever either an Element or a PseudoElementReference can be used.

The `AnimationEffect` interface

Animation effects are represented by the `AnimationEffect` interface. AnimationEffect is an abstract interface of which several concrete subinterfaces are provided.

attribute AccumulateOperation accumulate

The accumulation operation property of this animation effect as specified by one of the AccumulateOperation constants.

AnimationEffect clone ()

Creates and returns a new object of the same type as this object's most-derived interface such that it will produce the same output as this object.

We either need a more rigorous definition here or (probably better) a sets of steps on a per-subclass basis.

In future, we may expose ```any sample (double? timeFraction, double currentIteration, AnimationTarget? target, any underlyingValue)``` so that the animation effects can be driven apart from the timing model.

The `AccumulateOperation` enumeration

The possible values of an animation effect's accumulation behavior are represented by the AccumulateOperation enumeration.

sum
Corresponds to the sum accumulation operation value such that subsequent iterations of an animation build on the final value of the previous iteration.
none
Corresponds to the none accumulation operation value such that the intermediate animation value produced is independent of the current iteration.

The `CompositeOperation` enumeration

The possible values of an animation effect's composition behavior are represented by the CompositeOperation enumeration.

replace
Corresponds to the replace composition operation value such that the animation effect overrides the base value it is combined with.
Corresponds to the add composition operation value such that the animation effect is added to base value it is combined with.

The `KeyframeEffect` interface

Keyframe animation effects are represented by the KeyframeEffect interface.

Constructor ()

Creates a new KeyframeEffect object for the given set of keyframes.

Before storing, each of the keyframes in frames is normalized using the procedure in .

OneOrMoreKeyframes frames
The set of keyframes used for calculating animation values for this animation effect. The constraints on this parameter and its processing are identical to those for `setFrames`.
optional CompositeOperation composite = "replace"
The composition operation used to composite this animation with the animation stack, as specified by one of the CompositeOperation enumeration values. This is used for all keyframes that do not specify a composition operation.
optional AccumulateOperation accumulate = "none"
The accumulation operation used to define the way animation values build from iteration to iteration.
attribute CompositeOperation composite

The composition operation used to composite this animation with the animation stack, as specified by one of the CompositeOperation enumeration values.

This is used for all keyframes that do not specify a composition operation.

sequence<Keyframe> getFrames()

Returns the keyframes that make up this effect as a sequence of Keyframe objects.

Note that the normalization applied to the list of keyframes as defined in does not affect the value returned by this method.

void setFrames(OneOrMoreKeyframes frames)

Replaces the set of keyframes that make up this effect.

Upon setting, each keyframe in frames is normalized using the procedure in before storing.

Before being used by the animation model, the set of frames associated with this effect is normalized using the procedure defined in .

As a result of the normalization of the list, if frames is not loosely sorted by offset this effect will not contribute to the final composited value.

Normalizing the list of keyframes

This behavior is expected to be revised such that keyframe lists that are not in sequence are accepted and keyframe offsets outside the range [0, 1] are also allowed. Doing so may make this procedure unnecessary.

Before passing the list of Keyframes specified in the API to the animation model so that the unaccumulated animation value can be calculated (see ), the following normalization is performed.

1. Let normalized keyframes be a copy of the keyframe list returned by `getFrames`.
2. If normalized keyframes is not loosely sorted by offset, return an empty list.
3. If there exist any keyframes whose specified positional offset is less than zero, remove all keyframes from the start of normalized keyframes up to and including the keyframe with the largest specified positional offset that is still less than zero.
4. Likewise, if there exist any keyframes whose specified offset is greater than one, remove all keyframes from keyframe with the smallest specified positional offset that is still greater than one until the end of normalized keyframes.
5. Set the positional offset of any keyframes without a specified offset using the procedure defined in .
6. Remove all property values in normalized keyframes that are invalid or not supported by the implementation.
7. Return normalized keyframes.

Note that this normalization is only applied to the keyframes before they are passed to the model and does not affect the result returned by `getFrames`.

The `Keyframe` dictionary

Individual keyframes are represented by a special kind of Keyframe dictionary type whose members map to the properties to be animated. At the time of writing, this kind of open-ended dictionary cannot be represented using WebIDL and hence special ECMAScript-specific handling for this type is defined in . No handling is defined for other languages.

// ... property-value pairs ...
double? offset = null

The positional offset of the keyframe specified as a number between 0.0 and 1.0 inclusive or `null`.

Keyframes with offsets outside the range [0.0, 1.0] are ignored when calculating animation values as defined in .

A `null` value indicates that the keyframe should be positioned automatically using the algorithm defined in and applied in .

Is `offset` too generic? How about `timeOffset` or `keyTime`?
CompositeOperation? composite = null

The composition operation used to combine the values specified in this keyframe with the underlying value.

If `null`, the composition operation specified on the KeyframeEffect will be used.

Normalizing a `Keyframe` object

Since accessing the properties of an ECMAScript user object can have side effects, the manner in which these properties is accessed is important. In light of this consideration the procedure for normalizing a Keyframe has the following properties:

• Properties are read in a well-defined order.
• Properties corresponding to unsupported target properties or attributes are not read.

A Keyframe object, keyframe input, is converted to a normalized internal representation keyframe result using the following procedure:

1. Let the initial positional offset of keyframe result be `null`.
2. Let the initial composition operation of keyframe result be `null`.
3. Create a list, supported properties, of property names and attribute names that can be animated by the implementation.
4. Convert each property name in supported properties to the equivalent IDL attribute by applying the CSS property to IDL attribute algorithm [[!CSSOM]].
5. If the user agent supports animation of the float CSS property, replace 'float' in supported properties with 'cssFloat'.
6. Let animation properties be an empty sequence.
7. Iterate over the properties of keyframe input. For each property in keyframe input, perform the step corresponding to the first matching condition from below, if any.
If property is a case-sensitive match for the string 'offset',
If `keyframe input.offset` is a Number, set the positional offset of keyframe input to `keyframe input.offset`.
if property is a case-sensitive match for the string 'composite',
If `keyframe input.composite` is a case-sensitive match for one of the values of the CompositeOperation enumeration, set the composition operation of keyframe input to `keyframe input.composite`.
Otherise, if property also exists in supported properties based on a case-sensitive comparison,
append property to animation properties.
8. For user agents that support both a prefixed and an unprefixed version of some CSS properties, remove all prefixed properties from animation properties where the corresponding unprefixed version is also present in animation properties.
9. Sort animation properties lexicographically by the Unicode codepoints that define each element.
10. Iterate over animation properties and for each element, name, add a new property-value pair to keyframe result as follows:
• property name: the result of applying the the IDL attribute to CSS property algorithm [[!CSSOM]] to name unless name is a case-sensitive match for the string 'cssFloat' in which case use the string 'float'.
• property value: the result of calling `toString` on the name property of keyframe input.
11. Return keyframe result.

This procedure is performed exactly once per call to `setFrames` or the constructor for KeyframeEffect.

The above algorithm gives special meaning to the property names 'offset' and 'composite'. If a CSS property called 'offset' or 'composite' is ever introduced it will clash with the meaning here.

We have a few options:

• Add special handling at that time to allow addressing the property of the same name, e.g. `cssOffset`.
• Rename these keywords now to avoid risk of a later clash, e.g. 'keyframeOffset'.

The `OneOrMoreKeyframes` typedef

Throughout this specification we use the OneOrMoreKeyframes type to represent either a single keyframe or a list of such keyframes.

The `MotionPathEffect` interface

Motion path animation effects are represented by the MotionPathEffect interface.

Constructor ()

Creates a new MotionPathEffect object with the specified parameters.

(DOMString or SVGPathSegList) path

The path which defines the motion.

A string may be provided specifying the path using the syntax for SVG path data [[SVG11]].

If a string is provided, it is converted into an `SVGPathSegList` using the procedures defined for parsing path data in [[SVG11]]. Any errors encountered in the path data causing parsing to cease and the path data processed up to that point to be used.

The resulting SVGPathSegList is assigned to the `path` attribute of the generated object without copying.

optional AutoRotationMode autoRotate = "none"
The automatic rotation flag setting for the generated effect.
optional double angle = 0
The rotation angle for the generated effect.
optional CompositeOperation composite = "replace"
The composition operation used to composite this animation with the animation stack, as specified by one of the CompositeOperation enumeration values.
optional AccumulateOperation accumulate = "none"
The accumulation operation used to define the way animation values build from iteration to iteration.
attribute SVGPathSegList segments
The list of segments that make up the path.

Is this the correct data type here?

Is this sufficient to allow us to animate along an animated path? Do we need to spell out how this works in more detail?

attribute AutoRotationFlag autoRotate
The automatic rotation flag of the motion path animation effect.
attribute double angle
The rotation angle of the motion path animation effect.
attribute CompositeOperation composite
The composition operation used to composite this animation with the animation stack, as specified by one of the CompositeOperation enumeration values.

The `AutoRotationMode` enumeration

The values of the automatic rotation flag of a motion path animation effect are represented by the AutoRotationMode enumeration.

auto-rotate
Corresponds to setting the automatic rotation flag.
none
Corresponds to clearing the automatic rotation flag.

The `CustomEffect` callback interface

Custom effects can be defined in script using the CustomEffect interface.

attribute long? priority
The custom effect priority property of the effect (see ).
attribute CustomEffectCloneCallback? clone

An optional callback method used to create an independent copy of this object.

void sample ()
The callback used to produce an effect for the given timing information.
double? timeFraction
The time fraction for which to produce an effect. When this is `null`, the callback object SHOULD remove the effect.
double currentIteration
The current iteration beginning with zero corresponding to the first iteration.
AnimationTarget? target
The element or pseudo-element to which the effect should be applied, if any. When this method is called as a result of this object being associated with an Animation object A, this value will be `A.target`.
double? previousTimeFraction

The value of timeFraction that was passed to this CustomEffect when `sample` was previously called in the context of sampling the same Animation that generated the current call.

If this CustomEffect has not previously been called within the context of sampling the same Animation as with the current call, or if the time fraction was `null` on the previous call, this parameter will be `null`.

Do we need to pass the Animation to `sample` as well? If possible I'd prefer not to but it may necessary for some types of effect. Might be an additional parameter to add later if it proves necessary?

CustomEffectCloneCallback is a type of callback function used to create an independent copy of a CustomEffect.

When called, the callback this value refers to CustomEffect object to be cloned.

The `TimingEvent` interface

Constructor ()
Constructs a new TimingEvent object as described in Constructing events in [[!DOM4]].
DOMString type
The type of timing event corresponding to one of the types defined in .
optional TimingEventInit eventInit
The parameters of the new TimingEvent.
attribute double? localTime

The event local time.

This is the same time space used for `startTime` and `endTime` on TimedItem. This is the most useful time space if, for example, you receive a timing event and want to add a new animation that synchronizes with the item that dispatched the event by adding it to the same timing group.

attribute double? timelineTime
I think timeline time will be much more useful than global time. For the rarer case that you want to synchronize animations between documents using events, methods on Timeline will assist the conversion.
attribute unsigned long? iterationIndex
The event iteration index.
attribute boolean? seeked
The seeked dispatch flag.

The TimingEventInit dictionary type is used to specify the parameters when constructing a TimingEvent object.

double? localTime = null
double? timelineTime = null
double? iterationIndex = null
boolean? seeked = null

Extensions to the `Document` interface

The following extensions are made to the Document interface defined in [[!DOM4]].

The Timeline object representing the document timeline.

Extensions to the `Element` interface

To simplify the creation of Animation objects for a given Element, the Element interface [[!DOM4]] is extended as follows:

Animation animate()

Creates a new Animation object whose target element is the Element object on which the method is called, and calls the `play` method of the Timeline object of the document timeline of the node document [[!DOM4]] of the element passing the newly created Animation as the argument to the method.

The following code fragment:

```              var anim = elem.animate({ opacity: '0' }, 2);
```

is equivalent to:

```              var anim = new Animation(elem, { opacity: '0' }, 2);
elem.ownerDocument.timeline.play(anim);
```

Returns the newly created Animation object.

(AnimationEffect or CustomEffect or OneOrMoreKeyframes)? effect
The effect to apply. This value is passed to the Animation constructor as the effect parameter and has the same interpretation as defined for that constructor.
optional (double or TimingInput) timing
The timing parameters of the animation. This value is passed to the Animation constructor as the timing parameter and has the same interpretation as defined for that constructor.
sequence<Animation> getCurrentAnimations()

Returns the set of current Animation objects that have an animation effect whose target is the Element on which this method is called. Note that this does not include PseudoElementReferences whose `element` attribute refers to this Element.

The returned list of Animation objects is sorted by their associated animation effect using the procedure defined for sorting animation effects in .

Note that the definition of a current animation does not include those animations whose local time falls after the active interval but which are still in effect due to a fill mode. As a result such animations are not returned by this method.

This is because in order to return such animations, user agents would be required to maintain all animations with a forwards fill indefinitely. As a result the resources consumed by an animated document would steadily accumulate over time.

sequence<Player> getCurrentPlayers()

Returns the set of Player objects whose source content is current and contains at least one animation whose target element is this Element.

If this Element is the target element of two or more animations which are associated with the same player, the corresponding Player object will still only appear in the returned list once.

The returned list is sorted in increasing order by player sequence number.

The primary use case for this method is an application that wants to increase the speed of all animations targetting a particular element by a factor of 2 (not sure why and never mind that this will affect all sorts of other elements too).

With only `getCurrentAnimations` a naïve author might write:

```                elem.getCurrentAnimations().forEach(
function(anim) {
anim.player.playbackRate *= 2;
}
);
```

However, if `elem` is the target element for two animations that have the same player, then those animations will be sped up by a factor of 4.

Instead the author needs to generate a unique list of players first, hence this method.

Is this kind of situation common enough to warrant this method? Or is it likely that when performing this kind of operation you're mostly working with single animations and not timing groups (as otherwise this operation could affect many other elements)?

Your feedback is most welcome at public-fx@w3.org, subject [web-animations] ….

Script execution and live updates to the model

The interaction between script execution and the state of the model is as follows:

• Changes made to the Web Animations model via the script interface are reflected immediately in the values returned by the interfaces defined in this specification.

Similarly, methods that operate on the current state of the model such as pausing or reversing are applied to a fully-updated timing model, that is, after all previous modifications have been incorporated.

For example, if the Player associated with an Animation's is seeked via the API, the value returned when querying the animation's `startTime` will reflect updated state of the model immediately.

```                // Initially anim's startTime is 3
anim.player.currentTime += 2;
```

The same concept applies to more complex modifications of the Web Animations model such as adding and removing children from a TimingGroup.

• Changes to the model other than seek operations do not cause timing events to be queued immediately. Instead, such events are queued upon the next sample as defined in .

The behavior of events with relation to seek operations is defined in .

Operations such as updating the playback rate of a player that involve performing a seek operation cause events to be queued immediately.

For example, if a series of modifications to the timing model in a single script block causes a TimedItem's item time to jump from being outside the active interval, to inside the interval, and then outside again, no events are fired as in the following example.

```  // anim is due to start in 3s
anim.onstart = function() { alert("started"); };
// Accelerate the parent causing anim to enter its active interval
// (Note we are updating the playback rate of a *timed item* not a player)
anim.parent.playbackRate *= 2;
// Adjust the start delay of anim such that it is no longer in its
// active interval
anim.timing.delay = Infinity;
// Result: no alert is shown
```
• Modifications to the model using the script interface do not cause the properties of the target element to be updated and nor is any CustomEffect called until the next sample has been performed at some time after the current script block completes execution.

For example, if the used style of an element is queried immediately after applying a new Animation to that element, the result of the new animation will not be incorporated in the value returned.

```                // Set opacity to 0 immediately
elem.animate({ opacity: '0' });
// Displays '1'
```

I'm unsure if this is the desired behavior for actions such as seeking and `play()` (and thus `animate()`). Gecko, for example, forces a synchronous sample when a seek is performed. This certainly makes testing simpler but I'm not sure if this is a good idea or not.

• The value returned by the `currentTime` attribute of a document timeline will not change within a script block.

For example, querying the `currentTime` twice within a long block of code that is executed in the same script block will return the same value as shown in the following example.

```                var a = document.timeline.currentTime;
// ... many lines of code ...
var b = document.timeline.currentTime;
alert(b - a); // Displays 0
```

We may introduce timelines that can be started programmatically (e.g. for SVG). In such a case, the `currentTime` should probably become zero immediately which would violate this condition. If we do indeed want that then we should probably spec it to force a synchronous sample at that point and note it as an exception here.

Integration with Media Fragments

The Media Fragments specification [[!MEDIA-FRAGMENTS]] defines a means for addressing a temporal range of a media resource. The application of media fragments depends on the MIME type of the resource on which they are specified. For resources with the SVG MIME type [[!SVG11]], the application of temporal parameters is defined in the Animation elements specification.

Note that media fragments are defined to operate on resources based on their MIME type. As a result, temporal addressing may not be supported in all situations where Web Animations content is used.

Interaction with page display

HTML permits user agents to store user-agent defined state along with a session history entry so that as a user navigates between pages, the previous state of the page can be restored including state such as scroll position [[HTML5]].

User agents that pause and resume media elements when the referencing document is unloaded and traversed, are encouraged to apply consistent handling to documents containing Web Animations content. If provided, this behavior SHOULD be achieved by applying a time lag to any timelines bound to the global clock.

Implementation requirements

Precision of time values

The internal representation of time values is implementation dependant however, it is RECOMMENDED that user agents be able to represent input time values with microsecond precision so that 0.000001 is distinguishable from 0.0.

Conformance criteria

This specification defines an abstract model for animation and, as such, for user agents that do not support scripting, there are no conformance criteria since there is no testable surface area.

User agents that do not support scripting, however, may implement additional technologies defined in terms of this specification in which case the definitions provided in this specification will form part of the conformance criteria of the additional technology.

A conforming scripted Web Animations user agent is a user agent that implements the API defined in including dispatching events as defined in .

TBD

Algorithms for event dispatch

The following algorithms demonstrate a possible approach to handling event queuing that incorporates the various requirements outlined in .

Some of the features of the following approach are:

• Sorts only once per timeline.
• Handles cotemporal samples without dispatching duplicate events.
• Handles zero-length intervals.
• Stores sample state only at the player level. (The previous play state is still per-timed item however.) This makes it possible for an implementation to optimize the case when there are no registered event listeners on part of the timing hierarchy. In such a case the whole procedure for determining and dispatching events can be skipped for that part of the hierarchy. Should event listeners be attached at a later point, the state stored at the player can be used to ensure the previously ignored timed items begin providing events as if they had always had event listeners.

Interval boundaries and time marks

With regards to event dispatch, interval boundary conditions are particularly important. For example, if we were to conduct a sample at time 3s and then another sample at 5s, on that second sample we should dispatch all events between the two times. If a timed item were to start at time 5s, then we should dispatch the corresponding timingstart event since that time has arrived. However, since we will have already dispatched all events at time 3s during the previous sample, we should not dispatch any events coinciding with time 3s.

In other situations, however, such as when getting the events scheduled by child timed items within a given iteration, we should include timingstart events that coincide with the start of the iteration but not timingend events since, under Web Animations endpoint-exclusive timing model, those timingend events happened fractionally before the iteration started. To accommodate these different endpoint behaviors we introduce the concept of time marks.

A time mark is a triple consisting of:

• a time value,
• a position: minus, zero, or plus, and
• a Boolean flag indicating if the mark represents the endpoint of an interval or not (regardless of which ‘end’ of the interval the mark represents)

We can use subscript notation to indicate these properties. For example, tminus|end. If the time mark does not represent an interval endpoint, the ‘|end’ part of the subscript text is dropped, as in tminus.

For a given time mark, |t| indicates just the time value ignoring the other properties, and tpos indicates just the position.

The minus position represents a value an infinitely small amount less than the time value whilst the plus position represents a value infinitely small amount greater. zero represents the moment at the time value.

The meaning of these position values is not affected by the direction in which playback proceeds. We can compare positions and time values as follows:

For two time marks a and b, a is less than b if one of the following conditions is true:

• |a| < |b|, or
• |a| = |b| and apos = before and bposbefore, or
• |a| = |b| and apos= zero and bpos= after

For two time marks a and b, a equals b if |a| equals |b| and apos equals bpos.

Operations such as greater-than and less-than-or-equal can be extrapolated from these definitions.

Since these operations only apply to the position and time value of the time mark, we define the `first()` and `last()` operations which are for most purposes equivalent to `min()` and `max()` but in the case where the two arguments are equal, it preserves their order. Their definitions are as follows.

• first(a,b) = a if ab and b otherwise.
• last(a,b) = a if a > b and b otherwise.

Given an interval delimited by two time marks a and b, a time t is in the interval ab if the following relationship holds: first(a, b) ≤ tlast(a, b).

A time mark can be added to a time value by simply adding the time value components and keeping the position and interval endpoint state of the time mark. Addition of two time marks is not defined.

Events when sampling a timeline

For a timeline, sampled such that the current time value is t, the set of timing events to queue can be determined as follows:

1. Iterate over each player in the set of players associated with this timeline in the order in which the players were created starting from the first created to the last, and for each player, perform the steps defined in .
2. Let events be an empty sequence of timing events.
3. Iterate over each player in the set of players i associated with this timeline in the order in which the players were created starting from the first created to the last and get the partially ordered set of events for the player at t and append then to events.
4. Perform a stable sort on events by event timeline time such that earlier times sort first.
5. Add events to the event queue in their current order.

Events when sampling a player

The partially ordered set of events for a player at timeline time t, can be determined as follows:

1. Let previous sample mark be a time mark associated with the player that is initialized to 0zero|end when the player is first created.
2. Let sample time be the result of calculating the player’s current time at timeline time t.
3. Let sample mark be sample timeplus.
4. Let events be an empty sequence of timing events.
5. The events queued depends on whether or not the time adjusted flag is set as follows,
If the time adjusted flag of the player is set,
1. If this player has associated source content, then get the partially ordered set of events scheduled for seek time sample time and append them to events.
2. Clear the time adjusted flag.
Otherwise,
1. If this player has associated source content, then get the partially ordered set of events scheduled between previous sample mark and sample mark and append them to events.

Note that this approach should correctly handle consecutive samples with the same time value.

In such a case, both previous sample mark and sample mark will have a position of plus. Since no timing events are scheduled to be dispatched at the plus position there should be no duplicate events.

6. Set previous sample mark to sample mark.
7. Return events.

Events for a timed item during regular sampling

The partially ordered set of events for a timed item scheduled between time marks a and b, expressed in uneased inherited time, can be determined as follows:

1. Let events be an empty sequence of timing events.
2. Let range a be the time mark resulting from calculating a + start time.
3. Let range b be the time mark resulting from calculating b + start time.
4. Define a time mark t as being in range if it is in the interval (range a, range b).
5. Let range lhs be first(range a, range b).
6. Let range rhs be last(range a, range b).
7. Let active start be start delayzero|end.
8. Let active end be (start delay + active duration)minus|end.
9. If |active start| = |active end| then set the position of active end to zero.
10. If either of the following conditions is true:
• active end < range lhs; or
• active start > range rhs
return events.
11. If |active start| = |active end| and the timed item’s iteration count is infinity, let effective iteration count be 1, otherwise let it be the timed item’s iteration count.
12. Let iteration times be a sequence of time values populated with the results of calculating |active start| + i * iteration duration for each integer i in the range 0 < i < effective iteration count.
13. Remove all time values from iteration times where time valuezero is not in range.
14. Let subintervals be an empty sequence of time marks.
15. If active start is in range, append it to subintervals, otherwise append range lhs.
16. For each time value t in iteration times, add the following two time marks to subintervals, in order, tminus|end, tzero|end unless the iteration duration is zero, in which case add tzero|end, tzero|end instead.
17. If active end is in range, append it to subintervals, otherwise append range rhs.
18. If the first pair of time marks in subintervals are not in order, that is, if subintervals[0] > subintervals[1], remove those two time marks from subintervals.

This will happen if a non-zero-duration iteration ends at |range lhs| and the position of range lhs is not minus.

19. If range a < range b, let direction be forwards, otherwise let direction be backwards.
20. If direction is backwards, reverse the elements of subintervals.
21. Let directed active start be active start if direction is forwards and active end otherwise.
22. Likewise, let directed active end be active end if direction is forwards and active start otherwise.
23. Define the iteration index at local time mark t as follows:
1. Let iteration index be the result of calculating the current iteration at |t|.
2. If tpos is minus and (iteration index x active start) % iteration duration = 0, let iteration index be max(0, iteration index - 1).
3. The result is iteration index.
24. Define the timeline time at local time t as follows:
1. Let the uneased local root time be the result of repeatedly applying the procedures for calculating the uneased inherited time from uneased local time and uneased local time from uneased child time defined in for each ancestor of this timed item in turn up to the root timed item using t as the initial uneased local time.
2. Let the uneased local player time be the result of calculating the uneased inherited time from uneased local time for the uneased local root time using the uneased local root time as the uneased local time.
3. Let the timeline time be the result of calculating the timeline time from the current time of a player for the player with which this timed item is associated using the uneased local player time as the current time.
4. If the timeline time is undefined, let timeline time use the current time value of the timeline with which this timed item is associated.
5. The result is timeline time.
25. If directed active start is in range, append to events a timing event with the following parameters:
Alternatively, if range a is an interval endpoint, append a timing event to events as above but substituting range a in place of directed active start.
26. Let subinterval iteration index be the iteration index at the first time mark in subintervals.
27. Let first iteration be `true`
28. Iterate over each pair of time marks in subintervals in order such that each time mark is used only once. For each pair of time marks, (subinterval start, subinterval end) perform the following steps:
1. Let subinterval iteration index be the iteration index at subinterval start.
2. If either of the following conditions is true,
• first iteration is `false`, or
• subinterval start = range asubinterval end
append a new timing event to events with the following paramters:
3. Let child start be a time mark whose time value is the result of calculating the directed time corresponding to |subinterval start| but using subinterval iteration index as the current iteration value and assuming a fill mode of none and whose position is the same as that of subinterval start.
4. Likewise, let child end be the result of performing the same operation but for subinterval end.
5. Let child direction be forwards if |child start| < |child end|, backwards if |child start| > |child end|, and `null` if |child start| = |child end|.
6. If child direction is not `null` and is not equal to direction, invert the position of child start and child end each such that plus becomes minus, and vice versa, and zero remains unchanged.
7. Let child events be an empty sequence of timing events.
8. Iterate over each child timed item in order and for each child get the partially ordered set of events scheduled between child start and child end and append to child events.
9. Append child events to events.
10. If direction is forwards, increment subinterval iteration index, otherwise decrement it.

This manual handling of the subinterval iteration index (as opposed to simply recalculating the iteration index for each subinterval start is necessary for handling zero-length intervals.

11. Let first iteration be `false`.
29. If directed active end is in range, append to events a timing event with the following parameters:
Alternatively, if range b is an interval endpoint, append a timing event to events as above but substituting range b in place of directed active end.
30. Return events.

Events for a timed item during seeked event dispatch

The partially ordered set of events for a timed item seeked to time t, expressed in uneased inherited time, can be determined as follows:

1. Let events be an empty sequence of timing events.
2. Let local t be t + start time.
3. Let child time be a time value that is the result of calculating the directed time corresponding to local t assuming a fill mode of none.
4. Iterate over each child timed item in order and for each child get the partially ordered set of events for seek time child time and append to events.
5. Let current play state be the result of evaluating if this timed item is in play at time local t.
6. If this timed item has a previous play state of not playing, and a current play state of playing, add to the beginning of events a new timing event with the following parameters:
7. If this timed item has a previous play state of playing, and a current play state of not playing, append to the end of events a new timing event with the following parameters:
8. Return events.

Acknowledgements

Thank you to Michiel “Pomax” Kamermans for help with the equations for a proposed smooth timing function although this feature has been deferred to a subsequent specification.

Our deep gratitude goes out to Southern Star Animation for their kind generosity and patience in introducing the editors to the processes and techniques used producing broadcast animations.

Changes since last publication

The following changes have been made since the 25 June 2013 Working Draft.

• Altered the definition of effective current time.
• Introduced bounding behavior to players so that the current time behaves more like a DVD or cassette player.
• Introduced timing function chains and added the `easingTime` attribute to the TimingInput dictionary and the `getEasingTime` and `setEasingTime` methods to the Timing interface.
• Renamed ‘time drift’ to time lag and exposed the time lag in the Player interface of the programming interface.
• Changed the behavior of fill modes so that children that are clipped part-way through their active interval by a parent timing group only fill if they have the corresponding fill mode set.
• Reworked the description of timed item states to include phases as well. Renamed the ‘active’ state to the in play state.
• Fixed a bug in the calculation of the time fraction for zero-length iteration durations ().
• Clarified behavior in cases where a value of infinity may be multiplied with zero.
• Added the following members to the Player interface:
• `playing`
• `cancel()`
• `finish()`
• `play()`
• `pause()`
• `reverse()`
• Made the `paused` member of the Player interface readonly.
• Renamed the following members of the Timing interface and TimingInput dictionary:
• `iterationDuration``duration`
• `startDelay``delay`
• `fillMode``fill`
• `iterationCount``iterations`
• `timingFunction``easing`
• Introduced an auto value for FillMode and made it the default value for `fill` on TimingInput.
• Added timing function syntax directly to this specification rather than referring to [[CSS3-TRANSITIONS]].
• Removed `null` as a possible value for the timing parameter of the ParGroup, SeqGroup and Animation constructors and the `Element.animate` method.
• Renamed `KeyframeAnimationEffect` to KeyframeEffect.
• Renamed path animation effects to motion path animation effects and likewise `PathAnimationEffect` to MotionPathEffect.

The changelog provides a more detailed history.