Přejít k navigační liště

Zdroják » Webdesign » Podzim s SVG: Morphing alias Morfing

Podzim s SVG: Morphing alias Morfing

Články Webdesign

Plynulé transformace jednoho objektu do druhého patří k oblíbeným animačním technikám, přesto se ale v prostředí webu používají poměrně málo. Je to ale velká škoda, neboť s použitím SVG a SMIL, je to až trestuhodně snadné. V dnešním závěrečném dílu seriálu si ukážeme, jak morfovat mezi sebou nápis „PODZIM“ a několik dalších, podzim dobře reprezentujících tvarů, konkrétně dýně, klobouku čarodějnice a měsíce.

Nálepky:

Dnes budeme poněkud více pracovat v editoru Inkscape, neboť příprava těch správných křivek je pro morfing velice důležitá. Pro nápis si zvolíme v editoru požadovaný font (nástroj F8 a fontem je v našem případě Franklin Gothic Demi). Pro další netextové tvary budeme opět čerpat ze svobodných galerií clipartů na internetu (tvary pro zjednodušení ukazuji přímo v jejich finální podobě, ale platí pro ně víceméně totéž, co bude popsáno pro morfování textu).

NápisDalší podzimní tvary

Text musíme „rozbít“ a přestat s ním pracovat jako s textem, ale jako s křivkami, na což nám poslouží nástroj Object To Path (Shift+Ctrl+C) (uživatele Apple použijí namísto Ctrl samozřejmě Cmd). Výsledek konverze nám editor vloží do skupiny g, kterou ale nepotřebujeme a zrušíme ji pomocí stisku kláves Ctrl+U (Ungroup).

Nápis, konverze na křivky

Pro funkční morfing potřebujeme typově přesně stejné křivky pro každé jedno písmeno, čímž je míněno identický počet i typ uzlů, kterými je každá křivka tvořena. První tři písmena mají subsegmenty (vnitřní prázdné prostory, dutiny), které ale další tři písmena nemají, a proto je pro zjednodušení umažeme (nástroj pro editaci uzlů F2), tj. označit všechny tři subsegmenty (po jednom) a smažeme je (klávesou Delete). Na celkové čitelmnosti nám to naštěstí valně neubere a velmi to zjednoduší celý popisovaný příklad.

Nápis po umazání subsegmentu prvních písmen

Abychom tedy zajistili opravdu identický počet i typ uzlů, označíme vždy po jedné křivce písmene (stále v režimu editace uzlů F2), označíme všechny uzly křivky (Ctrl+A), zkontrolujeme si dole ve status řádku editoru, kolik že uzlů křivka přesně obsahuje, a pro sjednocení na jediný typ (použijeme Bézierovu křivku, schopnou vykreslit rovné i obloukové tvary) stiskneme Bézier konverzní klávesový příkaz Shift+U. U posledního písmene vyhodnotíme, které že je tvořeno největším počtem uzlů. V našem případě je to písmeno M složené ze 13 uzlů. Toto je tedy počet, na který budeme muset zvýšit počet uzlů křivek všech ostatních písmen. Ničeho se nebojte, pro přidání uzlu stačí dvojklik na libovolné volné místo na okraji křivky a toto opakovat až do potřebného počtu.

Nápis a přidávání uzlů křivkám na počet 13

Pozn: na obrázku vidíte navýšení počtu uzlů u písmene I z původních čtyřech na potřebných 13 (a jakkoliv se to může zdát absurdní, je to opravdu nutné).

Požadovaný efekt vyžaduje, abychom měli jedno písmeno pozicováno přes druhé na stejném místě, což v režimu selekčního nástroje (F1) provedeme přetažením všech ostatních na písmeno P. Nyní už můžeme vytvořený dokument uložit, ale ještě je vhodné editoru vnutit chování, aby ve výstupním formátu nepoužíval relativní souřadnice (což dělá pro zkrácení zápisu, kdykoliv je to výhodné), což provedeme v jeho preferencích (Shift+Ctrl+P) v záložce SVG Output, kde odškrtneme checkbox "Allow relative coordinates". Tím jsme připraveni k uložení dokumentu s požadovanými křivkami na disk (Save Ctrl+S). V uloženém dokumentu se snadno zorientujeme, v textovém editoru či IDE najdeme všechny elementy path, ze kterých nás zajímá pouze jejich atribut d se samotnou křivkou, které si zkopírujeme do nového dokumentu SVG.

Nápis, písmeno přes písmeno

Ano, principem celé animace nebude nic jiného, než že jediná vykreslená křivka bude postupně měnit své hodnoty values atributu d (animate attributeName="d") v požadovaná písmena, v trvání po dobu 10 sekund. Animace se bude opakovat stále dokola, takže bude pro plynulost začínat i končit stejnou křivkou písmene P. A protože chceme dát diváku šanci na chvíli si výsledek morfovaného tvaru v klidu prohlédnout, zdvojíme výskyt každého písmene, což se bude chovat tak, že každá druhá transformace bude do téhož samého tvaru jako je jeho výchozí, což pro diváka vytvoří efekt požadovaného chvilkového setrvání na právě zmorfovaném písmenu.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 49 49">
    <path>
        <animate attributeName="d" dur="10s" repeatCount="indefinite" values="
            &P; ; &P; ;
            &O; ; &O; ;
            &D; ; &D; ;
            &Z; ; &Z; ;
            &I; ; &I; ;
            &M; ; &M; ;
            &P; "/>
    </path>
</svg>

Pozn: zápis dat křivek písmen je ve formátu XML (SGML) entit. Co to je a proč je dobré je využít, se dozvíte vzápětí.

Jak vidíme, navrhovaný postup vyžaduje data každé křivky několikrát zopakovat, což je v případě datově objemné křivky celkem dost nevýhodné. Pomoci nám tomto případě může buď scriptování, a nebo a ještě elegantněji, entity dokumentu. Doposud jsme v uváděných příkladech nepovinnou DOCTYPE deklaraci opomíjeli, ale tentokrát ji k SVG dokumentu připojíme a právě v ní máme možnost pojmenované entity definovat a kdekoliv v dokumentu pak používat. V průběhu preprocesingu je entita v dokumentu nahrazena (obdobně jako v případě maker) za referencovaná data. SVG dokument s deklarací i použitím entit všech písmen pak vypadá takto:

<!DOCTYPE svg [
    <!ENTITY P "M 5.66,1.14 C 12.3,1.14 19,1.14 25.6,1.14 31.6,1.14 36.1,2.46 39.3,5.1 42.5,7.73 44.1,11.5 44.1,16.4 44.1,21.3 42.5,25 39.3,27.7 36.1,30.3 31.6,31.6 25.6,31.6 23,31.6 20.3,31.6 17.7,31.6 17.7,34.3 17.7,37 17.7,39.7 17.7,42.4 17.7,45.1 17.7,47.8 15.6,47.8 13.5,47.8 11.3,47.8 9.41,47.8 7.56,47.8 5.66,47.8 5.66,44.5 5.66,41.2 5.66,37.9 5.66,31.2 5.66,24.4 5.66,17.7 5.66,12.2 5.66,6.67 5.66,1.14 z">
    <!ENTITY O "M 24.6,0.3 C 28.6,0.3 32.2,0.917 35.3,2.15 38,3.22 40.3,4.75 42.3,6.74 43.7,8.14 44.8,9.73 45.8,11.5 47.7,15.1 48.6,19.5 48.6,24.5 48.6,28.4 48,31.9 46.9,34.9 45.9,37.7 44.3,40.2 42.3,42.3 38,46.6 32.1,48.7 24.6,48.7 17.2,48.7 11.2,46.6 6.94,42.3 4.74,40.1 3.14,37.4 2.04,34.3 1.04,31.5 0.544,28.2 0.544,24.5 0.544,19.3 1.54,14.9 3.64,11.2 4.54,9.55 5.64,8.06 6.94,6.74 11.2,2.45 17.2,0.3 24.6,0.3 z">
    <!ENTITY D "M 5.63,1.14 C 9.21,1.14 12.8,1.14 16.4,1.14 22.6,1.14 28,1.65 30.8,2.66 34.4,3.67 37,5.38 38.8,7.8 40.6,9.9 42.4,12.3 43.4,15.1 44.2,17.8 45.2,20.9 45.2,24.4 45.2,27.9 44.2,31.1 43.4,33.8 42.4,36.6 40.6,39 38.8,41.1 37,43.6 34.4,45.3 30.8,46.3 28,47.3 22.6,47.8 16.4,47.8 12.8,47.8 9.21,47.8 5.63,47.8 5.63,44.8 5.63,41.7 5.63,38.7 5.63,29.7 5.63,20.8 5.63,11.9 5.63,8.32 5.63,4.73 5.63,1.14 z">
    <!ENTITY Z "M 6.42,1.14 C 18.2,1.14 29.8,1.14 41.6,1.14 41.6,3.57 41.6,5.99 41.6,8.42 39.8,10.4 38.8,12.3 37,14.3 31.6,22.4 24.4,30.6 19,38.7 26.2,38.7 34.4,38.7 41.6,38.7 41.6,41.7 41.6,44.8 41.6,47.8 36.2,47.8 29.8,47.8 24.4,47.8 18.2,47.8 11.8,47.8 5.63,47.8 5.63,45.4 5.63,42.9 5.63,40.5 6.42,38.8 8.21,37.1 9.21,35.4 15.4,27 21.8,18.6 28,10.2 20.8,10.2 13.6,10.2 6.42,10.2 6.42,7.18 6.42,4.16 6.42,1.14 z">
    <!ENTITY I "M 19,1.14 C 20.8,1.14 22.6,1.14 25.4,1.14 26.2,1.14 28,1.14 29.8,1.14 29.8,3.72 29.8,6.3 29.8,8.87 29.8,11.6 29.8,14.3 29.8,17 29.8,19.8 29.8,22.7 29.8,25.5 29.8,33 29.8,40.4 29.8,47.8 28,47.8 26.2,47.8 24.4,47.8 22.6,47.8 20.8,47.8 19,47.8 19,43.8 19,39.9 19,35.9 19,32.5 19,29.2 19,25.8 19,22.8 19,19.9 19,17 19,14.3 19,11.6 19,8.87 19,6.3 19,3.72 19,1.14 z">
    <!ENTITY M "M 1.05,1.14 C 5.63,1.14 10,1.14 14.6,1.14 18.2,9.46 20.8,17.8 24.4,26.1 28,17.8 30.8,9.46 34.4,1.14 38.8,1.14 43.4,1.14 47.8,1.14 47.8,16.7 47.8,32.2 47.8,47.8 44.2,47.8 41.6,47.8 38,47.8 38,36.4 38,25.1 38,13.7 34.4,22.1 31.6,30.4 28,38.8 25.4,38.8 23.6,38.8 20.8,38.8 17.2,30.4 14.6,22.1 11,13.7 11,25.1 11,36.4 11,47.8 7.42,47.8 4.63,47.8 1.05,47.8 1.05,32.2 1.05,16.7 1.05,1.14 z">
]>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 49 49">
    <path>
        <animate attributeName="d" dur="10s" repeatCount="indefinite" values="
            &P; ; &P; ;
            &O; ; &O; ;
            &D; ; &D; ;
            &Z; ; &Z; ;
            &I; ; &I; ;
            &M; ; &M; ;
            &P; "/>
    </path>
</svg>

Pozn: je důležité neuvádět středník za poslední ze všech hodnot values, neboť Webkit/Blink-based prohlížeče toto neumí (navzdory specifikaci) vůbec vyrenderovat.

Abychom celou animaci udělali o něco zajímavější, přidáme do dokumentu ještě obrázek podzimní jesenické pastviny se šípky (autorkou je má žena Jana), na který budeme aplikovat masku #msk, přičemž naši morfingovou animaci přesuneme právě dovnitř této masky, čímž ji uděláme dynamickou, a vytvoří nám požadovaný závěrečný efekt. Není potřeba zařazovat definici masky do defs elementu, neboť sama o sobě není prohlížečem nijak renderována a vykreslována je až její aplikace na bitmapový obrázek.

<!DOCTYPE svg [
    <!ENTITY P "M 5.66,1.14 C 12.3,1.14 19,1.14 25.6,1.14 31.6,1.14 36.1,2.46 39.3,5.1 42.5,7.73 44.1,11.5 44.1,16.4 44.1,21.3 42.5,25 39.3,27.7 36.1,30.3 31.6,31.6 25.6,31.6 23,31.6 20.3,31.6 17.7,31.6 17.7,34.3 17.7,37 17.7,39.7 17.7,42.4 17.7,45.1 17.7,47.8 15.6,47.8 13.5,47.8 11.3,47.8 9.41,47.8 7.56,47.8 5.66,47.8 5.66,44.5 5.66,41.2 5.66,37.9 5.66,31.2 5.66,24.4 5.66,17.7 5.66,12.2 5.66,6.67 5.66,1.14 z">
    <!ENTITY O "M 24.6,0.3 C 28.6,0.3 32.2,0.917 35.3,2.15 38,3.22 40.3,4.75 42.3,6.74 43.7,8.14 44.8,9.73 45.8,11.5 47.7,15.1 48.6,19.5 48.6,24.5 48.6,28.4 48,31.9 46.9,34.9 45.9,37.7 44.3,40.2 42.3,42.3 38,46.6 32.1,48.7 24.6,48.7 17.2,48.7 11.2,46.6 6.94,42.3 4.74,40.1 3.14,37.4 2.04,34.3 1.04,31.5 0.544,28.2 0.544,24.5 0.544,19.3 1.54,14.9 3.64,11.2 4.54,9.55 5.64,8.06 6.94,6.74 11.2,2.45 17.2,0.3 24.6,0.3 z">
    <!ENTITY D "M 5.63,1.14 C 9.21,1.14 12.8,1.14 16.4,1.14 22.6,1.14 28,1.65 30.8,2.66 34.4,3.67 37,5.38 38.8,7.8 40.6,9.9 42.4,12.3 43.4,15.1 44.2,17.8 45.2,20.9 45.2,24.4 45.2,27.9 44.2,31.1 43.4,33.8 42.4,36.6 40.6,39 38.8,41.1 37,43.6 34.4,45.3 30.8,46.3 28,47.3 22.6,47.8 16.4,47.8 12.8,47.8 9.21,47.8 5.63,47.8 5.63,44.8 5.63,41.7 5.63,38.7 5.63,29.7 5.63,20.8 5.63,11.9 5.63,8.32 5.63,4.73 5.63,1.14 z">
    <!ENTITY Z "M 6.42,1.14 C 18.2,1.14 29.8,1.14 41.6,1.14 41.6,3.57 41.6,5.99 41.6,8.42 39.8,10.4 38.8,12.3 37,14.3 31.6,22.4 24.4,30.6 19,38.7 26.2,38.7 34.4,38.7 41.6,38.7 41.6,41.7 41.6,44.8 41.6,47.8 36.2,47.8 29.8,47.8 24.4,47.8 18.2,47.8 11.8,47.8 5.63,47.8 5.63,45.4 5.63,42.9 5.63,40.5 6.42,38.8 8.21,37.1 9.21,35.4 15.4,27 21.8,18.6 28,10.2 20.8,10.2 13.6,10.2 6.42,10.2 6.42,7.18 6.42,4.16 6.42,1.14 z">
    <!ENTITY I "M 19,1.14 C 20.8,1.14 22.6,1.14 25.4,1.14 26.2,1.14 28,1.14 29.8,1.14 29.8,3.72 29.8,6.3 29.8,8.87 29.8,11.6 29.8,14.3 29.8,17 29.8,19.8 29.8,22.7 29.8,25.5 29.8,33 29.8,40.4 29.8,47.8 28,47.8 26.2,47.8 24.4,47.8 22.6,47.8 20.8,47.8 19,47.8 19,43.8 19,39.9 19,35.9 19,32.5 19,29.2 19,25.8 19,22.8 19,19.9 19,17 19,14.3 19,11.6 19,8.87 19,6.3 19,3.72 19,1.14 z">
    <!ENTITY M "M 1.05,1.14 C 5.63,1.14 10,1.14 14.6,1.14 18.2,9.46 20.8,17.8 24.4,26.1 28,17.8 30.8,9.46 34.4,1.14 38.8,1.14 43.4,1.14 47.8,1.14 47.8,16.7 47.8,32.2 47.8,47.8 44.2,47.8 41.6,47.8 38,47.8 38,36.4 38,25.1 38,13.7 34.4,22.1 31.6,30.4 28,38.8 25.4,38.8 23.6,38.8 20.8,38.8 17.2,30.4 14.6,22.1 11,13.7 11,25.1 11,36.4 11,47.8 7.42,47.8 4.63,47.8 1.05,47.8 1.05,32.2 1.05,16.7 1.05,1.14 z">
]>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 49 49">
    <mask id="msk">
        <path fill="white">
            <animate attributeName="d" dur="10s" repeatCount="indefinite" values="
                &P; ; &P; ;
                &O; ; &O; ;
                &D; ; &D; ;
                &Z; ; &Z; ;
                &I; ; &I; ;
                &M; ; &M; ;
                &P; "/>
        </path>
    </mask>
    <image width="50" height="50" xlink:href="sipek.jpg" mask="url(#msk)"/>
