Archive for November, 2012

No SMIL+SVG in Internet Explorer

After noticing the SMIL animation in my previous post on SVG animations not working in Internet Explorer 10, I did a bit of digging to see what level of support was offered by IE10 and IE9 (previous versions do not support SVG). Simply put, Internet Explorer does not support SMIL animation of SVG. An entry from IEBlog regarding the an IE9 platform preview explains why:

… support for SMIL animation of SVG in the web development community is far from strong. The leader of the SVG standardization effort wrote that not supporting SMIL in its current state is probably best “since the SVG WG intends to coordinate with the CSS WG to make some changes to animation and to extend filters.” There’s already work started to reconcile CSS3 animations and SVG.

I’m not shedding any tears. That said, I’m not that enthusiastic about CSS3 animations for SVG either, as CSS3 animations bring with them the same loss of flexibility as SMIL. The current, flexible, cross-browser solution for SVG animation is Javascript, and I can’t see why that’s not a worthwhile solution for the foreseeable future as well.

SVG Animations

I decided to play around a bit with animating SVG content. There are actually multiple ways to animate SVG: CSS (transition, transform, @keyframes), Javascript, or Synchronized Multimedia Integration Language (SMIL). Where possible, I tend to prefer Javascript, as you have far more flexibility compared to markup languages; however, out of curiosity, I did try my hand at SMIL as well.

Method 1: Javascript

Here’s the SVG markup for the object being animated.

<svg version="1.1" x="0px" y="0px" width="74px" height="74px" viewBox="-1.751 -1.751 74 74" enable-background="new -1.751 -1.751 74 74" xml:space="preserve">
    <
g id="circularMarker" transform="rotate(0 35.163 35.521)">                
        <
path fill="#27AAE1" d="M46.336,7.908c2.174,0.678,4.236,1.538,6.199,2.54V3.69c-1.417-0.607-2.875-1.146-4.377-1.616
            C37.794-1.161,27.147-0.491,17.793,3.242v6.663C26.41,5.825,36.518,4.843,46.336,7.908z"/>
        <
path fill="#27AAE1" d="M62.423,46.338c-0.679,2.173-1.537,4.236-2.538,6.199h6.757c0.605-1.417,1.147-2.877,1.615-4.382
            c3.235-10.364,2.564-21.006-1.167-30.362h-6.664C64.505,26.41,65.489,36.52,62.423,46.338z"/>
        <
path fill="#27AAE1" d="M23.992,62.42c-2.171-0.678-4.236-1.536-6.199-2.538v6.759c1.418,0.604,2.877,1.146,4.381,1.616
            c10.364,3.233,21.009,2.564,30.362-1.17v-6.664C43.921,64.505,33.81,65.488,23.992,62.42z"/>
        <
path fill="#27AAE1" d="M7.909,23.994c0.678-2.174,1.538-4.237,2.538-6.2H3.691c-0.606,1.416-1.147,2.878-1.617,4.38
            c-3.234,10.364-2.564,21.012,1.168,30.365h6.664C5.825,43.921,4.843,33.813,7.909,23.994z"/>
        <
circle fill="#00AEEF" cx="35.163" cy="35.521" r="11.331"/>
    </
g>
</
svg>    

To animate, the transform attribute on the #circularMarker group element is updated every frame to do a simple rotation at a rate of 0.275 deg/ms. You can see the result in the iframe below.

Here’s the Javascript code that makes it happen:

<script src="jquery-1.8.2.min.js" type="text/javascript"></script>
<
script type="text/javascript">

// setup window.requestAnimationFrame
(function ()
{
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
                                 window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();


// set initial frame time (in milliseconds)
var ft1 = new Date().getTime();

// set initial angle (in degrees)
var angleDeg = 0;

// function to rotate circle
function rotateCircularMarker()
{
var ft = new Date().getTime();
var ftDelta = ft - ft1;
ft1 = ft;

// rotate at a rate of 0.275 deg/ms
angleDeg += ftDelta * 0.275;

if (angleDeg >= 360) {
// full circle!, reset angleDeg
angleDeg = 0;
}

// transform the #circularMarker group
// Note: the rotation is about the center of the circle element (35.163, 35.521)
$('#circularMarker').attr('transform', 'rotate(' + angleDeg + ' 35.163 35.521)');

// call requestAnimationFrame to continue animating
requestAnimationFrame(rotateCircularMarker);
}

$(document).ready(
function ()
{

rotateCircularMarker();

});
            
</script>

Note that window.requestAnimationFrame is used, so a modern browser is required. For older browsers it is possible to use window.setInterval as a fallback.

Method 2: SMIL

With SMIL, the SVG code remains the same, with the exception of an animateTransform tag within the #circularMarker group element.

<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 35.163 35.521" to="360 35.163 35.521" begin="0s" dur="1.336996s" repeatCount="indefinite"/>

The attributes of animateTransform describe the animation, mainly type, from, to, begin, dur, and repeatCount.

Obviously SMIL yields less code and removes all Javascript dependencies, but it does come at the cost of losing flexibility (as you can only perform transformations and timing operations supported by SMIL attributes) and having to learn yet another markup language.

MegaRace

One of the earliest computer games I played was MegaRace, which came bundled with a Quantex Pentium 60Mhz PC by dad bought sometime around the end of 1994. It was a cheesy game (really cheesy), but it was fun to play. The FMV race tracks were visually impressive for the time and the combat racing was exciting despite only being able to move cars side-to-side.

MegaRace: Particle Accelerator

The chiptune soundtrack, composed by Stéphane Picq, was particularly memorable. For those interested, this fan site has Ogg Vorbis encodings of the music for the race tracks as well as an MP3 of an FMV ending sequence. Well worth a listen.