Platform/Layout/Extended Timelines
This page is preserved to maintain history and not intended for current status of projects.
Summary: Following is a rough sketch of how the Web Animations API could be adapted to support scrubbing animations based on scroll position and (less critical) touch events.
Background reading: Web Animations spec, in particular the timeline and player concepts. Some additional background about players is on this blog. I (Brian) am not crazy about the idea but I think it's workable.
Contents
API
[Constructor ((Window or Element) scrollSource, Orientation orientation) interface ScrollTimeline : AnimationTimeline { attribute Orientation orientation; }; // Is there an existing enum somewhere we can use for this? enum Orientation { "vertical", "horizontal" };
The currentTime
of a ScrollTimeline
would be basically scrollTop/scrollY or scrollLeft/scrollX (with the exception that it would track smooth scrolling even though this isn't reported to the DOM, see bug 1010538). We could probably add scaling parameters here too, possibly based on scrollHeight/scrollMaxY etc.
The playbackRate
of an AnimationPlayer
provides the mapping from scroll units to time units.
(We probably don't need this feature for now) We could extend this member to take an "auto" value like so:
interface AnimationPlayer : EventTarget { ... // Can be "auto" or a double (double or DOMString) playbackRate; }
If AnimationPlayer
is associated with a fixed length timeline like ScrollTimeline
, the value "auto" sets the effective playbackRate
so that the duration of the player's animation content stretches to fit the range of the scroll container (players are already aware of the length of their source content so this isn't breaking the model).
If AnimationPlayer
is associated with an infinite timeline like the document timeline, then "auto" would simply be 1.0.
(We'd probably need a way of fetching the calculated value of playbackRate too. Not sure yet how best to represent this yet.)
Example usage
// Makes the character spin 180deg as you scroll the div var timeline = new ScrollTimeline(div, "vertical"); timeline.play(new Animation(character, { transform: "rotate(180deg)" }, 100));
Note that this current approach doesn't require a subclass of AnimationPlayer like I thought it might.
Also note that by using a regular player you can have several animations tracking the same scroll container and then call pause()
, reverse()
, finish()
, and update playbackRate
etc. to take them out of the flow or change the way they track the scroll position. Setting startTime
or adjusting the animation's delay can also allow offsetting them.
playbackRate
to we're not going to get meaningful times for running the animation.)Implementation issues
If smooth scrolling is performed on the compositor, but the animation being scrubbed can only be run on the main thread we'll probably need to run the smooth scrolling interpolation code on the main thread as well.
Update: Apparently the main thread still gets scroll events (lagging behind a bit) and we can drive the animation from there.
Implementation strategy
We could probably start with a very limited subset that:
- Is only enabled when OMTC and OMTA is enabled (no longer needed if we can drive main-thread animations via scroll events although it might be useful in terms of initially limiting the scope)
- Throws an exception when trying to associate animation content that targets anything other than 'transform' with a
ScrollTimeline
(also, no longer needed?) - Simply fails to animate if preserve-3d etc. is set (anything that prevents us from doing OMTA but which could change from sample to sample) (As with the first point, no longer strictly needed)
- Is only enabled for Gaia apps
Then we could gradually work at removing those restrictions in parallel with standardizing it.
Touch-based scrubbing
I'm not sure what the exact parameters would be here, but presumably we could use a similar approach.
Declarative syntax
If the API approach works, we could later map it to CSS using an animation-timeline
property. Tab previously had some ideas around this.
Other timelines
I think there is potential for addressing some other use cases by providing further timelines:
- FrameBasedTimeline - Some sorts of animations have fixed frames and they don't want to drop frames even if it leads to jank (e.g. [1]). This timeline would only increment the currentTime by a fixed amount on each sample (probably with some tolerance parameters).
- WorkerTimeline - Only really useful for setting up animations consisting entirely of javascript callbacks (see "custom effects" in the spec) but that could still be useful e.g. for animating a CanvasProxy, WebGL (bug 709490) etc. using the same animation API