SVG animaties met snap.svg

SVG is bedoeld om vector illustraties op het web te tonen. De structuur van de taal bestaat namelijk uit xml. Daarom is het ook gemakkelijk om svg objecten te beïnvloeden met javascript.

Snap.svg is een javascript library die daar heel mooi gebruik van maakt. Zo kun je gemakkelijk zelf keigave animaties en ander interactieve applicaties bouwen.

http://snapsvg.io/

Voor mijn porftolio intro wilde ik een kameleon animeren die met zijn tong een duizendpoot vangt en vervolgens op eet. Het resultaat kun je bekijken op http://daniel-dewit.nl als je een paar keer naar beneden scrollt. Het eerste wat ik nodig had was een svg-illustratie van  een kameleon. Die heb ik in het programma Inkscape gemaakt.

https://inkscape.org/en/

chameleon_compiled

Inkscape is een handig programma omdat het gebaseerd is op het svg formaat. Illustraties die je maakt in Inkscape worden dus standaard opgeslagen als svg-afbeelding. Als je een svg-afbeelding voor het web wilt maken is het wel belangrijk om bij het opslaan te kiezen voor ‘geoptimaliseerde svg’. Er wordt dan leesbare code gegenereerd en je krijgt dan een aantal extra opties zoals het instellen van een viewbox. Viewbox is belangrijk bij het maken van responsive svg-afbeeldingen.

inkscape-export

Als je de afbeelding hebt opgeslagen kun je die openen in een tekst-editor en alle code er uithalen om in je webapplicatie te gebruiken. De volgende stap is om je svg-afbeelding met snap aan een javascript variabele te binden. Dat doe je met de functie Snap(). Daarna kun je onderdelen uit je svg-afbeelding aan aparte variabelen binden met select() zodat je die kunt animeren.

var chameleon = Snap("#chameleon");
var chameleonWrap = chameleon.select("#chameleon-wrap"); 
var chameleonMaw = chameleon.select("#chameleon #jaw"); 
var chameleonTongue = chameleon.select("#chameleon #tongue");
var chameleonHead = chameleon.select("#chameleon #head");

Nu heb ik een svg-afbeelding gemaakt en die verbonden met javascript variabelen. Er beweegt echter nog niets en dat is natuurlijk wel wat we willen doen. Snap.svg heeft daar een mooie functie voor, genaamd animate(). Met die functie kun je een nieuwe positie aangeven, de tijd die de animatie in beslag neemt en een versnellingsfunctie.

In mijn geval wil ik eerst de kaak openen voordat de tong uit de bek van de kameleon schiet. Daarvoor moet ik eerst weten hoe de functie animate() precies werkt. Die functie accepteert namelijk voor de nieuwe positie een array met svg-attributen. Om een vlak uit de svg-afbeelding te draaien moet ik het attribuut ‘transform’ aanpassen met de functie rotate(). En in die functie kun je de graden van de draaihoek en de x- en y-positie van de as aangeven. Bij mij wordt dat dan transform=”rotate(-20, 260, 110)”. In de snap functie animate() ziet dat er weer een klein beetje anders uit:

chameleonHead.animate({transform: 'r-20, 260, 110'}, 500, mina.easein);
chameleonMaw.animate({transform: 'r30, 260, 110'}, 500, mina.easein);
chameleonTongue.animate({transform: 'r20, 260, 110'}, 500, mina.easein);

Wanneer je dit script uitvoert in de browser zullen het hoofd en de tong en kaak van de kameleon in een halve seconde een draai maken. Maar nu wil ik ook nog de tong uit de bek laten schieten en tegen de duizendpoot laten botsen. Dat is iets ingewikkelder omdat ik daarvoor een pad moet aanpassen. In de code is dat niet te doen, maar met Inkscape is dat een stuk makkelijker.

Eerst draai ik ook in inkscape het hoofd, de kaak en de tong van de kameleon zodat de tong tevoorschijn komt op het canvas. Dat doe ik door de XML-editor te openen (bewerken > XML-editor) en de juiste elementen op te zoeken. Vervolgens kan ik in de editor het attribuut ‘transform’ toevoegen en de functie rotate() invullen.

inkscape xml editor rotate

Als ik dat heb toegepast kan ik op het canvas de tong bewerken door simpelweg pad-punten te verslepen. Tenslotte moet het pad weer terugvertaald worden naar een code. Die vind ik terug door in de XML-editor het pad van de tong op te zoeken en het attribuut ‘d’ aan te klikken. De code die dan tevoorschijn komt kan ik kopiëren en gebruiken met snap.svg.

inkscape xml editor

chameleonTongue.animate({d: 'm 254.142,105.465 c -0.91945,-4.73936 212.92389,-28.907989 374.41877,-26.893877 14.68355,0.183128 30.33905,15.332279 43.93075,15.714335 17.63322,0.495662 25.77761,-27.528571 41.00876,-25.899587 12.10879,1.295046 21.50394,13.74826 29.96377,19.69398 17.4323,12.251739 18.0602,-38.721554 26.41324,-35.997065 18.82566,6.140313 10.78299,32.752814 12.73743,45.135922 1.70453,10.799752 19.51626,40.672592 2.80281,46.348052 -5.31187,1.80377 -15.86623,-33.98243 -36.06211,-32.1603 -18.51088,1.6701 -24.00996,-14.403424 -36.34335,-12.354748 C 700.70693,101.0957 690.0714,117.01068 675.42381,116.11625 658.40639,115.07712 631.04537,95.873998 612.28816,95.29318 480.63912,91.216661 328.49376,115.83493 322.005,118.183 c -13.249,3.929 -66.362,-4.981 -67.863,-12.718 z'}, 100, mina.linear);

Handig om te weten is dat de animate() functie ook een callback accepteert. Op die manier kun je nadat je animatie klaar is een nieuwe animatie uitvoeren door opnieuw de animate() functie aan te roepen.

chameleonTongue.animate({transform: 'r0, 260, 110'}, 500, mina.easein,function() {
    chameleonTongue.animate({transform: 'r15, 260, 110'}, 500, mina.easein);
});

Een gedachte over “SVG animaties met snap.svg”

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *