F2F/Auckland 2011/Animation improvements

From SVG

In this session I want to look at difficulties with the SMIL timing model and consider how we can fix it as well as making it more useful in the future.

I expect it to be a fairly high-level discussion with the most important outcome being some understanding of the direction in which we would like to take SMIL.

Executive summary

SMIL is hard, particularly because of syncbase timing which complicates document manipulation and is inconsistently implemented. There are other minor issues that complicate SMIL. Proposals to a number of these issues are put forward, most notably, removing syncbase timing and introducing SMIL time containers like <par> and <seq>. New features for reversing and re-using animations are also proposed. The migration path for these changes is also briefly considered.


SMIL use cases revisited

Do we even need declarative animation when we have script?

SMIL vs Script

  • Potentially more performant → negligible in light of JS improvements
  • Ease of authoring → nothing a javascript library can't fix (e.g. SMILScript, YUI extensions etc.)
  • The Semantic Web argument, i.e.
    • allows interchange between tools → what tools? Yet to be realised.
    • allows alternative presentations (e.g. SVGT1.2's snapshotTime) — are there other use cases? An animation debugger perhaps such as Firebug plugin?
    • supports an XML workflow (e.g. generation by XSLT) → Is anyone doing this?

The semantic argument is probably valid but few concrete use cases makes it hard to develop specs based on this criteria alone.

Security

This is a more compelling argument. Sometimes you can't/don't want to allow scripts. For example,

  • external content — banner ads, gravatars
  • SVG as img → SVG everywhere: CSS backgrounds, application chrome
  • SVG assets used in other documents
    • SVG filters applied to HTML content
    • SVG fonts :)

SVG is gradually penetrating deeper into the Web platform and in many of these situations you may want animation, but you either can't or don't want to allow script.

Slightly more concrete use cases

  • A third-party banner ad with various animated effects. Ideally, advertisers would probably like some interactivity (mouseover effects etc.) but do we allow event-based timing for SVG as image?
  • An SVG filter applied to HTML content. For example, a website advertising a movie where all the level 1 headings are styled with an SVG filter to give an eerie pulsating glow.
  • An animated glyph in an SVG font. Again, a movie website may be one such example.
  • An animated icon in browser chrome or a web app UI. The icon may animate in response to user actions (e.g. mouseover), or application events (e.g. a progress meter). Even if the application takes responsibility for triggering the animation it would be nice to offload running the animation loop to SMIL.
  • Animated wallpaper for GeocitiesMySpace webpages :)

Implications

I've only made minimal reference to the above use cases in the subsequent discussion but there are two things to note here:

  1. Complex interactions are probably not necessary for most of these use cases (the exception possibly being the third-party banner ad). Therefore, SMIL doesn't need to do everything. When complex interactions are required we're probably talking about a different kind of use case where the possibility of augmenting SMIL with script is also available.
  2. The use cases for SMIL depend significantly on whether event-based timing is available for SVG as image. Has this been decided yet?

SMIL shortcomings and proposed solutions

There is considerable concern about the suitability of SMIL.

SMIL can be thought of in two parts:

  • the timing model — defines when animations start and end
  • the animation model — defines how animation values are calculated and applied

The subsequent discussion focuses primarily on the timing model since the problems there are more fundamental in nature and less frequently discussed.

Issue: SMIL is greatly complicated by syncbase timing

Syncbase timing is problematic for implementers and authors.

From an implementation point of view:

  • Syncbase timing complicates structural manipulations (tree surgery).
    • Structural manipulations need to be defined (see next issue) but a major source of complexity is syncbase timing — each element is potentially a participant in a many-to-many relationship with time dependencies. As animation elements are added/removed/modified we need to dispatch a variety of different notifications which can trigger a chain of events. Requires a lot of testing.
      • (also leads to situations where you need to dispatch a lot of events e.g. inserting an animation into a document in play)
  • Syncbase timing is hard (as evidenced by inconsistent implementation)
    • cycle detection is problematic — See this test case which produces different results in every browser tested.
    • animation sandwich prioritisation based on time dependencies is largely unimplemented — See this test case. Batik and Opera don't seem to implement this, WebKit does only partially (fails for frozen animation).
    • dependencies established between animations in different SVG document fragments (but within the one compound document) become complicated when fragments are paused/resumed independently. The behaviour here is not specified.

