Web Animations/Meetings/Tokyo F2F Day 2

From Effects Task Force

2012-03-29, Mozilla Japan, Tokyo

Present

  • Shane Stephens
  • Rik Cabanier
  • Alex Danilo
  • Brian Birtles

Minutes

(This is just a snapshot of the etherpad.)

Day 2, Web Animations Tokyo F2F 29 March 2012
Topic: Review of Day 1
Day 1: http://openetherpad.org/H6VDOWrtnp
There are two things with the element syntax:
(1) how do we map this onto SVG? <- we know this is going into a technical note
(2) what is the generic element syntax? <- where does this go?
We're going to put it into a seperate specification for now, and possibly merge it back into the main WA spec later.
---
Having sequence, parallel and synched as elements would imply that we would need three IDL classes in the API too. Doing this purely for the purpose of preventing type attribute flipping seems like overkill.
---
One use case to consider is the following:
* There are a series of button-like groups in the DOM. They have a structure like:
<g>
  <rect>
  <text>
</g>
* The structure sometimes varies, e.g. it is a <circle> instead of a <rect>. The content of <text> also changes.
* We want to define a complex animation to be applied to these groups.
* The animation is so complex it cannot be represented using the simple time container primitives defined so far for CSS.
* Some animations will target the <rect>/<circle>, others the text etc.
* There are a number of these complex animations we want to substitute in and out.
YUK!
<g>
  <rect id="rect">
  <text id="text>
  <seq>
    <animate href="#rect">
    <par>
      <animate href="#rect">
      <animate href="#text">
    </par>
  </seq>
</g>
<g>
  <rect id="rect2">
  <text id="text2>
  <seq>
    <animate href="#rect2">
    <par>
      <animate href="#rect2">
      <animate href="#text2">
    </par>
  </seq>
</g>
(5 id fixups needed)
One attempt - use templating to fix up the rampant idrefs
g rect {
    animation-name: anim1, anim2;
    animation-group: attrib(name1), attrib(name2);
}
g text {
    animation-name: anim3;
    animation-group: attrib(name2);
}
<template elementName='button'>  //Deprecated sXBL
  <definition>
    <g>
        <content>
        <seq>
            <par>
        </seq>
    </g>
  </definition>
  <handlerGroup>
    <handler event="postbind">
       var name = evt.target.getAttribute("name");
       var content  = evt.target.shadowRoot.firstChild;
       var rect = content.firstChild;
       var text = rect.nextSibling;
       var seq = content.nextSibling;
       var par = seq.firstChild;
       rect.setAttribute('name1', name+1);
       rect.setAttribute('name2', name+2);
       text.setAttribute('name2', name+2);
       seq.setAttribute('id', name+1);
       par.setAttribute('id', name+2);
    </handler>
  </handlerGroup>
</template>
<button name="foo">
    <rect>
    <text>
</button>
<button name="bar">
    <rect>
    <text>
</button>
(nasty template script needed, but pretty nice apart from that)
<div class="button" shadowTemplate="button">
Another attempt - copying the HTML and using CSS as much as possible to minimise idrefs
g rect {
    animation-name: anim1, anim2;
    animation-group: attrib(name1), attrib(name2);
}
g text {
    animation-name: anim3;
    animation-group: attrib(name2);
}
<g>
  <rect name1="seq1" name2="par1">
  <text name2="par1">
  <seq id="seq1">
    <par id="par1">
  </seq>
</g>
<g>
  <rect name1="seq2" name2="par2">
  <text name2="par2">
  <seq id="seq2">
    <par id="par2">
  </seq>
