- From: Brian Birtles <bbirtles@mozilla.com>
- Date: Tue, 21 Oct 2014 15:50:46 +0900
- To: "public-fx@w3.org" <public-fx@w3.org>
Hi, I've been trying to spec the behavior when setting the start time of animation player but I've come across some questions like: * What happens if you set the start time while paused? * Should you be able to set the start time while idle if the current time is already set? * Should you be able to set the start time to null? * What about the current time? etc. etc. I think these questions are easier to answer if we work out the invariants of the model and what these properties mean. I had a go at doing that and, along the way, I noticed that we don't really need the pause flag. Here's what I came up with: Invariants / meaning of properties: 1. No current time means we're not applying any effect. This is the idle state. (The exception is that, at the API level, it can also mean "pause-pending" due to the weird behavior we discussed last time[1] that I'm still not crazy about.) 2. No start time means we're not playing. If we have no start time but we DO have a current time, then we're paused in some sense of the word. Either "pause-pending", "play-pending", or actually paused. (Actually, I think it would be more consistent if we preserved the start time while "pause-pending".) 3. Without an active timeline, you can only have EITHER a start time or a current time. (The start time and current time are tied together by the timeline time, so if there's no timeline time you can only set one side of the equation.) 4. If you have an active timeline and a resolved start time, the current time MUST be resolved. The key point is 2. I think we can actually represent pausing by an unresolved start time. This simplifies the model and helps answer some of the tricky questions that arise about start times. In particular I think it would look something like this: Q. What happens if you set the start time while paused? A. Since pausing is represented by an unresolved start time (2), setting the start time to a resolved value plays the animation. (In fact, 'play()' is just a way of resolving the start time that does a few extra steps like waiting until the UA is ready.) Q. What happens if you set the start time to null while running? A. Since pausing is represented by an unresolved start time (2), setting the start time to null pauses the animation. (Again, 'pause()' is just a nice way of doing this. In fact, setting the start time to null directly actually allows authors to opt-out of the "wait to sync up with the compositor" behavior with the caveat that they may see the animation jump backwards.) Q. What happens if you set the start time when you don't have an active timeline? A. If gets set but no effect will be applied until the timeline becomes active. This allows scheduling animations before the animation starts. For example, a timeline that is inactive until some event happens should start playing the animations after that point at their scheduled times. HOWEVER, based on (3) above, doing so would clear any current time that was set. Likewise, if you set the current time after that, the start time would be cleared. Q. What happens if you call play() when you don't have an active timeline? A. The player sits in the play-pending state until the timeline becomes active. Comparing these two behaviors when the timeline is inactive: (i) Setting the start time -> animation is scheduled. Current time is unresolved, no effect is applied, start time is resolved. When the timeline becomes active the animation plays at its scheduled time. (This may cause a sudden change.) (ii) Calling play() -> animation is pending. Current time is resolved, effect is applied, start time is unresolved. When the timeline becomes active the animation plays from its current time. Q. What about setting the current time to null (i.e. unresolved)? A. Based on (4) above, this is not allowed when you have an active timeline. So the options are: (i) throw always (ii) throw only when there is an active timeline and resolved start time (iii) allow it and also make start time unresolved (this is basically what cancelling does) (iv) allow it and let the usual behavior take place if the animation is running we'll recalculate the current time meaning the change will be ignored if the animation is paused we'll end up in the idle state if the animation is idle we'll stay in the idle state if the animation is play-pending we'll just clear the animation effect until it starts playing if the animation is pause-pending we'll end up in the idle state (I think (iv) is somehow more correct but (i) is probably ok in the short term. It's easier to drop the exception later.) Apart from the above (mostly edge) cases, this doesn't represent a significant change to the observed behavior. I made a start on writing up these changes here: https://github.com/w3c/web-animations/compare/startTimeFixes On a slightly related note, with regards to changing timelines I think the following behavior makes sense: * active timeline -> active timeline: preserve current time, update start time (This allows, e.g., driving an animation with a scroll-driven timeline / video-synced timeline and then subbing in the document timeline when the scroll-action / video playback finishes to let the animation run to completion.) * active timeline -> inactive/no timeline: preserve current time, make start time unresolved (The current time is usually much more important that the start time. If the inactive timeline becomes active, the animation will pick up where it left off.) * inactive/no timeline -> active/inactive/no timeline: we could preserve which ever was already set: current time / start time but I think it may actually be more consistent to only preserve the current time, if set, and treat start times as bound to a particular timeline. If anyone has any suggestions let me know. Best regards, Brian [1] http://lists.w3.org/Archives/Public/public-fx/2014OctDec/0009.html
Received on Tuesday, 21 October 2014 06:51:13 UTC