From an authoring point of view:

  • begin="a.begin" vs begin="a.beginEvent" — the difference is subtle
  • Cancelling a chain of animations is not possible. For example: A, B, and C are configured in a chain as follows:
<animate id="a" dur="5s" end="elem.mouseout" .../>
<animate id="b" begin="a.end+1s" ... />
<animate id="c" begin="b.begin+3s" ... />

We'd like to distinguish between A running to completion (in which case we want B and C to play) and A being cancelled via a mouse out event (in which case we DON'T want B and C to play).

Proposal: Remove syncbase timing and replace with time containers

For example:

<animate begin="5s" id="a" ... />
<animate begin="a.begin+2s" ... />
<animate begin="a.begin+1s" ... />

becomes:

<par begin="5s">
  <animate id="a" ... />
  <animate begin="2s" ... />
  <animate begin="1s" ... />
</par>
A little more detail: SMIL 3 time containers

SMIL 3.0 has three types of time container:

<par> - "parallel" — elements play at the same time, e.g.

<par begin="5s">
  <animate id="a" ... /> --> starts at t=5s
  <animate begin="2s" ... /> --> starts at t=7s
  <animate begin="1s" ... /> --> starts at t=6s
</par>

<seq> - "sequence" — elements play one after another, e.g.

<seq begin="5s">
  <animate dur="2s" ... /> --> starts at t=5s
  <animate dur="3s" ... /> --> starts at t=7s (5s + 2s dur)
  <animate begin="1s" dur="2s" ... /> --> starts at t=11s (7s + 3s dur + 1s offset)
</seq>

Unlike <par>, children of a <seq> can only have a single non-negative offset as a begin value. i.e. you can't use event-based timing, wallclock timing, etc. inside a <seq>.

<excl> - "exclusive"? — only one element can play at a time. Starting one element stops all others. e.g.

<excl>
  <animate begin="buttonA.click" ... />
  <animate begin="buttonB.click" ... />
  <animate begin="buttonC.click" ... />
</excl>

Containers can be nested. For example,

<seq>
  <!-- Phase 1 of animation -->
  <par>
    <animate/>
    <animate/>
  </par>
  <!-- Phase 2 -->
  <par>
    <animate />
    <animate />
  </par>
</seq>

Applying this to syncbase timing we can transform:

<animate begin="5s" id="a" ... />
<animate begin="a.end+1s" id="b" ... />
<animate begin="b.begin+2s" ... />

into:

<seq begin="5s">
  <animate id="a" ... />
  <par begin="1s">
    <animate id="b" ... />
    <animate begin="2s" ... />
  </par>
</seq>
Wins
  • Makes structural changes to the document MUCH simpler
    • even if we allow <seq>-style containers the dependency chain is simply 1-to-1
    • therefore structural changes are easier to specify and test since there are less permutations to consider → interop win
  • Removes much of the complexity of syncbase timing
    • animation sandwich priorities are much easier to establish
    • no need to do cycle detection and its associated inconsistencies
    • remove confusion with a.begin vs a.beginEvent
    • inter-document fragment dependencies can be achieved by either moving/duplicating the animation, or event-based timing—both of which are well-defined.
  • Cancelling a chain of animations is possible, just cancel the group
  • Corresponds more closely with CSS Animations which groups animation together
    • Combining this with something like SMIL Timesheets (see below) could potentially mean we could use a SMIL animation as an animation-name in CSS Animations.
Challenges

Challenge 1: There are some syncbase arrangements which can't be realised with these containers as specified.

e.g.

<animate id="a" ... />
<animate begin="a.end-1s"/>

We'd like to write:

<seq>
  <animate id="a" ... />
  <animate begin="-1s"/>
</seq>

But SMIL doesn't allow negative offset times for <seq> children. We may want to deviate from SMIL here.

e.g. (2)

