- From: Brian Birtles <bbirtles@mozilla.com>
- Date: Tue, 18 Dec 2012 16:01:00 +0900
- To: "public-fx@w3.org" <public-fx@w3.org>
Web animations minutes, 17 / 18 December 2012
(Bumper Christmas edition)
Etherpad: https://etherpad.mozilla.org/ep/pad/view/ro.McqSq5rhwYm/latest
Present: Dmitry Baranovskiy, Steve Block, Shane Stephens, Douglas
Stockwell, Brian Birtles
Agenda:
1. Status update
2. Keyframe revision
3. Comparing with QML
4. Comparing with Core Animation
5. Feedback from Rob Arnold
6. Null animation function
7. Interaction with script
8. Time sources
9. Fixing Anim.duration vs Anim.timing.duration
10. The chopping block
11. GroupedAnimationEffect
12. Override stylesheets
13. Animation stack & Keyframe animations
14. Default fill mode
1. STATUS UPDATE
================
Brian:
* Writing up events stuff
Shane:
* Travelling, polyfill hacking, talking to interested Googlers about Web
Animations
2. KEYFRAMES REVISION
=====================
(Brian)
I've revised the keyframes interfaces with the following changes:
* Add ctors
* Redone the way we interpret values to the ctor since
sequence<DOMString> and sequence<KeyframesDictionary> are not
distinguishable
* Add a distribute method to space all the keyframes out evenly
This distribute method in particular hopefully makes it easier to
add/remove keyframes whilst keeping them equally spaced.
(I had another proposal here where we allowed null offsets that meant
'space me out evenly' but it was complex so I dropped it.)
Shane: LGTM.
3. COMPARING WITH QML
=====================
(Brian)
ben
(http://brian.sol1.net/svg/2012/10/31/web-animations/comment-page-1/#comment-38011)
suggested we consider QML
http://doc.qt.nokia.com/4.8-snapshot/qdeclarativeelements.html
Some observations:
* Many features are similar, even the parallel and sequence animations
are similar. That's good news.
* SpringAnimation element
-- could be realised with the proposed SmoothTimingFunc and then add
some syntactic sugar to make bouncing animations easier
-- I've asked Pomax (author of
http://processingjs.nihongoresources.com/bezierinfo/) for some help with
SmoothTimingFunc.
* Includes a PauseAnimation -- temporal equivalent of a spacer gif
-- worth adding?
-- Shane: I have an alternative approach that is simpler than a new
primitive (and also useful for the trigger stuff :))
* Terminology
-- They don't have groups. Should we just call ParAnimGroup, ParAnim?
-- Shane: I think distinguishing between groups and root animations
is useful.
* Uses ms (integer) for duration. window.setTimeout etc. use ms as well.
Perhaps ms are more common on the web platform? Should we use ms
instead? And if so, is an integer too imprecise?
Shane: No! Seconds are really easy to use and make code look good.
Brian: some data gathering...
window.setTimeout - long - milliseconds
window.setInterval - long - milliseconds
XMLHttpRequest.timeout - unsigned long - milliseconds
HTMLMediaElement.duration - unrestricted double - seconds
Date.getTime - milliseconds
PerformanceTiming.* - milliseconds
PerformanceNavigationTiming.* - DOMHighResTimeStamp (double) - milliseconds
CSS Animation/TransitionEvent.elapsedTime - float - seconds
➙ Agreed to stick with seconds (double) in particular to line up with
HTMLMediaElement and CSS animation/transition events and also because
longs representing milliseconds do not offer enough precision.
4. COMPARING WITH CORE ANIMATION
================================
(Brian)
I've had a bit of a look over Core Animation to see how similar we are:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html
At a glance it looks like we're pretty close since it's based on SMIL
and CSS Transitions/Animations is based on Core Animation.
Some naming suggestions:
* Core Animation uses beginTime and timeOffset -- it has the same
double-offset!!!! We are not crazy!
* Some renaming possibilities here:
* s/startTime/beginTime/
* startTime: 'start' just seems friendlier, matches HTML5 text
tracks
* beginTime: matches CoreAnimation, close to SVG (begin attr)
* NOTE: HTMLMediaElement has startDate (was
startTimeOffset/startTime/initialTime) which is the initial offset into
the resource
* s/startDelay/beginOffset/
* startDelay: close to CSS (animation-delay)
* beginDelay: relationship to beginTime is obvious (assuming we
go with that), close to CSS (animation-delay)
* beginOffset: relationship to beginTime is obvious (assuming we
go with that), close to Core Animation (timeOffset)
* NOTE: HTMLMediaElement has startDate (was
startTimeOffset/startTime/initialTime) which is the offset into the resource
➙ Agreed to stick with startDelay and startTime
Rationale: delay is a lot clearer than offset. "beginDelay" sounds
silly. Therefore "startDelay". Therefore "startTime".
* Core Animation uses fillMode where we have fill
* fillMode: matches enum name (FillMode), Core Animation (fillMode),
CSS (animation-fill-mode)
* fill: matches SVG, shorter
* 2012-11-30[Brian]: Renamed fill to fillMode
* Core Animation uses timingFunction where we have timingFunc (see
above where I suggest we go with timingFunction)
* 2012-11-29[Brian]: Renamed
* This was discussed informally at the time and included in the
minutes from 2012-12-11.
* Core Animation uses speed where we have playbackRate
* the reason we went with playbackRate was to match
HTMLMediaElement. I think that wins.
* Our Timing object is represented in CoreAnimation by a MediaTiming
interface
➙ Some general sense that an interface may be preferable here. Will
consider when we discuss how to refactor defaults and so on.
* Core Animation uses parent time, active local time (=our item time),
basic local time (=our iteration time)
* There's no animation time but even in our model, animation time is
really an implementation detail. In terms of the API it's irrelevant.
Maybe we should try to hide it a bit more. The time spaces diagram
appears quite complicated.
* Should we rename?
* iteration time -> basic time (SMIL calls this simple time)
* item time -> active time (SMIL calls this active time)
➙ Iteration time is more descriptive than basic time
Item time is not great. It's also quite similar to iteration time. How
about local time?
➙ We'll give local time a try
Shane, Steve: If we have a time window then we could have
timeWindow.activeTime instead of animation time
➙ Rename animation interval to active interval.
5. FEEDBACK FROM ROB ARNOLD
===========================
(Brian)
“I think it would be helpful to have examples to use examples for
individual features (ex: seeking; I haven’t seen a need for that yet)
and indicate what areas the API is intended to be used for (games, rich
content, ui?)”
➙ Yes. We should put this in a different document (a primer). We will
also increase the number of examples in the specification, but these
will be for the purpose of illuminating how the specification works
rather than justifying the decisions made in the specification.
“I am sadly quite well aware that CSSOM for Transitions/Animations is
painful so having a good API there which addresses mutation (O(n²) to
remove all keyframes of an animation in WebKit) and triggering (no
awkward forced synchronous style calc) would be helpful.”
This ties into Shane's desire to expose web animations objects as
CSS/SVG manipulators.
"One thing that I do think is important but not addressed in the spec is
concurrency (I assume that this is what you meant by hardware
accelerated animations). In particular, asynchronous animations are
highly useful in covering up main thread lag due to events or
implementations beyond the author's control. This is key on mobile where
performance expectations are high due to a direct manipulation UI but
processing power is weak. As a motivating example, consider trying to
implement a feed of mixed content (say, Facebook's newsfeed) with native
quality scrolling. Things like garbage collection, image decoding,
style/layout from new content being inserted and time mysteriously
unaccounted for (thanks Chrome!) disrupt the framerate
during/transitioning into fling scrolling (which can use CSS animations
for better physics / dependable scroll position events). The current and
proposed APIs seem to assume some sort of synchronous execution between
the JS and on screen animation; for this reason I like asynchronous
events so that the animation thread isn't stalled by content."
* I (Brian) followed this up and Rob provided the following
clarification: "I think there are some implicit assumptions in the API
such as the relation between the start of an animation and when you tell
it to start; with asynchronous animations, you'll need to account for a
delay (due to vsync, IPC overhead, etc...) and the page may want to take
that into account when computing its UI."
Some discussion on synchronicity of events and the possible use of
observers.
> Brian to continue speccing events without observers.
> Shane to show events model (once specced) to observers guys and see
what they think.
This could also be about the delay between calling start() and when the
animation first updates. This would cause a jump.
We might add a feature in a future version for“start this animation asap
but whatever you do, start from the beginning”
→ startASAP()?
→ base it off a trigger?
“I do like that you can compute the animation in JS with your own
internal structure and then have the browser query that instead of
shoving it into the CSSOM (creating a lot of garbage via string
allocation).”
* I asked, “I just want to check I've understood this part. Are you
referring to CustomAnimFunc? If that's the case, then the user-supplied
function just applies the effect itself. It doesn't return anything to
the browser.”
* To which Rob responded: “Oh, I thought that it was to allow JS to
specify the animation curve so that the browser can asynchronously
render it. This is an example of where I mean that the spec does not
seem to permit an asynchronous (multithreaded) implementation.”
Perhaps Rob simply was referring to the fact that you can build up an
animation entirely from script without going through the CSSOM.
“Oh, and if we could get instrumentation on how well the animation was
played back (frame level timing would be sufficient) then that would
really help our testing I suspect.”
* Rob later helped with some ideas about how to get this data when
animations are offloaded to the GPU, “I suspect that it's not too tricky
to get the data; exposing it to script may be hard. There is a GL
extension (even available on some mobile devices) called GL_timer_query
which lets you time the GPU pipeline. DirectX has had a similar API for
a while.”
➙ Maybe a future version but some concern about all vendors being
willing to expose this information
6. NULL ANIMATION FUNCTION
==========================
(Brian)
Does it make sense to allow Animation.animationFunction to be null-able?
The reason this comes up is that if you call
new Animation(elem, { '-moz-transform': 'translate(-60)' });
This calls
AnimationFunction.createFromProperties({'moz-transform':
'translate(-60)'});
On a UA that doesn't support '-moz-transform' the algorithm there will
mean createFromProperties returns null. I think this is correct
behaviour and there's an example in the spec of where the null behaviour
can be useful.
But then, what is 'new Animation' supposed to do?
a) Just set animationFunction to null?
b) Throw an exception saying its bad input?
c) Make some sort of generic function to fill in its place?
I don't think (c) is really great since I can't think of a suitable
function for that unless you make a KeyframesAnimationFunction with a
blank property and no frames?
(b) warns you about the error but it will commonly mean that for a given
browser that the author hasn't tested the content with that doesn't
support said property, everything grinds to a halt. Whereas with (a) it
continues, it just does nothing.
The downside of (a) is that there's no visible warning and every time
you access Animation.animationFunction you need to check if it's null or
not. That said, Animation.animationFunction is already of type
(AnimationFunction or CustomAnimationFunction) so you probably should be
checking the type there anyway.
So my vote is (a) unless someone can suggest a good function for (c).
Note that making an animation function with '-moz-transform' as the
property EVEN on UAs that don't support it isn't an option due to the
way we process that property bag in order to avoid indeterminancy (it's
complicated).
Shane: I'm totally down with (a). It's the minimum specification effort
approach :-D
7. INTERACTION WITH SCRIPT
==========================
(Brian)
I think we need to clearly specify three things regarding liveness and
scripting:
* If I change any of the values (e.g. the duration), do all the other
timing values immediately update? (e.g. end time)
Brian: suggest yes
Shane: polyfill does
* Does the target property(ies) update? e.g. does the computed style
of the height I'm animating instantly update? (i.e. do we do a
synchronous sample in effect) or does it lazily update? (i.e. if I query
it I'll get the updated value but I won't see any change in rendering
otherwise)
Brian: suggest no update until current script block completes
Shane: "until the script block finishes". This is good enough.
* In a given script block is it possible for a clock tick to occur?
(i.e. can the value I get back for the currentTime of the global clock
at the start of a script execution block differ from the one I get back
at the end of the script execution block)
Brian: suggest no
Shane: there's a specific hack in the polyfill to implement no here :-)
Shane: ... so I think this is all LGTM.
8. TIME SOURCES
===============
Awaiting Shane's description of Timeline → Time source transformations
Shane: Sorry, still no progress here :(
9. FIXING Anim.duration VS Anim.timing.duration
===============================================
(Brian)
Long discussion based largely on the fact that we have the following
arrangement:
* Anim.duration -- read-only, calculated iteration duration
* Anim.timing.duration -- read/write, nullable, specified iteration
duration
This is not great. Full notes of proposals are available on the
etherpad: https://etherpad.mozilla.org/ep/pad/view/ro.McqSq5rhwYm/latest
In summary they include:
* Renaming Anim.timing to Anim.defaults
* Pushing the timing members into Anim, e.g. Anim.defaultDuration (cf
HTMLMediaElement's defaultPlaybackRate)
* Dropping defaults and putting everything on TimedItem. Values
initially reflect computed values unless they are overridden.
* Make attributes represent live/calculated values. Add accessor methods
for fetching or resetting to default/specified values.
This discussion has led to the notion of having a "default" set of
values and a "live" set similar to CSS' specified and computed style.
This allows an animation to be reversed without affecting the
animation's serialized state. The approach used here can likely be
re-used for templating and has led to a "time window" proposal where the
default values establish the "box" into which the animation is played
and changes to the live values do not effect it.
Related only vaguely, the idea was also floated about separating out
interfaces. For example, TimedItem simply represents an item in the time
graph with a start and end time, whilst subsequent interfaces add time
transformations and so on. This approach attempts to reduce the
complexity of TimedItem using inheritance instead of composition.
> Brian to come up with a different proposal
10. THE CHOPPING BLOCK
======================
(Brian)
What can we drop from v1 to make things simpler and faster to ship?
My (Brian's) suggestions:
* Templates
* Lots of complexity here. I think if we make animations easily
cloneable and add convenience methods that take a DOMNodeList/sequence
and generate the necessary animations we'd get 80% of the convenience.
For controlling multiple running animations we have groups that cover
some of the cases.
* The main argument for keeping templates that I can see is because
implementations are going to have to implement something like templates
anyway in order to manage changes to animations generated by markup so
why not formalise this behaviour from the start?
* Shane: I have some feedback from web developers too - the
"immediate" effect of Animation objects is strange to them but the
ability to create Templated animations ameliorates this significantly.
* Brian: Is this about animations playing as soon as you create them?
Doug, Steve and Shane had a bit of a discussion on what to do with
templates:
https://docs.google.com/document/d/1JYHXUJy-vaaw6C_zAh1vDpuQUVczegu6UZNeZ6U0z5s/edit
Brian: Looks good. I think we need to work out how defaults should work
first, then consider how template-like behaviour would fit in.
* Merging
* It's great but I'm not sure if it's necessary for currently
pressing use cases. We should still work on it to make sure when we do
go to add it the architecture doesn't explode.
* Shane: We've agreed it's necessary to make "to" animations clean.
I'm still in favor of including it because it doesn't add very much
complexity at all, and the merge behavior still needs to be specified
regardless.
➙ Shane to add diagrams.
➙ Need to talk about grouping and parameterized merge in more detail in
a future meeting.
* Sharing of Timing objects
* Really, how often will this be done?
* Shane: if we don't allow timing objects to be shared, then *that*
is when we have to start specifying stuff. They share naturally.
* Brian: In section 9 I'm proposing removing them for other reasons.
* Shane: There *will be* an object or objects with default values
that are accessible from script. It is more natural to allow these to be
shared than not. Having said that, the templating stuff that we were
looking at before might in fact imply these should not be sharable anyway.
* TimingFuncCallback
* This adds a lot of complexity (just see the massive TODO there)
and if we have SmoothTimingFunc then I think we can cover most cases.
* 2012-11-29[Brian]: I already removed this feature
* Shane: I support this
* TimedItem.animDuration
* Easy to calculate, but necessary?
* Shane: probably not. Also tiny. Defer removal unless we have to?
* TimedItem.locallyPaused
* Again, simple, but necessary? Would pause(), play() and unpause()
be enough? (We currently don't have unpause but MediaControllers do. The
difference is basically that it wouldn't auto-rewind.)
* Shane: this falls out *SO CLEANLY* in code! I'd be reluctant to
remove.
* Brian: It doesn't mean you remove the code, just that you hide
it from view.
* Maybe mark at risk?
11. GroupedAnimationEffect
==========================
(Brian)
Genuine question, is it needed or should it be merged with
KeyframeAnimationEffect?
What is it used for that couldn't be achieved by making
KeyframeAnimationEffect support targetting multiple properties like you
can do in CSS?
Of course, you could re-use timing to apply to a PathAnimationEffect and
KeyframeAnimationEffect, but do you do that often enough that you
couldn't just set up a group for that?
I guess doing so would be contingent on being able to represent that
arrangement in SVG? Or maybe not since changes to Animations don't
reflect back to SVG.
Shane: I'm not fussed either way. We do have a request to support a
group constructor that has keyframe offset as the primary key (rather
than property) - it would be natural to put this on a group; but less so
on a keyframes object directly I think.
Shane: Also it's important to keep in mind that groups were initially
included for the purpose of grouping operations inside the compositor.
I've got some proposals that would stop this from happening - we should
at least review those before committing to removing groups.
Also, I'd like to make KeyframeAnimationEffect a bit more friendly to
use by allowing operations such as:
effect.frames.add(0.3, 'left', '100px');
// Overwrites the frame at 0.3 if there is one
Currently, you need to do:
effect.frames.add({ property: 'left', offset: 0.3, value: '100px' });
It might even be worth supporting:
var frame = effect.frames['0.3'];
Returns the last frame with offset 0.3 if there is one. If there is
none, does the interpolation and returns a new frame?
Shane: Is this sort of thing something we should defer until v2? It
would sit cleanly on top of a more primitive API (and could be
polyfilled very nicely in the short term).
> Leave this for now (but make an annotation that these may be possible
future improvements)
12. OVERRIDE STYLESHEETS
========================
How are we going here? What was the issue even?
Shane: The issue is that Animations and Transitions in CSS inject into
different places in the stylesheet stack. It doesn't actually matter too
much though - time sources basically make this problem go away because
we can have a time source per injection point.
> We're looking good at the moment
13. ANIMATION STACK & KEYFRAME ANIMATIONS
=========================================
(Continuing actions from a previous meeting regarding merging and
behaviour where no keyframe is defined)
what should [{offset: 0.5, left: 100px}] do?
( polyfill currently does this: [{offset: 0, left: 0px}, {offset: 0.5,
left: 100px}, {offset: 1, left: 0px}] )
( CSS animations snapshot document state and fill in missing values with
that )
> We will revisit this later
14. DEFAULT FILL MODE
=====================
Feedback suggests "both" instead of "forward"
> Mark as an issue in the spec
Next meeting: Mon Dec 7, 17:30 PST / Tues 8 Jan 12:30 AEDST / Tues 8 Jan
10:30 JST @ https://etherpad.mozilla.org/6dtzemgWAe
Past meetings: http://www.w3.org/Graphics/fx/wiki/Web_Animations/Meetings
Received on Tuesday, 18 December 2012 07:10:04 UTC