</svg>

Finální dílo textového morfingu, fullscreen v novém okně

S morfováním textu jsme tímto hotovi. Ale jako ukázku přidáme ještě ukázku morfování také jiných tvarů (zmiňovaných v úvodu článku), kterou rozšíříme o barevné přechody výplně fill, synchronizované s časováním morfingu. Ukázky jsou výborně funkční v prohlížečích Firefox a Chrome (a samozřejmě i dalších Gecko/Webkit/Blink-based prohlížečích), na fungování v prohlížečích od společnosti Microsoft si ještě budeme muset ale chvíli počkat.

Toto je již ale opravdu vše a tímto třetím dílem uzavíráme i náš miniseriál Podzimu s SVG. Doufám, že se vám líbil, a v případě pozitivních ohlasů, kdo ví, možná zase v budoucnu znovu zase na shledanou.

Ukázka kódu s morfingem jiných tvarů

<!DOCTYPE svg [
    <!ENTITY Pumpkin "M 24.4,0.471 C 21,2.97 21.9,8.16 20.1,9.79 19.3,9.79 17.5,10.7 15.8,10.7 15.8,10.7 13.3,9.79 11.6,10.7 -0.323,12.4 -3.79,42.2 9.85,43.1 11.6,45.6 15,46.4 17.5,45.6 18.4,47.3 21,47.3 23.5,48.2 26.1,48.2 27.8,47.3 28.7,46.4 31.2,47.3 36.3,46.4 37.2,43.9 49.6,43.1 49.6,23.5 46.6,18.3 44,13.3 38.9,10.7 35.5,10.7 32.9,9.79 31.2,9.79 27,10.7 26.1,9.79 23.5,8.16 24.4,5.56 26.1,3.83 27,-0.399 24.4,0.471 z">
    <!ENTITY Moon "M 26.8,0.747 C 14.7,0.747 4.86,11.1 4.86,24.3 4.86,37 14.7,47.9 26.8,47.9 32.6,47.9 38.2,45.1 42,41.4 39.2,41.9 32.8,44.1 28,41.9 26.6,40.7 24.5,40.2 24.8,37 24.8,36.4 23.7,37 23.4,36.4 23.1,35.2 24.5,32 22.7,32 24.3,30.9 22,29.2 22.4,28.1 23,27.1 25.6,28.6 25.8,27.1 26.1,24.9 21.8,20.5 21.8,19.9 21.8,16 22.7,17.7 23.3,15 26.9,3.11 38.2,6.06 41.5,6.98 37.6,3.21 32.5,0.747 26.8,0.747 z">
    <!ENTITY Hat "M 30.2,2.19 C 26.2,2.19 24.8,5.54 22.1,8.44 16.7,15.7 15.3,27.4 11.3,33.4 11.3,35.1 8.65,33.6 5.95,34.7 -0.811,35.8 0.54,41.6 4.6,43.2 8.65,45.4 14,45.3 18,45.3 24.8,44.7 30.2,44.7 37,45.4 39.7,45.3 43.7,45 46.4,41.9 46.4,40.7 47.8,38.4 45.1,38.4 42.4,39.7 38.3,38.8 35.6,38.4 34.3,38.4 34.3,37.2 34.3,36.1 32.9,26.9 31.6,18 31.6,8.64 32.9,8.04 41,12.7 38.3,10.4 37,6.94 34.3,2.19 30.2,2.19 z">
]>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 49 49">
    <path fill="black">
        <animate attributeName="d" dur="5s" repeatCount="indefinite" values="
            &Moon; ; &Moon; ;
            &Hat; ; &Hat; ; 
            &Pumpkin; ; &Pumpkin; ;
            &Moon; "/>
        <animate attributeName="fill" dur="5s" repeatCount="indefinite" values="
            orange ; orange ;
            navy ; navy ; 
            red ; red ;
            orange "/>
    </path>
</svg>

Komentáře

Subscribe
Upozornit na
guest
0 Komentářů
Inline Feedbacks
View all comments

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.