Hlavní navigace

Pokročilejší animace ve formátu SVG

Pavel Tišnovský 20. 9. 2007

V dnešní části seriálu o grafických formátech a metaformátech si ukážeme, jakým způsobem je možné v grafickém vektorovém formátu SVG (Scalable Vector Graphics) vytvářet složitější animace založené na skládání lineárních transformací a také pohybu objektů po zadaných křivkách.

Obsah

1. Animace vytvořená skládáním transformací
2. První demonstrační příklad – animace vytvořená pomocí složené transformace
3. Animace pohybu objektů po zadané cestě
4. Druhý demonstrační příklad – animace pohybu grafických objektů
5. Pokročilejší možnosti nastavení animace pohybu objektů po zadané cestě
6. Třetí demonstrační příklad – pohyb grafických objektů s autorotací
7. Obsah další části tohoto seriálu

1. Animace vytvořená skládáním transformací

V předchozí seriálu o grafických formátech jsme si ukázali tvorbu animací založenou na postupné změně některého z atributů grafických objektů. Tímto způsobem je snadné například měnit barvu objektu, některou jeho souřadnici (typicky souřadnici vrcholu úsečky, středu kružnice, rohu obdélníka), průhlednost objektu, délku jeho stran, poloměr atd. V případě složitějších animací však přestávají tyto ve své podstatě jednoduché prostředky dostačovat a je zapotřebí využít dalších možností, které nám grafický formát SVG (Scalable Vector Graphics) pro tvorbu animací umožňuje používat. Jedná se především o skládání lineárních transformací, definici pohybu objektu po zadaných křivkách a využití skriptování společně s DOM (Document Object Model). V dnešní části se zaměříme především na popis způsobu skládání lineárních transformací a definici pohybu objektu po křivkách.

5601
Obrázek 1: První demonstrační příklad – začátek animace

Animace založená na průběžné změně transformační matice, která je na grafický objekt aplikována, se provádí pomocí značky <animateTransfor­m>. Tato značka má několik atributů. Některé bývají téměř vždy nastaveny na stejnou hodnotu; typicky se jedná o atributy attributeName=„Tran­sform“ – bude se měnit transformační matice, a attributeType=„XML“ – specifikace typu (resp. způsobu zápisu atributu). Další atributy a jejich význam již známe. Jedná se především o atribut begin (začátek změny transformace zadaný v časových jednotkách), dur (délka změny transformace opět zadaná v časových jednotkách), fill (na jakou hodnotu bude nastavena transformační matice po proběhnutí animace), from (počáteční hodnota transformace) a to (koncová hodnota transformace).

Pomocí hodnot atributů from a to se zadává počáteční a koncová hodnota plně popisující zvolenou transformaci (interně přepočítaná do podoby transformační matice), což znamená, že v případě posuvu (translate) zde budou uvedeny dvě číselné hodnoty oddělené čárkou a v případě rotace či změny měřítka je hodnota obou atributů pouze jedna.

5602
Obrázek 2: První demonstrační příklad – pokračování animace

Transformace je také možné skládat, například vytvořit animaci, při které se objekt otáčí a k tomu posunuje po úsečce. Složené transformace (a tím i složeného pohybu) se dosáhne jednoduše – použije se více značek <animateTransfor­m>. V tomto případě je však nutné specifikovat, zda se má opravdu jednat o skládání transformací, tj. kumulativní změnu transformační matice daného grafického objektu, nebo má každá transformace přepsat transformační matici na novou hodnotu bez ohledu na její původní obsah.

Rozhodnutí o kumulativní změně či neustálém přepisu transformační matice grafického objektu se provádí na základě hodnoty atributu additive. Pokud je nastavena hodnota „replace“, provádí se vždy změna celé transformační matice, v případě volby hodnoty „sum“ se provádí kumulativní změny (což je pro specifikaci mnoha animací výhodnější). Je zapotřebí si dát pozor na to, že výchozí hodnotou atributu additive je „replace“ a ne „sum“.

5603
Obrázek 3: První demonstrační příklad – střed animace

2. První demonstrační příklad – animace vytvořená pomocí složené transformace

