Thursday, February 15, 2007

My Proposal: Functional Animation

In this blog entry I'm going to explain some of the detail behind my proposal for functional animation, which was introduced in a previous entry.

The goals are to allow any XML document node or CSS stylesheet property to:

  1. Evolve as an explicit function of time and other (possibly also evolving) nodes or CSS values f(t, a, b, c, …)
  2. Apply the function conditionally, or depending on events such as key presses
  3. For continuously varying values, set or reference their speed and acceleration

Goal 1 says that the language should be functional. Rather than calculating an incremental change every millisecond, as per javascript, the property evolves according to a function. For example, it might be "width = 2 * height" which would maintain the width at twice the height, no matter how the height evolves.

This requires us to incorporate a referencing language, so that each element can refer to the others. There are lots of them around – there’s one in CSS and another in SMIL – but there is a more powerful standard, XPath, to take advantage of. The other benefit of XPath is that it introduces standard mathematical and string functions. For example, why not specify "width = avg(//img[@class='ball']/@width)", which sets the width to the average of every image width with 'ball' class.

It also implies that the language works like a spreadsheet - any time a value changes, the effects can ripple through all the dependent values. Like Microsoft Excel, the system needs a dependency engine in order to quickly figure this out and work all the way down the dependency chain (looking out for circular references).

Finally, XPath allows us to work with t, the time. Unfortunately there’s no pre-defined time variable that starts from zero when the animation begins – but we can create our own, by using the XPath system clock function and measuring from when the animation began.

Goal 2 demands that our function language has some conditional statements in it, possibly dependent on node values. For example, perhaps an SVG image is programmed to be repelled by another image, but only if they get too close. Or perhaps it speeds up when the mouse clicks (which requires integration with the events model in HTML/XML).

There are two existing XML animation technologies that go some way to meeting these two goals. The first is Synchronized Multimedia Integration Language (SMIL), which despite its name incorporates a general-purpose model for animating any XML document. It is very straightforward, and works well for basic animations.

Unfortunately, for more complex animations SMIL has severe limitations, which stem from the fact that it doesn’t meet Goal 1 fully. The most basic limitation is that SMIL animations follow a pre-defined path. SMIL doesn’t handle situations where the desired path is dependent on unpredictable evolving conditions – for example, the mouse position, or the location of other moving objects or even a random number generator. SMIL also doesn’t incorporate XPath, which means it’s difficult to reference the values of other nodes.

The second existing XML animation technology is XForms. It may seem surprising that a web forms technology incorporates sophisticated animation functionality, but it does - because it includes a functional binding language based on XPath, which meets Goal 1. All it needs is a few simple extensions.

For example, consider the following XForms line:

<bind calculate="2" infoset="//img/@css:width">
which takes every image tag in the document, and sets the width to equal twice the height (using the XPath statement). Now, any time the height of any image is altered, its width will automatically reset to be double.

This might not be sophisticated animation, but it’s not possible with SMIL, and let’s take things a step further:

<script >document.getElementById(‘divTime’).setAttribute(‘timeStarted’, now())</script >
<bind infoset="id(‘divTime’)">
./@timeElapsed = current-dateTime() - //divTime/@timeStarted;
</bind>
<bind infoset="//img">
./@css:top = 200;
./@css:left = 100 + 100 * sin(id(‘divTime’)/@timeElapsed);
</bind>

First I have used javascript to set the timeStarted attribute to the system time when the page loads. Next I have extended XForms so the contents of the <bind> element works just like a series of calculate attributes.

The first <bind> element sets up a counter – the timeElapsed attribute – that holds the number of seconds since the page loaded.

The second <bind> element animates every image on the page from side to side according to a sine function.

You can see the immediate parallels between the <bind> element and CSS. It’s just the same, except it uses XPath as a referencing tool, and you can assign functions to each variable, not just static values. You could even put the <bind> tags in a separate stylesheet, just like CSS. Or you could get rid of your exising .css files, and replace them with the syntax above.

If the W3C followed this approach, it would pull the XForms <bind> element into a separate XML Functional Animation spec, which would form a foundation for CSS and supersede most of SMIL.

I’d like to give some more examples to show just how powerful this approach is. First, I’ll introduce three more new pieces

  • The calculatewhile attribute, which is an XPath boolean statement that controls whether the <bind> element should be run or ‘paused’
  • The new XPath function d_dt(), which sets or retrieves the rate of change (speed) of any node
  • The new XPath function d_dt2(), which sets or retrieves the acceleration of any node – the equivalent of d_dt(d_dt())
These pieces enable Goal 3 to be achieved:
<bind infoset="//img">
d_dt2(./@css:left) = - ./@css:left;
</bind>
which turns the images into simple harmonic oscillators (i.e. springs), vibrating backwards and forwards like a child on a swing.

Or consider:

<bind infoset="id(‘img1’)">
d_dt2(./@css:left) = id(‘img2’)./@css:left – id(‘img1’)./@css:left;
</bind>
<bind infoset="id(‘img2’)">
d_dt2(./@css:left) = id(‘img1’)./@css:left – id(‘img2’)./@css:left;
</bind>
which models two balls, joined by a spring.

Once you’ve thought about it, you realize that this approach to animation allows pretty much anything in classical physics to be modeled – wind resistance, friction, magnetism, gravity, etc. Which means it’s pretty useful in programming computer games! And there isn’t a tougher test for an animation language than this.

In summary, I think the XForms <bind> element contains, with a few simple extensions, everything the XML developer needs to produce world-class animations.

2 comments:

Ruud Steltenpool said...

I see < often in this post, instead of < or <

'spelled out': i see ampersand el tee, no semi-colon, no littler-than symbol

Chris Jay said...

thanks stelt - now fixed.