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

Web Animations minutes, 25 May 2015

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

1. Name property
2. Can we drop AnimationTimeline.play?
3. AnimationTimeline.getAnimations() - sequencing
4. Use cases for AnimationTimeline.getAnimations()
5. Filling forwards
6. CSS animations and transitions specs
7. Filter for CSS vs Script getAnimations
8. Animation finish event (naming) and behavior on cancel
9. Grouping in CSS
10. Interaction of animation-play-state and the API
11. Generalized event dispatch


Ideally, I'd like to have:

* CSSAnimation.animationName (to indicate what animation-name generated
   the object even if the effect gets replaced)
* CSSKeyframeEffect.rule (let's you do animation.effect.rule.name)
* CSSTransition.transitionProperty

I was wondering about dropping the name property altogether.

After discussion, we think there's still use in having an
author-settable property purely for informational purposes, i.e.

* Animation.id

The 'id' name is following the precedent from ServiceWorkers and DOM.

Although 'id' may suggest the name should be unique, we don't ancitipate
having any requirement for this.

Mike: so can you write to animationName?
Shane: no I think animationName / rule / transitionProperty are all read
        only as they come from the style sheet.

Brian: it might be a good idea to add a query-by-id method to L2 of the
        specification, e.g. as a parameter to getAnimations.

2. CAN WE DROP AnimationTimeline.play?

Instead of:

   anim = document.timeline.play(new KeyframeEffect(elem, {..}, 1000);

You can already do:

   anim = new Animation(new KeyframeEffect(elem, {..}, 1000),

(As well, of course as elem.animate({..}, 1000))

Shane: my only concern is how this looks with groups


   anim = document.timeline.play(new SequenceEffect([...]));


   anim = new Animation(new SequenceEffect([..]), document.timeline);

Actually that's not any different really. But we have element.animate
for individual animations and nothing for groups if we remove

Q: How do you associate an animation with a timeline post-construction?
A: animation.timeline = ...;

Could we add document.start? Or document.play?

 > Move it to level 2 where we can also think about how to make
   constructing groups easier

3. AnimationTimeline.getAnimations() - SEQUENCING

See summary of issues here:

Current proposal is:

Seems like we could probably drop 1.i

4. USE CASES FOR AnimationTimeline.getAnimations()

* At first I wondered: is it even needed?
* More common use-case document.getAnimations() -- e.g. are the elements
   in this doc at rest?
* Or: elem.getAnimations({ deep: true }); -- e.g. is this sub-tree at rest?
* Perhaps similarly: elem.getAnimations({ includePseudos: true }); (but
   I'm less sure of this. Seems like we should just expose a means of
   getting CSSPseudoElement objects and call getAnimations() on them.)

* AnimationTimeline.getAnimations() is still useful as a way of getting
   animations that aren't attached to any element

Doug: I suspect people will use Timelines as a primitive grouping
       mechanism, especially if we provide getAnimations.

 > For the time being, we realise we need
   AnimationTimeline.getAnimations() as a way of representing animations
   that don't target an element -- they need somewhere to live and
   something that (conceptually at least) keeps them alive since they
   will still dispatch events, fulfill promises etc.


Two issues:

1. For script-generated animations, continually creating
    forwards-filling animations will leak memory over time. (The same
    issue doesn't apply to CSS animations since you typically replace the
    animations, or at least you obviously see you're leaking memory by
    creating a massive animation-name list.)

2. When you have a forwards-filling animation it clobbers other changes
    to style which can be very confusing. In the case where some
    script/content you don't control is creating the forwards-filling
    animation you either have to try writing to style and see if it
    works, or use getAnimations() and check the result.

(Problem 2 is also less of an issue for CSS animations as at least the
  computed style carries a record of the animation that's blocking other
  style updates)

For CSS animations we probably can't fix 2 due to compatibility
limitations but for script-generated animations we might be able to
address both by adding a sort of forwards fill that cancels whenever
another (non-animation?) style change occurs.

Shane will follow up on this and send a mail.

Supposing we add two different kinds of fill: "cancel-on-change-fill"
and "permanent-fill", should we expose "permanent-fill" to script? It is
a sort of a footgun but is probably necessary to expose it so that
script can polyfill SMIL, for example.

Also, should the cancelling behavior be per-property or per-animation?
After some discussion, we think it should be per-property.

Q: Would there be any API to detect if a particular property had been
A: No.
Q: Isn't that bad?

Some discussion about adding an API for querying per-property metadata 
such as:

i.   Is this property being animated by this effect? Or is it being
      clobbered by something else?
ii.  What is the current contribution of this effect to the property's
      value? -- i.e. its intermediate effect value
iii. Is this property being animated on the compositor? (since UAs may
      do some properties on the compositor and others on the main thread
      within the same animation)

AI: Shane to email public-fx/www-style and draft some specification text
(in a branch) for this feature.


Already a delta spec for CSS Animations level 2:

There's also http://dev.w3.org/csswg/web-animations-css-integration

Level 2 must haves:

* API mapping
* CSSAnimation / CSSTransition interfaces
* cancel events

Difficult areas to spec:

* overlapping animation names (not really specific to the API)
* play/pause interaction
   Outline here:
* dispatch of events in light of seeking

Brian: Keen not to add much/any new stuff or at least to have a stable
        subset we can ship soon. Might we worth investigating a simple
        group mechanism though (see item 9 below).

Shane: I'd like to investigate how to expose additive animation too.

Discussed adding an animation-composite property for this. Seems

Interface proposal:

   interface CSSAnimation : Animation {
       readonly attribute DOMString animationName;

   interface CSSKeyframeEffectReadOnly : KeyframeEffectReadOnly {
       readonly attribute CSSKeyframesRule rule;

   interface CSSTransition : Animation {
       readonly attribute DOMString transitionProperty;

 > We will start working on a fork of css-animations-2 then present to
   CSS WG, adding in:
- the interfaces above
- a description of animation-play-state interaction with the API (see
   item 10 below)
- mapping to the API (based on
- more generalized event dispatch description to handle seeking,
   reversing etc. (see item 11 below)


Q: What about adding a filter to getAnimations() to return, say, only
    script-generated animations / only CSS animations?
A: Sounds feasible for a future level (we already mentioned the
    possibility of additional options parameters to getAnimations() in
    item 4)

Q: What would the default be? All animations or just script-generated
A: All animations.


Can't call it animationend. What should we call it?

Suggestion, two events:
* finish, and
* cancel

Possible risk with already-implemented finish event in Chrome (it also
fires on cancel). Doug & Shane to check.


Strawman proposal to get discussion going:

* Add animation-group: <name>, <name>, <name>
* These names match up with the animation-name property
* For each time you have an animation-name with an associated
   animation-group, we look for an existing group in the context and add
   the generated KeyframeEffect to that group
* animation-group-reset: <name>, ... establishes a new instance of the
   group for  that subtree in the same way counter-reset does
* setting animation-duration etc. updates the individual KeyframeEffect
* The only property that affects the shared Animation object is
   animation-play-state which is where it gets tricky.
* Prefer to support a single level GroupEffect initially and later
   extend to SequenceGroups and hierarchies of groups, possibly by
   introducing an @group rule


.a {
     animation-name: anim-a;
     animation-duration: 1s;
     animation-group: foo;
.b {
     animation-name: anim-b;
     animation-duration: 2s;
     animation-group: foo;

Animations anim-a and anim-b will have the same start time regardless of
when the classes get added to the matching elements.

Discussed the possibility of specifying an insertion index as well:

   animation-group-name: group-name index;

Discussed an alternative proposal that introduces group-name. group-name
establishes a group for the subtree rooted by the element; in the
absence of a group-name specifier, the document root will introduce one.

This is essentially animation-group-reset by a different name but is
more conducive to extending with other group properties.

Comparing the two:

A) animation-group-reset:

  - minimal modification, no @group necessary initially
  - matches counter-reset
  - no way to specify group timing properties without @group
  - won't ever be able to declaratively modify group timing

B) group-name:

  - no need for @group
  - group creation at a node seems somehow simpler to reason about than
    group resetting (although actually the behavior is the same)
  - doesn't match counter-reset
  - have to define a bunch of group timing properties to match animation
    timing properties

Proposal C, animation name can reference @group as well as @keyframe
descriptions; if an @group is referenced then the animation
specification defines a group rather than an animation.

  - less stuff needs to be defined
  - need @group definitions from the start
  - really difficult to understand

The big issue is what to do about animation-play-state (the other
animation-* properties are generally ok since they map to the individual
KeyframeEffect objects but animation-play-state maps to the shared
Animation object so we need to resolve how they combine together).

Some possibilities:

* animation-play-state computes to 'slaved' for animations that are part
   of groups. group-play-state is used to toggle the play state of groups.
* If any of the children of an animation group are paused, the shared
   Animation object is paused but this isn't reflected in style in any
* Others?

10. INTERACTION OF animation-play-state AND THE API

Two proposals:

A: Sticky pause
* As implemented in Gecko:
* An animation's natural state is running. Pausing takes it out of that
* A call to pause() on a particular element sticks until play() is
   called which returns the element to its natural state.
* So long as you have a sticky action, you need a way to unstick it
   hence pause() is sticky but play() is not.
* play() will trigger an animation paused by style but won't override
   any subsequent changes to style.
* pause() acts as a piece of local state overriding any global state
* useful for devtools to be able to pause an animation and have that
   continue to apply regardless of any changes to style

B: Latest action wins
* If you call pause() / play() then change style back and forth, the
   style changes will take affect
* More symmetrical
* Less power to script

 > Decided A is ok


CSS event dispatch assumes time keeps progressing forwards. Once we
introduce Web Animations there is the possibility of seeking and playing
backwards so we need a more generalized approach to event dispatch.

Proposed approach (as implemented at least in Gecko):

* Define the "active range" as the period from the startTime to the end
   of active interval since animationstart fires at beginning of delay
* At a moment an animation can be in one of three states
   - left-side of the "active range"
   - inside the "active range"
   - right-side of the "active range"
* Before updating the time (due to seeking or regular sampling) record
   the current state
* After updating the time compare the new state with the previous state
   and dispatch events as follows:
   - inside -> outside = animationend
   - outside -> inside = animationstart
   - outside -> outside but with a change in side =
     animationstart + animationend
   (- inside -> inside with a change in current iteration
     = animationiteration)
* the exact definitions depend on the playback rate but that's the rough

Topics for next time:
* Custom effects
* Specing frames/sampling

Received on Tuesday, 26 May 2015 01:55:39 UTC