Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

16. diel - Časovača a animácie v JavaScripte

V predchádzajúcom cvičení, Riešené úlohy k 14. a 15. lekcii JavaScriptu, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.

Vítam vás u ďalšej lekcie nášho on-line kurzu JavaScriptu. V minulej lekcii, Riešené úlohy k 14. a 15. lekcii JavaScriptu , sme sa venovali 2D kontextu plátna. V tomto JavaScript tutoriálu sa pozrieme ako môžeme rôzne veci časovať a na to nadviažeme efektom animácie.

Časovača

Časovača môžeme v JavaScripte obsluhovať pomocou dvoch funkcií.

SetInterval () a setTimeout ()

Funkcia setInterval() a setTimeout() prijímajú dva parametre. Funkciu, ktorá sa bude volať, a časový interval (ako často alebo za ako dlho sa bude volať). Časové intervaly sa udávajú v milisekundách (1 sekunda = 1000 milisekúnd). Rozdiel medzi týmito dvoma funkciami je vcelku zásadný. Kým setInterval() bude metódu volať každých X milisekúnd, setTimeout() ju zavolá iba raz jediný raz a to za X milisekúnd.

Príklad

Cieľom bude vytvoriť text, ktorý sa bude postupne vypisovať. Najprv bude vidieť písmeno "A", o sekundu neskôr priskočí "h" a budú pokračovať napríklad písmená "o", "j", "s", "v", "ě", "t", "e". Akonáhle budú vypísaná všetky písmená, text sa vymaže a začne to celé znova.

Teraz nebudeme mať už v HTML žiadny element, vytvoríme ho až v JavaScripte (implementácia je len na nás, ale pre zopakovanie domov necháme <body> prázdne :) ).

Do premennej text uložíme text, ktorý sa bude vypisovať, a vytvoríme element <p>. Pretože aj <body> ešte nemusí byť načítané (pokiaľ importujeme skript v <head>), element <p> pridáme do elementu <body> až po načítaní stránky.

let text = "Ahoj svete";
let element = document.createElement("p");
window.onload = function() {
    document.body.appendChild(element);
}

Teraz prejdeme k samotnej funkcii, ktorá bude meniť text v našom elementu.

function zmenText() {

}

V tejto funkcii si najskôr overíme, či sme už nevyzvali na predloženie všetky písmená. Ak by sme totiž získali ďalšie písmeno v poradí (keď sme na konci a žiadne ďalšie písmeno neexistuje), dostali by sme chybu. Ak sa zadanie (premenná text) už zhoduje s obsahom elementu, zmeníme hodnotu elementu na prázdny textový reťazec, aby sa mohol text začať vypisovať znova. Pripravíme si aj ďalšie vetva, kam budeme písať ďalšie kód.

if (element.textContent == text) {
    element.textContent = "";
} else {
}

Ďalej si zoberieme písmeno (znak), ktoré pridáme k textu elementu. Už vieme, že length obsahuje dĺžku reťazca. Vezmeme teda ďalší znak v poradí tak, že zmeriame dĺžku reťazca, ktorý je vypísaný na obrazovku, a pripočítame k nej 1. Lenže to má háčik. Kým dĺžka reťazca sa počíta od 1 (1 znak = dĺžka 1), tak znak na určitej pozícii (index) sa počíta od nuly (1. znak = index 0). Preto musíme ešte jedničku odpočítať, nakoniec sa +1 a -1 vynuluje, takže vezmeme znak na indexe aktuálnu dĺžku textu vypísaného na obrazovke.

let pismenoKpridani = text[element.textContent.length];

A písmeno pridáme k textu zobrazenom v elementu.

element.textContent += pismenoKpridani;

Teraz už nezostáva než len spustiť interval. Do obsluhy udalosti onload pridajme volanie metódy setInterval(), ktoré ako prvý parameter odovzdáme názov metódy zmenText (bez zátvoriek) a ako druhý číslo 1000, aby bol interval zmeny textu presne 1 sekundu.

setInterval(zmenText, 1000);

Interval sa spustí až po jednej sekunde. Dovtedy sa bude aplikácia javiť ako že 1 sekundu nereaguje, preto predtým ešte spustíme raz metódu zmenText() ručne:

zmenText();
setInterval(zmenText, 1000);

Aplikáciu si ešte môžete vylepšiť, pretože u medzery sa aplikácia bude javiť ako že sa zasekla.

Vyhlasujúca sa text
localhost

Zložitejšie animácie

Istoiste by bolo pekné mať na webe nejakú zložitejšie animáciu. Tie jednoduché dá vyriešiť v CSS, ale tie zložitejšie už musíme riešiť JavaScriptom. Celá pointa animácií je, že v nejakom intervale ovplyvňujeme vlastnosti animovaného objektu.

Vezmeme si napríklad jesenné výzdobu webu. Naprogramujeme skript, ktorý nechá padať lístie odhora nadol. Obrázky lístia budeme mať v koreňovom elemente <body> a každý obrázok bude mať dáta-atribút data-podzim. Cielene budeme vyberať len tieto obrázky, pretože nie webu môžu (a bývajú) aj iné obrázky a tie nechceme ovplyvňovať.

Stiahnite si obrázok listu nižšie a vložte ho do nového projektu s nasledujúcim HTML obsahom:

list - Základné konštrukcie jazyka JavaScript
<img src="list.jpg" data-podzim />
<img src="list.jpg" data-podzim />
<img src="list.jpg" data-podzim />
<img src="list.jpg" data-podzim />
<img src="list.jpg" data-podzim />

Do projektu si pridajme CSS štýl, v ktorom nastavíme obrázkom absolútnu pozíciu (opäť budeme nastavovať len našim jesenným) a <body> nastylujte tak, aby nezobrazovalo scrollbar.

body > img[data-podzim] {
    position:absolute;
}

body {
    overflow:hidden;
}

Nadefinujte si premenou listy, kam si po načítaní stránky uložíme obrázky listov s data atribútom data-podzim.

let listy;
window.onload = function () {
    listy = document.querySelectorAll("body > img[data-podzim]");
}

Listy prejdeme cyklom:

for (let i = 0; i < listy.length; i++)

Budeme im chcieť nastaviť východiskovú pozíciu, ktorá bude zľava pätina šírky okna pre každý (pozri ďalej, tak aby sa presne rozprestreli) a zhora mínus ich výška (tak aby pri načítaní stránky začali schádzať z hornej hrany).

Veľkosť okna

Občas (ako napr. Teraz) je potrebujeme pracovať s veľkosťou okna. Existuje niekoľko spôsobov a vlastností, ktoré s touto veľkosťou súvisia.

Skutočná veľkosť obrazovky

Úplne tú najskutočnejší veľkosť obrazovky vám povedia vlastnosti width a height na objekte screen.

Oblasť obrazovky vyhradené aplikáciám

Jedná sa o veľkosť, ktorú môžu použiť aplikácie. Inými slovami v podstate o veľkosť obrazovky vyššie mínus veľkosť systémových panelov (napr. Taskbaru). Vlastnosti nájdeme opäť na objekte screen ako availWidth a availHeight.

Veľkosť okna webovej stránky

Nakoniec si necháme tú najdôležitejšiu. Veľkosť plochy, ktorú môže zaberať naše aplikácie. Vlastnosti nájdeme tentoraz na objekte window a to ako innerWidth a innerHeight.

Nastavovanie CSS vlastností

Zatiaľ nám ešte chýba jedna podstatná informácia a to ako sa nastavujú vlastnosti CSS elementom domov.

Všetky elementy domov majú vlastnosť style, ktorá obsahuje vlastnosti pomenované ako CSS vlastnosti. Tie sa nezapisujú pomlčkovou notáciou, ale notáciou CamelCase (prvé slovo celé malými písmenami, každé ďalšie má začiatočné písmeno veľké, nie sú tu žiadne medzery). Takže napríklad:

document.body.style.backgroundColor = "red";

nastaví farbu pozadia elementu <body> na červenú.

Vráťme sa k nášmu padajúcim lístia. Nastavme teda pozície. U nastavovaní hodnôt CSS je častá chyba zabudnutia jednotky:

listy[i].style.left = i * window.innerWidth / listy.length + "px";
listy[i].style.top = -listy[i].height + "px";

Posun

Teraz sa vrhneme na funkciu posun(), ktorá posunie všetky listy nadol. Funkcia cyklom prejde všetky listy a nastaví im novú pozíciu. Tú získa na základe súčasnej pozície listu (ktorú musíme kvôli odstráneniu CSS jednotky z hodnoty naparsovat) a následného pripočítaní nejaké rozumné hodnoty, aby animácie nebola ani moc rýchla ani veľmi pomalá. Hodnotu si môžete skúsiť upraviť (hodnota 2 v kóde).

function posun() {
    for (let i = 0; i < listy.length; i++) {
        let novaPozice = parseInt(listy[i].style.top) + 2;
        listy[i].style.top = novaPozice + "px";
    }
}

Ešte je potrebné ošetriť prípad, keď list vyjde z okna. V takom prípade musíme pozíciu znovu nastaviť na mínus výšku obrázku. Dodajme podmienku medzi predchádzajúce 2 riadky, aby sme nemuseli CSS hodnotu nastavovať 2 ×.

if (novaPozice > window.innerHeight) {
    novaPozice = -listy[i].height;
}

Nakoniec teda v obsluhe udalosti načítanie okná nastavme interval na nejakú rozumnú hodnotu (opäť vyskúšajte).

setInterval(posun, 20);

Pretože postup bol komplexnejší, uveďme si pre kontrolu kompletný zdrojový kód skriptu:

// Načítanie stránky
window.onload = function () {
    listy = document.querySelectorAll("body > img[data-podzim]");

    // nastavenia počiatočnej pozície
    for (let i = 0; i < listy.length; i++) {
        listy[i].style.left = i * window.innerWidth / listy.length + "px";
        listy[i].style.top = -listy[i].height + "px";
    }

    setInterval(posun, 20);
}

// Funkcie pre časovač
function posun() {
    for (let i = 0; i < listy.length; i++) {
        let novaPozice = parseInt(listy[i].style.top) + 2;
        if (novaPozice > window.innerHeight) {
            novaPozice = -listy[i].height;
        }
        listy[i].style.top = novaPozice + "px";
    }
}

Aplikáciu spustite. Uvidíte, že lístie bude padať zhora nadol a po vytečeniu z obrazovky zase odznovu.

Padajúce lístie
localhost

Gratulujem, vaše prvé JavaScriptová animácie je na svete. Môžete si ju samozrejme vylepšiť, aby bola ešte zaujímavejšie.

Animácie na plátne

V podobnom duchu sa nesú animácie na plátne, kde v určitom intervale celej plátno vymastíme a znovu vykreslíme a tak stále dokola. Ako ukážku si môžeme naprogramovať koleso šťastia. Pre jednoduchosť si ho načítame zo statického obrázku. Vytvorme si teda stránku s plátnom a to si načíta v JavaScripte. Do stránky si pridajme aj obrázok s id="kolo".

Stiahnite si obrázok nižšie a spolu s nasledujúcim HTML kódom ho vložte do nového projektu:

koleso šťastia - Základné konštrukcie jazyka JavaScript
<img src="kolo.png" id="kolo" />
<canvas id="platno" width="500" height="500"></canvas>

V skripte si tieto objekty načíta a pridajme si rovno aj premennú, kde budeme mať uložený uhol otočenia. Obrázok nezabudneme zo stránky skryť.

let platno;
let kontext;
let otoceni = 0;
let obrazek;

window.onload = function () {
    platno = document.getElementById("platno");
    kontext = platno.getContext("2d");
    obrazek = document.getElementById("kolo");
    obrazek.style.display = "none";
}

V metóde prekresli() potom jednoducho vymastíme plátno a znovu naň koleso vykreslíme. Najprv vhodne presunieme a otočíme kontext a potom obrázok vykreslíme. Nakoniec pridáme k otočeniu jeden stupeň a to rovno v jednotkách radiánov, nech sa vyhneme prepočítavanie. Vieme že 360 ° = 2 * Pí, takže jeden stupeň je (2 * Pí) / 360.

function prekresli() {
    kontext.clearRect(0,0,500,500);
    kontext.save();
    kontext.translate(250, 250);
    kontext.rotate(otoceni);
    kontext.drawImage(obrazek, -225, -225);
    kontext.restore();
    otoceni += (2 * Math.PI) / 360; // otočenie o 1 stupeň, ale v radiánoch
}

V udalosti načítanie stránky opäť nastavíme interval a vykreslíme koleso hneď na začiatku, aby sme nemuseli čakať na dovŕšenie prvého intervalu.

setInterval(prekresli, 20);
prekresli();

výsledok:

Koleso šťastia
localhost

Gratulujem, už by ste mali zvládať prácu s animáciami. Dokázať si to môžete na cvičenie.

Správne riešené animácie

Všetky naše riešenia animácií síce fungujú, ale pozrime sa na ne z hľadiska výkonu. Keď používateľ opustí našej záložku prehliadača, animácie stále beží a vyťažuje procesor. Horšie je to na mobilných zariadeniach, kde to ide aj poznať. Ako sa animácia dajú riešiť, aby za nás webový prehliadač vyriešil animáciu skutočne len keď je potreba, si povieme v budúcej lekcii, Riešené úlohy k 16. lekcii JavaScriptu .

V nasledujúcom cvičení, Riešené úlohy k 16. lekcii JavaScriptu, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 1354x (218.35 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript

 

Predchádzajúci článok
Riešené úlohy k 14. a 15. lekcii JavaScriptu
Všetky články v sekcii
Základné konštrukcie jazyka JavaScript
Preskočiť článok
(neodporúčame)
Riešené úlohy k 16. lekcii JavaScriptu
Článok pre vás napísal Michal Žůrek - misaz
Avatar
Užívateľské hodnotenie:
2 hlasov
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity