1. Introduction

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.

Overview of the animation worklet threading model.

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 a Worklet responsible for all classes related to custom
animations. The worklet can be accessed via animationWorklet attribute.

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:

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:

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.

5.3. Removing an Animator Instance

5.4. Migrating an Animator Instance

User agents are responsible for assigning an animator instance to a WorkletGlobalScope.
There can be many such WorkletGlobalScopes, 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 :

a serialized options which is serializable object that is used when
constructing a new animator instance.

Overview of the WorkletAnimation timing model.

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.5. Timeline Attachment

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.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.

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.
<divid='scrollingContainer'><divid='header'style='height: 150px'></div><divid='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>

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:

This is an example of an informative example.

Informative notes begin with the word “Note”
and are set apart from the normative text with class="note", like this:

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. ↵