V dnešním prvním demonstračním příkladu, jehož zdrojový kód ve formátu SVG lze získat pod tímto odkazem, je ukázána tvorba jednoduché animace založené na složené transformaci rotace a translace (posunu), která je kombinovaná s průběžnou změnou jednoho vizuálního atributu objektu. Objektem, na který je animace aplikována, je obdélník o velikosti 40×40 délkových jednotek (pokud zůstane zachován poměr stran obrázku, tak se jedná o čtverec). Ve výchozím stavu má obdélník zaoblené všechny čtyři rohy pomocí kruhového oblouku o poloměru 20 délkových jednotek, což znamená, že skutečný tvar tohoto objektu se spíše podobá kružnici.

Samotná animace je specifikovaná pomocí dvou značek <animateTransfor­m> a jedné značky <animate>. Význam značky <animate> je jednoduchý – pomocí ní je nastavena průběžná změna zaoblení rohů grafického objektu. Původní zaoblení o poloměru 20 délkových jednotek se po čtyřech sekundách snižuje na poloměr 0 délkových jednotek – tvar objektu se tedy mění od kružnice do čtverce.

5604
Obrázek 4: První demonstrační příklad – snímek pořízený krátce před koncem animace

Pomocí první značky <animateTransfor­m> je nastavena průběžná změna translace (posunu) objektu. Počáteční souřadnice pro tuto transformaci mají hodnotu [0, 0] délkových jednotek, koncová souřadnice hodnotu [190, 190] délkových jednotek. U obdélníku se zadávají souřadnice levého horního rohu, které mají v našem případě hodnotu x=0 a y=0. To znamená, že na začátku animace se levý horní roh grafického objektu posune na souřadnice [10+0, 10+0] a objekt je posouván po přímé cestě až na souřadnice [190+0, 190+0]. Současně se však provádí i transformace zadaná druhou značkou <animateTransfor­m>.

V této značce je specifikovaná transformace rotace objektu okolo svého počátečního bodu, což je v případě obdélníku jeho levý horní roh. Na začátku animace je rotace nulová (0°), na konci animace pak rotace dosahuje hodnoty 360°. To znamená, že se objekt po dokončení celé animace otočí okolo svého levého horního rohu. Pokud by bylo vhodnější objektem rotovat okolo středu, bylo by nutné zavést třetí lineární transformaci – posun o vektor (20, 20) délkových jednotek.

Vzhledem k tomu, že při animaci dochází k současnému provádění dvou transformací, tj. k posunu a rotaci, je pohyb objektu komplikovanější, než tomu bylo u demonstračních příkladů uvedených v předchozí části tohoto seriálu. To ještě podtrhuje fakt, že se objekt neotáčí okolo své osy, ale okolo levého horního rohu, který není vždy zakreslen (pokud je zrovna poloměr zaoblení rohů nenulový). Zdrojový kód dnešního prvního demonstračního příkladu má tvar:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
                     "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400"
     height="400"
     viewBox="0 0 200 200"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

     <!-- obdélník o velikosti 40x40 délkových jednotek se zaoblenými rohy -->
     <rect x="0" y="0" width="40" height="40" rx="20"
           stroke="black" stroke-width="1" fill="yellow">

         <!-- animovaná transformace posunu objektu s délkou trvání 20 sec -->
         <animateTransform attributeName="transform" attributeType="XML"
                           additive="sum" type="translate"
                           begin="0s" dur="20s" fill="freeze"
                           from="10,10" to="190,190" />

         <!-- animovaná transformace rotace objektu s délkou trvání 20 sec -->
         <animateTransform attributeName="transform" attributeType="XML"
                           additive="sum" type="rotate"
                           begin="0s" dur="20s" fill="freeze"
                           from="0" to="360" />

         <!-- animovaná změna zaoblení rohů obdélníka s délkou trvání 5x4 sec -->
         <animate attributeName="rx" attributeType="XML"
                  begin="0s" dur="4s" fill="remove"
                  from="20" to="0" repeatCount="5" />
     </rect>
</svg> 

5605
Obrázek 5: První demonstrační příklad – konec animace

