Coder Social home page Coder Social logo

wicg / animation-worklet Goto Github PK

View Code? Open in Web Editor NEW
92.0 92.0 35.0 355 KB

🚫 Old repository for AnimationWorklet specification ➡️ New repository: https://github.com/w3c/css-houdini-drafts

Home Page: https://drafts.css-houdini.org/css-animationworklet/

License: Other

HTML 18.37% Makefile 81.63%

animation-worklet's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

animation-worklet's Issues

Allow animators to specify their desired frame rate

(Note: Issue was created based on feedback from Houdini Paris F2F - irc logs)

At the moment, the specification does not declare how frequent animation should be pumped and it is left up to the user agents with a recommendation to pump as fast as possible.

However, not all effects needs to be pumped as fast as possible and running them faster than necessary will lead to unnecessary power usage. Mechanisms to better optimize the frame pump rate per animation is useful.

Idea 1 - Explicit frame-rate declared

Have animators request a particular pump rate (e.g., at least once every 4ms). Browser then tries to pump the desired rate with option to slow down if animation is missing the deadlines. Perhaps notifying the animation of rate change.

Idea 2 - Speculative pump rate

Browsers can pump as fast as possible but if no change was produced then reduce frame rate. This can be problematic for effects similar to position-sticky where they don't produce update in many frames but want to be pumped every frame.

API for communicating state between frames

Some effects rely on communicating state from one frame to the next (eg. a physics-based animation which tracks current momentum of different elements). Worklets don't permit state to be stored on the global object (see w3c/css-houdini-drafts#308). We should define an explicit API for passing state from one animate invocation and the next for a given Animator.

For example, the spring-timing demo stores properties directly onto the AnimationProxy.

Mechanism to pause an animation

For example, in the spring example it should be possible for the Animator to somehow say "I'm done now, stop invoking my animate function".

Maybe it should be more powerful, eg. "sleep for 5 seconds"? Or a main-thread API to resume the Animator?

Attribute Delay, Iterations, Fill not working

<div class="small"><img src="images/01.jpg" /></div> var smallContent = document.querySelector('.small'); new KeyframeEffect(smallContent, [{ 'opacity': 1 }, { 'opacity': 0 }], { duration: 7, fill: 'forwards', delay:5000, iterations:1 })
In the above keyframe effect, the below mentioned options are not working:
Delay
Iterations
Fill
From html page we can only call either “play()” to start the animation or “cancel” to stop and remove the animation.
How to handle “Pause” and “Finish” animations?
Also, no documentation regarding, how to pass values to “additionalTimelines_” variable of “WorkletAnimation” class.
Need your input.
Tried Browser versions:
Google Chrome - 64.0.3282.186
IE 11
IE Edge

Move to CSS.animationWorklet

Paint and Layout worklets have moved to CSS namespace, CSS.paintWorklet and CSS.layoutWorklet. I think animation worklet should follow suit!

API for influencing pre-painting

Browsers typically takes CSS animations / WebAnimations into account when computing pre-paint skirt data. But (like other JS-driven animations) there may be no opportunity to do so for animations driven by AW. The browser can't predict what the animation will look like in the future.

To fully explain the CSS animation behavior here, we should consider adding some sort of API for giving hints to the pre-paint system.

For example, in an effect where elements slide left/right onto the screen while scrolling vertically at a certain point, an AW implementation should be able to provide some sort of hint to influence when prepainting of those elements should occur.

Hopefully this is a feature we could add in the future, and just encourage people to use CSS scroll-linked animations for common cases like this today.

Data on performance impact of syncing state for stateful animators across threads

(Note: Issue was created based on feedback from Houdini Paris F2F - irc logs)

There are a few cases where the current spec requires data to be send across thread and process boundaries:

  1. When an animator is migrated across threads, its state should be serialized/sent/deserialized.
  2. When scrolling happens on a separate thread/process, UA needs to sync scroll state to the animation thread and also the animation thread output to main thread.

There were some concern raised on performance/complexity impact of these cases. We should try to actually quantify such impact to better guide the working group.

Improve potential for generating multiple animation frames in parallel

(Note: Issue was created based on feedback from Houdini Paris F2F - irc logs)

There is interest in improving opportunities for user-agent to generate more animation frames in
parallel. Current API only allows running individual animators in parallel but there are still
potential to do more. For example it is useful to generate multiple frames for the same
animations in parallel an/or ahead of time.

Pure Effects

