views:

359

answers:

2

So I have an SVG file created in Inkscape embedded in a webpage, and I'd like it to rotate slowly. I've tried using Javascript and inserting animation commands directly into the SVG, but nothing works. I don't want to load in an entire JS library for this one task. This is what I have so far:

<html>
    <body bgcolor="#333333">
        <embed src="gear.svg" id="gear" width="1000" height="1000" style="position: absolute; top: -500px; left: -500px;" />
        <script type="text/javascript">
            var gear = document.getElementById("gear");
            window.setInterval(function() {
                // Somehow animate the gear.
            }, 10);
        </script>
    </body>
</html>
+2  A: 
  • Add a <g> element inside your <svg> element that wraps everything inside the <svg>, and add <animateTransform type="rotate" attributeName="transform" values="0 cx cy;360 cx cy" dur="30s"/> as a child of that <g> element, and replace "cx" and "cy" with whatever actual absolute point you want to use as the center of rotation, e.g "100 300". Should work in the newest generation of web browsers, apart from IE9.
  • Animate the rotatation using CSS3 2d transforms, noting that you'll have to use at least three different vendor prefixes in the process (-webkit-transform, -moz-transform, -o-transform). Should work in the newest generation of web browsers, unsure about IE9 though.
  • Add a <g> element inside your <svg> element that wraps everything inside the <svg> and then add a <script> inside it that does yourGelement.setAttribute("transform", "rotate(" + (newRotation++) + " cx cy)") from a window.setInterval timer, as before replace the cx and cy with your center of rotation. This solution should be less than 10 lines of code, and should work fine even in older implementations that don't support declarative (SMIL) animations (e.g IE9, Firefox2, Safari3).
Erik Dahlström
Good, complete answer, you were faster than me! :-)Does FF3 support Smil animation now? I haven't tried yet.
PhiLho
The firefox 3.7 alpha I have supports at least parts of it: http://blog.dholbert.org/2009/10/smil-enabled-by-default-on-nightly.html. Feel free to test it yourself against the w3c svg testsuite, http://dev.w3.org/SVG/profiles/1.1F2/test/harness/
Erik Dahlström
+1  A: 

Interesting topic because AFAIK currently Firefox doesn't support animation in SVG.
So I made a little investigation and found a working solution. Tested in Firefox 3.6, IE7 with Adobe plug-in, Opera 10.51, Safari 4.0.5, Chrome 5.0.
The background of the SVG area has no transparency in IE7, Safari and Chrome... I might try with the object tag (not supported by IE, probably need some conditional HTML...).

[EDIT] OK, I changed to use the more standard object (embed have never been defined in HTML...) except for IE where it isn't well supported by Adobe SVG plugin. The latter allows to add an attribute to have transparency of the embed object. For Webkit-based browsers, no transparency: see object embedded in HTML: default background should be transparent bug.

The HTML code:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
                      "http://www.w3.org/TR/html4/strict.dtd"&gt;
<html lang="en">
    <head>
        <title>Animating SVG</title>
    </head>
    <body bgcolor="#CCAAFF" onload="RotateSVG()">
        <!--[if !IE]> -->
        <object id="gear" data="gear.svg" type="image/svg+xml"
                width="500" height="500"
                style="position: absolute; top: -250px; left: -250px;">
        <!--<![endif]-->
            <embed id="gear" src="gear.svg" type="image/svg+xml"
                    width="500" height="500" wmode="transparent"
                    style="position: absolute; top: -250px; left: -250px;"/>
        <!--[if !IE]> -->
        </object>
        <!--<![endif]-->

        <div onclick="RotateSVG()"
                style="position: absolute; top: 250px; background-color: #ACF;">Start / Stop</p>

        <script type="text/javascript">
var animator;
var angle = 0;
function RotateSVG()
{
    if (animator != null)
    {
        // Just stop
        clearInterval(animator);
        animator = null;
        return;
    }

    var svgTag = document.getElementById("gear");
    var svgDoc = null;
    try
    {
        // Most modern browsers understand this
        svgDoc = svgTag.getSVGDocument();
    }
    catch (ex) {} // Ignore error
    if (svgDoc == undefined)
    {
        svgDoc = svgTag.contentDocument; // For old Mozilla?
        if (svgDoc == undefined)
        {
           alert("Cannot get SVG document");
           return;
       }
    }

    var gear = svgDoc.getElementById("gearG");
    if (gear == null)
    {
        alert("Cannot find gearG group");
        return;
    }

    animator = setInterval(
        function ()
        {
            angle += 5;
            gear.setAttribute("transform", "rotate(" + angle + " 250 250)");
        }, 100);
}
        </script>
   </body>
</html>

The SVG code I used (only the ID is important, the SVG is from Mozilla SVG Project):

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     version="1.1"
     baseProfile="full">
<!-- http://www.mozilla.org/projects/svg/ -->
  <g id="gearG" fill-opacity="0.7" stroke="black" stroke-width="0.1cm">
    <circle cx="6cm" cy="2cm" r="100" fill="red"
                    transform="translate(0,50)" />
    <circle cx="6cm" cy="2cm" r="100" fill="blue"
                    transform="translate(70,150)" />
    <circle cx="6cm" cy="2cm" r="100" fill="green"
                    transform="translate(-70,150)" />
  </g>
</svg>
PhiLho