Web Animations minutes, 25 May 2015

Present: Doug, Mike, Shane, Brian
Archived etherpad: https://web-animations.etherpad.mozilla.org/ep/pad/view/ro.92487irtSfEow/rev.37544

Agenda:
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


1. NAME PROPERTY
=================
(Brian)

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),
                       document.timeline);
  anim.play();

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

Shane: my only concern is how this looks with groups

from:

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

to:

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

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

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:
https://github.com/w3c/web-animations/issues/62

Current proposal is:
https://github.com/w3c/web-animations/issues/62#issuecomment-104486590

Seems like we could probably drop 1.i


4. USE CASES FOR AnimationTimeline.getAnimations()
==================================================
(Brian)

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

However:
* 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.


5. FILLING FORWARDS
===================

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
   ignored/cancelled?
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.


6. CSS ANIMATIONS AND TRANSITIONS SPECS
=======================================

Already a delta spec for CSS Animations level 2:
http://dev.w3.org/csswg/css-animations-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:

http://mxr.mozilla.org/mozilla-central/source/layout/style/nsAnimationManager.h?rev=70c5890d9577#94
* 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
feasible.

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
  http://dev.w3.org/csswg/web-animations-css-integration)
- more generalized event dispatch description to handle seeking,
  reversing etc. (see item 11 below)


7. FILTER FOR CSS VS SCRIPT getAnimations
=========================================

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
   animations?
A: All animations.


8. ANIMATION FINISH EVENT (NAMING) AND BEHAVIOR ON CANCEL
========================================================

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.


9. GROUPING IN CSS
==================
(Brian)

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

e.g.

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

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

B) group-name:

Advantages:
 - 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)
Disadvantages:
 - 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.

Advantages:
 - less stuff needs to be defined
Disadvantages:
 - 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
  way.
* Others?


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

Two proposals:

A: Sticky pause
* As implemented in Gecko:

http://mxr.mozilla.org/mozilla-central/source/layout/style/nsAnimationManager.h?rev=70c5890d9577#94
* An animation's natural state is running. Pausing takes it out of that
  state.
* 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


11. GENERALIZED EVENT DISPATCH
==============================

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
  phase
* 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
  outline


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

Reply via email to