If an animation is pure (i.e., has no internal state), then it is possible to
generate multiple frames for it in parallel by passing new input and recording the output.
Here are few improvements to the API that leverage this:

  • Introduce a mode (maybe this should be the default) where animator is assumed to be pure. We can enforce this via the same mechanisms that is used for paint worklet e.g., random assignments to global scope and dropping the animator object. (Strawman API: https://gist.github.com/anonymous/e22250dbdfa92da59508a220b8087d9d)

  • Enable even more effects to be written in this mode. For example if we expose scroll velocity and acceleration then a lots of existing effects don't need to have to keep state to compute it.

Additional idea - Speculative execution

Browsers can also speculatively run an animator in parallel as if it is pure and then fallback to normal operation if they detect a conflict.

partial interface AnimationEffect exposure set doesn't match original defintion

https://wicg.github.io/animation-worklet/#worklet-group-effect has:

[Exposed=AnimationWorklet]
partial interface AnimationEffect {
    // Intended for use inside Animation Worklet scope to drive the effect.
    attribute double localTime;
};

And https://drafts.csswg.org/web-animations/#the-animationeffect-interface has:

[Exposed=Window]
interface AnimationEffect {
    EffectTiming         getTiming();
    ComputedEffectTiming getComputedTiming();
    void                 updateTiming(optional OptionalEffectTiming timing);
};

This combination is not valid because https://heycam.github.io/webidl/#Exposed say: "If [Exposed] appears on a partial interface or partial namespace, then the partial’s own exposure set must be a subset of the exposure set of the partial’s original interface or namespace."

In other words, [Exposed=AnimationWorklet] needs to be added to https://drafts.csswg.org/web-animations/, or some change made in this spec.

@lukebjerring, I discovered this thanks to a failing "Partial AnimationEffect interface is exposed to 'AnimationWorklet', the original interface is not." test when reviewing web-platform-tests/wpt#12439.

Allow constructing WorkletAnimation with single KeyframeEffect.

It might make sense to allow passing a single keyframe effect or an array of keyframe effects for improved consistency with animations.

i.e.

// Implicitly constructs and uses a GroupEffect because an array of effects was given.
new WorkletAnimation('foo', [new KeyframeEffect(...), new KeyframeEffect(...)], ...);

// Passes in the single keyframe effect as the effect on the animate function.
new WorkletAnimation('foo', new KeyframeEffect(...), ...);

Define when animations start

The animation starts immediately after the animation property is set and one of it's input properties changes.

Adapt to removal of AnimationEffectReadOnly from Web Animations

w3c/csswg-drafts#2432 removed AnimationEffectReadOnly from the Web Animations spec. I noticed this in web-platform-tests/wpt#9758 because Animation Worklet does partial interface AnimationEffectReadOnly and that doesn't work.

Adapting to the changes doesn't look like a trivial search+replace, because there's also use of GroupEffectReadOnly which is only in https://drafts.csswg.org/web-animations-2/, which hasn't removed the AnimationEffectReadOnly interface...

`[Exposed=Worklet]` is too wide

It should be a bit narrower in scope. Otherwise, it's going to be exposed in all other Worklets, such as the AudioWorklet or the PaintWorklet.

Design for per-child output properties

Some use cases rely on setting different output properties on different children, some of which create a stacking context (eg. transform) and some of which don't (eg. scrollTop). It may be problematic to force a stacking context for all children when it's not strictly necessary.

We need to design an API that would allow output properties to be specified on a child-by-child basis. We'll rely in specific use cases / demos to decide if this API needs to be part of the level 1 API or can be something we could add later.

Support animating all properties

Some (eg. @birtles) have argued that we should be consistent with animations on the web and allow any property as an output property. Eg. to avoid requiring a spec change to expand the set of animatable properties (since some browsers may move faster on that than others).

I think there's broad support for expanding the design for that, though there is debate over how exactly that should behave.

In particular, by default we'd like an error delivered to window.onerror by default whenever a not accelerated property is animated (indicating that animation can only be performed at the rate of the main thread). Optionally a developer can indicate that they are OK with main-thread animations and disable this warning (perhaps a 3rd setting for the option in #1).

Also there is significant debate over what should happen when an Animator changes an accelerated property of one element as well as a non-accelerated property of another element. There are two main options:

  1. Synchronized: all elements update at the rate of rAF
  2. Unsynchronized: the elements where only accelerated properties are changed will update off-thread, while other elements will update at least a frame behind.

Proposal: have an option for now to support either mode and build concrete demos which are better in one mode over the other. We can pull the mode switch from the v1 API if no critical use cases end up requiring one of the modes.

Pure/idempotent representation

The animators in the README use the class keyword and static properties to construct an animation worklet. For animators that remember state across frames (#4), this seems reasonable. However, many animators will be pure transformations of input to output. For both readability/stylistic purposes and to avoid needlessly allocating memory/CPU cycles, it may be desirable to have an alternate representation for pure animators.

Perhaps:

function animator(root, children, timeline) {
  // compute frame
}

animator.inputProperties = ['--scroll-position'];
animator.outputProperties = ['opacity'];

or

const animator = { 
  inputProperties: [
    '--scroll-position',
  ],
  outputProperties: [
    'opacity',
  ],
  animate(root, children, timeline) {
    // compute frame
  },
}

NOTE: The present API is also mutative - output is expressed by settings properties on the input, not by returning values. Some authors will prefer a truly pure API, but that's more a matter of style than of minimizing resource usage.

Option to run in-sync with rAF

@birtles argues that you may sometimes want to have an animation that is guaranteed to run in-sync with rAF on the main thread. Perhaps there should be an option on the animator for this?

Personally I'm not sure when you'd choose to use AnimationWorklet like this instead of just writing animations using rAF, but perhaps there are code sharing benefits?

Optional arguments in Web IDL must be trailing arguments

https://wicg.github.io/animation-worklet/#creating-worklet-animation says:

[Constructor (DOMString animatorName,
              optional (AnimationEffectReadOnly or array)? effects = null,
              AnimationTimeline? timeline,
              optional WorkletAnimationOptions)]
interface WorkletAnimation : Animation {
        readonly attribute DOMString animatorName;
};

The 2nd and 4th arugment are optional, that doesn't work because the 3rd is not. Not clear if only the 4th should be optional, or 2-4 all optional.

Add threading motivation details to introduction

@dbaron says it would be helpful if the spec had an introduction describing that an implementation is free to run a worklet on either the main thread or (if all the output properties are supported off-thread) a separate thread. The idea is that this implements the same threading model as CSS animations and Web Animations (performance isolated if supported by the implementation, otherwise locked to main thread).

When do time-based animations run?

Only when on-screen? What if some JS queries the value of one of it's output properties?

Can we look to WebAnim here? Eg. @shans says that WebAnim defines that the timestamp for an animation that hasn't started yet is null.

Example doesn't meet idempotency requirement in Worklet spec.

In Animation Worklet example animation-with-local-state:

  constructor(options, state) {
    // |options| may be either:
    //  - The user provided options bag passed into the WorkletAnimation constructor on first initialization i.e, {value: 1}.
    //  - The object returned by |destroy| after each migration i.e. {value: 42}.
    this.options_ = options;
    this.state_ = state || {value: Math.random()};
  }

The Worklet class constructor initialize this.state_.value with Math.random() random value.
But according to spec:

These specifications must require user agents to always have at least two WorkletGlobalScopes per Worklet and randomly assign a method or set of methods on a class to a particular global scope.

When two of the example worklet got initialized, each of them might get a unique value, which may cause different localTime been set, and animation may jump between two continuous localTime flow (adding 0.1 each step).

In conclusion, I think the code example doesn't meet idempotency requirement in Worklet spec.
Maybe can someone kindly explain the issue for me? Thank you!

Animating without DOM/CSS

The current proposal relies heavily on DOM APIs and CSS custom properties to send input to an animator. How would you control (play, pause, send input to, etc.) an animator from JavaScript without serializing to/from a style map? Is there an API (like element.animate) that would give JavaScript the ability to trigger an animation without touching the style map?

Define AnimationWorklet as subset of Animation

AnimationWorklet may fit better as a custom animation, rather than a scripted effect. This could throw on operations like reverse() since it is not idempotent (with possibility in the future to script reversing). This allows it to define its own timelines (or not), create and drive effect nodes if desired, etc. Thoughts?

e.g.

new CustomAnimation('expando', {
  'expand': [elem1],
  'shink': [elem2],
}, [
  document.timeline,
  new ScrollTimeline(options...),
]).play();

Defaulting root to document is bad

From Houdini F2F discussion:
For parallelism we want to avoid using the document as a root. Perhaps if there's no root specified we should use the element itself as the implicit root? Also fix the spring example not to use the document as the root.

Define semantic of finish/reverse/playbackRate for Worklet Animation

Problem

The web animation's timing model is "stateless" with a notable exception of methods which change the timing properties such as finish, or pause.

Worklet animations deviate from this timing model to enable effects that are script-driven, stateful, and runnable in a parallel worklet execution context. In particular a worklet animation output is not only dependent on its time input but also its internal state. As such the worklet animations may not necessarily be amenable to constant time seeking and direction or rate agnostic playback.

However it is desirable to make worklet animations conform to the existing Animation interface as much as possible. This include finish method which seeks a particular time, or reverse method and playbackRate attribute that change playback rate.

Idea 1 - allow author defined behavior

Any methods that seeks a time or changes playback rate would cause a corresponding callback to be called on the corresponding animator in the worklet context. The user script will be responsible to provide best possible mapping for the given effect.

Here is a strawman API:

registerAnimator('foo', class {
  animate(timeline, output) {
    if (this.finished)
     output.localTime(10);
    else 
     output.localTime(timeline.time * rate * Math.rand());  
 }
  finish() {
      this.finished = true;
  }
  reverse() { 
    console.warn("foo animation is not reversible") 
  }
  
 playbackRateChanged(rate) {
    this.playbackRate = math.abs(rate);
 }
}

Pros:

  • Authors has to work hard to "Do the Right Thing".

Cons:

  • If the animation is stateless, this is too much work that could have all been done automatically. See next proposal.

Idea 2- modify the timeline.currentTime

We can modify the timeline.currentTime to reflect the seeked value and playbackRate.

Pros:

  • Works fine for stateless effect.

Cons:

  • Most likely the wrong behavior for any stateful effect. We will probably still need to do callbacks as well so that the animation can adjust accordingly.

Conclusion

There may be an elegant solution that sits somewhere between these two proposals where we do the stateless animations are automatically doing the right thing without a lot of boilerplate without it negatively affecting the stateful animation case. But I am not sure what it is. Ideas?

Even we don't find that elegant solution. I am inclined to go with idea 1 in particular because 1) I think it is appropriate for AnimationWorklet API to be slightly biased toward addressing the more complex stateful usecase 2) It provides more power on top of which we can add additional simplifying sugar in future.

Pass additional timelines as part of additional options and only have a single timeline in constructor.

I think WorkletAnimation would be more consistent with Web Animations if we just passed the primary timeline in the constructor and moved additional timelines to the additional options bag.

i.e.

new WorkletAnimation('foo', [new KeyframeEffect(...)], scrollTimeline, {'documentTime': document.timeline});

Then we could allow attaching to / detaching from additional timelines within the object. For example:

registerAnimator('twitter-header', class {
  constructor(options) {
    this.options_ = options;
  }

  animate(timeline, effect) {
    ...
    if (condition) {
      this.options_.documentTime.attach(this);
      // Or this.attach(this.options_.documentTime);
      // At this point in time the animation will now tick with the DocumentTimeline as well
      // as the ScrollTimeline.
    } else if (other_condition) {
      // detach from document timeline.
    }
  }
});

It's also possible that since there is a single DocumentTimeline it may be available on the global scope to attach to / detach from.

s/it's/its/

In several places of the text, "it’s" is used instead "its".

Add generic mechanism for warning of non-accelerated animations

In #2 we've talked of generating a warning/window.onerror (unless the developer has opted-out) whenever an animation cannot be accelerated and occurs on main. @esprehn points out that this is really not a AW-specific issue, we should solve it for CSS / WebAnim generally (although in those existing cases it may need to be opt-in rather than opt-out).

Running author function without proper preparation.

"create a new animator instance" step 6 invokes an arbitrary author function through Construct without performing "prepare to run script" nor "prepare to run a callback".

From the beginning, animatorCtor is a callback function, and callback function is not designed to be used as a constructor IIUC. "invoke" algorithm is expected to be used instead, where "prepare to run script" and "prepare to run a callback" are supported.

By the way, "run animators" looks strange, too. It pretty much looks like callback interface, but it's actually defined as a callback function and behaves differently. The difference looks to me an unnecessary confusion.

From a point of view of Web IDL, it would be natural to define animatorCtor as a generator (not a constructor) that returns a new instance of callback interface that supports animate operation. Then, we can call a user object's operation with the instance and operation name "animate". Or, we can define animatorCtor as a generator that returns a callback function if callback function is preferred.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.