W3C home > Mailing lists > Public > public-fx@w3.org > April to June 2015

[web-animations] Web Animations minutes, 28 May 2015

From: Brian Birtles <bbirtles@mozilla.com>
Date: Tue, 30 Jun 2015 16:33:27 +0900
To: "public-fx@w3.org" <public-fx@w3.org>
Message-ID: <55924647.5040300@mozilla.com>
[ Sorry for the delay here, I just discovered these notes in the
   Etherpad and I don't appear to have ever sent them to the list. ]

Web Animations minutes, 28 May 2015

Present: Doug, Mike, Shane, Brian
Archived etherpad: 

1. Custom effects
2. Navigation transitions
3. Effect clipping
4. Stacked timing functions


* This has been moved to level 2 but we'd like to get a rough outline of
   it so we can work on it in the polyfill
* Tricky part is how to integrate with all the playback algorithms
* There may be a way to integrate it into the regular sampling behavior

Basic idea:
* Add AnimationEffect.onsample
* Any time the progress (including going to/from null) or current
   iteration has changed we'd call this - basically, onsample needs to be
   called any time the animation state changes in a way that could
   potentially lead to a change in the visual effect of the animation
* (Some discussion about *not* calling these for offscreen
   elements--off-screen iframes would have a timeline that is ticked less
   often so might be ok?)
* Should we pass the AnimationEffect to the callback? Yes, makes sense
* Should we *also* pass the Animation? Probably, since you can't
   currently go from effect back to its animation. (Some discussion about
   the fact that we'll probably eventually want to be able to go from
   effect to animation.)
* What do we do about the target?
   * Groups don't have targets
   * Do you even want GroupEffect.onsample? Or is 
KeyframeEffect.onsample enough?
      - Yes, you need GroupEffect.onsample. (e.g. a sequence group that
        updates a progress bar via an onsample callback as the sequence
* Regarding groups, the callback should be called whenever the
   descendant group structure changes
    * This also includes, e.g. tweaking the keyframes of a descendant
      effect (since that could produce a different visual result)
    * This might seem excessive but we'd still only call these once per
      frame. i.e. set a dirty flag and mark all ancestors dirty for that
* Regarding changing the target of a KeyframeEffect, that would also
   trigger a callback but would it also trigger 2 callbacks: once with
   the old target and a null progress and once with the new target and
   a resolved progress? (this is what is currently specced)
    * Previously the target was clearly a parameter of the custom effect
      but now that's not necessarily the case.
    * We *could* pass in the old target but why make the target special?
      Why not also pass in the old set of children etc.? Old set of
      children's targets?
    * We could just make tracking changes to the target the
      responsibility of the callback function.
* Regarding the signature, what to pass:
    - progress (nullable)
    - effect
    - animation

Viewport events topic:
* Some discussion about where these callbacks happen within a frame
* Agreed they should probably happen after rAF callbacks
* Shane introduced the topic of viewport events which may create a loop
   that repeatedly updates style and layout. If this happens we may need
   to ensure that onsample callbacks participate in this loop.


Discussions ongoing between Google and Mozilla at the moment. Main
sticking point is how to address latency.


* This is one of the pieces needed to polyfill groups on top of the
   existing features
* Proposal: add a clip-start and clip-end value to Animations. These
   clip the fill (or animation) and are -Infinity/Infinity by default.
* Use cases: polyfilling groups, representing transitions' backwards
* It seems somewhat related to the issue about the forwards fill of
   animations persisting forever and clobbering subsequent style changes
   so we investigated a more general mechanism for cancelling fill.

   e.g. fill: "forwards" fills each property until there is a subsequent
   change to the property, "forwards-forever" fills forwards
   unconditionally, "forwards (3s)" fills for 3s

   We didn't really arrive at any conclusion.

   However, if we're going to add "forwards-forever" then we probably
   need to add that from the start otherwise we can't repurpose
   "forwards" later
* Adding Animation.clipStart and clipEnd might be worthwhile but it
   would be great to get some validation from existing JS libraries (e.g.
   GSAP, Velocity), i.e. get them to use Web Animations as a backend and
   see what limitations they hit. If clipStart/clipEnd, for example,
   would solve their problems then we should definitely add them.


* Stacked timing functions would allow you to emulate the effect of
   nested groups.
* However, Brian points out that chained timing functions have the same
   ability to emulate arbitrary easings, and are also more accessible and
   more widely applicable - e.g. to produce spring-like easings.

We worked on a syntax for chained timing functions and came up with:

easing: [ tf? point? ]?

Concretely, easings look like
easing: cubic-bezier(a,b,c,d) (x, y) cubic-bezier(e,f,g,h) (x2,y2) ...

You can leave out the points (they're evenly distributed between
provided points, where easings always start at (0,0) and end at (1,1).

You can leave out the timing functions (in which case they'll default to

cubic-bezier parameters are always in global (0,0,1,1)-space. This means
that you can accidentally provide erroneous easings, e.g.:

easing: cubic-bezier(0.2, 0.8, 0.6, 0.6) (0.5, 0.3) cubic-bezier( 0.6, 
0.9, 0.7, 1.0)

Here the first point has an x coordinate that is less than the second
x control point of the first bezier (0.5 < 0.6). Concretely, an easing
is OK as long as *all* of the x coordinates (specified and inferred) are
in nondescending[1] order.

So this is incorrect too, although it's hard to see why:
easing: cubic-bezier(0.2, 0.8, 0.6, 0.6) cubic-bezier( 0.6, 0.9, 0.7, 1.0)
easing: cubic-bezier(0.2, 0.8, 0.6, 0.6) (0.5,0.5) cubic-bezier( 0.6, 
0.9, 0.7, 1.0)
(because that's what easing: linear linear would do)

We could instead infer point x coordinates to be evenly spaced between
adjacent specified x coordinates, which would mean that the above would
be equivalent to

easing: cubic-bezier(0.2, 0.8, 0.6, 0.6) (0.6,0.5) cubic-bezier( 0.6, 
0.9, 0.7, 1.0)

which is actually fine. But if we're doing that, should we do the same
thing for the y coordinate?

easing: cubic-bezier(0.2, 0.8, 0.6, 0.6) (0.6,0.75) cubic-bezier( 0.6, 
0.9, 0.7, 1.0)

 > Google to polyfill this. If it's good then we'll add something to L2.

[1] nondescending == increasing 
Received on Tuesday, 30 June 2015 07:33:52 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:49:54 UTC