Konwertuj animowane SVG do filmu

21

Mam animowany plik SVG i chciałbym go przekształcić w film (zrobiłaby to również seria zdjęć). Animacja jest odtwarzana w przeglądarkach internetowych (Safari, Chrome) oraz w squiggle Batika ). Próbowałem uchwycić to za pomocą przechwytywacza ekranu. ale film jest dość nieciekawy.

Czy jest na to dobre narzędzie?

Oto przykładowa animacja:

<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
źródło
2
Istnieje konwerter SVG na APNG ( littlesvr.ca/apng/svg2png ), prawdopodobnie można użyć innego narzędzia do konwersji z APNG na film lub rozdzielenia klatek.
kartikmohta
1
@kartikmohta: Dodaj to jako odpowiedź.
Ślimak mechaniczny

Odpowiedzi:

4

Czy próbowałeś użyć squiggle do wyeksportowania serii ramek? Znalazłem kłębek bólu, aby uzyskać linię dokładnie tam, gdzie chciałem, aby poprawnie ustawić serię ramek. Jednak gdy już to zrobisz, możesz użyć imagemagick - najwyraźniej mojej ulubionej odpowiedzi w tym tygodniu ;-), aby przekształcić ją w dowolny sposób.

Zakładając, że zapisujesz wszystkie ramki jako frame01.svg, frame02.svg itp. Następnie:

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

utworzy z animacji pojedynczy animowany gif, który zapętla się na zawsze, 5 ms między ramkami.

konwersja przekształci SVG na, ale imagemagick nie przetwarza znacznika animateTransform, więc każde wyjście jest statyczne.

Aktualizacja: Odkryłem, że squiggle jest tak bolesny w pracy (przynajmniej próbując zatrzymać animację we właściwym miejscu, aby zrobić zdjęcie, byłem zawstydzony, że nawet to zasugerowałem!

Oto skrypt bash wykorzystujący imagemagick do przekonwertowania pliku svg na animowany gif: Przed uruchomieniem tego skryptu podzieliłem przykładowy plik svg na 2 części: bg.svg zawiera elipsę, a element „pit”, a hand.svg zawiera tylko sekcję „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

~
Jestem pewien, że ktoś sprytniejszy ode mnie może wymyślić, jak połączyć konwersję i połączyć wszystko w jednym kroku bez obracania bg.png, ale to dostajesz za darmo ;-)

Chciałem również zachować to proste, na wypadek, gdyby trzeba go było zaimplementować jako plik nietoperza systemu Windows.

I = i + 5 to kompromis między gładkością animacji a rozmiarem pliku.

Uwaga: Nawet przy -delay 1 (1 ms między ramkami) firefox nie przesunąłby ręki w pełnym kole w ciągu 5 sekund. To było bliżej 10 sekund.

I oto, co wyprodukował skrypt

DaveParillo
źródło
4

Znalazłem sposób na stworzenie serii obrazów za pomocą canvg . Aby uruchomić następną stronę, musisz użyć zmodyfikowanego skryptu pliku canvg.js, w którym funkcja rysowania jest dostępna.

Zmiany w skrypcie canvg.js (v1.0):

W linii 2321 zmiana z:

var draw = function() {

do:

svg.draw = function() {

W wierszach 2361 i 2390 zmiana z:

draw();

do:

svg.draw();

Skrypt mojej generacji:

<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
źródło
3

Jeśli używasz FireFox, możesz wypróbować SVG Render Plug podczas próby: http://adasek.cz/svgrender/

IOOI
źródło
To dobra sugestia. Ale nie mogę wymyślić, jak zacząć i kończyć przechwytywanie, gdy rozpocznie się i zakończy faktyczna animacja.
posfan12