Bouncing Tiger and King Tut

The final example of SVG animation is done through CSS3 animation. It's a fairly limited demonstration but does show the basics of CSS3 animation with keyframes.

There are three components of the SVG as a whole:

  • A stroked red rect that delimits the bounds of the animation
  • A very complex SVG drawing of a tiger's head, originally done in Illustrator
  • A very complex SVG drawing of King Tut's head and torso, also done in Illustrator.

Both of the drawings are relatively ancient Adobe demo drawings (original artists not known).

As usual, the base document is HTML, which loads the SVG via an object tag. There is no JavaScript so that's it. Here is the root svg element, very bare bones:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="768" height="1024">

Both of them are relatively large drawings, but we just want smaller ones, so we scale them down to about 100x100. Here is the tiger:

<svg id="tiger" viewBox="-190 -150 510 510" height="100" width="100">

You see that we use the viewBox to scale the drawing which is in points so it fits in a 100x100 box. And we give the element an ID of "tiger" Simple.

Unfortunately, we can't do that with King Tut because none of the browsers support animating a nested svg element (boo! hiss!). So we have to fake a viewBox by specifying the equivalent transform elements:

<g  id="kingtutX">
    <g id="kingtutY">
        <g transform="translate(-10.156 -6.3636) scale(0.15625, 0.127)">

Also note that we have to have two g elements, one for X and one for Y because two CSS animations can't target a single element (or at least it didn't work in any browser the author has).

So now for the animation. Animating the tiger couldn't be easier:

<animate xlink:href="#tiger" attributeName="x" values="0;668;0" dur="9s" repeatCount="indefinite"/>
<animate xlink:href="#tiger" attributeName="y" values="0;924;0" dur="5s" repeatCount="indefinite"/>

CSS animation works by specifying a CSS style that has the properties that are to be animated and the timing info (duration, repeats, etc.). Then there is a separate @keyframe rule that defines when the steps of the animation occur.

   <style>
        #kingtutX {
            animation: kingtutX 10s linear infinite;
            transform: translateZ(0);
        }

        #kingtutY {
            animation: kingtutY 4.5s linear infinite;
            transform: translateZ(0);
        }

        @keyframes kingtutX {
            0% {
                transform: translateX(693px);
            }
            50% {
                transform: translateX(0px);
            }
            100% {
                transform: translateX(693px);
            }
        }

        @keyframes kingtutY {
            0% {
                transform: translateY(0px);
            }
            50% {
                transform: translateY(930px);
            }
            100% {
                transform: translateY(0px);
            }
        }
    </style>

Not as concise a clear as the equivalent SMIL, but it does work.

If you go and try the animation you'll find the tiger and King Tut bouncing happily around the page. Unfortunately, they are such complex drawings that the animation isn't smooth. Wouldn't it be nice if we could offload the work on the GPU? In theory, you can. If you specify a GPU-specific property, some browsers (e.g. Chrome) will create a "layer" and essentially rasterize the specified HTML element and load it into the GPU as GL texture where it will be animated as a whole. This is why you see the transform:translateZ(0) property in the kingTut rules. Unfortunately, it doesn't work. Apparently this support doesn't work for SVG.

And that's it! Click on this link to see the actual rendered demo in all its bouncing glory!!!