Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C liability, trademark and document use rules apply.
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.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published by the CSS Working Group (part of the Style Activity) and SVG Working Group (part of the Graphics Activity) as a First Public Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-fx@w3.org (subscribe, archives). All feedback is welcome.
Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by groups operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of each group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
Timeline
interfacePlayer
interfaceTimedItem
interfaceTiming
interfaceTimingInput
dictionaryTimingGroup
interfaceTimedItemList
interfaceParGroup
interfaceSeqGroup
interfaceAnimation
interfacePseudoElementReference
interfaceAnimationTarget
typedefAnimationEffect
interfaceAccumulateOperation
enumerationCompositeOperation
enumerationKeyframeAnimationEffect
interfaceKeyframe
dictionaryOneOrMoreKeyframes
typedefPathAnimationEffect
interfaceCustomEffect
callback interfaceTimingEvent
interfaceDocument
interfaceElement
interfaceThis section is non-normative.
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.
The Web Animations model aims at two broad areas of application:
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).
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:
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.
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].
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.
This section is non-normative.
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:
Graphically, this flow can be represented as follows:
For example, consider an animation that:
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.
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 section 5. Timing events.
This section is non-normative.
Two features characterise the Web Animations timing model: it is stateless and it is hierarchical.
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:
There are a few apparent 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, the model is stateless.
The other 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.
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.
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 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.
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.
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 section 6.24 Script execution and live updates to the model.
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 range 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.
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.
Since a timeline may be defined to relative 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.
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.
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.
This section is non-normative.
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 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 players.
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 - start
time) * playback rate
- time drift
Where:
If the timeline with which is player is associated is
not started then the current time is null
.
It is often useful to treat the current time as zero when it
would otherwise be null
.
We define the effective current time as being equal
to current time unless the current time is
null
,
in which case the effective current time is zero.
The procedure for performing manual updates to the current time is defined in section 3.5.2.6 Performing a seek.
Seeking and pausing a player are closely related and are described here together.
This section is non-normative.
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 section 4.2 Combining animations) and so we cannot simply adjust the start time. Instead, an additional offset is introduced called the time drift that further offsets a player's current time from its timeline. The effect of the time drift when seeking is illustrated below.
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.
This section is non-normative.
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 drift.
The effect of pausing on a player's time drift is illustrated below.
Players track three properties related to seeking and pausing.
A number of calculations for performing seeking and pausing 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; if the timeline is not started, then the effective timeline time is zero.
The time drift value is both a stored and a calculated value. When a player is paused, the value is calculated from the pause start time. When a player is not paused, the stored value is used. The stored value is initially zero, and is updated when the player is unpaused or seeked.
The value of time drift at a given moment is calculated as follows:
(effective timeline time - start time) * playback rate -
pause start time
.
These formulae need to be verified since removing the special behavior regarding pausing before the start time.
The procedure for updating the paused state is as follows:
Seeking is the process of updating a player's current time to a desired value. It is achieved using the following procedure:
(effective timeline time - start time)
* playback rate -
seek time
.
The timing events queued when a seek is performed are described in section 5.7.2 Event dispatch and seeking a player.
This section is non-normative.
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.
Changes to the playback rate also 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:
The source content of a player, if set, is a type of timed item. There are two types of timed item:
At a given moment, a timed item can be associated with at most one player.
Timed items can be chained together into a hierarchy using timings groups. Only the root timed item of such a hierarchy can be directly associated with a player. Attempting to associate a timed item that has a parent timing group with a player results in the timed item being removed from the parent timing group first. A timed item with an ancestor timing group that is directly associated with a player is indirectly associated with that player.
A timed item, item, is associated with a timeline, timeline, if item is directly or indirectly associated with a player which, in turn, is associated with timeline.
All types of timed item define a number of common properties which are described in the following sections.
This section is non-normative.
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.
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 section 3.13.4.1 The start time of children of a sequence timing group.
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 section 3.6.2 Local time and inherited time) and active time.
The length of the active interval is called the active duration, the calculation of which is defined in section 3.10.2 Calculating the active duration.
This section is non-normative.
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.
For a timed item, the inherited time at a given moment is based on the first matching condition from the following:
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
.
This section is non-normative.
At given moment, a timed item may 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.
The different states are illustrated below.
These states and their useage within the model are summarised as follows:
The timed item's local time falls either before or inside the item's active interval, or the local time of an ancestor timing group falls before or inside its active interval 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, in the absence of dynamic changes to the model, 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 since they will not have any dynamic effect.
null
.
The normative definition of each of these states follows.
A timed item is scheduled if either of the following conditions is true:
null
and is
less than the item's startDelay
, orA timed item is active if all of the following conditions are met:
null
, andA timed item is current if it is either scheduled or active or it has a parent timing group and the parent timing group is current.
A timed item is in effect if its active time as
calculated according to the procedure in section 3.10.3.1 Calculating the active time is not
null
.
The effect of a timed item outside its active interval is determined by its fill mode.
The possible fill modes are:
The normative definition of these modes is incorporated in the calculation of the active time in section 3.10.3.1 Calculating the active time.
This section is non-normative.
The effect of each fill mode is as follows:
Some examples of the these fill modes are illustrated below.
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.
As currently defined, when filling, a timed item uses an active time equal to either zero or its active duration, and this is used as the basis for the time which is inherited by its children.
This has the effect of ‘snapshotting’ the children for the duration of the parent's fill. As a result, if a child is active at the boundary of an ancestor's active interval and that ancestor is configured to fill at the point, the child will remain active through the ancestor's fill even if the child is not configured to fill in the given direction.
This behavior may be surprising in some circumstances.. It is particularly noticeable in the case of an ancestor with backwards fill, as for the common case where children are aligned at the start of the parent's active interval, they will also fill backwards regardless of their fill mode.
In order to provide control of this behavior we are considering modifying the definition of fill to depend on the parent's fill state. In particular, when a parent is filling, a child will only be active (and its descendants thus have an effect) if it too is configured to fill in that direction.
In order to provide the currently-defined behavior (which we expect is useful for many situations), we would likely introduce a new 'auto' fill mode, which means that a timed item's fill mode should match that of its parent, if present, or use forward fill otherwise.
See section 2 (Fill modes on descendants) of minuted discussion from Tokyo 2013 F2F.
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.
See section 15 (Overflowing fill) of minuted discussion from Tokyo 2013 F2F.
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 section 3.13.3.2 The intrinsic iteration duration of a parallel timing group and section 3.13.4.2 The intrinsic iteration duration of a sequence timing group).
The iteration duration of a timed item may be set by the author to represent a value other than the intrinsic iteration duration.
This section is non-normative.
Comparing the iteration duration and the active duration we have:
The relationship between the iteration duration and active duration is illustrated below.
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 section 3.10 Core timed item calculations.
This section is non-normative.
The effect of the iteration count and iteration start parameters is illustrated below.
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.
This section is non-normative.
We have already encountered different time spaces in describing local time and inherited time (see section 3.6.2 Local time and inherited time). 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.
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 section 3.10.3.1 Calculating the active time 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.
This section is non-normative.
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 active; there is no overlap.
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 section 3.10.3.3 Calculating the iteration time and is illustrated below.
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 section 3.10 Core timed item calculations.
This section is non-normative.
In summary, the behavior of the playback rate of a timed item is as follows:
Changing the playback rate of a timed item whose local time is within its active interval will cause it to jump. This is because the active duration will be updated but the local time will not.
Furthermore, if other timed items depend on the timed item's active duration, such as sibling timed items in a sequence timing group, they too may jump as a result of setting the timed item's playback rate.
For runtime speed control the playback rate of the player should be used.
This section is non-normative.
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 boundary when the timed item is active, that is, the active duration.
This process is illustrated below.
The process for calculating the active duration is normatively defined in section 3.10.2 Calculating the active duration.
Having established the active duration, the process for transforming a timed item's inherited time into its transformed time is illustrated below.
The first step, calculating the local time is described in section 3.6.2 Local time and inherited time. Steps 2 to 4 in the diagram are described in the following sections. Steps 5 and 6 are described in section 3.11.1 Calculating the directed time and section 3.12.6 Calculating the transformed time respectively.
In order to calculate the active duration we first define the repeated duration as follows:
repeated duration =
iteration duration *
iteration count
The active duration is calculated according to the following steps:
Infinity
.
repeated duration
/ abs(playback rate)
.
The active time is based on the local time and start delay. It is defined only when the timed item is in effect and is calculated according to the following steps:
null
, return
null
.
local time < start delay
the result depends on the fill mode as follows,
null
.
local time < start time + active
duration
, return local time - start
delay
.
null
.
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
The scaled active time is calculated according to the following steps:
null
, return
null
.
(active time -
active duration)
* playback rate
+ start offset
.
active time
* playback rate
+ start offset
.
The iteration time is calculated according to the following steps:
null
,
return null
.
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.
scaled active time
% iteration duration
.
The current iteration can be calculated using the following steps:
null
, return
null
.
floor(iteration start + iteration count)
.
iteration start
+ iteration count - 1
.
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.
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:
The semantics of these values are incorporated into the calculation of the directed time which follows.
This section is non-normative.
A non-normative definition of these values is as follows:
The directed time is calculated from the iteration time using the following steps:
null
, return
null
.
normal
,
reverse
,
alternate-reverse
increment
d by 1.
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?
d % 2 == 0
, let the
current direction be forwards, otherwise let
the current direction be reverse.
Otherwise, return the iteration duration - iteration time.
This section is non-normative.
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.
Such timing functions can be applied to an iteration of a timed item.
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.
We are considering introducing the concept of chained timing functions.
A chained timing function is composed of a set of primitive timing functions, where each primitive timing function maps a limited portion of the input range to a portion of the output range. Available primitive timing functions include cubic Bézier timing functions, step timing functions and the linear timing function.
A chained timing function can be configured to explicitly specify the input and output ranges of each primitive timing function, or to align the input ranges of the primitive timing functions with the offsets of the corresponding animation effect's keyframes or path segments.
See section 5 (Chained timing functions) of minuted discussion from Tokyo 2013 F2F.
This section is non-normative.
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.
Some example cubic Bézier timing functions are illustrated below.
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].
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.
This section is non-normative.
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.
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 section 3.8.4 Interval timing), the output time at the transition point is the time after applying the increase (i.e. the top of the step).
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.
The syntax for specifying a paced timing function is:
paced(<property>)
.
The <property>
argument is the referenced
property of the paced timing function.
This section is non-normative.
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:
The result of evaluating a paced timing function at input time is calculated as follows:
Need to confirm this approach is actually backwards-compatible with SVG with regards to motion-path behavior.
input time × total length
.
current distance
+ current length
, perform the following steps:
current distance / total length +
(distance - current distance) /
current length
Is this algorithm necessary? Would a prose description suffice?
The length between any two property values depends on the type of values as follows:
Need to explain how this applies to length values.
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.
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.
The transformed time is calculated from the directed time using the following steps:
null
,
return null
.
directed time / iteration
duration
unless iteration duration is
zero, in which case let iteration fraction be
zero.scaled
fraction * iteration duration
.
This section is non-normative.
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.
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 section 3.6.2 Local time and inherited time).
This section is non-normative.
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.
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.
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.
Some further consequences of timing group children basing their timing on their parent group's transformed time are:
This section is non-normative.
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:
Timing groups can also contain other timing groups which allows for more sophisticated synchronization. An example is illustrated below.
Web Animations defines two types of 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 a child timed item of a parallel timing group is zero.
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.
Define the end time of a timed item as :
end time =
start time + start
delay + active duration
The intrinsic iteration duration depends on the number of child timed items as follows,
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 section 3.13.4.2 The intrinsic iteration duration of a sequence timing group).
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 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.
This section is non-normative.
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 is equivalent to the start time of a hypothetical child timed item appended to the group's children calculated according to the definition in section 3.13.4.1 The start time of children of a sequence timing group 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 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.
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:
the time fraction is as follows,
start delay - 1
) and an iteration
duration of 1.
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.
This section is non-normative.
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 section 4.2 Combining animations).
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 section 6.24 Script execution and live updates to the model.
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 section 4.5 Animatable properties.
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.
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 section 4.6 Animation of property types. 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.
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 section 4.2 Combining animations.
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.
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 section 4.3.1 The unaccumulated animation value of a keyframe animation effect and section 4.4.1 The unaccumulated animation value of a path animation effect).
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.
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.
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.
This section is non-normative.
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:
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.
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:
Animation effects that sort earlier have lower 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.
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 section 4.2.4 Combining with other styles: the override stylesheet.
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.
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:
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.
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 section 4.1 Animation effects).
The composited value calculated for a property is applied using the following process.
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 chain of timing functions on the timed item (proposal for this is still in the works).
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 section 4.3.1 The unaccumulated animation value of a keyframe animation effect.
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 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.
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.
underlying value + value to
add
.
(time fraction - start offset) /
(end offset - start offset)
Note that this procedure assumes the following about the list of keyframes specified on the effect:
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.
See section 4 (Keyframe offsets outside [0, 1]) of minuted discussion from Tokyo 2013 F2F.
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:
then the offset of k is
a + (b - a)
* i
/ (n + 1)
A path animation effect is an animation effect that produces transform unaccumulated animation values such that a target element follows a specified geometric curve.
The path of a 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 path animation effect, if set, specifies that the unaccumulated animation value generated by the path animation effect produces a rotation that matches the directional tangent vector of the path.
The rotation angle parameter of a 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 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 path animation effect for a given time fraction and underlying value is given by the following process:
This section is non-normative.
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:
floor(progress)
.
progress - floor(progress)
.
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:
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 section B. Algorithms for path animation effects for a non-normative treatment of this topic.
For a given path element and element fraction, the translation value is determined using the following procedure:
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).
element fraction × length
.
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?
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 section B. Algorithms for path animation effects for a full non-normative treatment of this topic.
Need to describe how transform-origin is applied.
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.
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.
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 section 4.6.7 Default animation procedures 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,
For addition,
When an addition procedure is not commutative, Va represents the first term of the operation and Vb represents the second.
This section is non-normative.
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.
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?
This section is non-normative.
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.
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.
Interpolation is calculated as Vres = (1 - p) * Vstart + p * V end.
Addition is calculated as Vres = calc(V a + Vb).
Interpolation is calculated as Vres = (1 - p) * Vstart + p * Vend.
Addition is calculated as Vres = calc(Va + Vb).
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].
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).
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.
Interpolation is calculated as defined in [CSS3-TRANSFORMS].
Addition is calculated as an accumulation as defined in [CSS3-TRANSFORMS].
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).
For addition:
Vres = calc(Va + Vb).
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 section 4.6.1 Animation of like types or section 4.6.2 Animation of non-matching primitive types.
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.
Shorthand properties are animated as defined in [CSS3-TRANSITIONS].
For interpolation:
Vres = calc((1 - p) * Vstart + p * Vend).
For addition:
Vres = calc(Va + Vb).
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.
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
Note that interpolation is never performed on invalid values.
- If 0 ≤ p < 0.5
- Vres = Vstart
- Otherwise,
- Vres = Vend
Addition is between two values Va and Vb. The result Vres is given by
Vres = Vbunless Vb is the neutral value for composition, in which case
Vres = Va
This section is non-normative.
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.
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 section 4.2.4 Combining with other styles: the override stylesheet).
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 section 4.2.1 The animation stack. 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.
Items sorted earlier are executed before those sorted later.
The current event model has two undesirable consequences:
One alternative under consideration is as follows:
See sections 8 and 14 of minuted discussion from Tokyo 2013 F2F.
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.
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).
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
.
Occurs at the moment when a timed item leaves its active interval (from either direction).
Occurs when a timed item loses its association with a player.
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?
This section is non-normative.
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:
Timing functions are not always invertible.
In order to dispatch events in the correct order it is often necessary to convert from a timed item's local time to a common time space for sorting and non-invertible timing functions make this impractical.
Timing functions on parent timing groups can cause unnecessary events to be generated.
For example, consider a timing group that has a timing function that is not monotonically increasing such as a bounce effect. Within a single iteration of the timing group child timed items may repeatedly exit and enter their active interval. Dispatching a timing event on each such moment is unlikely to be useful to most applications.
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.
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.
Let the uneased iteration time be the result corresponding to the first matching condition from below.
iteration duration - child time
Let the uneased scaled active time be the result corresponding to the first matching condition from below.
repeated duration * start offset
iteration index * iteration duration
+ uneased iteration time
Let the uneased active time be the result corresponding to the first matching condition from below.
(uneased scaled active time - start
offset) / playback
rate
(uneased scaled active time - start
offset) / playback
rate + active duration
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 drift) /
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.
Timing events have an associated event local time, event timeline time, event iteration index, and seeked dispatch flag.
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 section 5.3 Inverse timing calculations) it lies within the range 0 ≤ uneased iteration time ≤ iteration 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 section 5.3 Inverse timing calculations.
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.
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.
The sequence in which timing events are queued is as follows:
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.
Note that sorting end events before start events is consistent with the end-point exclusive nature of intervals (see section 3.8.4 Interval timing). 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.
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 section 5.7.3 Event dispatch and time adjustments 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 section 5.7.2 Event dispatch and seeking a player.
Make sure we update the previous sample time for a seek/etc.
Note that section C. Algorithms for event dispatch provides non-normative algorithms that incorporate the behavior defined in this section as well as section 5.6 Sequence of events.
This section is non-normative.
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 active or not at some initial moment and at some final moment.
To facilitate this, each timed item has an associated previous active state property that initially has the value inactive.
For a given timed item the events queued as a result of performing seeked event dispatch at uneased local time t is as follows:
For timing groups, this procedure is applied recursively to all child timed items. The resulting events are sorted using the sequence defined in section 5.6 Sequence of events.
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 section 5.7.3 Event dispatch and time adjustments.
When a seek is performed on a player (see section 3.5.2.6 Performing a seek) seeked event dispatch is applied.
Prior to performing the seek, the previous active 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 active 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 active 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.
This section is non-normative.
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.
null
.
This includes timed items that become newly associated with the
player or likewise cease to be associated with the
player.Note that the fill mode and timing function associated with a timed item are not included in this list since they do not effect uneased timing.
This behavior extends only to actual changes to the values. Setting a property to its current value—for example, by using the script interface— does not cause the flag to be set.
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.
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.
null
.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.
This section is non-normative.
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?)
This section is non-normative.
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.
Timeline
interface
Timelines, including the document
timeline are represented in the Web Animations API by the
Timeline
interface.
interface Timeline {
readonly attribute double? currentTime;
Player
play (optional TimedItem
? source = null);
sequence<Player
> getCurrentPlayers ();
double? toTimelineTime (double otherTime, Timeline
other);
double? toTimelineTime (Event event);
};
currentTime
of type double, readonly, nullable
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.
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 section 3.5.1 The current time of a player.
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.
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.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
source |
| ✔ | ✔ (null ) |
The source content to assign to the newly-created
The |
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.
sequence<Player
>
toTimelineTime
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:
InvalidNodeTypeError
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
otherTime | double | ✘ | ✘ | |
other |
| ✘ | ✘ |
double
, nullabletoTimelineTime
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.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
event | Event | ✘ | ✘ |
double
, nullablePlayer
interface
Players are represented in the Web Animations
API by the Player
interface.
interface Player {
attribute TimedItem
? source;
readonly attribute Timeline
timeline;
attribute double startTime;
attribute double currentTime;
attribute double playbackRate;
attribute boolean paused;
};
source
of type TimedItem
, nullableThe 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—either directly or via an ancestor—with at most one player. In order to maintain these invariants, on setting this value, the following procedure is performed:
source
attribute.null
,
disassociate old value from this player.null
,
perform the steps associated with the first matching condition
of the following:
new value.remove()
.source
attribute to new
value.timeline
of type Timeline
, readonlystartTime
of type doublecurrentTime
of type doubleplaybackRate
of type doublepaused
of type booleanA reverse method would be very useful here for effects like transitions.
The behavior would be:
currentTime
is beyond the end
time of the source content seek back to the end of
the active interval.
playbackRate
to
-playbackRate
.This reflects how transitions work as well as common usage.
Some objections:
reverse
twice should be a noop.Some suggestions:
reverseSource
to make the link to the the
source content obvious and remove any expectation that
calling it twice is a noop.Your feedback is most welcome at public-fx@w3.org, subject [web-animations] ….
TimedItem
interface
Timed items are represented in the Web
Animations API by the TimedItem
interface.
interface TimedItem : EventTarget {
// Playback state
readonly attribute double? localTime;
readonly attribute unsigned long? currentIteration;
// Specified timing
readonly attribute Timing
specified;
// Calculated timing
readonly attribute double startTime;
readonly attribute unrestricted double iterationDuration;
readonly attribute unrestricted double activeDuration;
readonly attribute unrestricted double endTime;
// Timing hierarchy
readonly attribute TimingGroup
? parent;
readonly attribute TimedItem
? previousSibling;
readonly attribute TimedItem
? nextSibling;
void before (TimedItem... items);
void after (TimedItem... items);
void replace (TimedItem... items);
void remove ();
// Associated player
readonly attribute Player
? player;
// Event callbacks
attribute EventHandler onstart;
attribute EventHandler oniteration;
attribute EventHandler onend;
attribute EventHandler oncancel;
};
localTime
of type double, readonly, nullableThe local time of this timed item.
localTime
will be null
if this timed
item is not directly or indirectly associated with
a player or if it has a parent timing group that is
not in effect.
currentIteration
of type unsigned long, readonly, nullablespecified
of type Timing
, readonlyReturns the input timing properties for this timed item.
Representing these parameters has been a particularly contentious topic.
The current arrangement:
Timing
interface and
a TimingInput
dictionary type which increases the API
surface area somewhat
anim.specified.iterationDuration
) to reading
the value (typically, anim.iterationDuration
)
Timing
objects
should be share-able or not
"3s"
should be allowed (and allowing
them makes walking the tree more complex).
It is also not permitted by WebIDL.
However, it separates "specified" timing from "computed" timing which some consider advantageous.
The only situation where calculated values and input values
differ is for iterationDuration
and
activeDuration
.
One alternative that has been proposed is to introduce
a Duration
interface as follows:
interface TimedItem : EventTarget { // Timing attribute double startDelay; attribute FillMode fillMode; attribute Duration iterationDuration; attribute Duration activeDuration; attribute double playbackRate; // ... // Scheduled time readonly attribute double startTime; readonly attribute unrestricted double endTime; }; interface Duration { double sec; DOMString string; }
Usage is as follows:
var specifiedDur = anim.iterationDuration.string; // "auto" var calculatedDur = anim.iterationDuration.sec; // 5 // Update duration to 3s anim.iterationDuration.sec = 3; // anim.iterationDuration.string -> "3s" // Update duration to 3s (alt.) anim.iterationDuration.string = "3s"; // anim.iterationDuration.sec -> 3 // Reset to auto anim.iterationDuration.string = "auto"; // anim.iterationDuration.sec -> 5
Your feedback is most welcome at public-fx@w3.org, subject [web-animations] ….
startTime
of type double, readonlyThe 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.
iterationDuration
of type unrestricted double, readonlyThe iteration duration of this timed item.
Unlike the iterationDuration
attribute of
the Timing
interface or TimingInput
dictionary,
this attribute returns the calculated value of the iteration
duration.
If specified.iterationDuration
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
iterationDuration
attribute of the
specified
member of this interface.
activeDuration
of type unrestricted double, readonlyThe active duration of this timed item.
As with iterationDuration
, 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 section 3.10.2 Calculating the active duration.
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.
endTime
of type unrestricted double, readonlyThe 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.startDelay;
parent
of type TimingGroup
, readonly, nullable
The parent timing group of this timed item or
null
if this timed item does not have
a parent timing group.
parentGroup
?
previousSibling
of type TimedItem
, readonly, nullablenextSibling
of type TimedItem
, readonly, nullableplayer
of type Player
, readonly, nullableThe player associated with this timed item—either directly or indirectly. 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.
onstart
of type EventHandleroniteration
of type EventHandleronend
of type EventHandleroncancel
of type EventHandlerbefore
Inserts items before this timed item.
HierarchyRequestError
exception and
terminate these steps.
Note that this definition precludes the following usage since
item
is an inclusive ancestor of itself:
item.before(item); // throws HierarchyRequestError
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
items | TimedItem... | ✘ | ✘ |
void
after
Inserts items after this timed item.
HierarchyRequestError
exception and
terminate these steps.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
items | TimedItem... | ✘ | ✘ |
void
replace
Replaces this TimedItem
with the passed in
items.
HierarchyRequestError
exception and
terminate these steps.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
items | TimedItem... | ✘ | ✘ |
void
remove
void
Note that the EventHandler callback interface type is defined in [HTML5].
Timing
interface
Timing parameters for a TimedItem
are collected together under
the Timing
type.
interface Timing {
attribute double startDelay;
attribute FillMode
fillMode;
attribute double iterationStart;
attribute unrestricted double iterationCount;
attribute (unrestricted double or DOMString) iterationDuration;
attribute (unrestricted double or DOMString) activeDuration;
attribute double playbackRate;
attribute PlaybackDirection
direction;
attribute DOMString timingFunction;
};
startDelay
of type doubleThe start delay which represents the number of seconds from a timed item's start time to the start of the active interval.
fillMode
of type FillMode
The fill mode as specified by one of the FillMode
enumeration values.
iterationStart
of type doubleThe 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 iterationCount
is effectively
added to the iterationStart
such that
a timed item with an iterationStart
of
‘0.5’ and iterationCount
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’.
iterationCount
of type unrestricted doubleThe 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.
iterationDuration
of type (unrestricted double or DOMString)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.
activeDuration
of type (unrestricted double or DOMString)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 section 3.10.2 Calculating the active duration.
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.
playbackRate
of type doubleThe 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.
direction
of type PlaybackDirection
The playback direction of the timed item as
specified by one of the PlaybackDirection
enumeration
values.
timingFunction
of type DOMStringThe timing function used to scale the time to produce easing effects.
The acceptable values and their meanings are those defined for the transition-timing-function property in CSS Transitions [CSS3-TRANSITIONS].
In addition to the values defined in CSS Transitions, this method
extends the steps()
function notation to allow
‘middle’ as a transition point keyword (e.g.
steps(3, middle)
).
Similarly, the keyword ‘steps-middle’ is recognized
and given the meaning steps(1, middle)
.
Strings that specify a cubic-bezier()
timing function
result produce a cubic Bézier timing function.
Strings that specify a steps()
function produce a
step timing function. Strings that specify apaced()
timing function result produce a paced timing function.
Unrecognized string values are treated as if the
linear
keyword was specified for the purpose of
timing model calculations.
TimingInput
dictionary
The TimingInput
dictionary is used as a convenience for
specifying the timing properties of a TimedItem
in bulk.
dictionary TimingInput {
double startDelay = 0;
FillMode
fillMode = "forwards";
double iterationStart = 0.0;
unrestricted double iterationCount = 1.0;
(unrestricted double or DOMString) iterationDuration = "auto";
(unrestricted double or DOMString) activeDuration = "auto";
double playbackRate = 1.0;
PlaybackDirection
direction = "normal";
DOMString timingFunction = "linear";
};
TimingInput
MembersstartDelay
of type double, defaulting to 0
The specified start delay.
See the description of the startDelay
attribute on
the Timing
interface.
fillMode
of type FillMode
, defaulting to "forwards"
The fill mode as specified by one of the FillMode
enumeration values.
Note that in both CSS Animations [CSS3-ANIMATIONS] and SVG [SVG11] the default fill mode is "none". Web Animations differs in this regard since it was determined that when generating animations from script, forwards filling is the more commonly-desired behavior.
Some feedback suggests the default here should be "both".
iterationStart
of type double, defaulting to 0.0
The timed item's iteration start property.
See the description of the iterationStart
attribute
on the Timing
interface.
iterationCount
of type unrestricted double, defaulting to 1.0
The timed item's iteration count property.
See the description of the iterationCount
attribute
on the Timing
interface.
iterationDuration
of type (unrestricted double or DOMString), defaulting to "auto"
The iteration duration of the timed item.
See the description of the iterationDuration
attribute on the Timing
interface.
activeDuration
of type (unrestricted double or DOMString), defaulting to "auto"
The active duration of the timed item.
See the description of the activeDuration
attribute
on the Timing
interface.
playbackRate
of type double, defaulting to 1.0
The timed item's playback rate property.
See the description of the playbackRate
attribute
on the Timing
interface.
direction
of type PlaybackDirection
, defaulting to "normal"
The playback direction of the timed item.
See the description of the direction
attribute
on the Timing
interface.
timingFunction
of type DOMString, defaulting to "linear"
The timing function used to scale the time to produce easing effects.
See the description of the timingFunction
attribute
on the Timing
interface.
FillMode
enumerationenum FillMode { "none", "forwards", "backwards", "both" };
none
forwards
backwards
both
PlaybackDirection
enumerationenum PlaybackDirection { "normal", "reverse", "alternate", "alternate-reverse" };
normal
reverse
alternate
alternate-reverse
TimingGroup
interface
The different types of timing groups
defined by Web Animations share a common TimingGroup
interface as defined below.
interface TimingGroup : TimedItem
{
readonly attribute TimedItemList
children;
readonly attribute TimedItem
? firstChild;
readonly attribute TimedItem
? lastChild;
void prepend (TimedItem... items);
void append (TimedItem... items);
};
children
of type TimedItemList
, readonlyfirstChild
of type TimedItem
, readonly, nullablelastChild
of type TimedItem
, readonly, nullableprepend
HierarchyRequestError
exception and
terminate these steps.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
items | TimedItem... | ✘ | ✘ |
void
append
HierarchyRequestError
exception and
terminate these steps.
null
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
items | TimedItem... | ✘ | ✘ |
void
The next sibling of item not included in a set of timed items, items is determined using the following steps:
null
perform the following steps:
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:
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:
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
.
interface TimedItemList {
readonly attribute unsigned long length;
getter TimedItem
? item (unsigned long index);
};
length
of type unsigned long, readonlyitem
[index]
Returns the timed item at index
.
If index
is greater than or equal to
length
returns null
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
index | unsigned long | ✘ | ✘ |
TimedItem
, nullableParGroup
interface
Parallel timing groups are
represented by the ParGroup
interface.
[Constructor (sequence<TimedItem
>? children,
optional (unrestricted double or TimingInput
)? timing = null)]
interface ParGroup : TimingGroup
{
ParGroup
clone ();
};
ParGroup
Creates a new ParGroup
object using the following
procedure:
ParGroup
object, group.TimingInput
object,double
,TimingInput
object with all members set to their
default values and iterationDuration
set to
timing.
null
or
undefined),TimingInput
object with all members set to their default values.
group.specified
to a new
Timing
object whose attributes are assigned the
value of the member of the same name on timing input.
The above two steps are identical with the constructor for Animation
and should be
factored out somewhere.
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.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
children | sequence< | ✔ | ✘ |
A sequence of timed items to add as children of this group.
These children are appended in sequence using the same
semantics as the |
timing | (unrestricted double or | ✔ | ✔ (null ) |
The timing properties or iteration duration of the new timing group. |
clone
Creates a deep copy of this ParGroup
object using the
following procedure.
ParGroup
object, the
object to be cloned.TimingInput
object whose members are assigned the value of the attribute
with the same name on
source.specified
.TimedItem
objects.source.children
, append the result
of calling child.clone()
to cloned children.
ParGroup
object created by
calling the ParGroup
constructor with parameters
ParGroup(cloned children,
cloned timing)
.ParGroup
SeqGroup
interface
Sequence timing groups are
represented by the SeqGroup
interface.
[Constructor (sequence<TimedItem
>? children,
optional (unrestricted double or TimingInput
)? timing = null)]
interface SeqGroup : TimingGroup
{
SeqGroup
clone ();
};
SeqGroup
ParGroup
.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
children | sequence< | ✔ | ✘ | |
timing | (unrestricted double or | ✔ | ✔ (null ) |
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
.
SeqGroup
Animation
interface
Animations are represented by the
Animation
interface.
[Constructor (AnimationTarget
? element,
(AnimationEffect
or CustomEffect
or OneOrMoreKeyframes
)? effect,
optional (unrestricted double or TimingInput
)? timing = null)]
interface Animation : TimedItem
{
attribute (AnimationEffect
or CustomEffect
)? effect;
readonly attribute AnimationTarget
? target;
Animation
clone ();
};
Animation
Creates a new Animation
object
using the following procedure:
Animation
object, animation.TimingInput
object,double
,TimingInput
object with all members set to their
default values and iterationDuration
set to
timing.
null
or
undefined),TimingInput
object with all members set to their default values.
animation.specified
to a new
Timing
object whose attributes are assigned the
value of the member of the same name on timing input.
AnimationEffect
object or a CustomEffect
object,animation.effect
to
effect.
OneOrMoreKeyframes
,animation.effect
to
a new KeyframeAnimationEffect
object constructed by
passing effect as the frames parameter
and with the other parameters set to their default values.
animation.effect
to
null
.
Examples of the usage of this constructor are given in section 6.10.4 Creating a new Animation object.
Note that as with the
constructor for TimingGroup
s
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.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
element |
| ✔ | ✘ |
The target element or target pseudo-element.
This may be null for animations that do not target
a specific element.
|
effect | ( | ✔ | ✘ |
The animation effect used to set the effect
attribute of the newly-created Animation object.
If this parameter is an
If this parameter of type
If this parameter is |
timing | (unrestricted double or | ✔ | ✔ (null ) |
The timing properties or iteration duration of the new animation. |
effect
of type (AnimationEffect
or CustomEffect
), nullable
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 section 5. Timing events).
target
of type AnimationTarget
, readonly, nullable
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.
clone
Creates a copy of this Animation
object using the following procedure.
Animation
object to
clone, that is, this object.TimingInput
object whose members are assigned the value of the attribute
with the same name on
source.specified
.AnimationEffect
is cloned depending on the type of
source.effect
as follows,
source.effect
is an
Animation object,source.effect.clone()
.
source.effect
is a
CustomEffect
object,source.effect
has a method
called clone
let cloned effect be
the result of calling that method, otherwise let
cloned effect be
source.effect
.
null
.
Animation(source.target, cloned
effect, cloned timing)
.Animation
Animation
objectThis section is non-normative.
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 PathAnimationEffect("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' }, { iterationDuration: 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 fillMode
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);
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)]
interface PseudoElementReference {
attribute Element
element;
attribute DOMString pseudoElement;
};
element
of type Element
Exceptions:
NoModificationAllowedError
pseudoElement
of type DOMString::after
’.
Exceptions:
NoModificationAllowedError
AnimationTarget
typedeftypedef (Element
or PseudoElementReference
) AnimationTarget;
AnimationTarget
is used wherever either an Element
or
a PseudoElementReference
can be used.
AnimationEffect
interface
Animation effects are represented by
the AnimationEffect
interface.
AnimationEffect
is an abstract interface of which several
concrete subinterfaces are provided.
interface AnimationEffect {
attribute AccumulateOperation
accumulate;
AnimationEffect
clone ();
};
accumulate
of type AccumulateOperation
The accumulation operation property of this animation
effect as specified by one of the AccumulateOperation
constants.
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.
AnimationEffect
AccumulateOperation
enumeration
The possible values of an animation effect's
accumulation behavior are represented by the
AccumulateOperation
enumeration.
enum AccumulateOperation { "sum", "none" };
sum
none
CompositeOperation
enumeration
The possible values of an animation effect's
composition behavior are represented by the
CompositeOperation
enumeration.
enum CompositeOperation { "replace", "add" };
replace
add
KeyframeAnimationEffect
interface
Keyframe animation effects are represented by the
KeyframeAnimationEffect
interface.
[Constructor (OneOrMoreKeyframes
frames, optional CompositeOperation
composite = "replace",
optional AccumulateOperation
accumulate = "none")]
interface KeyframeAnimationEffect : AnimationEffect
{
attribute CompositeOperation
composite;
sequence<Keyframe
> getFrames ();
void setFrames (OneOrMoreKeyframes
frames);
};
KeyframeAnimationEffect
Creates a new KeyframeAnimationEffect
object for the
given set of keyframes.
Before storing, each of the keyframes in frames is normalized using the procedure in section 6.17.2 Normalizing a Keyframe object.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
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 .
|
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.
|
accumulate |
| ✘ | ✔ ("none" ) | The accumulation operation used to define the way animation values build from iteration to iteration. |
composite
of type CompositeOperation
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.
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 section 6.16.4 Normalizing the list of keyframes does not affect the value returned by this method.
sequence<Keyframe
>
setFrames
Replaces the set of keyframes that make up this effect.
Upon setting, each keyframe in frames is normalized using the procedure in section 6.17.2 Normalizing a Keyframe object before storing.
Before being used by the animation model, the set of frames associated with this effect is normalized using the procedure defined in section 6.16.4 Normalizing the list of keyframes.
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.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
frames |
| ✘ | ✘ |
void
Before passing the list of Keyframes
specified in the API to the
animation model so that the unaccumulated animation value can
be calculated (see section 4.3.1 The unaccumulated animation value of a keyframe animation effect), the following normalization is performed.
getFrames
.
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
.
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
section 6.17.2 Normalizing a Keyframe object.
No handling is defined for other languages.
dictionary Keyframe {
// ... property-value pairs ...
double? offset = null;
CompositeOperation
? composite = null;
};
Keyframe
Membersoffset
of type double, nullable, defaulting to 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 section 6.16.4 Normalizing the list of keyframes.
A null
value indicates that the keyframe
should be positioned automatically using the algorithm defined in
section 4.3.2 Procedure for evenly distributing keyframes and applied in
section 6.16.4 Normalizing the list of keyframes.
composite
of type CompositeOperation
, nullable, defaulting to 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 KeyframeAnimationEffect
will be used.
Keyframe
objectSince 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:
A Keyframe
object, keyframe
input, is converted to a normalized internal representation
keyframe result using the following procedure:
null
.
null
.
keyframe input.offset
is
a Number, set the positional offset
of keyframe input to
keyframe input.offset
.
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
.
toString
on the name property of
keyframe input.
This procedure is performed exactly once per call to
setFrames
or the constructor for
KeyframeAnimationEffect
.
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:
cssOffset
.
OneOrMoreKeyframes
typedeftypedef (Keyframe
or sequence<Keyframe
>) OneOrMoreKeyframes;
OneOrMoreKeyframes
type to represent either a single keyframe or a list of such
keyframes.
PathAnimationEffect
interface
Path animation effects are
represented by the PathAnimationEffect
interface.
[Constructor ((DOMString or SVGPathSegList) path,
optional AutoRotationMode
autoRotate = "none", optional double angle = 0,
optional CompositeOperation
composite = "replace")]
interface PathAnimationEffect : AnimationEffect
{
attribute SVGPathSegList segments;
attribute AutoRotationFlag autoRotate;
attribute double angle;
attribute CompositeOperation
composite;
};
PathAnimationEffect
Creates a new PathAnimationEffect
object with the specified
parameters.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
path | (DOMString or SVGPathSegList) | ✘ | ✘ |
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
The resulting SVGPathSegList is assigned to the
|
autoRotate |
| ✘ | ✔ ("none" ) | The automatic rotation flag setting for the generated effect. |
angle | double | ✘ | ✔ (0 ) | The rotation angle for the generated effect. |
composite |
| ✘ | ✔ ("replace" ) |
The composition operation used to composite this
animation with the animation stack, as specified by one
of the CompositeOperation enumeration values.
|
segments
of type SVGPathSegListIs 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?
autoRotate
of type AutoRotationFlagangle
of type doublecomposite
of type CompositeOperation
CompositeOperation
enumeration values.
AutoRotationMode
enumeration
The values of the automatic rotation flag of a path
animation effect are represented by the AutoRotationMode
enumeration.
enum AutoRotationMode { "auto-rotate", "none" };
auto-rotate
none
CustomEffect
callback interface
Custom effects can be defined in script
using the CustomEffect
interface.
callback interface CustomEffect {
attribute long? priority;
attribute CustomEffectCloneCallback
? clone;
void sample (double? timeFraction, double currentIteration, AnimationTarget
? target,
double? previousTimeFraction);
};
priority
of type long, nullableclone
of type CustomEffectCloneCallback
, nullableAn optional callback method used to create an independent copy of this object.
sample
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
timeFraction | double | ✔ | ✘ |
The time fraction for which to produce an effect.
When this is null , the callback object should
remove the effect.
|
currentIteration | double | ✘ | ✘ | The current iteration beginning with zero corresponding to the first iteration. |
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 .
|
previousTimeFraction | double | ✔ | ✘ |
The value of timeFraction that was passed to this
If this |
void
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?
callback CustomEffectCloneCallback = CustomEffect
();
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.
CustomEffect
TimingEvent
interface[Constructor (DOMString type, optional TimingEventInit
eventInit)]
interface TimingEvent : Event {
attribute double? localTime;
attribute double? timelineTime;
attribute unsigned long? iterationIndex;
attribute boolean? seeked;
};
TimingEvent
TimingEvent
object as described in Constructing
events in [DOM4].
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
type | DOMString | ✘ | ✘ | The type of timing event corresponding to one of the types defined in section 5.1 Types of timing events. |
eventInit |
| ✘ | ✔ |
The parameters of the new TimingEvent .
|
localTime
of type double, nullableThe event local time.
timelineTime
of type double, nullableThe event timeline time.
iterationIndex
of type unsigned long, nullableseeked
of type boolean, nullable
The TimingEventInit
dictionary type is used to specify the
parameters when constructing a TimingEvent
object.
dictionary TimingEventInit {
double? localTime = null;
double? timelineTime = null;
double? iterationIndex = null;
boolean? seeked = null;
};
TimingEventInit
MemberslocalTime
of type double, nullable, defaulting to null
timelineTime
of type double, nullable, defaulting to null
iterationIndex
of type double, nullable, defaulting to null
seeked
of type boolean, nullable, defaulting to null
Document
interfaceThe following extensions are made to the Document interface defined in [DOM4].
partial interface Document {
readonly attribute Timeline
timeline;
};
timeline
of type Timeline
, readonlyTimeline
object representing
the document timeline.
Element
interfaceTo simplify the creation of Animation objects for a given Element, the Element interface [DOM4] is extended as follows:
partial interface Element {
Animation
animate (
(AnimationEffect
or CustomEffect
or OneOrMoreKeyframes
)? effect,
optional (double or TimingInput
)? timing = null);
sequence<Animation
> getCurrentAnimations ();
sequence<Player
> getCurrentPlayers ();
};
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.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
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. |
timing | (double or | ✔ | ✔ (null ) | 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. |
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
PseudoElementReference
s 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 section 4.2.1 The animation stack.
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<Animation
>
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] ….
sequence<Player
>
The iteraction 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.
This section is non-normative.
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; alert(anim.startTime); // Displays '5'
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 section 5.7 Event dispatch.
The behavior of events with relation to seek operations is defined in section 5.7.2 Event dispatch and seeking a player.
Operations such as updating the playback rate of a player that involve performing a seek operation cause events to be queued immediately.
This section is non-normative.
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.startDelay = 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.
This section is non-normative.
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' }); alert(window.getComputedStyle(elem).opacity); // 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.
This section is non-normative.
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.
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 will be defined in the Web Animations and SVG Integration 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.
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 drift to any timelines bound to the global clock.
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.
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 section 6. Script interface including dispatching events as defined in section 5. Timing events.
interface Timeline { readonly attribute double? currentTime;Player
play (optionalTimedItem
? source = null); sequence<Player
> getCurrentPlayers (); double? toTimelineTime (double otherTime,Timeline
other); double? toTimelineTime (Event event); }; interface Player { attributeTimedItem
? source; readonly attributeTimeline
timeline; attribute double startTime; attribute double currentTime; attribute double playbackRate; attribute boolean paused; }; interface TimedItem : EventTarget { // Playback state readonly attribute double? localTime; readonly attribute unsigned long? currentIteration; // Specified timing readonly attributeTiming
specified; // Calculated timing readonly attribute double startTime; readonly attribute unrestricted double iterationDuration; readonly attribute unrestricted double activeDuration; readonly attribute unrestricted double endTime; // Timing hierarchy readonly attributeTimingGroup
? parent; readonly attributeTimedItem
? previousSibling; readonly attributeTimedItem
? nextSibling; void before (TimedItem... items); void after (TimedItem... items); void replace (TimedItem... items); void remove (); // Associated player readonly attributePlayer
? player; // Event callbacks attribute EventHandler onstart; attribute EventHandler oniteration; attribute EventHandler onend; attribute EventHandler oncancel; }; interface Timing { attribute double startDelay; attributeFillMode
fillMode; attribute double iterationStart; attribute unrestricted double iterationCount; attribute (unrestricted double or DOMString) iterationDuration; attribute (unrestricted double or DOMString) activeDuration; attribute double playbackRate; attributePlaybackDirection
direction; attribute DOMString timingFunction; }; dictionary TimingInput { double startDelay = 0;FillMode
fillMode = "forwards"; double iterationStart = 0.0; unrestricted double iterationCount = 1.0; (unrestricted double or DOMString) iterationDuration = "auto"; (unrestricted double or DOMString) activeDuration = "auto"; double playbackRate = 1.0;PlaybackDirection
direction = "normal"; DOMString timingFunction = "linear"; }; enum FillMode { "none", "forwards", "backwards", "both" }; enum PlaybackDirection { "normal", "reverse", "alternate", "alternate-reverse" }; interface TimingGroup :TimedItem
{ readonly attributeTimedItemList
children; readonly attributeTimedItem
? firstChild; readonly attributeTimedItem
? lastChild; void prepend (TimedItem... items); void append (TimedItem... items); }; interface TimedItemList { readonly attribute unsigned long length; getterTimedItem
? item (unsigned long index); }; [Constructor (sequence<TimedItem
>? children, optional (unrestricted double orTimingInput
)? timing = null)] interface ParGroup :TimingGroup
{ParGroup
clone (); }; [Constructor (sequence<TimedItem
>? children, optional (unrestricted double orTimingInput
)? timing = null)] interface SeqGroup :TimingGroup
{SeqGroup
clone (); }; [Constructor (AnimationTarget
? element, (AnimationEffect
orCustomEffect
orOneOrMoreKeyframes
)? effect, optional (unrestricted double orTimingInput
)? timing = null)] interface Animation :TimedItem
{ attribute (AnimationEffect
orCustomEffect
)? effect; readonly attributeAnimationTarget
? target;Animation
clone (); }; [Constructor (Element
element, DOMString pseudoElement)] interface PseudoElementReference { attributeElement
element; attribute DOMString pseudoElement; }; typedef (Element
orPseudoElementReference
) AnimationTarget; interface AnimationEffect { attributeAccumulateOperation
accumulate;AnimationEffect
clone (); }; enum AccumulateOperation { "sum", "none" }; enum CompositeOperation { "replace", "add" }; [Constructor (OneOrMoreKeyframes
frames, optionalCompositeOperation
composite = "replace", optionalAccumulateOperation
accumulate = "none")] interface KeyframeAnimationEffect :AnimationEffect
{ attributeCompositeOperation
composite; sequence<Keyframe
> getFrames (); void setFrames (OneOrMoreKeyframes
frames); }; dictionary Keyframe { // ... property-value pairs ... double? offset = null;CompositeOperation
? composite = null; }; typedef (Keyframe
or sequence<Keyframe
>) OneOrMoreKeyframes; [Constructor ((DOMString or SVGPathSegList) path, optionalAutoRotationMode
autoRotate = "none", optional double angle = 0, optionalCompositeOperation
composite = "replace")] interface PathAnimationEffect :AnimationEffect
{ attribute SVGPathSegList segments; attribute AutoRotationFlag autoRotate; attribute double angle; attributeCompositeOperation
composite; }; enum AutoRotationMode { "auto-rotate", "none" }; callback interface CustomEffect { attribute long? priority; attributeCustomEffectCloneCallback
? clone; void sample (double? timeFraction, double currentIteration,AnimationTarget
? target, double? previousTimeFraction); }; callback CustomEffectCloneCallback =CustomEffect
(); [Constructor (DOMString type, optionalTimingEventInit
eventInit)] interface TimingEvent : Event { attribute double? localTime; attribute double? timelineTime; attribute unsigned long? iterationIndex; attribute boolean? seeked; }; dictionary TimingEventInit { double? localTime = null; double? timelineTime = null; double? iterationIndex = null; boolean? seeked = null; }; partial interface Document { readonly attributeTimeline
timeline; }; partial interface Element {Animation
animate ( (AnimationEffect
orCustomEffect
orOneOrMoreKeyframes
)? effect, optional (double orTimingInput
)? timing = null); sequence<Animation
> getCurrentAnimations (); sequence<Player
> getCurrentPlayers (); };
This section is non-normative.
TBD
This section is non-normative.
The following algorithms demonstrate a possible approach to handling event queuing that incorporates the various requirements outlined in section 5. Timing events.
Some of the features of the following approach are:
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:
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:
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.
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) ≤ t ≤ last(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.
For a timeline, sampled such that the current time value is t, the set of timing events to queue can be determined as follows:
The partially ordered set of events for a player at timeline time t, can be determined as follows:
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.
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:
This will happen if a non-zero-duration iteration ends at |range lhs| and the position of range lhs is not minus.
true
false
, or
null
if
|child start| =
|child end|.
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.
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.
false
.
The partially ordered set of events for a timed item seeked to time t, expressed in uneased inherited time, can be determined as follows:
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.