Convierte SVG animado a película

21

Tengo un SVG animado y me gustaría convertirlo en una película (una serie de imágenes también lo haría). La animación se reproduce en los navegadores webkit (Safari, Chrome) y en el garabato de Batik ). Intenté capturarlo con un capturador de pantalla. Pero la película termina bastante desigual.

¿Hay una buena herramienta para esto?

Aquí hay un ejemplo de animación:

<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>
Benjamin Wohlwend
fuente
2
Hay un convertidor SVG a APNG ( littlesvr.ca/apng/svg2png ), probablemente se puede usar alguna otra herramienta para convertir el APNG a una película o separar los fotogramas.
kartikmohta
1
@kartikmohta: Agregue eso como respuesta.
Caracol mecánico

Respuestas:

4

¿Has intentado usar Squiggle para exportar una serie de cuadros? Encontré que hacer garabatos era un fastidio para que tu línea llegara justo donde quería que fuera para configurar correctamente una serie de cuadros. Sin embargo, una vez que tenga eso, puede usar imagemagick , aparentemente mi respuesta favorita esta semana ;-) para transformarlo como quiera.

Suponiendo que cada uno guarda los cuadros como frame01.svg, frame02.svg, etc. Luego esto:

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

creará un único gif animado de sus cuadros que se repetirá para siempre, 5 ms entre cuadros.

convert convertirá svg a, pero imagemagick no procesa la etiqueta animateTransform, por lo que cualquier salida es estática.

Actualización: Me pareció muy difícil trabajar con el garabato (al menos al tratar de detener la animación en el lugar correcto para tomar una imagen, ¡me avergonzaba haberlo sugerido!

Aquí hay un script bash que usa imagemagick para convertir tu svg en un gif animado: antes de ejecutar este script, dividí tu svg de ejemplo en 2 partes: bg.svg contiene el elipse y el elemento 'pit' y hand.svg contiene solo el 'sec' elemento

`#!/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

~
Estoy seguro de que alguien más inteligente que yo podría descubrir cómo fusionar la conversión y combinar todo en un solo paso sin girar también el bg.png, pero esto es lo que obtienes gratis ;-)

Además, quería mantener esto simple, en caso de que necesite volver a implementarse como un archivo bat de Windows.

El i = i + 5 es una compensación entre lo suave que se ve la animación y el tamaño del archivo.

Nota: Incluso con -delay 1 (1 ms entre cuadros), firefox no movería la mano en un círculo completo en 5 segundos. Estaba más cerca de 10 segundos.

Y esto es lo que produjo el guión

DaveParillo
fuente
4

Encontré una manera de crear la serie de imágenes con la ayuda de canvg . Para ejecutar la siguiente página, debe usar una secuencia de comandos modificada de canvg.js ya que la función de dibujo es accesible.

Cambios en el script canvg.js (v1.0):

En la línea 2321 cambie de:

var draw = function() {

a:

svg.draw = function() {

En la línea 2361 y 2390 cambiar de:

draw();

a:

svg.draw();

Mi script de generación:

<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>
Manni
fuente
3

Si está utilizando FireFox, puede probar SVG Render Plug en: http://adasek.cz/svgrender/

IOOI
fuente
Esta es una buena sugerencia. Pero no puedo entender cómo hacer que la captura comience y termine cuando la animación real comience y termine.
posfan12