Platform/GFX/2013-April-2
- Exceptionally Tuesday at 2:30 PM US/Pacific Time, because of Easter
- +1 650 903 0800 x92 Conf# 99366
- +1 416 848 3114 x92 Conf# 99366
- +1 800 707 2533 (pin 369) Conf# 99366 (toll free, Skype)
- Video (Vidyo) link: https://v.mozilla.com/flex.html?roomdirect.html&key=vu1FKlkBlT29
- Vidyo room 9366 (if you have LDAP and can log in at https://v.mozilla.com)
Contents
Urgent Bug Triage
Bugs tracked for upcoming Firefox releases:
Gfx bugs
Including Image, Canvas 2D, and WebGL.
Layout bugs
Media bugs
Agenda
- GDC wrap-up
- Web Animations feedback
- Async pan/zoom work update
- SkiaGL update
- Images and Temporary Surfaces
Web Animations feedback
Editor's Draft: https://dvcs.w3.org/hg/FXTF/raw-file/default/web-anim/index.html
Background:
- Make a common model for animation features on the Web encompassing CSS animations/transitions and SVG animations.
- Synchronization: global clock. Can synchronize animations from CSS/SVG/script.
- Possible to implement using same animation engine—all declarative markup benefits from same optimizations
- Add an API onto the model
- Possible to inspect the state of animations in a page regardless of source (CSS/SVG/script)
- Easy to create animations from script that are accelerated/synchronized/frame-rate independent/etc.
Status: Hoping to ask for permission to publish FPWD in 1~2 months.
Vendor status:
- Mozilla, Google, and Adobe developing spec and polyfill
- Apple support model, concern about API surface area
- Microsoft have made only a few comments, seem supportive?
- Developed in response to previous PM's request for a unified model and an API
- Polyfill may provide some fallback in short-term: https://github.com/web-animations/web-animations-js
Would appreciate Mozilla input, particularly on the following 3 issues
Send feedback to:
- Brian (bbirtles@mozilla.com /
birtles
on IRC), or - public-fx@w3.org, subject [web-anim] ...
Issue 1: Compositing animations together
Background: There are three ways to combine animations that target the same property:
- The one with the highest priority wins (CSS; SVG w/ additive="replace")
- Add them together: lower + higher (SVG w/ additive="sum")
- Interpolate from the "underlying value" (result of lower priority animations) to the destination value (SVG "to-animation"; CSS appears to do this but actually snapshots the underlying value and does (1))
Issue: How do we represent these in the model?
Approach A) Offer three compositing modes: replace (1), add (2), and merge (3)
- Complex. Especially for the very common case of wanting to simply animate "to" a value. You have to set up a merge operation for this or have a constructor that does magic behind the scenes to do it for you.
- Adds new functionality.
Approach B) Offer two compositing modes: replace (1) or add (2)
When you have a keyframes animation with no 0%/100% do (3)
- Simple.
- Similar to CSS with regards to missing keyframes (but subtly different since it doesn't snapshot the underlying value).
- Concern about it being incomplete—you can have "holes" at the ends of the keyframes but not in the middle.
Approach C) Allow each key frame value to specify if it is additive or not
e.g. left: "+0", "50", "+20"
- Most flexible.
- Doesn't help with other types of animations like path animations.
- Difficult to set behavior across-the-board (add a default compositing mode as well?)
- Syntax like the above wouldn't work: extra constructs (e.g.
add('6px')
) would probably be required
Issue 2: Separating play control from animation definition
Background: Timing groups can repeat and sequence their children.
Issue: Adding play control (pause, seeking etc.) to animations and timing groups themselves produces a lot of situations where the resulting behavior is not obvious (what happens if you seek the child of a group that loops? Does the group wait? Is everything back to normal on the next loop?)
Approach A) Put play control on the animations / timing groups themselves
Define how the operations behave when there is a parent timing group (e.g. seeking an animation that is part of a group throws/silently fails)
- Simple
- Similar to HTMLMediaElement / MediaController (when seeking an HTMLMediaElement that has a media controller, it throws an InvalidStateError exception)
- Methods behave differently on animations depending on whether they have a parent group or not
Approach B) (Current spec) Make a separate object for play control (the Player) associated with the root timing group an animation is part of
To pause an animation you do animation.getPlayer().pause()
and it pauses everything in that tree
- Consistent—no exceptions or changing behavior
- More complex
- Makes it obvious that an animation may be part of a more complex arrangement
Issue 3: Representing timing parameters in the API
Background: Timing groups and animations (collectively called timed items) have various timing parameters such as "iteration duration". The iteration duration can take a value like "auto". For things like timing groups that means the duration of the group stretches to fit its children.
Issue: We need a way from the API to represent both the "auto" value and the resolved numeric value. In the future we'll probably also extend durations to include percentages. (We are also trying to make these objects easy to create and keep the API surface area low.)
Approach A) (Current spec) Have a dictionary for specified timing parameters
To change parameters you set the whole thing.
interface TimedItem : EventTarget { // Specified timing TimingDictionary getTiming (); TimingDictionary setTiming (TimingDictionary timing); // Calculated timing readonly attribute double startTime; readonly attribute unrestricted double iterationDuration; readonly attribute unrestricted double activeDuration; readonly attribute unrestricted double endTime; }; interface Animation : TimedItem { ... }; interface TimingGroup : TimedItem { ... }; dictionary TimingDictionary { double startDelay = 0; FillMode fillMode = "forwards"; (unrestricted double or DOMString) iterationDuration = "auto"; (unrestricted double or DOMString) activeDuration = "auto"; double playbackRate = 1.0; ... };
Animations and TimingGroups have a ctor that takes a TimingDictionary.
elem.animate({ left: '100px' }, { iterationDuration: 3, fillMode = "none" });
(There's also a shortcut for just setting the iterationDuration)
Usage:
var specifiedDur = anim.getTiming().iterationDuration; // "auto" var computedDur = anim.iterationDuration; // 5 // Update duration to 3s var timing = anim.getSpecified(); timing.iterationDuration = 3; anim.setTiming(timing); // Reset duration to 'auto' timing.iterationDuration = "auto"; anim.setTiming(timing);
Note that the following clobbers all other properties:
anim.setTiming({ iterationDuration: 3 })
- Re-uses the TimingDictionary definition to keep API surface area small.
- Changing timing parameters can have knock-on effects since it effects the scheduling of other items in the hierarchy and this API makes that more obvious.
- Specified timing and computed timing are separate (I'm not sure if this is helpful or not. It means that in many cases the place where you read parameters differs from where you set them but others in the group find this distinction useful.)
- The fact that
anim.setTiming({ iterationDuration: 3 })
clobbers other parameters is sure to trip people up
Approach B) Introduce an additional Timing interface that is basically a live version of the dictionary used for construction
Usage:
var specifiedDur = anim.specified.iterationDuration; // "auto" var computedDur = anim.iterationDuration; // 5 // Update duration to 3s timing.specified.iterationDuration = 3; // Reset duration to 'auto' timing.specified.iterationDuration = "auto";
- Duplication of parameters: a dictionary version and an interface version → increases API surface area, awkward to maintain / spec
- Specified timing and computed timing are separate (again, not certain if this is helpful or confusing)
Approach C) Combine the specified and computed timing
interface TimedItem : EventTarget { // Timing attribute double startDelay; attribute FillMode fillMode; attribute Duration iterationDuration; attribute Duration activeDuration; attribute double playbackRate; // ... // Scheduled time readonly attribute double startTime; readonly attribute unrestricted double endTime; }; interface Duration { double sec; DOMString string; }
Usage:
var specifiedDur = anim.iterationDuration.string; // "auto" var computedDur = anim.iterationDuration.sec; // 5 // Update duration to 3s anim.iterationDuration.sec = 3; // anim.iterationDuration.string -> "3s" // Update duration to 3s (alt.) anim.iterationDuration.string = "3s"; // anim.iterationDuration.sec -> 3 // Reset to auto anim.iterationDuration.string = "auto"; // anim.iterationDuration.sec -> 5
- Some duplication of parameters between the dictionary and TimedItem
- Mixes specified and computed timing
- Setting and reading duration happens in same place
- Mimicks patterns proposed for CSS Lengths and SVGLength
- Easy to extend this to support percentage measures in the future (which is likely for duration properties)
- Not easy to apply this pattern to other parameters in the future (e.g. if we want to make playbackRate accept a string we'd have to introduce another attribute in order to use the same pattern)