3. Animace pohybu objektů po zadané cestě

Animace prováděná postupnou změnou transformací je sice velmi mocným prostředkem, ne vždy je však možné pohyb objektu (tj. jeho trajektorii) zachytit pomocí skládání posunů a rotací. Pokud je pohyb objektu složitější, což se v případě mnoha animací stává spíše pravidlem, je pro popis pohybu vhodnější použít nějakou křivku. Ve druhé části našeho povídání o grafickém formátu SVG jsme si ukázali tvorbu cest, což jsou ve skutečnosti otevřené či uzavřené křivky vytvářené pomocí úsečkových elementů, kvadratických Bézierových křivek a kubických Bézierových křivek. Podobným způsobem jako tvar cesty lze specifikovat i trajektorii pohybu objektu. K tomuto účelu je ve formátu SVG určena značka <animateMotion>, která se, podobně jako i ostatní značky pro specifikaci animace, vkládá mezi počáteční a koncovou značku nějakého grafického objektu, kterým může být například kruh, obdélník, text či dokonce samotná cesta.

5606
Obrázek 6: Druhý demonstrační příklad – začátek animace

Ke značce <animateMotion> se váže mnoho atributů, z nichž některé už známe – jsou to atributy sloužící k načasování animace, tj. begin, dur a fill. Dále se v této značce může pomocí hodnoty atributu calcMode specifikovat režim interpolace mezi jednotlivými vrcholy křivky, kterou se zadává trajektorie objektu. Při nastavení calcMode=„dis­crete“ bude objekt „skákat“ mezi jednotlivými vrcholy, což je pro naprostou většinu animací nepřijatelné. Další přípustné hodnoty jsou calcMode=„linear“ (lineární přechod), calcMode=„paced“ (interpolace se snahou o plynulý pohyb) a calcMode=„spline“ (interpolace na základě Bézierových křivek, ovšem musí být zadány klíčové řídicí body). Nejvhodnější je, zejména při ručním vytváření SVG souborů, použít režim calcMode=„paced“, při kterém se nemusí složitě specifikovat žádné dodatečné hodnoty kromě časování animace a samotné křivky představující trajektorii.

5607
Obrázek 7: Druhý demonstrační příklad – průběh animace

Posledním důležitým atributem značky <animateMotion> je zápis trajektorie, který je proveden stejným způsobem, jako zápis tvaru cesty. Jinými slovy se jedná o atribut nazvaný jednoduše path (v případě cest šlo o atribut d, jehož označení je odvozeno od slova definition či data), jehož hodnotou je řetězec popisující křivku. Způsob vytváření tohoto řetězce jsme si již vysvětlili v druhé části povídání o formátu SVG.

Zde pouze připomenu, že znak M znamená přechod na zapsané souřadnice (move), znak L kresbu úsečky/lineární přechod (line), znak C kresbu Bézierovy kubické křivky (cubic) a konečně znak Q kresbu Bézierovy kvadratické křivky (quadratic). Kromě toho se v posledním demonstračním příkladu setkáme se znakem T, kterým se také vytváří Bézierova kvadratická křivka, ovšem nespecifikují se u ní tři řídicí body, ale pouze bod jeden (ostatní dva body jsou vypočteny na základě tečny k již zkonstruované křivce).

5608
Obrázek 8: Druhý demonstrační příklad – cca polovina animace

Při nastavení režimu calcMode=„paced“ je proveden postupný výpočet souřadnic bodů ležících na zadané křivce a výsledná poloha bodu je v každém snímku animace připočtena k transformační matici příslušného grafického objektu. To znamená, že transformace lze opět skládat, například objektem otáčet a k tomu ho posunovat po složité trajektorii. Typicky se pro posuny používají Bézierovy křivky, protože lineární přechody (zapisované pomocí znaků M a L) lze využít pouze pro jednodušší pohyby. Ve druhém demonstračním příkladu, který je vypsán v následující kapitole, si však ukážeme jak lineární posun objektu po úsečce, tak i složitější pohyb téhož objektu po Bézierově křivce.

4. Druhý demonstrační příklad – animace pohybu grafických objektů