<animate id="a" begin="b.end; click" restart="whenNotActive" ... />
<animate id="b" begin="a.end; click" restart="whenNotActive" ... />

This is a ping-pong arrangment when either element can start the animation.

A regular ping-pong arrangement is easy:

<seq repeatDur="indefinite">
  <animate/>
  <animate/>
</seq>

But in this case we want to be able to start the animation mid-way. We'd like to do:

<seq repeatDur="indefinite">
  <animate begin="id1.click" .../>
  <animate begin="id2.click" .../>
</seq>

But again, <seq> children can't have event-based begin conditions.

We could:

  1. Deviate from SMIL
  2. Just use hyperlinking in this case
  3. Just say this arrangement is not possible with SMIL alone.
    • As discussed in the section on use cases, this may be one of the cases where we say, if you actually need this kind of complicated interaction then you're probably also in a situation where you're able to run script. i.e. SMIL alone doesn't stretch that far.

Challenge 2: Migration path. How can we drop syncbase timing without anyone noticing? In order to realise many of the implementations benefits outlined above we'd probably also like to drop syncbase timing from our code but that's going to break existing content.

As discussed later, one option is to make something that looks completely different to SMIL (and take the chance to clear out some other cruft) but I'm not sure how feasible that is.

Another possibility is to say that children of one of these new time containers can't use syncbase timing (much like SMIL already restricts the children of <seq> containers), nor form part of any other syncbase network. Furthermore we could define new features such as auto-reversing, animation re-use etc. as only applying to such time containers and gradually deprecate syncbase timing that way.

Limiting the scope

We probably don't want to import SMIL time containers wholesale. For example <excl> might not be useful (or at least we could leave it out for SVG2 and add it later if it proves useful).

There are a range of other features that need to be weighed up: endsync, fillDefault, restartDefault etc.

Note that using SMIL time containers doesn't necessary mean introducing <par> and <seq> elements. SMIL also discusses the possibility of a host language adding a timeContainer attribute to existing elements. e.g.

<g timeContainer="par">
  <animate ... />
</g>

Issue: Structural manipulations need specification

For example:

  • If an <animate> element is removed whilst in play and later rebound what animation state is preserved? (In Firefox we discard all animation state and recreate it since the element may be rebound to another container.) See http://lists.w3.org/Archives/Public/www-svg/2010Oct/0048.html (and discussion in Mozilla bug 628407).
  • Similarly if an <svg> element is removed and rebound what state is preserved? In Firefox we remember the current time. This is problematic because when we rebuild the timegraph upon being rebound there may be many events that need to be dispatched leading to a performance hit. Can we say that the document acts as if a seek were performed and suppress most events?
  • Tests would also be welcome for dynamic modification of timing properties. For example, if the fill attribute is set to 'freeze' after an animation has finished, presumably the appropriate fill value should be instantly applied. This is not specified but seems intuitive and should be tested.

    Perhaps we can follow Jansen et. al's approach of testing a change to each attribute/element when the affected item is:
    1. currently active
    2. has been active in the past
    3. will only become active in the future

Proposal: Specify and test structural manipulations

  • Specify the expected behaviour for:
    • adding, removing, and rebinding animation elements after document load including moving animation elements between <svg> document fragments within a compound document
    • removing and rebinding <svg> document fragments after document load including when the fragment is promoted to/demoted from being the outermost <svg> element in a fragment
    • adding, removing, and modifying animation attributes after document load
    • dynamic changes to ID references
  • Add test cases for the above to the test suite

Issue: Discrete to-animation is counter-intuitive

Compare:

  <rect width="100" height="50">
    <animate attributeName="width"
             calcMode="discrete"
             begin="0s" dur="2s"
             to="300"
             fill="freeze"/>
  </rect>

and:

  <rect height="50">
    <animate attributeName="width"
             calcMode="discrete"
             begin="0s" dur="2s"
             from="100"
             to="300"
             fill="freeze"/>
  </rect>

