Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have an animated SVG and would like to turn it into a movie (a series of pictures would also do). The animation plays in webkit browsers (Safari, Chrome) and in Batik's squiggle). I tried capturing it with a screen capturer. but the movie ends up pretty jerky.

Is there a good tool for this?

Here's an example animation:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
    <rect id="BB" x="0" y="0" height="100%" width="100%" fill="white"/>
    <g id="firstone" stroke="black">
        <g id="g3" fill="none" stroke-width="2">
            <animateTransform attributeName="transform" type="rotate" dur="5s" from="360 100 100" to="0 100 100" repeatCount="indefinite"/>
            <g id="g2">
                <ellipse id="g1" cx="100" cy="100" rx="75" ry="75">
                </ellipse>
                <g id="sec">
                    <line x1="100" y1="100" x2="45" y2="45" style="stroke: rgb(99, 99, 99); stroke-width: 6;"/>
                </g>
            </g>
        </g>
        <g id="pit">
            <line x1="100" y1="175" x2="100" y2="200" style="stroke: red; stroke-width: 6;"/>
        </g>
    </g>
</svg>
share|improve this question
2  
There is a SVG to APNG converter (littlesvr.ca/apng/svg2png), probably some other tool can be used to convert from the APNG to a movie or separate the frames. –  kartikmohta Sep 29 '09 at 21:54
1  
@kartikmohta: Add that as an answer. –  Mechanical snail Jul 16 '12 at 23:23

3 Answers 3

up vote 3 down vote accepted

Have you tried using squiggle to export a series of frames? I found squiggle a pain to get your line just where I wanted it to be to properly set up a series of frames. However, once you have that, you can use imagemagick - apparently my favorite answer this week ;-) to transform it however you like.

Assuming each you save the frames off as frame01.svg, frame02.svg, etc. Then this:

convert -delay 5 -loop 0 frame??.svg animated.gif

will make a single animate gif from your frames that loops forever, 5 ms between frames.

convert will convert svg to , but imagemagick doesn't process the animateTransform tag, so any output is static.

Update: I found squiggle so painful to work with (at least trying to stop the animation at just the right spot to grab an image, I was embarrassed to have even suggested it!

Here's a bash script using imagemagick to convert your svg into an animated gif: Before running this script I split your example svg into 2 parts: bg.svg contains the elipse and the 'pit' element and hand.svg contains just the 'sec' element

`#!/bin/bash`

rm *.png
rm anim.gif

convert bg.svg -crop 200x200+0+0 +repage bg.png
convert hand.svg -crop 200x200+0+0 +repage -transparent white hand.png

for ((i=1; i<=359; i=i+3))
do
  convert hand.png -gravity center -rotate $i tmp.png
  n=`printf "%03d" $i`
  composite -gravity center tmp.png bg.png hand${n}.png
  rm tmp.png
done

convert -delay 1  -loop 0 hand*.png anim.gif

~
I'm sure someone more clever than me could figure out how to merge the convert and combine all in one step without also rotating the bg.png, but this is what you get for free ;-)

Also, wanted to keep this simple, just in case it needs to be reimplemented as a windows bat file.

The i=i+5 is a trade-off between how smooth the animation looks vs. file size.

Note: Even with -delay 1 (1 ms between frames), firefox would not move the hand in a complete circle in 5 seconds. It was closer to 10 secs.

And here's what the script produced

share|improve this answer
    
thank you very much for taking the time! –  Benjamin Wohlwend Oct 1 '09 at 18:27

I found a way to create the series of images with the help of canvg. To run the following page, you have to use a modified script of canvg.js in that the draw function is accessable.

Changes in script canvg.js (v1.0):

In line 2321 change from:

var draw = function() {

to:

svg.draw = function() {

In line 2361 and 2390 change from:

draw();

to:

svg.draw();

My generation script:

<html>
<head>
<script type="text/javascript" src="rgbcolor.js"></script> 
<script type="text/javascript" src="canvg.js"></script> 
<script type="text/javascript">

loadSVG = function() {
  canvg('canvas', '<animated SVG>', { ignoreMouse: true, ignoreAnimation: true });
}

function RenderNext(delta) {
    var c = document.getElementById("canvas");
    var svg = c.svg;

    for (var i=0; i<svg.Animations.length; i++) {
        svg.Animations[i].update(delta);
    }
    svg.draw();
}

function CreateImage(imgStr) {
    var oImg=document.createElement("img");
    oImg.setAttribute('src', imgStr);
    return oImg;
}

function start() {
    var c = document.getElementById("canvas");
    var result = document.getElementById("resultDiv");
    var maxDur = 5; // seconds
    var framerate = 5; // imgages per second

    for (var i = 0; i < framerate * maxDur; i++) {
        RenderNext(1000 / framerate);

        var oImg = CreateImage(c.toDataURL('image/png'));
        result.appendChild(oImg);
    }
}

</script>
</head>
<body onload="loadSVG()">

<canvas id="canvas" width="30px" height="30px"></canvas> 

<p>
<input type="button" id="start" value="Start" onclick="start()" /> 
</p>

<div id="resultDiv">
</div>

</body>
</html>
share|improve this answer

If you're using FireFox you might give SVG Render Plug in a try: http://adasek.cz/svgrender/

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.