</g>
(this doesn't really work because you still need to do 5 id fixups)
What I suspect we really should do - embed timelining into CSS 
g rect {
    animation-name: anim1, anim2;
    animation-timeline: animTimeline;
    animation-group: group1;
}
g text {
    animation-name: anim3;
    animation-timeline: animTimeline;
    animation-group: group2;
}
@animationTimeline animTimeline {
    @animationGroup {
        type: sequence;
        name: group1;
        @animationGroup {
            type: synched;
            name: group2;
        }
    }
}
<g>
  <rect>
  <text>
</g>
<g>
  <rect>
  <text>
</g>
(very likely to get pushback from CSSWG about this)
Another possible approach:
* As already decided, we switch to the element syntax to represent the complex animations.
* The <animate> elements can take a select attribute to target elements. The selector is scoped where the group is instantiated.
e.g.
.a:hover {
  animation-name: swirly-thing;
}
<g class="a"> ... </g>
Somewhere else:
<timeline id="swirly-thing">
 <seq>
  <animate select=":first-child" attributeName="width" ... />
  <par>
    <animate select="text" />
    <animate select="..." />
  </par>
 </seq>
</timeline>
* When the .a:hover selector matches, new AnimationGroups are created according to the template (the parent group of the root animation group will be the animation group where it is instantiated).
* New Animator objects are also created which keep a reference to the AnimationGroup which their generated Animations will belong to (we already have this behaviour elsewhere such as for the Animators created from  SVG's <animate> elements).
* The Animators resolve their selectors and create Animation objects accordingly, belonging to the appropriate groups.
* When these animation definitions need to be combined with other time containers in the document there are a number of possibilities available (limited only by what we have exposed to CSS):
e.g.
.a:hover {
  animation-name: swirling-thing;
  mediagroup: attr(group);
}
or
.a:hover {
  animation-name: a, swirly-thing, c;
  animation-sequence: attr(sequence);
}
or
<g class="a" mediagroup="video">
<video mediagroup="video">
(Nothing else in browsers has this kind of templatey behaviour for DOM elements)
<g class="a"> ... </g>
Somewhere else:
<timeline>
  <seq id="swirly-thing-seq">
    <par id="swirly-thing-par">
    </par>
  </seq>
</timeline>
<seq id="bob">
</seq>
.b {
    animation-group: bob;
}
.a:hover {
    animation-timeline: attrib(name);
}
.a:hover:first-child {
    animation-name: anim1, anim2;
    animation-group: swirly-thing-seq, swirly-thing-par;
}
@keyframes anim1 {
    ...
}
@keyframes anim2 {
    ...
}
.a:hover text {
    animation-name: anim3;
    animation-group: swirly-thing-par;
}
Where we ended up:
CSS Keyframes are animation definitions. When a CSS rule selects a keyframes definition via an animation-name: property, then an Animator is minted from the definition.
SVG or HTML <par> <seq> or <synched> element trees are also animation definitions. When they are referenced by another element, an AnimatorGroup is minted from the definition.
1) Both Animations and AnimationGroups reference their parent AnimationGroup.
2) There is a top-level AnimationGroup which is a <par>-derived group and does not have a container.
3) We want to extend the animation-name: property so that it can reference both Animators and AnimatorGroups.
<seq> <-- AnimatorGroup
    <par> <-- AnimatorGroup (contains ref to <seq>, when it generates an AnimationGroup it is a child of the <seq>'s AnimationGroup)
       <animate>  <-- Animator (contains ref to <par>, when it generates Animation objects they are children of the <par>'s AnimationGroup)
    </par>
    <animate> <-- Animator
</seq>
What are we specifying?
* an API for generating AnimatorGroup and Animator objects. 
* how AnimatorGroup and Animator objects can be used to generate AnimationGroup and Animation objects.
*?? that Animations are MediaElements
*?? that AnimationGroups are MediaControllers
*?? mediagroup applies to <animate>, <par> etc. too???
What are we recommending?
* that SVG <animate> elements be/generate Animator objects.
* that CSS @keyframe rules be/generate Animator objects.
* that <sequence>, <parallel> and <synched> tags (or something somewhat similar) are added to the SVG specification, and that these elements be/generate AnimatorGroup objects.
*?? <- DEPENDENT ON SOUNDING OUT HIXIE that <sequence>, etc. and <animate> be added to the HTML5 specification as well, wit the same behaviours
* that the CSS animation-name: property be able to reference Animators and AnimatorGroup objects generated by SVG or HTML elements as well as @keyframe rules.
What are we going to note down as a possibility for the future?
* that we can slightly extends CSS in a couple of different ways in order to enable the specification of simple AnimatorGroups in CSS directly.
  -- one possibility for this is functional notation, e.g. animation-name: a, b, seq(c, par(d, e))
    -- the outer container is an implicit par
    -- one advantage of this is it more closely parallels what you do in element syntax (and its easy to switch between the two)
    -- it also should be self-evident when you've pushed CSS too far and need to go to element syntax (because you'll get too many brackets)
  -- another possibliity is a separate property, e.g. animation-sequence: par or animation-sequence: seq
  
What do we still need to resolve
* VIDEO and synchronization with.
Topic: Synchronising script and animation aka making things happen at the same time
Reference: http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/f023c8b65f010210?pli=1
-- Synchronization --
<!DOCTYPE html>
<style>
div:hover {
  color: red;
}
</style>
<div>Some text is here</div>
<script>
var div = document.querySelector("div");
for (var i = 0; i < 10000; i++) {
  setTimeout(function() {console.log(window.getComputedStyle(div)["color"]);}, 0);
}
</script>
Requirements for dispatch of animation events:
* Animations triggered by an event handler appear to have started at the time the event was scheduled to be triggered.
* no effect of an animation for any time 't' can be reflected in style, DOM or animation object until any animation event handlers associated with dispatch times at or before 't' have returned from execution.
( In effect this is something like saying: "When event handlers due to  animation events run, the state of the world (DOM properties etc.) so  far as it is influenced by animation, is as if the current time was the time when the event was scheduled to be triggered ")
There may be many ways to realise this:
- one possibility would be dispatching animation events synchronously
- another may involve careful updating of the animation time (after waiting for corresponding animation events to return)
- a third might involve pausing the world
We would like to investigate the new approach to mutation events and see if that can apply here.
http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/1622.html
ACTION: Shane to look into new "batching" mutation observer proposal and report on its applicability to animation
Topic: API
http://dl.dropbox.com/u/11894343/web-animations/web-animations.html
https://github.com/birtles/web-animations
- Not sure about the "Web" prefix on IDLs but we'll stick with it for now
- Call Animators WebAnimationTemplates, likewise for groups
  -- is WebAnimationGroupTemplate too long? 
- We don't feel the need to include <discard> and other declarative means for modifying the DOM in this version. Implementations of SVG 1.2 Tiny are free to implement this however. We might revisit this sort of functionality in a later version.
RESOLUTION: We will defer the stack property on the CSSAnimator interface for the first version and wait and see if efforts to provide a more generically useful interface (such as getMatchedCSSRules) make progress in the meantime.
ACTION: Brian to look into the promotion of SVG attributes to properties proposal and see if there are implications for use using a single "property" attribute on the AnimationFunction interface to refer to either an attribute or property.
Talked about the timeline API--we don't need to return a list of Animation objects, just a list of times and references to the Animators that created them?
  -- talked about the idea of having a time-based window, e.g. 5 minutes, for which implementations are required to store all time "events" (moments). Beyond that window it's not guaranteed everything will be available -- does that apply just backwards? or forwards too?
  -- talked also about backwards seeking. Depending how we define the behaviour there, the window may also be helpful in defining the limits of which animations generated by events are recorded/restored
  -- also we talked about probably making Animations immutable
  -- when we pause events, we probably need to record that moment. Implementations can store a compact representation of times, repeat counts, pause events etc. and synthesise a full list of times when required.