Ve druhém demonstračním příkladu, jehož zdrojový kód lze získat pod tímto odkazem – ovšem bohužel opět se špatným MIME typem – je ukázáno, jakým způsobem se vytváří animace založená na pohybu objektů po zadané trajektorii. Nejdříve jsou nakresleny dvě cesty, které odpovídají zvoleným trajektoriím. Tyto cesty se v průběhu animace nemění a jsou umístěné na pozadí celého výkresu. Nad cestami jsou vytvořeny dva objekty, jeden ve tvaru kruhu a druhý ve tvaru čtverce se zaoblenými rohy. Oba objekty se pohybují po trajektoriích, jejichž průběh je stejný jako tvar nakreslených cest (řetězce u atributu d a atributu path jsou naprosto stejné). Povšimněte si, že je možné kombinovat lineární úseky s Bézierovými křivkami, prohlížeč si poradí i se skokovými změnami vektoru rychlosti.

5609
Obrázek 9: Druhý demonstrační příklad – průběh animace
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
                     "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400"
     height="400"
     viewBox="0 0 200 200"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

     <!-- vykreslení cest, po kterých se objekty pohybují -->
     <path stroke="lightblue" stroke-width="1" fill="none"
         d="M0,0 C100,0 100,200 160,100" />
     <path stroke="#f80" stroke-width="1" fill="none"
         d="M100,100 L10,100 L10,10 C200,0 100,200 190,190" />

     <!-- obdélník o velikosti 40x40 délkových jednotek se zaoblenými rohy -->
     <rect x="0" y="0" width="40" height="40" rx="10"
           stroke="black" stroke-width="1" fill="yellow"
           transform="translate(-20, -20)">
         <!-- animovaná transformace posunu objektu s délkou trvání 20 sec -->
         <animateMotion calcMode="paced"
                        path="M0,0 C100,0 100,200 160,100"
                        begin="0s" dur="5s" fill="freeze" />
     </rect>

     <!-- kružnice o poloměru 10 délkových jednotek -->
     <circle cx="0" cy="0" r="10"
           stroke="black" stroke-width="1" fill="red">
         <!-- animovaná transformace posunu objektu s délkou trvání 20 sec -->
         <animateMotion calcMode="paced"
                        path="M100,100 L10,100 L10,10 C200,0 100,200 190,190"
                        begin="0s" dur="5s" fill="freeze" />
     </circle>
</svg> 

5610
Obrázek 10: Druhý demonstrační příklad – konec animace

5. Pokročilejší možnosti nastavení animace pohybu objektů po zadané cestě

Při pohybu objektů po trajektorii je interně v každém snímku animace měněna transformační matice příslušná k danému grafickému objektu. To znamená, že je možné kombinovat pohyb objektu po trajektorii s rotací objektu, jeho zkosením, změnou měřítka atd. I tyto transformace se samozřejmě mohou měnit v čase a ovlivňovat tak celou animaci. Ovšem v mnoha případech potřebujeme, aby se objekt při posunu po zadané křivce natáčel tak, aby jeho aktuální natočení odpovídalo tečnému vektoru v daném místě křivky. V praxi by bylo velmi složité takovouto transformaci popsat pomocí skládání několika rotací, avšak ve formátu SVG – přesněji řečeno přímo ve značce <animateMotion> – je možné povolit automatické natáčení objektu. Postačuje nastavit atribut rotate na hodnotu „auto“ a prohlížeč sám na základě tečných vektorů dopočítá rotaci objektu.

5611
Obrázek 11: Třetí demonstrační příklad – začátek animace

Kromě toho je možné nastavit hodnotu atributu rotate na nějaký konkrétní úhel (počítaný od osy x) nebo na hodnotu „auto-reverse“. Při tomto nastavení je opět automaticky počítán úhel na základě tečného vektoru ke křivce, ovšem k tomuto úhlu se vždy připočítá hodnota 180°. Veškeré takto vypočtené rotace jsou na objekt aplikovány až po všech dalších transformacích, což díky způsobu skládání transformací znamená, že je objekt nejdříve natočen do správné polohy a teprve poté posunut do místa určeného aktuálním bodem na křivce. Opačné provádění transformací (tj. posun objektu od počátku a teprve poté rotace) by v praxi nedávalo smysl.

