Lekce 17 - JS requestAnimationFrame - Za lepší vykreslování

Vydávání, hosting a aktualizace umožňují jeho sponzoři.
V minulé lekci, Časovače a animace v JavaScriptu, jsme se věnovali animacím. Spolu s HTML5 přišlo nové javascriptové API - requestAnimationFrame. Jedná se o technologii, která nám umožňuje plynuleji a s vyšším výkonem vykreslovat animace v prohlížeči a my si ji v tomto tutoriálu představíme.
Pokud jste někdy zkoušeli napsat např. nějakou jednoduchou hru v prohlížeči, jistě vaše hlavní smyčka vypadala nějak takto.
setInterval(function() { posun(); vykresli(); }, 1000 / FPS);
Naše dosavadní animace vypadaly velmi podobně, pouze jsme spojili posouvání a vykreslování do jedné funkce. Alternativní vykreslovací smyčka může vypadat i např. takto:
function smycka() { setTimeout(smycka, 1000 / FPS); posun(); vykresli(); } smycka();
Kód funguje, dokonce si můžeme i omezit FPS. Co je na něm ale špatně?
Plýtvání výkonem počítače
Problém výše uvedeného kódu je ten, že prohlížeč jej vykonává, i když se uživatel na danou stránku zrovna nedívá (má překliknuto na jinou záložku, případně je prohlížeč minimalizovaný). Prohlížeč Google Chrome tyto situace řeší omezením takovýchto smyček pouze na 1 FPS. To je ale pouze jeho dobrovolné chování a v ostatních prohlížečích to tak vůbec být nemusí, takže na mobilních zařízeních může docházet zbytečně k poklesu výkonu a vybíjení baterie.
requestAnimationFrame to řeší!
S použitím funkce requestAnimationFrame()
místo
setTimeout()
bude náš kód vypadat velmi podobně.
function smycka() { requestAnimationFrame(smycka); posun(); vykresli(); } smycka();
Tuto funkci vymyslela Mozilla a později ji převzal a vylepšil tým WebKitu. Pomocí funkce se může vykreslovat CSS, DOM elementy, WebGL nebo na canvas.
Výhody
requestAnimationFrame()
nám zajistí, že všechny naše
animace se budou vykreslovat najednou, s vyšším výkonem a nižší
spotřebou baterie.
Pokud v prohlížeči překliknete na jinou stránku, nebo prohlížeč minimalizujete, vykreslování se zastaví, aby se šetřil výkon a bude se pokračovat, jakmile bude stránka opět viditelná.
Mohli jste si také všimnout, že u použití
requestAnimationFrame()
jsme nikde nenastavovali počet FPS. Funkce
ve výchozím nastavení používá 60 FPS, záleží ale na implementaci v
prohlížeči. Nemělo by se to ale příliš lišit a spíše záleží na
výkonu PC, než na rozhodnutí výrobce prohlížeče. Také podpora v
prohlížečích je poměrně dobrá.
Demo
Na závěr si ukážeme jednoduchou aplikaci, ve které se čtverec pohybuje
po canvasu a implementujeme jí jak pomocí setInterval()
, tak
pomocí requestAnimationFrame()
. Plátno schválně tentokrát
nebudeme mazat, čímž bude vidět stopa čtverce.
Řešení pomocí setInterval()
window.onload = function() { let platno = document.querySelector("#platno"); let kontext = platno.getContext("2d"); let ctverec = { "x": 25, "y": 25, "smerX": -1, "smerY": 1, "rychlost": 2, "sirka": 50, "vyska": 50, "barva": "red" }; function smycka() { posun(); prekresli(); } setInterval(smycka, 1000 / 60); smycka(); function posun() { if (ctverec.x + ctverec.sirka + ctverec.rychlost * ctverec.smerX > platno.width) ctverec.smerX = -1; if (ctverec.x + ctverec.rychlost * ctverec.smerX < 0) ctverec.smerX = 1; if (ctverec.y + ctverec.vyska + ctverec.rychlost * ctverec.smerY > platno.height) ctverec.smerY = -1; if (ctverec.y + ctverec.rychlost * ctverec.smerY < 0) ctverec.smerY = 1; zmenBarvu(); ctverec.x += ctverec.rychlost * ctverec.smerX; ctverec.y += ctverec.rychlost * ctverec.smerY; } function prekresli() { kontext.fillStyle = ctverec.barva; kontext.fillRect(ctverec.x, ctverec.y, ctverec.sirka, ctverec.vyska); } function zmenBarvu() { barvy = ['green', 'blue', 'red', 'yellow']; ctverec.barva = barvy[Math.floor(Math.random() * barvy.length)]; } }
Výsledek:
Řešení pomocí requestAnimationFrame()
window.onload = function() { let platno = document.querySelector("#platno"); let kontext = platno.getContext("2d"); let ctverec = { "x": 25, "y": 25, "smerX": -1, "smerY": 1, "rychlost": 2, "sirka": 50, "vyska": 50, "barva": "red" }; function smycka() { posun(); prekresli(); requestAnimationFrame(smycka); } smycka(); function posun() { if (ctverec.x + ctverec.sirka + ctverec.rychlost * ctverec.smerX > platno.width) ctverec.smerX = -1; if (ctverec.x + ctverec.rychlost * ctverec.smerX < 0) ctverec.smerX = 1; if (ctverec.y + ctverec.vyska + ctverec.rychlost * ctverec.smerY > platno.height) ctverec.smerY = -1; if (ctverec.y + ctverec.rychlost * ctverec.smerY < 0) ctverec.smerY = 1; zmenBarvu(); ctverec.x += ctverec.rychlost * ctverec.smerX; ctverec.y += ctverec.rychlost * ctverec.smerY; } function prekresli() { kontext.fillStyle = ctverec.barva; kontext.fillRect(ctverec.x, ctverec.y, ctverec.sirka, ctverec.vyska); } function zmenBarvu() { barvy = ['green', 'blue', 'red', 'yellow']; ctverec.barva = barvy[Math.floor(Math.random() * barvy.length)]; } }
Výsledek:
Doufám, že vám byla lekce užitečná a že od teď budete pro animace v
prohlížeči používat requestAnimationFrame()
Stáhnout
Staženo 75x (3.42 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript
Komentáře


Zobrazeno 5 zpráv z 5.