[web-animations] Web Animations minutes, 18 / 19 June 2013

Web Animations minutes, 18 / 19 June 2013

Present: Doug, Shane, Brian
Etherpad: https://etherpad.mozilla.org/ep/pad/view/ro.BTKjE5fjGvu/latest

Agenda:

1. Status updates
2. Spec patches
3. Parabolic cubic-bezier timing functions
4. Revising signature for CustomEffect.sample
5. Inheriting fill mode
6. Making players stop
7. Shorthand properties and dictionaries don't mix :(


1. STATUS UPDATES
=================

Brian:
- Fill modes
- Blogging:
     Introduction: 
http://brian.sol1.net/svg/2013/06/26/introducing-web-animations/
     Explaining timing groups: 
http://brian.sol1.net/svg/2013/07/09/group-and-conquer-timing-groups-for-your-synchronization-woes/
     (Next: explaining players; keyframes outside [0,1])

Doug:
- Implementing CSS Animations on Web Animations model in Blink

Shane:
- Digging holes


2. SPEC PATCHES
===============

Chained timing functions - 
https://github.com/web-animations/web-animations-spec/pull/1
   - Brian to integrate after review
Fill modes - https://github.com/web-animations/web-animations-spec/pull/2
   - See point 5
Keyframes outside [0, 1] - 
https://github.com/web-animations/web-animations-spec/pull/4
   - Brian to get feedback (probably in a couple of weeks' time)


3. PARABOLIC CUBIC-BEZIER TIMING FUNCTIONS
==========================================

Bug 22483: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22483

Shane: This assumes parabolas that start/end with zero velocity and 
end/start at a particular fixed velocity. I'd rather defer this to the 
Timing Functions specification and develop specific primitives that 
actually capture the range of parabolic effects.

Furthermore, I'm getting increasingly concerned with the use of timing 
functions to emulate things that don't seem to fit into the realm of 
timing functions. Some examples:
  - physics (for more than very trivial effects there are interactions 
between objects. Using timing functions makes this impossible)
  - path smoothing (e.g. 'perfect' timing)

I think this needs some more thought and discussion

Doug: This specific ask seems to be about readaility of CSS (names vs 
bezier points). Some of this could be achieved using CSS Variables.

 > Deferred to separate timing functions spec so we can think about it 
properly (for the reasons Shane raised above).

AI: Shane to follow up with Dean Trower as to the nature of his use 
case. Would a pre-rolled bounce timing function work better?


4. REVISING SIGNATURE FOR CustomEffect.sample
=============================================

Bug 22487: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22487

Doug, Shane: +1 on passing Animation rather than Player, but shouldn't 
worry until more use cases arrive.


5. INHERITING FILL MODE
=======================
(Brian)

Background discussion: 
https://etherpad.mozilla.org/ep/pad/view/ro.H-Y4dCgrqL$/latest

Agreed we like the model where children can't fill beyond their parent's 
fill. i.e. if parent says fill:none, it clips children regardless of 
their fill mode.

Furthermore, parents pass down their fill state and fill:none children 
do NOT produce an output when their parents are filling.

Questions remaining:
a) Do we need an 'auto' fill mode?
b) What should the default be?

Regarding (a), the difference between 'none' and 'auto' would be:
'none' - If I'm within my interval (in the strict sense) AND my parent 
is NOT filling, DO produce an output
'auto' - If I'm within my interval (or exactly at the end) DO produce an 
output

(This definition of being 'within my interval' includes when the parent 
is filling since it is based on the inherited time)

(The 'exactly at the end' condition is so that the following fills forwards:
    <par fill="forwards">
       <animate fill="auto"/>
    </par>)

'auto' is similar to what we currently have specced but with the 
additional handling of interval end points.

Alternative names: 'parent', 'snapshot', 'hold' etc.

When we consider asymmetrical fill modes ('forwards', 'backwards') does 
the behavior when cut-off mimick 'none' or 'auto'? For example, does the 
following fill backwards?

   <par fill="both">
      <animate fill="forwards"/>
   </par>

It seems we can:
1. Make a choice, e.g. fill:none -> doesn't fill backwards. Seems a bit 
arbitrary.
2. Split the properties out. There are a few ways we could do this:

     2a. parent-fill applies to any time the parent is filling
        fill: none | backwards | forwards | both
        parent-fill: hold | ignore

        This lets you do:
        <par fill="forwards">
           <animate fill="forwards" parent-fill="ignore">
        </par>
        And the <animate> would only fill to the end of the <par> which 
might be useful.

        This would suggest that the default for parent-fill would be 
"hold" so that the following does what you expect:
        <par fill="forwards">
            <animate fill="forwards">
        </par>

        Then:
        <par fill="forwards">
            <animate fill="none">
        </par>
        Would fill forwards (since parent-fill:hold is the default).

        To get the behaviour where you don't extend the child you would 
have to do:
        <par fill="forwards">
            <animate fill="none" parent-fill="ignore">
        </par>

    2b. Add a property which only applies to when an item may be 
extended by the parent.
        fill-mode: none | backwards | forwards | both
        fill-hold: none | hold

     Obviously, when exposing to CSS (and probably SVG) we'd make it a 
shorthand along the following line:
         fill: <fill-type> (<fill-hold>)*
         fill-mode: none | backwards | forwards | both
         fill-hold: none | hold

     But from the model and API point of view you'd have 2 different 
properties.

     The default for fill-hold is less critical in this case since,

        <par fill-mode="forwards">
           <animate fill-mode="forwards">
        </par>

     Fills forwards regardless of the setting of fill-hold. It really 
depends on the default of 'fill-mode'.

     This doesn't give you the nice feature where you can make an 
animation only fill until the end of its parent though. I guess you 
could achieve this in many cases by simply setting fill:none on the 
parent (but that would prevent you having, for example, some children of 
a sequence extend to the end of their parent and some extend beyond).

    With both 2a and 2b, can we make an animation that:
    - fills forwards if cut-off (i.e. snapshots) but otherwise doesn't 
fill forwards
    - never fills backwards
    ?

    i.e. fills forwards in the following case
     <par dur="2s" fill="both">
        <animate delay="-1s" dur="4s" ?? ??>
     </par>

    but fills in neither direction in the following?
     <par dur="4s" fill="both">
        <animate delay="-1s" dur="4s" ?? ??>
     </par>

     I think we probably can't. Doing that would require having two 
fill-hold settings. e.g. fill-mode="none" fill-hold="none hold". That 
seems really unlikely and something we could add later if needed so I'm 
not going to bother enumerating it as a possibility.

I'm going to suggest 2b as my preferred option.

I made a diagram with how this looks:
http://people.mozilla.org/~bbirtles/web-animations/diagrams/fill-matrix.html

Or there is a fiddle if anyone wants to experiement with alternatives: 
http://jsfiddle.net/FL2Dr/

Shane: I could be completely wrong about this, but it seems like 
fill-hold as currently specified:
(1) only impacts the animations to which it is applied
(2) doesn't make anything possible that wasn't already possible. By this 
I mean that if you know where an animation ends with regards to its 
container (a fairly common case) then fill-hold doesn't do anything for 
you. If you _don't_ know, then you get to make some extra assertions 
about the behaviour of the animation, but I'm not sure that these 
assertions are useful in this context.

If this is true, then we should consider fill-hold maybe as a property 
one can set on an animation group (and have it apply to all children) 
rather than on an animation. This lets us force the kind of behaviour 
that is currently specified on subtrees of content.

Brian: Regarding (b)--the default fill mode--we have the following 
situation:
- CSS and SVG use a default fill mode of 'none' and it would be 
difficult for authors if they translate a fragment of markup into script 
calls (or vice-versa) and it starts behaving differently, sometimes in 
subtle ways.

Shane, Doug: CSS transitions have an implied fill mode of 'both' :-D
Shane: I'm not overly concerned about the script defaulting differently 
to CSS / SVG. It already does in a myriad of ways.

Doug: In Chrome, animation-fill-mode appears to be set about 30% as 
often as animation-duration.

Brian:
- Our API uses a default fill mode of 'forwards' since we observed that 
is is often most useful for scripted calls, at least when using the 
Element.animate shortcut
- It is *probably* most useful to make groups fill:both by default so 
then when you wrap up your animations for sequencing purposes their 
behaviour doesn't change.

Some possible approaches:

i. fill-mode:none is the default. Element.animate overrides this with 
fill:forwards.
    - Wrapping an animation with fill:forwards in a par group without 
specifying the fill mode causes it to get clipped.

Doug: I'd prefer that element.animate didn't behave differently.

ii. Introduce fill-mode:default. For timing groups this is 
fill-mode:both, for animations this is fill-mode:none. Element.animate 
overrides this with fill-mode:forwards.

Shane: I actually think I'd rather go with iii. always default fill-mode 
to both. If there is violent disagreement with this then I prefer what 
we currently have, followed by i., followed by ii.
Doug: +1 but I'm not too worried

Brian: In both cases I think I'd suggest fill-hold:none be the default 
and you have to opt-in to the snapshotting behavior? That's probably 
something that's easy to change with implementation feedback.

Shane: Definitely fill-hold:none should be the default.

Brian: One more alternative, set the fill-hold state on the parent. We 
initially avoided this because we thought there may be some children 
that should hold and some that shouldn't. How important a use case is 
this? There are ways to get this behavior by adding additional animations.

Shane: As mentioned above, I've come around and think this is a good 
idea now.

 > For now, let's incorporate the fill-mode changes into the spec minus 
fill-hold. When Steve returns we'll revisit fill-hold and see if it 
could be put on the group instead.

Shane: what about some kind of fill-mode: inherit that returns 'none' 
for root nodes? This way, at least trees of animation can be set to 
fill-mode: forward in one place rather than everywhere.

Further discussed defaults for fill-mode. Couldn't decide what is best 
here. In summary:
  - fill:none -- mimicks other specs; seems more natural in some cases.
  - fill:both -- in practice, is often more useful. Making authors 
specify this all the time is burdensome.

AI: Shane to write a CONCISE email about default fill mode to send to 
ww-style, public-fx, tab's blog (?), Alex's G+ feed, etc. etc.


6. MAKING PLAYERS STOP
======================
(Brian)

I think players should stop when their source content finishes.

Reasons:
* It parallels what real video players etc. do
* The current time of a player should represent the position within the 
source content.
* Having a notion of stopping allows for defining events on players 
('onend' etc.) or making them then-able
* It allows for defining a reverse() method which, if you call twice, is 
a no-op

Issues:
- What is the paused state when a player stops?
- What happens if I update the player's source content after it has stopped?

(Related issue: we did decide, right, that setting the startTime doesn't 
reset the time drift... I think that's a bit surprising. I think we 
should expose the time drift as "pausedTime")

A few models:

a) When we reach the end, we auto-pause.

If it gets longer, start playing from previous end to new end; if it 
gets shorter, just jump to new end. Need to define how this works for 
batch changes.

At a slightly more detailed level this operates like pausing in that we 
keep accumulating a timeDrift like we normally do when paused. There are 
two exceptions though: if the source content gets shorter though we 
increment the timeDrift by the difference in length. If the source 
content gets longer we automatically unpause.

This gives intuitive results in most cases and also produces sensible 
values for "paused", "pausedTime", "currentTime" etc.

The main issue is bulk changes. If you change the source content so it 
gets shorter and then make a subsequent change that makes it get longer 
you'll find you'll find it jumps back and starts playing from the 
shorter end time. The bad news is this is a different result than if you 
just made the source content longer. The good news is you should get the 
same result regardless of the order of operation.

b) Just ignore the change: it has stopped.

The paused state is true automatically but doesn't automatically reset. 
You'd have to do that manually *and* update the current time to get it 
to play again (since setting the pause state without changing the 
current time would make it auto-pause again).

That last point is a bit odd. It's also problematic because if you got a 
sample before you added any content to your player (or any content with 
greater than zero duration) you'd get stuck. That could be really 
problematic for media which might initially have zero duration but after 
buffering get a longer duration.

c) Don't auto-pause, just cap the current time

In this model, the paused state doesn't get set and nor does the 
pausedTime change. But the reported current time is never greater than 
the end of the source content.

In effect we change the formula for the current time as follows:

current time = min((timeline time - start time) * playback rate - time 
drift,
                                 source content start delay + source 
content active duration)

Under this approach if you change the length of the source content to 
make it longer, you might, for example, jump to half way through the 
extended part or you might jump to the end depending where the "actual" 
current time is up to.

One advantage of this approach is that you don't run into changes in 
behavior due to the timing of changes to the source content.


Personally I wonder if there's some way to tweak approach (a) to remove 
some of the issues there.

d) Doug: I think we want a model with these properties:
- current time should stop increasing when we reach the end of the 
source content
- setting a shorter source content should not change the current time
- setting a longer source content should not change the current time

Shane: I think Doug's right. This is basically a hybrid of (a) and (c) 
right?

Brian: Sounds good. Does it auto-unpause when the source content gets 
longer? I think it has to or else you have the problems associated with (b).

Shane: Alternate wording: Players have a time bound that extends from 
startTime to endTime. Players do not advance currentTime if it is 
outside their time bound.
   - paused is false when this happens (i.e. we don't automatically 
switch the pause state)
   - you can still set currentTime to a time outside the bound - it just 
won't advance after
     that happens

Brian: How about exposing the time drift? I think people will get 
tripped up because that's hidden. But what to call it?

Shane: Yes, let's expose the time drift.

Brian: time drift is a bad name. Should it be positive or negative? 
pausedTime is obviously positive, but it doesn't indicate that seeking 
(or this non-advancing behaviour) is incorporated in the value.

timeOffset? timeLag?

 > timeLag

RESOLVED: 'time drift' to be renamed 'time lag' and exposed as timeLag.

A further question which applies  to all models: What happens when you 
play in reverse? Do you stop advancing when you hit currentTime=0 or 
when you hit the start of the source content?

 > currentTime = 0

How about when you have a negative delay, a positive playback rate and 
you set the current time to prior to the negative delay? Or in the 
negative delay?

Shane: For currentTimes before 0 then (1) the currentTime should not 
advance and (2) the source should behave as if it is in its backwards 
fill mode, fixed at a local time of 0.

Brian: A bit concerned about the play head getting stuck when you change 
the source content.

 > We'll think about it a bit more.


7. SHORTHAND PROPERTIES AND DICTIONARIES DON'T MIX :{
=====================================================
(Doug)

In CSS, ordering dictates priority within a style rule. For example

background: red;
background-color: blue;
  -> background color is blue

background-color: blue;
background: red;
  -> background color is red

Per the JS specification, Objects don't have a defined ordering, so we 
can't use this. Even if we did define an ordering (e.g. alphabetic), 
this is unlikely to match the in-text-order ordering that the author 
expects.

Options?
1. Shorthand or longhand wins, the others would be discarded.
2. Only one property per keyframe.
3. List of property, value pairs.
4. Some other well defined order.

Actually current order for accessing properties of a passed in keyframe 
object is well-defined (basically alphabetic):
http://www.w3.org/TR/web-animations/#normalizing-a-keyframe-object

The problem is our animation priority model needs to address shorthands. 
We could define a blanket ordering (e.g. shorthands before longhands). 
Or we could drop shorthands from web animations altogether--say they are 
expanded at a higher level.

AI: Brian to investigate when shorthands are expanded in Gecko.


Next meeting: Thurs July 25 18:00 PDT / Fri 26 July 11:00 AEST / Fri 26 
July 10:00 JST @ https://etherpad.mozilla.org/u6hQRTEyzi

Past meetings: http://www.w3.org/Graphics/fx/wiki/Web_Animations/Meetings

Received on Friday, 19 July 2013 02:45:42 UTC