5612
Obrázek 12: Třetí demonstrační příklad – snímek zachycený blízko začátku animace

6. Třetí demonstrační příklad – pohyb grafických objektů s autorotací

Ve třetím demonstračním příkladu je vytvořena animace posunu objektu po trajektorii specifikované pomocí Bézierových kvadratických křivek, spolu s automatickou rotací tohoto objektu. Za zmínku stojí již samotné vytvoření trajektorie: nejdříve je specifikován počáteční bod cesty, potom se vytvoří jeden oblouk Bézierovy kvadratické křivky (v tomto případě postačuje zadat pouze dva řídicí body, protože první bod již známe) a všechny další oblouky jsou specifikovány pouze jedním řídicím bodem (konkrétně koncovým bodem křivky), protože zbylé dva řídicí body jsou dopočítány automaticky na základě tečného vektoru na konci konstruované křivky.

Na tomto způsobu zápisu můžeme vidět, že použití Bézierových kvadratických křivek vede k velmi kompaktnímu kódu, který má i další přednost: křivky jsou na sebe hladce navázány, takže nebude docházet ke skokové změně směru pohybu objektu (i z tohoto důvodu jsou Bézierovy kvadratické křivky použity ve formátu TrueType).

5613
Obrázek 13: Třetí demonstrační příklad – průběh animace
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
                     "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400"
     height="400"
     viewBox="0 0 200 200"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

     <path stroke="#08f" stroke-width="1" fill="none"
         d="M90,0 q0,0,20,20 t-20,20 t20,20 t-20,20 t20,20 t-20,20
            t20,20 t-20,20 t20,20 t-20,20 t20,20" />

     <!-- obdélník o velikosti 20x20 délkových jednotek se zaoblenými rohy -->
     <rect x="0" y="0" width="20" height="20" rx="5"
           stroke="black" stroke-width="1" fill="red" fill-opacity="0.5">

         <!-- animovaná transformace posunu objektu s délkou trvání 20 sec
              a s automatickou rotací -->
         <animateMotion calcMode="spline" rotate="auto"
                        path="M90,0 q0,0,20,20 t-20,20 t20,20 t-20,20
                        t20,20 t-20,20 t20,20 t-20,20 t20,20 t-20,20 t20,20"
                        begin="0s" dur="20s" fill="freeze" />
     </rect>

</svg> 

5614
Obrázek 14: Třetí demonstrační příklad – snímek zachycený blízko konce animace

7. Obsah další části tohoto seriálu

V následující části seriálu o grafických formátech a metaformátech si popíšeme způsob vytváření animací pomocí skriptů (například JavaScriptu, resp. přesněji ECMA Scriptu) a řízení vzhledu dokumentu pomocí DOM (Document Object Model). Tyto techniky sice nejsou dostupné ve všech aplikacích určených pro práci se SVG, ale minimálně internetové prohlížeče nebo jejich zásuvné moduly by měly tuto zajímavou a užitečnou funkcionalitu poskytovat.

5615
Obrázek 15: Třetí demonstrační příklad – konec animace
Našli jste v článku chybu?

24. 9. 2007 9:31

Zdravim,

docela dobry rozcestnik o SVG je na http://www.svgi.org/ (na tu stranku se da proklikat i z klasickeho w3c.org). Mezi animacni editory patri napriklad XStream RapidSVG 1.0, WebEngine 2 a Ikivo animator. Ne vsechno vsak bezi pod Linuxem nebo Windows.

SVG se s uspechem nasazuje na intranety, na verejnem internetu je to ta znama mapa s JavaScriptem (po kliku na region se objevi doplnujici informace) + docela zajimavy pokus o nahradu PowerPointovych prezentaci kombinaci SVG, XML a JavaScr…



25. 4. 2008 10:54

Harvie (neregistrovaný)
Bylo by kool, kdyby svg casem nahradil flash...
DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

Vitalia.cz: Pečete cukroví a zbyl vám bílek?

Pečete cukroví a zbyl vám bílek?

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně