[web-anim] Web animations minutes, 12 February 2013

Web animations minutes, 12 February 2013

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

Agenda:
1. Play control re-revisited


1. PLAY CONTROL
===============

Two categories of issues remain:
① the four clock issues
② getCurrentAnimations — what does it return?

As for ①:

1. What should we call the clock?

Options:
--------

Brian & Dmitry like Clocks, but:
   - Shane doesn’t like clock.reverse()
   - Steve doesn’t like the confusion between ‘Clock’ and ‘TimeSource’
   - Doug notes that the timing of Clock isn’t provided by the Clock.

Shane's preferred option:
IDL interface is called PlayController. Referenced from a TimedItem via 
timedItem.controller.
   - Dmitry thinks this is too much typing
   - Brian thinks ‘controller’ is too generic

Other considerations
type: Player, timedItem.player.
Matches DVD Player quite well.
Seems to be a reasonable level of acceptance of this, but maybe not just 
‘Player’.

We need a name for the tree thing which is played by the Player.

Suggestions so far: Bundle, Set, Timeline, Timegraph, Assembly, 
Storyboard, Script, Story, Composition, Agglomerate, Bunch, 
Conglomerate, Commune, Coop, Cartel, Family, Scene, Stage

We’ll use Scene as a placeholder for now. That gives us ScenePlayer as 
the interface name for the item formerly known as Clock/PlayController.

2. How should we get ①?

Options are getScenePlayer / getPlayer, or attach / start / insert. 
Semantically, attach creates the ScenePlayer whereas with the getPlayer 
approach the ScenePlayer is created when the TimedItem is.

Advantages of creating-up-front
   • player is never undefined
   • It’s clear what happens when getPlayer is called on a child (you 
get the root player)

Advantages of creating-on-demand
   • don’t need an extra start-time state. In-play === ScenePlayer exists.
   • separates building up of the scene from playback control
   • Avoids need for proxy players (although could avoid this in other ways)

Proxy pattern may be confusing.

What do most authors expect in the following situation:

   var player = anim.getPlayer();
   document.createParGroup([anim]);
   console.log(player.currentTime);

Suggestion that it may be more intuitive to have getPlayer() just return 
the actual ScenePlayer and not a proxy.

Approach 1:
-----------

var anim = document.createAnimation(...);
anim.getPlayer(); // Returns a ScenePlayer(Proxy)
anim.getPlayer().currentTime; // null
anim.getPlayer().startTime; // null, read-only
anim.getPlayer().start(); // Sets startTime to the current time of the 
time source (clears time drift)
anim.getPlayer().startAt(4); // Sets startTime to 4 (and clears time drift)
anim.getPlayer().startTime == 4
anim.getPlayer().stop(); // Clears the startTime (sets to null)

Player:
   startTime;
   currentTime;
   timeDrift; // Might drop this
   paused;
   play();
   pause();
   start();
   stop();

Approach 2:
-----------

var anim = document.createAnimation(...);
anim.getPlayer(); // Returns null
anim.attach(4); // Returns ScenePlayer?
anim.getPlayer().currentTime; // 0
anim.getPlayer().startTime; // 4

How do you seek before attaching?
could at least do anim.attach().pause().currentTime = 4;
or say, “too bad”

Compromise proposal: Approach 2 s/attach/start/g

var anim = document.createAnimation(...);
anim.getPlayer(); // is null
anim.start(); // returns a ScenePlayer, starts the animation NOW
var p = anim.getPlayer();
anim.stop(); // deletes the ScenePlayer. Animation ceases to have any effect
p.pause(); // What does this do? throw AreYouStupidException

Starting at t=4s:
   anim.start().startTime = 4;
   alternatively: anim.startAt(4);

Starting in 2s:
   anim.start().startTime += 2 // This ++
alternatively
• anim.startAt(document.timeline.currentTime + 2); </struckthrough>
• anim.start().startTime = document.timeline.currentTime + 2

We could leave out startAt for now, and add it later

Start on a child:
• starts just that child, removes from parent, parent relayout
• throws an exception
• nothing
• clones and starts child
Probably the first option here is more obvious, i.e. reparenting

Stop on a child:
• stops just that child, removes from parent, parent relayout
• throws an exception
• nothing
• clones and starts child
Again, probably the first option — reparenting

Is getPlayer() a proxy or real player:
   var player = anim.getPlayer();
   ... (eg. stop())
   player... // can throw null pointer exception - it's not always a proxy
Probably should return the real player since it can sometimes be null. 
If it were a proxy, it should never be null.

Lonely player (player with no TimedItem):
   var p = anim.start();
   document.createParGroup([anim]);
   p.pause(); // Does what?
   p.currentTime; // Returns what?
Plays as normal but without observable effects

Calling start twice:
   var p1 = anim.start();
   var p2 = anim.start();
   • do nothing: p1 === p2
   • restart: p1 !== p2
Restarting is more consistent with the behaviour when calling child.start();

Start seeked by 4 seconds
   • anim.start().startTime -=4
   [ In this case currentTime will be 4 and timeDrift will be 0 ]
   • anim.start().currentTime = 4
   [ In this case startTime will not change, but timeDrift will be 4 ]
   • new ParGroup([anim], { startDelay: -4 }).start();
   [ In this case the first 4 seconds of the scene will be clipped ]

Approach 3:
-----------

Both startTime and currentTime are writable. currentTime is 
automagically updated in response to startTime, but not the other way 
around.

var a = document.createScenePlayer()
a.startTime == ?
a.play(foo);
a.play(bar); // foo will be stopped.
a.pause()
a.unpause() / resume()

var a = document.createScenePlayer(foo)
a.play()

• a.play(null);
• a.timedItem = null; // Should be mutable if exposed, but no need to expose
• a.cancel() ← THIS ONE
• a.destroy()

Starting now:
   var a = document.createScenePlayer();
   // a.startTime = null
   // a.currentTime = null
   a.play(foo);
   // a.startTime = document.timeline.currentTime
   // a.currentTime = 0
   if play returns the player:
   var a = document.createScenePlayer().play(foo);

Starting at t=4s:
   var a = document.createScenePlayer();
   a.play(foo);
   a.startTime = 4;

Starting in 2s:
   var a = document.createScenePlayer();
   a.play(foo);
   a.startTime += 2;

Play on a child:
   • plays just that child, removes from parent, parent relayout

Is getPlayer() a proxy or real player:
   as in approach 2, getPlayer can return null, proxy won't work

A lonely player:
   a.cancel();
   // a.startTime = null
   // a.currentTime = null
   // <previously-played-scene>.getPlayer() = null
   • currentTime and startTime are null. Can always reuse by calling 
play(..) again.

Calling play on a player twice:
i.e. player.play(player.timedItem) [Note that we might not expose timeditem]
with the same timed item - restarts the scene (startTime = now, 
currentTime = 0)
equivalant player.startTime = now();  // player.currentTime is updated 
in response

Start seeked by 4 seconds:
• document.createScenePlayer().play(new ParGroup([anim], { startDelay: 
-4 }))
• document.createScenePlayer().play(foo).currentTime = 4
• document.createScenePlayer().play(foo).startTime -= 4

Calling play with a toplevel item that is already playing
• plays the item, makes old player lonely (this is called the 
‘nostalgia’ operation)

Pausing:
   player.pause();

Unpausing:
   player.unpause();

Cancelling:
   player.cancel(); (startTime = null, currentTime = null, 
timedItem.getPlayer() = null)

Initial comparison between approach 2 and approach 3 for simply creating 
an animation and starting it:

Approach 2:
   var anim = document.createAnimation(...);
   anim.start();

Approach 3:
   var anim = new Animation(...);
   var player = document.createScenePlayer();
   player.play(anim);

Main weakness with approach 2 is the behaviour of start() on children
Main weakness with approach 3 is the verbosity?

Suggestions to make 3 nicer:
• s/createScenePlayer/createPlayer/
• Allow createPlayer() to take anim as an arg and automatically play it? 
Or just chain the function calls?

That gives:

   var anim = new Animation(...);
   var player = document.createPlayer().play(anim);
   -or-
   var player = document.createPlayer(anim);  // ctor with side-effects?

What about:
   var player = document.play(timedItem);
As a short-cut for document.createPlayer().play(anim) ?

Or:
   var player = document.timeline.play(timedItem);   ?


For tomorrow:
* What do we do with document.getCurrentAnimations()?

Next meeting: Wed 13 Feb 9:00 AEDST @ Google Sydney

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

Received on Tuesday, 12 February 2013 06:17:14 UTC