Lekce 29 - Časovače a animace v JavaScriptu
V předešlém cvičení, Řešené úlohy k 25.-28. lekci JavaScriptu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V tomto tutoriálu základů JavaScriptu si ukážeme, jak našim kresbám nastavit časovače a docílit tím efektu animace na webové stránce.
Časovače a animace
Časovače můžeme v JavaScriptu obsluhovat pomocí dvou funkcí, které si nyní představíme.
Funkce setInterval()
Funkce slouží k opakovanému volání jiné funkce ve stanoveném intervalu. Jako parametry přijímá funkci, která se bude opakovaně volat, a časový interval, který určuje, jak často se volání bude opakovat. Funkci do parametru uvádíme bez závorek a čas udáváme v milisekundách, jedna sekunda odpovídá tisíci milisekund. Tuto funkci využijeme, když potřebujeme nastavit pravidelné opakování určité akce.
Funkce setTimeout()
Funkce setTimeout()
slouží k odložení zavolání funkce o
stanovený čas. Na rozdíl od funkce setInterval()
se zavolá
pouze jednou. Funkce setTimeout()
přijímá stejné parametry –
volanou funkci (bez závorek) a čas v milisekundách. Po zavolání funkce
setTimeout()
se čeká po dobu uvedenou v parametru, poté se
zavolá předaná funkce.
Postupné vypsání textu
Ukažme si použití časovače nejprve na jednoduchém příkladu. Budeme v
něm postupně vypisovat text Ahoj světe
. Nejprve bude vidět
písmeno A
, o sekundu později přiskočí h
a takto
se budou přidávat další písmena. Jakmile bude vypsán celý text, smaže se
a začne se vypisovat opět od začátku.
V těle HTML nebudeme mít žádný element, vše vytvoříme až z JavaScriptu:
<!DOCTYPE html> <html lang="cs-cz"> <head> <meta charset="UTF-8" /> <title>Animace textu</title> <script src="animace_textu.js"></script> </head> <body> </body> </html>
V projektu vytvoříme soubor animace_textu.js
a vložíme do
něj následující kód:
let text = "Ahoj světe"; let paragraph = document.createElement("p"); window.onload = function() { document.body.appendChild(paragraph); }
Vytvořili jsme proměnnou text
, kam jsme uložili náš výpis
Ahoj světe
. Poté jsme vytvořili element <p>
a
po načtení stránky jej přidali do těla dokumentu.
Funkce zmenText()
Pustíme se do tvorby funkce, která bude měnit text v našem elementu. Do našeho JavaScriptového souboru přidáme následující kód:
function zmenText() { if (paragraph.textContent == text) { paragraph.textContent = ""; } else { // sem vzápětí doplníme další kód } }
Jako první jsme vytvořili podmínku, která kontroluje, jestli je celý text už zobrazený. Pokud ano, obsah odstavce se smaže, aby bylo možné začít znovu. Tato kontrola je důležitá – kdybychom se pokusili zobrazit další znak za koncem textu, dostali bychom chybu, protože takový znak neexistuje.
Do větve else
přidáme kód, který zajistí postupný výpis
textu:
let pismenoKpridani = text[paragraph.textContent.length]; paragraph.textContent += pismenoKpridani;
Tento kód vybere další znak z proměnné text
a přidá ho ke
stávajícímu textu elementu paragraph
. Pomocí vlastnosti
length
zjistíme délku textu aktuálně zobrazeného na obrazovce
a tuto délku použijeme jako index pro výběr následujícího znaku, který
se bude přidávat. Operátor +=
pak tento znak připojí na konec
textu v elementu paragraph
.
Je důležité si uvědomit, že:
- Délka řetězce (
length
) začíná na hodnotě1
(např. text s jedním znakem má délku1
). - Indexy znaků začínají na
0
(první znak má index0
, druhý1
atd.).
Proto aktuální délka textu vypsaného na obrazovce odpovídá indexu dalšího znaku k vypsání v proměnné text.
Nakonec přidáme podmínku, která zjistí, jestli nevypisujeme mezeru.
Pokud ano, ihned zobrazíme další znak, aby program působil plynule. Celý
blok else
bude vypadat takto:
else { let pismenoKpridani = text[paragraph.textContent.length]; paragraph.textContent += pismenoKpridani; if (pismenoKpridani == " ") { zmenText(); } }
Pokud je přidaný znak mezera, zavoláme funkci zmenText()
,
která zajistí okamžité přidání dalšího znaku. Tím využíváme princip
rekurze, což znamená, že funkce volá sama sebe, dokud není splněna
podmínka pro ukončení. Rekurze zde zajišťuje, že mezera nebude zpomalovat
plynulost programu.
Nastavení časovače
Nyní zbývá spustit interval. Obsluhu události onload
upravíme tak, aby vypadala následovně:
window.onload = function() { document.body.appendChild(paragraph); zmenText(); setInterval(zmenText, 1000); }
Jako první jsme zavolali funkci zmenText()
, aby se první
písmeno vypsalo okamžitě po spuštění programu. Pokud bychom tuto funkci
nezavolali, výpis textu by začal až po uplynutí první sekundy, což by
mohlo působit dojmem, že aplikace nereaguje.
Dále voláme funkci setInterval()
, která jako první parametr
přijímá funkci zmenText()
(bez závorek) a jako druhý číslo
1000
, čímž jsme nastavili interval změny textu na jednu
sekundu.
Celý kód vypadá takto:
let text = "Ahoj světe"; let paragraph = document.createElement("p"); window.onload = function() { document.body.appendChild(paragraph); zmenText(); setInterval(zmenText, 1000); } function zmenText() { if (paragraph.textContent == text) { paragraph.textContent = ""; } else { let pismenoKpridani = text[paragraph.textContent.length]; paragraph.textContent += pismenoKpridani; if (pismenoKpridani == " ") { zmenText(); } } }
Výsledek v prohlížeči:
Složitější animace
Bylo by hezké mít na webu i nějakou složitější animaci. Jednoduché animace lze vyřešit v CSS, ale u těch složitějších již musíme použít JavaScript. Celá pointa animací spočívá v tom, že v nějakém intervalu ovlivňujeme vlastnosti animovaného objektu.
Vezmeme si například podzimní výzdobu webu. Naprogramujeme skript, který
nechá padat listí odshora dolů. Každý obrázek bude mít atribut
data-podzim
. Cíleně budeme vybírat pouze tyto obrázky, protože
na webu mohou být (a bývají) i jiné obrázky a ty nechceme ovlivňovat.
Stáhneme si obrázek listu níže a vložíme jej do nového projektu:

V HTML souboru doplníme opět pouze hlavičku a tělo necháme prázdné:
<!DOCTYPE html> <html lang="cs-cz"> <head> <meta charset="UTF-8" /> <title>Podzimní výzdoba</title> <script src="listy.js"></script> <link href="styl.css" rel="stylesheet" /> </head> <body> </body> </html>
Do projektu si přidáme CSS soubor s názvem styl.css
a
vložíme do něj následující kód:
body > img[data-podzim] { position: absolute; } body { overflow: hidden; }
Obrázkům jsme v souboru nastavili absolutní pozici a
<body>
nastylovali tak, aby nezobrazovalo scrollbary.
Vytvoříme v projektu soubor listy.js
a do něj umístíme
následující kód:
document.addEventListener("DOMContentLoaded", function() { for (let i = 0; i < 5; i++) { let list = document.createElement("img"); list.src = "list.jpg"; list.setAttribute("data-podzim", ""); list.alt = "List"; document.body.appendChild(list); } // Zde vzápětí nastavíme počáteční pozici listů });
V události DOMContentLoaded
jsme nejprve pomocí cyklu
vytvořili elementy obrázků listů s atributem data-podzim
a
vložili je do těla HTML.
Zjištění velikosti okna
Listům nyní budeme chtít nastavit výchozí pozici, kterou vypočítáme zleva jako pětinu šířky okna pro každý list. Horní pozici vypočítáme jako výšku okna mínus výška listu, aby při načtení stránky začaly sjíždět z horní hrany. Protože potřebujeme pracovat s velikostí okna, ukážeme si několik vlastností, které s tím souvisejí:
- Velikost obrazovky - zjišťuje se pomocí vlastností
screen.width
ascreen.height
. Velikost obrazovky bez systémových panelů, jako je například taskbar, zjistíme pomocíscreen.availWidth
ascreen.availHeight
. - Velikost okna webové stránky – reprezentuje plochu
dostupnou pro obsah webu. Šířku a výšku zjistíme pomocí
window.innerWidth
awindow.innerHeight
.
Nastavení CSS vlastností z JavaScriptu
Ukažme si ještě, jak nastavovat CSS vlastnosti elementům pomocí
JavaScriptu. Každý DOM element má vlastnost style
, která
obsahuje CSS vlastnosti přepsané do camelCase notace místo pomlčkové.
Například pro změnu barvy pozadí elementu <body>
na
červenou bychom mohli použít tento zápis:
document.body.style.backgroundColor = "red";
Nastavení počáteční pozice listů
Vraťme se k našemu padajícímu listí a nastavme mu počáteční pozice.
Nezapomeneme na doplnění jednotky px
. Namísto komentáře v
kódu výše doplníme:
let listy = document.querySelectorAll("body > img[data-podzim]"); for (let i = 0; i < listy.length; i++) { listy[i].style.top = -listy[i].height + "px"; listy[i].style.left = i * window.innerWidth / listy.length + "px"; } // Sem později doplníme funkci setInterval()
V tomto kódu nejprve získáme jednotlivé listy. V cyklu poté nastavíme
postupně každému listu pomocí CSS stejnou horní pozici
style.top
. Levý okraj jednotlivých obrázků
style.left
posouváme násobkem aktuálního indexu cyklu, který
se postupně inkrementuje.
Funkce posun()
Nyní vytvoříme funkci posun()
, která bude posouvat všechny
listy dolů:
function posun(listy) { for (let list of listy) { let novaPozice = parseInt(list.style.top) + 2; if (novaPozice > window.innerHeight) { novaPozice = -list.height; } list.style.top = novaPozice + "px"; } }
Funkce cyklem projde všechny listy a nastaví jim novou pozici. Aktuální pozici získá z jejich vlastnosti v CSS, kterou je potřeba naparsovat (převést na číslo). K této pozici se přičte vhodná hodnota, aby animace byla plynulá.
Pomocí podmínky funkce kontroluje, zda list nevyjel z okna. Pokud ano, nastaví jeho pozici na zápornou hodnotu výšky obrázku. Tím zajistí, že list začne znovu na horním okraji obrazovky.
Nyní zbývá pouze doplnit v obsluze události načtení okna nastavení časovače, přidáme tedy poslední řádek:
setInterval(function() { posun(listy); }, 20);
Protože jsme potřebovali předat funkci posun()
parametr, museli jsme místo klasického volání setInterval()
použít anonymní funkci. Anonymní funkce zde slouží jako
obal, který volá funkci posun a předává jí parametr listy
.
Bez tohoto obalu by kód nefungoval, protože setInterval()
očekává pouze odkaz na funkci bez parametrů.
Aplikaci spustíme a uvidíme, že listí padá shora dolů a po opuštění obrazovky se znovu objeví nahoře:
Nyní bychom měli již zvládat základy práce s animacemi. Jak zajistit,
aby za nás webový prohlížeč spouštěl animaci jen když je potřeba, si
řekneme jindy
V následujícím cvičení, Řešené úlohy k 29. lekci JavaScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1626x (13.02 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript