[web-anim] Web Animations minutes, 28 / 29 August 2012

Web Animations minutes, 28 / 29 August 2012

Etherpad: https://etherpad.mozilla.org/ep/pad/view/ro.7clGoF1me6H/latest
Present: Tab Atkins, Dmitry Baranovskiy, Shane Stephens, Brian Birtles

Agenda:

1. Status update
2. Constructors
3. Multiple intervals, reversing etc.
4. Sequence containers and media controllers
5. Pausing outside the animation interval
6. Other issues

1. STATUS UPDATE
================

Brian: fixed some timing stuff, added timing functions, worked on respec 
(Constructors, NamedConstructors, default parameter values, union types)
Shane: Coded emulator Like A Baws. (http://github.com/shans/web-anim-js)

2. CONSTRUCTORS
===============

Issue from two meetings ago: https://etherpad.mozilla.org/IW8zT9yCin, item 7

Proposal:

new Anim(Element? elem, (AnimFunc or object) animFunc, (double or Timing 
or TimingDict) timing, AnimGroup? parentGroup, optional double startTime)

new AnimGroup((double or Timing or TimingDict) timing, AnimGroup? 
parentGroup, optional double startTime);

Changes:
- Split animation from timing
- Put animation first
- Allow specifying duration just by using a double
- Animation: either a AnimFunc object or a property bag of the form { 
attr/prop: value, ... }
- Timing: either (a) a double or (b) a dictionary (TimingDict) where you 
can specify several properties or (c) a shared Timing object

Regarding the anim parameter values, we want to be able to support the 
following:

{ left: '100px' } ➙ KeyframesAnimFunc
{ left: '100px', top: '200px' } ➙ GroupedAnimFunc

And probably also this:
{left: ['0px', '25px', '100px']} ➙ KeyframesAnimFunc

We (might) like to support similar notation in the ctors for the 
specific AnimFunc objects, e.g.

anim.animFunc = new KeyframesAnimFunc('left', ['0px' ... ]);

One possibility is to add a utility function to do this kind of mapping 
that gets implicitly called from the Anim ctor when needed, e.g.:

anim.animFunc = AnimFunc.fromProperties(...);

 > Proposal generally acceptable. Brian to work on speccing.

3. MULTIPLE INTERVALS, REVERSING ETC.
=====================================

Issue from last time: https://etherpad.mozilla.org/IFCnsPoRSr, item 4

Shane would like to try and implement the approach where we have 
animations that don't add to other instances of the same template and 
see how it feels. We’ll reconsider based on that feedback if this is a 
suitable approach.

Discussion on reversing: currently reversing requires breaking the link 
with the template because you need to change the playback rate and fill 
mode. This shouldn't be—i.e. it should be possible to reverse something 
without breaking the link to the template. Either add override playback 
rate and override fill mode to the Anim instance or some special 
reversing flag.

4. SEQUENCE CONTAINERS AND MEDIA CONTROLLERS
============================================

Pausing inside a sequence container is a bit weird. Currently I've 
defined endTime so that, for example, if the item is paused, the endTime 
is infinite. This gives you the behaviour where if you pause one child 
the next one won't start until it is unpaused (since the next child's 
start time is based on the previous child's endTime).

I'm pretty sure that's what you want since once you add media elements 
to the equation if you pause or seek a video, you expect subsequent 
children in the group to react to its new end time.

(For example, pause the video for 2 seconds and the endTime gets 2 
seconds later. Skip forward 3 seconds in the video and the endTime 
becomes 3 seconds earlier.)

But it's weird for a few reasons:

1) If you play a sequence container that contains a paused descendent in 
reverse all you'll see is that first frame of the paused animation. You 
won't get the behaviour where it plays the children in reverse sequence 
and then pauses at the last frame of the paused child.

2) Suppose, while child B is playing, you pause it for 2 seconds then 
resume. If you then seek back to the start of the container you'll get A 
playing, then 2 seconds of nothing, then B playing. (Effectively, by 
pausing the child, you've shifted its time by 2 seconds)

3) It's a little odd that endTime reacts to pausing/seeking but 
startTime does not. Also endTime can come before startTime (due to 
negative delays or seeking forwards).

I think there are a few possibilities here:

A) Add a facility to reset the timeDrift

Basically TimedItem.reset(). It does a seek to time 0 and clears the 
timeDrift and locallyPaused state of all descendants.

This fixes (2) and is something you often want to do.

B) Auto-reset time drift

Basically A, but if you do a seek to a time before the beginning of the 
animation interval you clear the timeDrift automatically.

This kind of matches my intuition of what should happen but it breaks 
the idea that the model is stateless. That's a problem because 
implementations have to be very careful to detect all circumstances when 
the effective time is before the start of an animation interval with 
non-zero timeDrift. It sounds like a real source of interop problems, or 
worse, problems that only crop up in some implementations when the frame 
rate is low (if they just check at sample time).

So I think the explicit call is better.

C) Slave sequence groups' pause state and seek time to their children 
(or actually descendents)

There seem to be a lot of parallels between the way sequence groups and 
media controllers work. You could just defer all pause requests to the 
container. That doesn't let you run child A while child B is paused 
however. Pausing child B would pause the group meaning child A won't run.

Seeking however, could work fairly intuitively. You'd convert the times 
to group time and then apply the seek to the group. The 
counter-intuitive bit is when A is playing and you seek B... you'd skip 
A and start B. You also lose flexibility... you can't shift just one 
child back / forward.

For this to work however, i.e. to solve (2), I think this has to apply 
to all descendents. In effect, any animation with an ascendent sequence 
group is slaved.

D) No seeking a descendent of a sequence group, pausing is slaved to the 
group

That's how HTML5 media controllers work. You can't set currentTime if 
you have a media controller. Pausing is slaved. With play(), if you have 
a media controller you skip the seeking step.

For issue (1) above (the fact that you can't really play a sequence 
group in reverse if it has a paused child) I think you just have to say, 
"that's how the model works". To do otherwise would break down the 
ability to randomly sample the model.

For issue (3) above (the fact that endTime reacts to pauses/seeks but 
startTime doesn't, and also the fact that endTime can come before 
startTime), we could possible rename endTime to animEnd.

Discussed the issue but also with reference to par groups that repeat:

• One proposal was to have a type of par group that cannot be iterated, 
a “loose” group. For all other types of groups, pausing a descendant 
pauses the group (i.e. pausing anywhere pauses everywhere).
  - questions about whether exposing this kind of group is actually 
useful or just confusing. An alternative would be to make the document 
timeline such a “loose” group (in effect) but not allow creating such 
groups elsewhere (i.e. just make it special behaviour defined on the 
timeline).
  - concern that if a group gets added at any point (e.g. a <svg> is 
mapped to a par group) then suddenly you can’t independently pause 
children — this may be reason to have loose groups other than just the 
document timeline
    - question: why would you do that? groups are for synchronising. 
Don't use them unless you want synchronisation.

• Another proposal was to ignore child pause state when scheduling par 
and seq groups. This results in some “weird” behaviour — e.g. sequences 
getting out of order because pausing one item doesn’t result in the next 
item failing to play. Of course you can always pause the sequence…
  - also concern about whether this is fundamentally different to the 
cascading nature of time in the model defined so far (but conversely, 
why should pausing a child modify an explicitly set iterationDuration on 
a parent?)

 > This requires more thought but the "loose" group idea seems to hold 
some promise. Not sure yet if they should be generally available or just 
specified on the top-level (timeline) group.

5. PAUSING OUTSIDE THE ANIMATION INTERVAL
=========================================

A while ago we had a discussion about what happens if you pause a child 
outside its animation interval. The expected behaviour in that case is 
that it has no effect until the animation starts.

For example, I have

anim {
     startTime: 5;
     startDelay: 5;
}

At t=3s, I pause anim.

The expected behaviour we thought was that time continues to tick and 
then at t=10s, the animation starts paused (i.e. the first frame appears 
and doesn't move).

Presumably the same would happen in reverse.

Currently we don't do that. Pausing at t=3s, pauses at t=3s. If you 
unpause it, you still have to wait 7s before the things starts.

Supporting the behaviour where times outside the animation interval 
don't contribute to the pause is possible. I even wrote out the algorithm:

Inside the calculation for timeDrift:

   If locallyPaused is false
      ... as before ...
   If locallyPaused is true
     Let anim start = startTime + timing.startDelay
     If pause start < anim start
       If effective parent time < anim start
         return 0
       Otherwise
         return max(0, effective parent time - anim start)
     Otherwise
        Let anim end = anim start + animDuration + stored value of timeDrift
        If pause start >= anim end
          If effective parent time > anim end
            return stored value of timeDrift
          Otherwise,
            return max(0, anim end - effective parent time)
        Otherwise,
          return effective parent time - startTime - pause start

Anyway, that's just there for posterity, but it introduces complexity 
because if you're paused at t=3s in the previous example, and do a seek 
to t=0s what do you expect?

If we want to make that take effect I think internally we'll need to 
separate out pauseDrift and seekDrift (which basically equates to the 
"stored value of timeDrift" above).

I just want to check if this is really the behaviour we want.

 > After some discussion, we agree that if you pause during the delay 
phase it should take effect. In essence, pause takes effect at the 
earlier of two moments, the start time or the animation interval start. 
This is needed both for CSS compatibility and because in our model the 
delay is part of the animation.

6. ISSUES FOR NEXT TIME
=======================

* How to seek when currentTime is null
    -- Brian and Shane discussed this --- basically divorce currentTime 
from item time. We said currentTime always exists and can be set, but is 
sometimes not live; if it's live then currentTime == itemTime. In a 
sense, currentTime is the item time calculated using the "effective 
parent time" as defined in the spec.

* Specified start times should not update when moving animations between 
containers, but automatically calculated start times should. (However, 
if the start time was specified with the intention of being a relative 
amount from the parent's iteration time then it *should* update). We 
(Shane and Brian) also discussed adding startTime as a parameter to add, 
and always updating startTime.

* Sensible behaviour for changePlaybackRate(0)
    -- If you call changePlaybackRate(0) mid-way through an animation 
you expect it to pause. Currently it does not because a playback rate of 
zero means an infinite duration which means you never get past the 
starting point. You can work around this by adjusting the 
iterationStart, or by just special-casing 0 to make it actually pause, 
or you can just say "that's the model". What do you prefer?

* Integrating with video and audio... is this really going to work?
    -- video and audio need a concept of direction but our timing 
functions etc. mean all bets are off regarding the direction of the next 
sample. And its not just enough to disallow certain timing features on 
the video since these things can happen all the way up the tree. Maybe 
we need some process where we approximate the effect... e.g. walk up the 
tree, ignore timing functions, work out the direction, playbackRate etc. 
and then apply those properties to the video itself (behind the scenes?)

Next meeting: 4 Sep 18:20 PDT / 5 Sep 11:20 AEST / 5 Sep 10:20 JST @ 
https://etherpad.mozilla.org/uDxc2Hwa8n

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

Received on Wednesday, 29 August 2012 03:17:22 UTC