- 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