(Test URL: https://bug544855.bugzilla.mozilla.org/attachment.cgi?id=493392)

According to SMIL, the first one, a discrete to-animation, simply sets the width to 300.

For the shorthand form to animation, there is only 1 value; a discrete to animation will simply set the "to" value for the simple duration.

http://www.w3.org/TR/smil-animation/#AnimFuncCalcMode

But the second, a discrete from-to animation, sets the width to 100 for 1s, then 300.

Test http://dev.w3.org/SVG/profiles/1.2T/test/svg/animate-elem-227-t.svg still mandates the wrong behaviour.

Proposal: Fix discrete to-animation

Deviate from SMIL here and make discrete to-animation set the animation value to the base value for half the duration and then the to-value for the remainder of the duration.

i.e. <animate calcMode="discrete" to="<value>" .../> is equivalent to:
<animate calcMode="discrete" from="<underlying-value>" to="<value>" .../>

Opera and WebKit already deviate from the spec here so we can probably get away with just updating the spec.

Issue: Frozen to-animation is broken

To-animation behaves differently when frozen to when active. According to SMIL:

A frozen to animation takes on the value at the time it is frozen, masking further changes in the underlying value. This matches the dominance of the to value at the end of the simple duration. Even if other, lower priority animations are active while a to animation is frozen, the value does not change. http://www.w3.org/TR/SMIL/smil-animation.html#animationNS-ToAnimation

Test case: http://brian.sol1.net/svg/interop/frozen-to-animation-simplified.svg
(See also: http://brian.sol1.net/svg/tests/frozen-to-animation.html. WebKit appears to be correct for this test case but only because the animation value at point where the to-animation is frozen happens to coincide with the to-value)

You get very different results in WebKit/Opera/Firefox/Batik

WebKit Sets the 'to' value when frozen even if frozen part-way through the simple duration (i.e. ignores the 'at the time it is frozen' condition).
Opera The value continues to change but is constrained by the partly applied to-animation (i.e. ignores the 'masking further changes in the underlying value' condition)
Firefox Follows the spec I believe (there is code specially for this condition) but fails if you perform a seek. Implementing it correctly is quite difficult.
Batik Not quit sure

A more thorough description of the problem has been written up here: http://brian.sol1.net/svg/report/report.pdf#page=85

Proposal: Fix frozen to-animation

Opera's behaviour seems most intuitive, suggesting adopting that.

Issue: The requirement for an end-instance time is confusing

Specifically, the following piece of pseudocode from SMIL 3.0 5.4.5 End of an interval:

// Events leave the end open-ended. If there are other conditions
// that have not yet generated instances, they must be unresolved.
if endHasEventConditions()
   OR if the instance list is empty
   tempEnd = UNRESOLVED;
// if all ends are before the begin, bad interval
else
    return FAILURE;

This is confusing for content authors since the presence of a single end time or end instance changes the behaviour considerably.

i.e.

<animate begin="1s; 3s" ... /> --> 2 intervals
<animate begin="1s; 3s" end="2s" .../> --> 1 interval

It also contributes to a problem with reset behaviour.

For example on the following element:

<animate begin="1s" end="2s" ... />

The sequence of calls is performed at time t=3s:

beginElementAt(1);
endElementAt(2);

This results in an interval being created from 4-5s. When the interval is begun at t=4s, a reset is performed (this behaviour also requires clarification), the end instance time is deleted, and, based on this condition, the interval will also be deleted.

Depending on when an implementation re-evaluates the current interval are range of confusing behaviour could result such as:

  • nothing happening at all, i.e. it is impossible to re-start such an animation via script without first removing the end attribute.
  • almost nothing happening at all with the exception of a beginEvent and endEvent being dispatched almost simultaneously.
  • an interval starting as hoped, but then when some attribute is modified causing the current interval to be re-evaluated, the animation suddenly terminating.

(Test URL: http://brian.sol1.net/svg/interop/reset-test.svg)

There are other problems with this pseudocode which have been discussed and acknowledged on www-smil:
http://lists.w3.org/Archives/Public/www-smil/2009OctDec/0007.html
http://lists.w3.org/Archives/Public/www-smil/2010JanMar/0000.html

Proposal: Fix end-instance condition

I think we want to change this pseudocode:

// Events leave the end open-ended. If there are other conditions
// that have not yet generated instances, they must be unresolved.
if endHasEventConditions()
   OR if the instance list is empty
   tempEnd = UNRESOLVED;
// if all ends are before the begin, bad interval
else
    return FAILURE;

To simply:

tempEnd = UNRESOLVED;

But rather than hacking the pseudocode, it would be enough simply to say,

In SVG, the end attribute is always considered to include the 'indefinite' value as the last item in the list of end times, whether it is explicitly specified or not.

That seems to be what Opera and WebKit do anyway.

Issue: wallclock timing isn't useful

It doesn't seem to help with actual use cases: http://lists.w3.org/Archives/Public/www-smil/2010AprJun/0006.html.

The use case in question here was digital signage where something should only be shown on certain days which can't be achieved with wallclock timing. Are there any real-world use cases for which wallclock timing is actually useful?

Proposal: Deprecate/remove wallclock timing

I don't think anyone's using this so could we get away with just dropping it?

Issue: <animateColor> isn't needed

It's not necessary provided <animate> honours color-interpolation. See http://lists.w3.org/Archives/Public/www-svg/2010Oct/0069.html and Mozilla bug 436296.

Proposal: Deprecate <animateColor>

And describe the meaning of the color-interpolation when applied to <animate>.

Jwatt originally proposed:

  1. if 'color-interpolation' is set on the <animate> element, interpolate in that color space
  2. else, if the user specifies a 'to'/'by' color using 'hsl()' or 'hsla()' function syntax, then animate in HSL space
  3. else, if 'color-interpolation' is explicitly set on the target element, interpolate in that color space
  4. (otherwise we'll end up using the default value of 'color-interpolation' which is sRGB)

Update 27 Feb 2011. It's a done deal, will be deprecated. Step 2 above is probably not necessary.

Issue: min/max aren't necessary

I don't think they're currently used, but they may actually become useful if we go with time containers.

e.g.

<par max="10s">
  <animate repeatDur="indefinite" ... />
</par>

This arrangement allows us to define an animation that will stretch-to-fill. Is this useful?

I'd like to propose dropping this but I'll wait to see if they're useful when used in combination with time containers.

Issue: animateTransform

There are many issues here, for example:

  • the transform attribute refers to a transform list but animateTransform only operates on a single transform object.
  • from a DOM point of view does an additive animateTransform:
    • append a transform to the end of the transform list, one for each <animateTransform> element?
    • or just append one transform and subsequent <animateTransform> elements just get post-multiplied to that one?
  • is a separate <animateTransform> element really necessary? Can't we just define the additional type attribute as applying to <animate> but being ignored unless attributeName="transform"?
  • there seems to be some clarification required regarding the interaction of <animateMotion> and <animateTransform> according to this thread, continued here.

I don't have any specific proposal for these issues at this time other than suggesting that they need to be reviewed for SVG 2.

Issue: Error handling behaviour is too strict

SVG is strict about bad input. For example:

If there are any errors in the ‘keyTimes’ specification (bad values, too many or too few values), the document fragment is in error (see error processing). http://dev.w3.org/SVG/profiles/1.1F2/publish/animate.html#KeyTimesAttribute

The error processing section elaborates:

If the document has animations, the animations shall stop at the point at which an error is encountered and the visual presentation of the document shall reflect the animated status of the document at the point the error was encountered. http://dev.w3.org/SVG/profiles/1.1F2/publish/implnote.html#ErrorProcessing

SVG 1.2 Tiny has relaxed this behaviour:

If the 'keyTimes' attribute has a value that doesn't conform to the above requirements the 'keyTimes' attribute has an unsupported value and is processed as if the attribute had not been specified. http://www.w3.org/TR/SVGTiny12/animate.html#KeyTimesAttribute

Most implementations seems to be more lenient on bad input than the spec requires.

Proposal: Review error handling behaviour for animation

We should be lenient on bad input and define how to handle errors/conflicts. This may basically mean just importing what's already defined in SVG 1.2 Tiny.

Animation model issues?

So far I've mostly only been looking at problems with the timing model. There are probably lots more problems with the animation model, e.g.

  • the whole attributeType=XML/CSS/none issue
  • the need to clearly specify the interaction between CSS Animations, Transitions, SMIL etc. etc. (pretty sure this is dealt with elsewhere though)
  • others?

Wanted feature: reversing animations

The swelling button use case. That is, create a button that swells over a period of 1s on mouseover, and shrinks at the same rate back to its original size on mouseout. Currently this does not appear to be possible if the mouseout occurs midway through the swelling phase. If the mouseout occurs after 0.3s, it should take 0.3s to return to the original size.

This should be a container level operation so that a group of animations could be reversed easily and sensibly.

CSS Transitions already has this although there is some discussion about the actual mechanics of producing an intuitive result. See these two threads:
http://lists.w3.org/Archives/Public/www-style/2009Nov/0302.html
http://lists.w3.org/Archives/Public/www-style/2010Jan/0204.html

SMIL 3.0 also features an autoReverse attribute however I'm not sure if this quite meets our needs since it will reverse as soon as the active duration is reached. For the button use case, we want to the animation to be frozen after reaching the active duration until, for example, a mouseout event is received.

Proposal: add a reverse feature to time containers

A couple of possibilities to consider:

Option A. Introduce a container level attribute reverse that takes a begin-value-list, e.g.

<par begin="mouseover" reverse="mouseout">
  <animate ... />
</par>

Points to note:

  • The relationship with end is confusing. Is it useful to distinguish the two? i.e. a list of times/conditions that will cause the animation to reverse, and a parallel list that will cause it to stop it in its tracks?
  • We could add a special reverse="auto" value to match SMIL's autoReverse, i.e. reverse as soon as the group reaches its active end.

Option B. Redefine the behaviour of end.

<par begin="mouseover" end="mouseout" reverse="auto">
  <animate ... />
</par>
  • The only other value for reverse being none (the default).

There are lots of issues to consider here (e.g. what events get dispatched for an animation that is partially applied and then reversed, reset behaviour, interval evaluation). It might be best to consider the reverse animation as an entirely independent animation with regards to events, resetting, etc.

A bigger issue however is the nature of the reverse animation. CSS Transitions ran into this and discovered many different possibilities.

Basically, some of the issues that arise are:

  • If one specifies an ease-in transition using keySplines, does the reverse transition also perform an ease-in or an ease-out?
    • If the animation is fully applied then probably the former is intuitive, but if it's partially applied then perhaps the latter—but that would introduce an inconsistency between an animation that's 99.9% applied and one that's 100% applied.
    • CSS Transitions seems to be going with ease-in remains ease-in upon reversal (although CSS Animations animation-direction="alternate" makes ease-in become ease-out).
  • If both directions use ease-in then you can't just trace the animation function backwards (the "follow back" option).
  • Value-scaling seems to be the best option for CSS Transitions but would at least need significant reworking for SMIL due to the additional complexity of having animation functions with multiple values (not just A-to-B) and groups of animations each targeting different attributes.

Wanted feature: re-use animations

SMIL animations are not very scalable since the target element is either (a) the parent element, or (b) referred to by ID.

This means:

  • It's not possible to re-use an animation effect like you can a filter, pattern etc.
    • Example use case: a mouse-over effect applied to a number of similar (but slightly different) UI elements.
  • DOM manipulation in documents with animation quickly becomes clunky due to ID ref spaghetti. (ID refs are not only used for identifying the animation target but also within syncbase relationships and event-based timing.)
  • It's hard to harmonise with CSS Animations. It would be great to be able to use the name of some SMIL animation group in a stylesheet anywhere you would otherwise put the name of a CSS Animation. This, however, requires making animations re-usable.

One major issue though is that whilst CSS Animations target a single element at a time, a group of SMIL animation elements should be able to target different elements (within a target group).

For example, a mouse over effect on a button where one animation changes the colour of the <rect> defining the button shape whilst another animation in the same animation group modifies the <text> element with the label, perhaps shifting the label. Here is such an example.

As it happens, SMIL Timesheets provides just this functionality using CSS selectors to specify animation targets, and allowing further selectors to subsequently select children of the animation target.

Brief overview of SMIL Timesheets

A very simple example (all following examples are from the SMIL Timesheets spec):

<timesheet>
  <seq>
    <item select="#Slide1" dur="5s" />
    <item select="#Slide2" dur="5s" />
    <item select="#Slide3" dur="5s" />
  </seq>
</timesheet>

which can also be written:

<timesheet>
  <seq>
    <item select=".Slide" dur="5s"/>
  </seq>
</timesheet>

Selectors can also be nested:

<timesheet>
  <seq>
    <item xml:id="first" select=".Slide" dur="7s">
      <seq>
        <item xml:id="second" select=".Bullet" dur="1s" />
      </seq>
    </item>
  </seq>
</timesheet>

One point to note here is that SMIL Timesheets introduces the <item> element which behaves like an animation, applying the appropriate timeAction to the target. SMIL has a nation of intrinsic actions for different types of elements (typically hiding/showing) but these can be overridden by use of the timeAction attribute.

Integrating with <animate> looks something like this:

<timesheet>
  <seq>
    <item select=".Slide" dur="15s">
      <par>
        <item select=".Bullet" beginInc="3s">
          <animate select=".Bullet" attributeType="CSS" 
              attributeName="margin-left" values="200;0" dur="1s" />
        </item>
      </par>
    </item>
  </seq>
</timesheet>

Other features introduced by SMIL Timesheets:

  • beginInc
<par>
  <item select=".Bullet" beginInc="1s" />
</par>

Increments the begin time of each of the elements, but the first one, by the defined value.

  • index() function

Allows this:

<timesheet>
  <excl>
    <item select="#Image1" begin="Thumbnail1.DOMActivate" />
    <item select="#Image2" begin="Thumbnail2.DOMActivate" />
    <item select="#Image3" begin="Thumbnail3.DOMActivate" />
    <item select="#Image4" begin="Thumbnail4.DOMActivate" />
  </excl>
</timesheet>

to be replaced with this:

<timesheet>
  <excl>
    <item select=".Image" begin="index(Thumbnail).DOMActivate" />
  </excl>
</timesheet>
  • External timing: allows for timing information to be separated from the presentation.

Proposal: Consider integrating SMIL Timesheets

One area of concern here is the <item> which relies on intrinsic actions/timeAction behaviour for target elements. We could just say that for SVG elements the timeAction is none but I wonder if that is confusing.

So we could have something like the following:

<item select=".buttonGroup">
  <animate select="text:first-child" ... />
  <animate select="rect" attributeName="fill" ... />
</item>

Or could we overload <g> for this as well? i.e.

<g select=".buttonGroup" timeContainer="par">
  <animate select="text:first-child" ... />
  <animate select="rect" attributeName="fill" ... />
</g>

Or <par>?

<defs>
  <!-- This animation is used on-demand like a filter -->
  <par id="hoverAnim">
    <animate select="text:first-child" ... />
    <animate select="rect" attributeName="fill" ... />
  </par>
</defs>
<g style="animation-name:'hoverAnim'">...</g>
<!-- This animation is automatically applied -->
<par select=".className">
  ...
</par>

We need to be careful since animating styles may cause CSS selectors to match different elements on each sample.

Migration path

  • Many of these changes deviate from SMIL to different degrees
  • We want to avoid an uncanny valley situation where we have something that looks very much like SMIL but isn't quite SMIL

Some possible routes

  1. "SMIL but saner"
    • Continue to refer to SMIL but make differences fairly obvious
    • Largely backwards compatible—most of the changes that are not backwards compatible from a spec point of view are not properly implemented anyway (e.g. frozen to-animation, discrete to-animation) so we wouldn't be breaking existing content for many of those changes
  2. "SVG Animation"
    • Import all relevant SMIL text into SVG and freely modify on the way
    • SMIL: normative → informative
    • Still largely backwards compatible with SVG 1.1
  3. "Web Animation 1.0"
    • Complete break from SMIL—something that looks completely different
    • Would allow fixing up syntax (attributeNameattr), dropping features (attributeType, syncbase timing etc.), greater simplifications, aligning better with CSS