+Title: CSS Animation Worklet API +Status: CG-DRAFT +Group: WICG +URL: https://wicg.github.io/animation-worklet/ +Repository: wicg/animation-worklet +Shortname: css-animation-api +Level: 1 +Abstract: +Editor: Majid Valipour, majidvp@google.com +Editor: Robert Flack, flackr@chromium.org +Editor: Stephen McGruer, smcgruer@chromium.org +Ignored Terms: AnimationWorklet ++ +
+spec:infra; type:dfn; text:list +spec:dom; type:interface; text:Document ++ +
+urlPrefix: https://heycam.github.io/webidl/; type: dfn; + text: NotSupportedError + urlPrefix: #dfn-; + text: callback this value + text: exception + text: throw + url: throw; text: thrown + urlPrefix: #; + url: Function; text: Function + url: VoidFunction; text: VoidFunction + url: invoke-a-callback-function; text: Invoke + url: construct-a-callback-function; text: constructing + url: es-type-mapping; text: converting +urlPrefix: https://html.spec.whatwg.org/#; type: dfn; + url: run-the-animation-frame-callbacks; text: running the animation frame callbacks +urlPrefix: http://w3c.github.io/html/infrastructure.html#; type: dfn; + text: structuredserialize + text: structureddeserialize +urlPrefix: https://www.w3.org/TR/css3-transitions/#; type: dfn; + text: animatable properties +urlPrefix: https://w3c.github.io/web-animations/#; type: dfn; + url: the-documents-default-timeline; text: default document timeline + url: concept-animation; text: animation + text: effect value + text: effect stack + text: target property + text: timeline + text: animation effect + text: current time + text: local time + text: inherited time + text: ready + text: play state + text: playback rate + text: set the target effect of an animation + text: set the timeline of an animation + text: finished + text: idle + text: paused + text: pending + text: running + text: composite operation + text: animation class +urlPrefix: https://w3c.github.io/web-animations/level-2/#; + type: dfn; + text: group effect + text: child effect +urlPrefix: https://tc39.github.io/ecma262/#sec-; type: dfn; + text: IsCallable + text: IsConstructor + text: HasProperty + url: ecmascript-data-types-and-values; text: Type + url: map-objects; text:map object + url: get-o-p; text: Get + url: set-o-p-v-throw; text: Set + urlPrefix: native-error-types-used-in-this-standard- + text: TypeError +urlPrefix: https://www.w3.org/TR/hr-time-2/#dom-; type: dfn + text: DOMHighResTimeStamp +urlPrefix: https://wicg.github.io/scroll-animations/#; type: interface + url: scrolltimeline; text: ScrollTimeline + url: dictdef-scrolltimelineoptions; text: ScrollTimelineOptions + url: dom-scrolltimeline-scrollsource; text: scrollSource +urlPrefix: https://wicg.github.io/scroll-animations/#; type: dfn + url: current-time-algorithm; text: current time of the ScrollTimeline; ++ +
+{ + "explainer": { + "href": "https://github.com/WICG/animation-worklet/blob/gh-pages/README.md", + "title": "Animation Worklet Explainer", + "status": "CR", + "publisher": "WICG", + "deliveredBy": [ + "https://github.com/WICG/animation-worklet//" + ] + } +} ++ +Introduction {#intro} +===================== +This section is not normative. + +This document introduces a new primitive for creating scroll-linked and other high performance +procedural animations on the web. For details on the rationale and motivation see [[explainer]]. + +The Animation Worklet API provides a method to create scripted animations that control a set +of animation effects. The API is designed to make it possible for user agents to run such +animations in their own dedicated thread to provide a degree of performance isolation from main +thread. + +Relationship to the Web Animations API {#relationship-to-web-animations} +------------------------------------------------------------------------ + +Animations running inside an Animation Worklet execution context expose the {{Animation}} +interface from the Web Animations specification on the main javascript execution context. This means +they can be controlled and inspected from main thread using many of the Web Animation APIs. However +Animation Worklet animations follow a different timing model that enables them to be script-driven, +stateful, and runnable in a parallel worklet execution context. As such Web Animation APIs that seek +or alter the input time (reverse, finish, etc.) have different semantics for Animation Worklet +animations. + + +Threading Model {#threading-model} +================================== +This section is not normative. + +Animation Worklet is designed to be thread-agnostic. Rendering engines may create one or more +parallel worklet execution contexts separate from the main javascript execution context, e.g., on +their own dedicated threads. Rendering engines may then choose to assign Animation Worklet +animations to run in such contexts. Doing so allows Animation Worklet animations to avoid being +impacted by main thread jank. + +Rendering engines may wish to make a best-effort attempt to execute animate callbacks synchronously +with visual frame production to ensure smooth animation. However it is legal for rendering engines +to produce visual frames without blocking to receive animation updates from a worklet (i.e., letting +the effects slip behind). For example, this could occur when the animate function callback is +unable to complete before the frame deadline. + +We believe that scripted animations which are run in a parallel execution environment and which +limit themselves to animating properties which do not require the user agent to consult main thread +will have a much better chance of meeting the strict frame budgets required for smooth playback. + +If a Worklet Animation animation is executing in a parallel worklet execution context, the last +known state of its animation effects should be periodically synced back to the main javascript +execution context. The synchronization of effect values from the parallel worklet execution +context to the main javascript execution context must occur before running the animation +frame callbacks as part of the document lifecycle. Note that due to the asynchronous nature of +this animation model a script running in the main javascript execution context may see a stale value +when reading a target property that is being animated in a Worklet Animation, compared to the +value currently being used to produce the visual frame that is visible to the user. This is similar +to the effect of asynchronous scrolling when reading scroll offsets in the main javascript execution +context. + + +
+ + A simplified visualization of how animators running in a parallel execution environment can sync + their update to main thread while remaining in sync with visual frame production. +
+ class FooAnimator { + constructor(options) { + // Called when a new animator is instantiated. + } + animate(currentTime, effect) { + // Animation frame logic goes here. + } + } ++
+ + The animation current time is input to the animator instance, which produces a local time value + for the animation effect. If the animator instance is running in a parallel global scope the + implementation may also choose to use the local time value to produce the final effect value and + update the visuals in parallel. + +
CSS Animation Worklet API
+Draft Community Group Report,
+-
+
- This version: +
- https://wicg.github.io/animation-worklet/ +
- Issue Tracking: +
- GitHub
+
- Inline In Spec +
- Editors: +
Copyright © 2018 the Contributors to the CSS Animation Worklet API Specification, published by the Web Platform Incubator Community Group under the W3C Community Contributor License Agreement (CLA). +A human-readable summary is available.
++
Abstract
+Status of this document
+This specification was published by the Web Platform Incubator Community Group. + It is not a W3C Standard nor is it on the W3C Standards Track. + + Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. + + Learn more about W3C Community and Business Groups.
+ +1. Introduction
+ This section is not normative. +This document introduces a new primitive for creating scroll-linked and other high performance +procedural animations on the web. For details on the rationale and motivation see [explainer].
+The Animation Worklet API provides a method to create scripted animations that control a set +of animation effects. The API is designed to make it possible for user agents to run such +animations in their own dedicated thread to provide a degree of performance isolation from main +thread.
+1.1. Relationship to the Web Animations API
+Animations running inside an Animation Worklet execution context expose the Animation
interface from the Web Animations specification on the main javascript execution context. This means
+they can be controlled and inspected from main thread using many of the Web Animation APIs. However
+Animation Worklet animations follow a different timing model that enables them to be script-driven,
+stateful, and runnable in a parallel worklet execution context. As such Web Animation APIs that seek
+or alter the input time (reverse, finish, etc.) have different semantics for Animation Worklet
+animations.
2. Threading Model
+ This section is not normative. +Animation Worklet is designed to be thread-agnostic. Rendering engines may create one or more +parallel worklet execution contexts separate from the main javascript execution context, e.g., on +their own dedicated threads. Rendering engines may then choose to assign Animation Worklet +animations to run in such contexts. Doing so allows Animation Worklet animations to avoid being +impacted by main thread jank.
+Rendering engines may wish to make a best-effort attempt to execute animate callbacks synchronously +with visual frame production to ensure smooth animation. However it is legal for rendering engines +to produce visual frames without blocking to receive animation updates from a worklet (i.e., letting +the effects slip behind). For example, this could occur when the animate function callback is +unable to complete before the frame deadline.
+We believe that scripted animations which are run in a parallel execution environment and which +limit themselves to animating properties which do not require the user agent to consult main thread +will have a much better chance of meeting the strict frame budgets required for smooth playback.
+If a Worklet Animation animation is executing in a parallel worklet execution context, the last +known state of its animation effects should be periodically synced back to the main javascript +execution context. The synchronization of effect values from the parallel worklet execution +context to the main javascript execution context must occur before running the animation +frame callbacks as part of the document lifecycle. Note that due to the asynchronous nature of +this animation model a script running in the main javascript execution context may see a stale value +when reading a target property that is being animated in a Worklet Animation, compared to the +value currently being used to produce the visual frame that is visible to the user. This is similar +to the effect of asynchronous scrolling when reading scroll offsets in the main javascript execution +context.
++
A simplified visualization of how animators running in a parallel execution environment can sync + their update to main thread while remaining in sync with visual frame production.
+3. Animation Worklet
+ Animation Worklet is aWorklet
responsible for all classes related to custom
+animations. The worklet can be accessed via animationWorklet
attribute.
+ The animationWorklet
's worklet global scope type is AnimationWorkletGlobalScope
.
AnimationWorkletGlobalScope
represents the global execution context of animationWorklet
.
+partial namespace CSS { + [SameObject ]readonly attribute Worklet ; +}; +
animationWorklet
[+Exposed =AnimationWorklet ,Global =AnimationWorklet ] +interface :
AnimationWorkletGlobalScope WorkletGlobalScope { +void (
registerAnimator DOMString ,
name VoidFunction ); +}; +
animatorCtor
+class FooAnimator{ + constructor( options) { +// Called when a new animator is instantiated. +} + animate( currentTime, effect) { +// Animation frame logic goes here. +} +} +
4. Animator Definition
+ An animator definition is a struct which describes the author defined custom +animation as needed byAnimationWorkletGlobalScope
. It consists of:
+ -
+
-
+
An animator name <ident>#.
+ -
+
A class constructor which is a VoidFunction callback function type.
+ -
+
An animate function which is a Function callback function type.
+ -
+
A destroy function which is a Function callback function type.
+
4.1. Registering an Animator Definition
+ AnAnimationWorkletGlobalScope
has a animator name to animator definition map.
+The map gets populated when registerAnimator(name, animatorCtorValue)
is called.
+ When the registerAnimator(name, animatorCtorValue)
method is called in a AnimationWorkletGlobalScope
, the user agent must run the
+following steps:
-
+
-
+
If name is not a valid <ident>, throw a TypeError and abort all these +steps.
+ -
+
If name exists as a key in the animator name to animator definition map, throw a NotSupportedError and abort all these steps.
+ -
+
If the result of IsConstructor(animatorCtorValue) is false, throw a TypeError and abort all these steps.
+ -
+
Let animatorCtor be the result of converting animatorCtorValue to the VoidFunction callback function type. If an exception is thrown, rethrow the +exception and abort all these steps.
+ -
+
Let prototype be the result of Get(animatorCtorValue, "prototype").
+ -
+
If the result of Type(prototype) is not Object, throw a TypeError and abort all these steps.
+ -
+
Let animateValue be the result of Get(prototype, "animate").
+ -
+
Let animate be the result of converting animateValue to the Function callback function type. If an exception is thrown, rethrow the exception and abort +all these steps.
+ -
+
Let destroyValue be the result of Get(prototype, "onDestroy").
+ -
+
Let destroy be the result of converting destroyValue to the Function callback function type. If an exception is thrown, rethrow the exception and abort +all these steps.
+ -
+
Let definition be a new animator definition with:
+-
+
-
+
animator name being name
+ -
+
class constructor being animatorCtor
+ -
+
animate function being animate
+ -
+
destroy function being destroy
+
-
+
-
+
Add the key-value pair (name - definition) to the animator name to animator +definition map.
+
5. Animator Instance
+An animator instance is a struct which describes a fully realized custom animation
+instance in an AnimationWorkletGlobalScope
. It has a reference to an animator definition and owns the instance specific state such as animation effect and timelines. It consists of:
-
+
-
+
An animator name.
+ - + +
-
+
An animator effect which is an animation effect.
+ -
+
An animator current time which is the corresponding worklet animation’s current + time.
+ -
+
An animator timeline which is a timeline.
+ -
+
An animator attached timelines which is list of attached timelines
+ -
+
An animator serialized options which is a serializable object.
+
5.1. Creating an Animator Instance
+Each animator instance lives in an AnimationWorkletGlobalScope
.
Each AnimationWorkletGlobalScope
has an animator instance set. The set is populated
+when the user agent constructs a new animator instance in the AnimationWorkletGlobalScope
scope. Each animator instance corresponds to a worklet animation in the document scope.
To create a new animator instance given a name, timeline, effect, serializedOptions, serializedState, and workletGlobalScope, the user agent must run the following steps:
+-
+
-
+
Let the definition be the result of looking up name on the workletGlobalScope’s animator name to animator definition map.
+If definition does not exist abort the following steps.
+ -
+
Let animatorCtor be the class constructor of definition.
+ -
+
Let timelineList be a new list with timeline added to it.
+ -
+
Let options be StructuredDeserialize(serializedOptions).
+ -
+
Let state be StructuredDeserialize(serializedState).
+ -
+
Let animatorInstance be the result of constructing animatorCtor with +[options, state as args. If an exception is thrown, rethrow the exception and abort all +these steps.
+ -
+
Set the following on animatorInstance with:
+-
+
-
+
animator name being name
+ - + +
-
+
animator current time being unresolved
+ -
+
animator effect being effect
+ -
+
animator timeline being timeline
+ -
+
animator attached timelines being timelineList
+ -
+
animator serialized options being options
+
-
+
-
+
Add animatorInstance to workletGlobalScope’s animator instance set.
+
5.2. Running Animators
+When a user agent wants to produce a new animation frame, if for any animator instance the +associated animation requested flag is frame-requested then the the user agent must run animators for the current frame.
+Note: The user agent is not required to run animations on every visual frame. It is legal to defer + generating an animation frame until a later frame. This allow the user agent to + provide a different service level according to their policy.
+When the user agent wants to run animators in a given workletGlobalScope, it must iterate over all animator instances in the workletGlobalScope’s animator +instance set. For each such instance the user agent must perform the following steps:
+-
+
-
+
Let animatorName be instance’s animator name
+ -
+
Let the definition be the result of looking up animatorName on the workletGlobalScope’s animator name to animator definition map.
+If definition does not exist then abort the following steps.
+ -
+
If the animation requested flag for instance is frame-current or the effect + belonging to the instance will not be visible within the visual viewport of the current + frame the user agent may abort all the following steps.
+Consider giving user agents permission to skip running animator instances to + throttle slow animators.
+ -
+
Let animateFunction be definition’s animate function.
+ -
+
Let currentTime be animator current time of instance.
+ -
+
Let effect be animator effect of instance.
+ -
+
Invoke animateFunction with arguments «currentTime, effect», + and with instance as the callback this value.
+
5.3. Removing an Animator Instance
+To remove an animator instance given instance and workletGlobalScope the user agent must run the following steps:
+-
+
-
+
Remove instance from workletGlobalScope’s animator instance set.
+
5.4. Migrating an Animator Instance
+User agents are responsible for assigning an animator instance to a WorkletGlobalScope
.
+There can be many such WorkletGlobalScope
s, which may exist across different threads or
+processes. To give the most flexibility to user agents in this respect, we allow migration of an animator instance while it is running. The basic mechanism is to serialize the internal state
+of any author-defined effect, and restore it after migration.
To migrate an animator instance from one WorkletGlobalScope
to another, given instance, sourceWorkletGlobalScope, destinationWorkletGlobalScope, the user agent must run the following steps :
-
+
-
+
Let serializedState be undefined.
+ -
+
Queue a task on sourceWorkletGlobalScope to run the following steps:
+-
+
-
+
Let animatorName be instance’s animator name
+ -
+
Let definition be the result of looking up animatorName on sourceWorkletGlobalScope’s animator name to animator definition map.
+If definition does not exist then abort the following steps.
+ -
+
Let destroyFunction be the destroy function of definition.
+ -
+
Invoke destroyFunction with instance as the callback this value and +let state be the result of the invocation. If any exception is thrown, rethrow the +exception and abort the following steps.
+ -
+
Set serializedState to be the result of StructuredSerialize(state). +If any exception is thrown, then abort the following steps.
+ -
+
Run the procedure to remove an animator instance given instance, and sourceWorkletGlobalScope.
+
-
+
-
+
Wait for the above task to complete. If the task is aborted, abort the following steps.
+ -
+
Queue a task on destinationWorkletGlobalScope to run the following steps:
+-
+
-
+
Run the procedure to create a new animator instance given:
+-
+
-
+
The instance’s animator name as name.
+ -
+
The instance’s animator timeline as timeline.
+ -
+
The instance’s animator effect as effect.
+ -
+
The instance’s animator serialized options as options.
+ -
+
The serializedState as state.
+ -
+
The destinationWorkletGlobalScope as workletGlobalScope.
+
-
+
-
+
5.5. Requesting Animation Frames
+Each animator instance has an associated animation requested flag. It must be +either frame-requested or frame-current. It is initially set to frame-current. Different circumstances can cause the animation requested flag to be +set to frame-requested. These include the following:
+-
+
-
+
Changes in the current time of any timeline in the animator’s animator attached timelines
+ -
+
Changes in the current time of the animator’s corresponding Worklet Animation
+
§5.2 Running Animators resets the animation requested flag on animators to frame-current.
+6. Web Animations Integration
+6.1. Worklet Animation
+ Worklet animation is a kind of animation that delegates the animation playback to +an animator instance. It controls the lifetime and playback state of its corresponding animator instance. +Being an animation, worklet animation has an animation effect and a timeline. However unlike other animations the worklet animation’s current time does +not directly determine the animation effect’s local time (via its inherited time). +Instead the associated animator instance controls the animation effect’s local time directly. Note that this means that the timeline’s current time does not fully determine the +animation’s output.
+Worklet animation has the following properties in addition to the Animation
interface:
-
+
-
+
an animation animator name which identifies its animator definition.
+ -
+
a serialized options which is serializable object that is used when +constructing a new animator instance.
+
+
The animation current time is input to the animator instance, which produces a local time value + for the animation effect. If the animator instance is running in a parallel global scope the + implementation may also choose to use the local time value to produce the final effect value and + update the visuals in parallel.
+6.2. Creating a Worklet Animation
+[+Constructor (DOMString , +
animatorName optional (AnimationEffect or sequence <AnimationEffect >)?=
effects null , +optional AnimationTimeline ?, +
timeline optional any )] +
options interface :
WorkletAnimation Animation { +readonly attribute DOMString ; +}; + +
animatorName
WorkletAnimation(animatorName, effects, timeline, options)
+ Creates a new WorkletAnimation
object using the following procedure.
-
+
-
+
Let workletAnimation be a new
+WorkletAnimation
object. -
+
Run the procedure to set the timeline of an animation on workletAnimation passing timeline as the new timeline or, if a timeline argument is not provided, +passing the default document timeline of the
+Document
associated with theWindow
that is the current global object. -
+
Let effect be the result corresponding to the first matching condition from below.
+-
+
- If effects is a
AnimationEffect
object, + -
+
Let effect be effects.
+ - If effects is a list of
AnimationEffect
objects, + -
+
Let effect be a new
+WorkletGroupEffect
with its children set to effects. - Otherwise, +
-
+
Let effect be undefined.
+
- If effects is a
-
+
Run the procedure to set the target effect of an animation on workletAnimation passing effect as the new effect.
+ -
+
Let serializedOptions be the result of StructuredSerialize(options). +Rethrow any exceptions.
+ -
+
Set the serialized options of workletAnimation to serializedOptions.
+ -
+
Set the animation animator name of workletAnimation to animatorName.
+
6.3. Worklet Animation timing model
+This section describes how worklet animation’s timing model differs from other animations.
+In addition to the existing conditions on when the animation is considered ready, a worklet animation is only considered ready when the following condition is also true:
+-
+
-
+
the user agent has completed any setup required to create the worklet animation’s corresponding animator instance.
+
As described in §6.1 Worklet Animation, the worklet animation’s current time does
+not determine its animation effect’s local time. Instead the associated animator
+instance controls the animation effect’s local time directly. This means that the
+animation effect’s local time is controlled from a WorkletGlobalScope
which may be in a parallel
+execution context.
Here are a few implications of the above semantics:
+-
+
-
+
Setting the current time or start time of a worklet animation does not +necessarily change its output, but may change the animation play state.
+ -
+
Similarly, invoking
+finish()
or updating a worklet animation’s playback +rate will only change the animation play state and may not change the output. -
+
Querying the animation effect’s local time using
+getComputedTiming()
may return stale information, in the case where the animator instance is running in a +parallel execution context.
Come with appropriate mechanism’s for animator instance to get notified when its + animation currentTime is changing e.g., via reverse(), finish() or playbackRate change. So that + it can react appropriately. <https://github.com/wicg/animation-worklet/issues/63>
+6.4. Interaction with Animator Instances
+A worklet animation corresponds to at most one animator instance at any time, and may +have no current corresponding animator instance. The correspondance of an animator +instance for a worklet animation depends on the animation play state.
+To associate animator instance of worklet animation given workletAnimation, +the user agent must run the following steps:
+-
+
-
+
If workletAnimation has a corresponding animator instance, abort the following steps.
+ -
+
Let workletGlobalScope be the
+AnimationWorkletGlobalScope
associated with workletAnimation. -
+
Queue a task on workletGlobalScope to run the procedure to create a new animator + instance, passing:
+-
+
-
+
The workletAnimation’s animation animator name as name.
+ -
+
The workletAnimation’s timeline as timeline.
+ -
+
The workletAnimation’s animation effect as effect.
+ -
+
The workletAnimation’s serialized options as options.
+ -
+
The workletGlobalScope as workletGlobalScope.
+
-
+
-
+
If the procedure was successful, set the resulting animator instance as corresponding to workletAnimation.
+
To disassociate animator instance of worklet animation given workletAnimation, the user age must run the following steps:
+-
+
-
+
If workletAnimation does not have a corresponding animator instance, abort the +following steps.
+ -
+
Let workletGlobalScope be the
+AnimationWorkletGlobalScope
associated with workletAnimation. -
+
Let animatorInstance be workletAnimation’s corresponding animator instance.
+ -
+
Queue a task on the workletGlobalScope to run the procedure to remove an animator + instance, passing animatorInstance as instance and workletGlobalScope as + workletGlobalScope.
+ -
+
Set workletAnimation as having no corresponding animator instance.
+
To set animator instance of worklet animation given workletAnimation, the user agent must run the following steps:
+-
+
-
+
disassociate animator instance of worklet animation given workletAnimation.
+ -
+
associate animator instance of worklet animation given workletAnimation.
+
When a given workletAnimation’s play state changes to pending, running, or paused, run the procedure to associate animator instance of worklet animation given workletAnimation.
+When a given workletAnimation’s play state changes to idle or finished, +run the procedure to disassociate animator instance of worklet animation given workletAnimation.
+When the procedure to set the target effect of an animation for a given workletAnimation is called, then set animator instance of worklet animation given workletAnimation.
+When the procedure to set the timeline of an animation for a given workletAnimation is called, then set animator instance of worklet animation given workletAnimation.
+6.5. Timeline Attachment
+Define semantics of attachment and detachment. <https://github.com/wicg/animation-worklet/issues/61>
+6.6. ScrollTimeline
+ScrollTimeline
is a new concept being proposed for addition to web animation API. It defines
+an animation timeline whose time value depends on the scroll position of a scroll container. Worklet animations can have a scroll timeline and thus drive their scripted effects based
+on a scroll offset.
+ Note: Access to input: We are interested on exposing additional user input beside +scrolling (e.g., touch/pointer input) to these animations so that authors can create jank-free +input driven animations which are not really possible today. We are still trying to figure out the +right abstractions and mechanisms to do this.
+6.7. WorkletGroupEffect
+WorkletGroupEffect
is a type of group effect that allows its child effect’s local times to be mutated individually.
When a WorkletGroupEffect
is set as the animation effect of a WorkletAnimation
, the
+corresponding animator instance can directly control the child effects' local
+times. This allows a single worklet animation to coordinate multiple effects - see §7.2 Example 2: Twitter header. for an example of such a use-case.
+interface { +
WorkletGroupEffect sequence <AnimationEffect >(); +}; + +[
getChildren Exposed =AnimationWorklet ] +partial interface AnimationEffect { + // Intended for use inside Animation Worklet scope to drive the effect. +attribute double ; +}; +
localTime
To set the localTime
property on a effect to value t, the user agent should perform the
+action that corresponds to the first matching condition from the following:
-
+
- If the effect does not have a parent group, +
-
+
Set the effect local time to t.
+ - If the effect has a parent group and it is of
WorkletGroupEffect
type, + -
+
Set the effect start time to (parent’s transformed time - t). Note this effectively set’s the effect’s local time to t.
+ - Otherwise +
-
+
Throw an exception indicating that the child effect time can only be controlled by +its parent group.
+
The above interface exposes a conservative subset +of GroupEffect proposed as part of web-animation-2. Once that is available we +should switch to it. <https://github.com/w3c/csswg-drafts/issues/2071>
+6.8. Effect Stack and Composite Order
+As with other animations, worklet animations participate in the effect stack. A +worklet animation does not have a specific animation class which means it has the same +composite order as other Javascript created web animations.
+7. Examples
+7.1. Example 1: Hidey Bar.
+ An example of header effect where a header is moved with scroll and as soon as finger is lifted it +animates fully to close or open position depending on its current position. ++< div id = 'scrollingContainer' > +< div id = 'header' > Some header</ div > +< div > content</ div > +</ div > + +< script > +await CSS. animationWorklet. addModule( 'hidey-bar-animator.js' ); +const scrollTimeline= new ScrollTimeline( $scrollingContainer, { timeRange: 1000 }); +const documentTimeline= document. timeline; + +// Note we pass in two timelines in the options bag which allows the animation to read their +// currenTime values directly. +const animation= new WorkletAnimation( +'hidey-bar' , +new KeyFrameEffect( $header, +[{ transform: 'translateX(100px)' }, { transform: 'translateX(0px)' }], +{ duration: 1000 , iterations: 1 , fill: 'both' }]), + scrollTimeline, +{ scrollTimeline, documentTimeline}); + +animation. play(); +</ script > +
+// Inside AnimationWorkletGlobalScope + +registerAnimator( 'hidey-bar' , class { + constructor( options) { +this . scrollTimeline_= options. scrollTimeline; +this . documentTimeline_= options. documentTimeline; +} + + animate( currentTime, effect) { +const scroll= this . scrollTimeline_. currentTime; // [0, 100] +const time= this . documentTimeline_. currentTime; + +const activelyScrolling= this . scrollTimeline_. phase== 'active' ; + +let localTime; +if ( activelyScrolling) { +this . startTime_= undefined ; + localTime= scroll; +} else { +this . startTime_= this . startTime_|| time; +// Decide on close/open direction depending on how far we have scrolled the header +// This can even do more sophisticated animation curve by computing the scroll velocity and +// using it. +this . direction_= scroll>= 50 ? + 1 : - 1 ; + localTime= this . direction_* ( time- this . startTime_); +} + +// Drive the output effect by setting its local time. + effect. localTime= localTime; +} +}); +
This example uses a hypothetical "phase" property on timeline as a way to detect when user +is no longer actively scrolling. This is a reasonable thing to have on scroll timeline. A simple +fallback can emulate this by detecting when timeline time (i.e. scroll offset) has not changed in +the last few frames.
+7.2. Example 2: Twitter header.
+ An example of twitter profile header effect where two elements (avatar, and header) are updated in +sync with scroll offset. +// In document scope. ++< div id = 'scrollingContainer' > +< div id = 'header' style = 'height: 150px' ></ div > +< div id = 'avatar' >< img ></ div > +</ div > + +< script > +await CSS. animationWorklet. addModule( 'twitter-header-animator.js' ); +const animation= new WorkletAnimation( +'twitter-header' , +[ new KeyFrameEffect( $avatar, /* scales down as we scroll up */ +[{ transform: 'scale(1)' }, { transform: 'scale(0.5)' }], +{ duration: 1000 , iterations: 1 }), +new KeyFrameEffect( $header, /* loses transparency as we scroll up */ +[{ opacity: 0 }, { opacity: 0.8 }], +{ duration: 1000 , iterations: 1 })], +new ScrollTimeline( $scrollingContainer, { timeRange: 1000 , startScrollOffset: 0 , endScrollOffset: $header. clientHeight})); +animation. play(); + +// Since this animation is using a group effect, the same animation instance +// is accessible via different handles: $avatarEl.getAnimations()[0], $headerEl.getAnimations()[0] + +</ script > +
+// Inside AnimationWorkletGlobalScope. +registerAnimator( 'twitter-header' , class { + constructor( options) { +this . timing_= new CubicBezier( 'ease-out' ); +} + + clamp( value, min, max) { +return Math. min( Math. max( value, min), max); +} + + animate( currentTime, effect) { +const scroll= currentTime; // scroll is in [0, 1000] range + +// Drive the output group effect by setting its children local times individually. + effect. children[ 0 ]. localTime= scroll; + effect. children[ 1 ]. localTime= this . timing_( clamp( scroll, 0 , 500 )); +} +}); +
7.3. Example 3: Parallax backgrounds.
+ A simple parallax background example. ++< style > +. parallax { +position : fixed ; +top : 0 ; +left : 0 ; +opacity : 0.5 ; +} +</ style > +< div id = 'scrollingContainer' > +< div id = "slow" class = "parallax" ></ div > +< div id = "fast" class = "parallax" ></ div > +</ div > + +< script > +await CSS. animationWorklet. addModule( 'parallax-animator.js' ); +const scrollTimeline= new ScrollTimeline( $scrollingContainer, { timeRange: 1000 }); +const scrollRange= $scrollingContainer. scrollHeight- $scrollingContainer. clientHeight; + +const slowParallax= new WorkletAnimation( +'parallax' , +new KeyframeEffect( $parallax_slow, [{ 'transform' : 'translateY(0)' }, { 'transform' : 'translateY(' + - scrollRange+ 'px)' }], { duration: 1000 }), + scrollTimeline, +{ rate: 0.4 } +); +slowParallax. play(); + +const fastParallax= new WorkletAnimation( +'parallax' , +new KeyframeEffect( $parallax_fast, [{ 'transform' : 'translateY(0)' }, { 'transform' : 'translateY(' + - scrollRange+ 'px)' }], { duration: 1000 }), + scrollTimeline, +{ rate: 0.8 } +); +fastParallax. play(); +</ script > +
+// Inside AnimationWorkletGlobalScope. +registerAnimator( 'parallax' , class { + constructor( options) { +this . rate_= options. rate; +} + + animate( currentTime, effect) { + effect. localTime= currentTime* this . rate_; +} +}); +
Conformance
+Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. + The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” + in the normative parts of this document + are to be interpreted as described in RFC 2119. + However, for readability, + these words do not appear in all uppercase letters in this specification.
+All of the text of this specification is normative + except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
+ Examples in this specification are introduced with the words “for example”
+ or are set apart from the normative text with class="example"
, like this:
Informative notes begin with the word “Note”
+ and are set apart from the normative text with class="note"
, like this:
Note, this is an informative note.
+Index
+Terms defined by this specification
+-
+
- animate function, in §4 +
- animation animator name, in §6.1 +
- animation requested flag, in §5.5 +
- Animation Worklet, in §3 +
- animationWorklet, in §3 +
- AnimationWorkletGlobalScope, in §3 +
- animator attached timelines, in §5 +
- animator current time, in §5 +
- animator definition, in §4 +
- animator effect, in §5 +
- animator instance, in §5 +
- animator instance set, in §5.1 +
- animator name, in §4 +
- animatorName, in §6.2 +
- animator name to animator definition map, in §4.1 +
- animator serialized options, in §5 +
- animator timeline, in §5 +
- associate animator instance of worklet animation, in §6.4 +
- class constructor, in §4 +
- create a new animator instance, in §5.1 +
- destroy function, in §4 +
- disassociate animator instance of worklet animation, in §6.4 +
- frame-current, in §5.5 +
- frame-requested, in §5.5 +
- getChildren(), in §6.7 +
- localTime, in §6.7 +
- migrate an animator instance, in §5.4 +
- registerAnimator(name, animatorCtor), in §3 +
- registerAnimator(name, animatorCtorValue), in §4.1 +
- remove an animator instance, in §5.3 +
- run animators, in §5.2 +
- serialized options, in §6.1 +
- set animator instance of worklet animation, in §6.4 +
- Worklet animation, in §6.1 +
- WorkletAnimation, in §6.2 +
- WorkletAnimation(animatorName, effects, timeline, options), in §6.2 +
- WorkletGroupEffect, in §6.7 +
Terms defined by reference
+-
+
-
+ [css-transitions-1] defines the following terms:
+
-
+
- start time +
-
+ [css-values-4] defines the following terms:
+
-
+
- <ident> +
-
+ [cssom-1] defines the following terms:
+
-
+
- CSS +
-
+ [DOM] defines the following terms:
+
-
+
- Document +
-
+ [HTML] defines the following terms:
+
-
+
- Window +
- current global object +
- queue a task +
-
+ [INFRA] defines the following terms:
+
-
+
- list +
- struct +
-
+ [web-animations-1] defines the following terms:
+
-
+
- Animation +
- AnimationEffect +
- AnimationTimeline +
- finish() +
- getComputedTiming() +
-
+ [WebIDL] defines the following terms:
+
-
+
- DOMString +
- Exposed +
- Global +
- SameObject +
- VoidFunction +
- callback function +
- double +
-
+ [worklets-1] defines the following terms:
+
-
+
- Worklet +
- WorkletGlobalScope +
- worklet global scope type +
References
+Normative References
+-
+
- [CSS-TRANSITIONS-1] +
- David Baron; Dean Jackson; Brian Birtles. CSS Transitions. 30 November 2017. WD. URL: https://www.w3.org/TR/css-transitions-1/ +
- [CSS-VALUES-4] +
- CSS Values and Units Module Level 4 URL: https://drafts.csswg.org/css-values-4/ +
- [CSSOM-1] +
- Simon Pieters; Glenn Adams. CSS Object Model (CSSOM). 17 March 2016. WD. URL: https://www.w3.org/TR/cssom-1/ +
- [DOM] +
- Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/ +
- [HTML] +
- Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/ +
- [INFRA] +
- Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/ +
- [RFC2119] +
- S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
- [WEB-ANIMATIONS-1] +
- Brian Birtles; et al. Web Animations. 13 September 2016. WD. URL: https://www.w3.org/TR/web-animations-1/ +
- [WebIDL] +
- Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/ +
- [WORKLETS-1] +
- Ian Kilpatrick. Worklets Level 1. 7 June 2016. WD. URL: https://www.w3.org/TR/worklets-1/ +
Informative References
+-
+
- [EXPLAINER] +
- Animation Worklet Explainer. CR. URL: https://github.com/WICG/animation-worklet/blob/gh-pages/README.md +
IDL Index
++partial namespace CSS { + [SameObject ]readonly attribute Worklet ; +}; + +[
animationWorklet Exposed =AnimationWorklet ,Global =AnimationWorklet ] +interface :
AnimationWorkletGlobalScope WorkletGlobalScope { +void (
registerAnimator DOMString ,
name VoidFunction ); +}; + +[
animatorCtor Constructor (DOMString , +
animatorName optional (AnimationEffect or sequence <AnimationEffect >)?=
effects null , +optional AnimationTimeline ?, +
timeline optional any )] +
options interface :
WorkletAnimation Animation { +readonly attribute DOMString ; +}; + + +
animatorName interface { +
WorkletGroupEffect sequence <AnimationEffect >(); +}; + +[
getChildren Exposed =AnimationWorklet ] +partial interface AnimationEffect { + // Intended for use inside Animation Worklet scope to drive the effect. +attribute double ; +}; + +
localTime