SVG 2 Animation

SVG F2F Auckland 2011

Agenda

Declarative animation vs script

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

Security / SVG assets

Sometimes you can't/don't want to allow scripts. For example,

SVG is gradually penetrating deeper into the Web platform.

Implications

But SMIL isn't perfect…

SMIL is complicated by syncbase timing

From an implementation point of view:

SMIL is complicated by syncbase timing contd.

From an authoring point of view:

<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 (→ B and C should play) and A being cancelled via mouseout (→ B and C should not play).

Remove syncbase timing and replace with time containers

<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>

SMIL 3 time containers - <par>

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>

SMIL 3 time containers - <seq>

<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>.

SMIL 3 time containers - <excl>

<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>

SMIL 3 time containers - nesting

Containers can be nested. For example,

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

SMIL 3 time containers - nesting contd.

Applying to syncbase timing:

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

becomes:

<seq begin="5s">
  <animate id="a" ... />
  <par begin="1s">
    <animate id="b" ... />
    <animate begin="2s" ... />
  </par>
</seq>

Wins

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.

Challenges contd.

e.g. (2)

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

A regular ping-pong arrangement is easy:

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

Challenges contd.

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 — probably script is also available for these kind of use cases

Challenges contd.

Challenge 2: Migration path. How can we drop syncbase timing without anyone noticing?

One possibility:

Limiting the scope

Don't necessarily need <par> and <seq> elements. SMIL also allows adding a timeContainer attribute to existing elements. e.g.

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

Structural manipulations need specification

Specify and test structural manipulations

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:

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

Fix discrete to-animation

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 do this.

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.

Opera WebKit

Proposal: Adopt Opera's behaviour

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;

The presence of a single end time / end instance changes the behaviour considerably. e.g.

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

Even with beginElement you can't restart the second one after t=2s.

It also contributes to a problem with reset behaviour.

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.

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.

Proposal: Deprecate/remove wallclock timing

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

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 (and phase out syncbase timing). e.g. repeat-to-fill

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

Let's wait to see if min/max are useful in combination with time containers.

animateTransform

Many issues, e.g.:

Reversing animations

The swelling button use case.

button

Add a reverse feature to time containers

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

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

Add a reverse feature to time containers contd.

Lots of issues:

Re-use animations

SMIL animations are re-usable or scalable. They have a single target:

  1. the parent element, or
  2. referred to by ID

This means:

Re-use animations contd.

For example,

As it happens, SMIL Timesheets provides CSS selectors to specify animation targets.

Brief overview of SMIL Timesheets

<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>

SMIL Timesheets introduces <item> which behaves like an animation, applying the appropriate timeAction to the target.

Selectors can also be nested

<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

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

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

Consider integrating SMIL Timesheets

e.g.

<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>

Migration path

  1. “SMIL but saner”
    • Continue to refer to SMIL but make differences fairly obvious
  2. “SVG Animation”
    • Import all relevant SMIL text into SVG and freely modify on the way
    • SMIL: normative → informative
    • 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