mgr inż. Wacław Libront * Bobowa 2019
ZSO Bobowa, ul. Długoszowskich 1, 38-350 Bobowa, tel: 0183514009, fax: 0183530221, email: sekretariat@zsobobowa.eu, www: zsobobowa.eu
Animacja w JS
Na czym polega animacja? Rysujemy obiekt, potem wymazujemy ekran, ustawiamy nowe współrzędne i powtarzamy te trzy instrukcje wiele razy
- to taki najprostszy schemat. W JS animację realizujemy rekurencyjnie.
W ramce zestaw instrukcji realizujących algorytm animacji. Funkcje clearTimeout i setTimeout odpowiedzialne są za uruchamianie funkcji animacja co określony przedział czasu w milisekundach – zmienna skok. Zmienna czas jest tzw. „uchwytem” funkcji.
var w = c.canvas.width; var h = c.canvas.height; var skok = 10; var czas; function animacja() { c.clearRect(0, 0, w, h); //rysowanie i przesuwanie obiektu clearTimeout(czas); czas = setTimeout(animacja, skok); } //pierwsze wywołanie funkcji rekurencyjnej animacja(); |
Przesuwanie
Aby przesunąć obiekt musimy za każdym zwiększyć jego współrzędne (X,Y) o określony skok (vX,vY). Im większe wartości vX i vY, tym obiekt będzie się szybciej przesuwał.
var w = c.canvas.width; var h = c.canvas.height; var skok = 10; var czas; //początkowe położenie var x = 0; var y = 0; //początkowa prędkość var vx = 2; var vy = 1; //bok kwadratu var bok = 50; function animacja() { //czyszczenie okna canvas c.clearRect(0, 0, w, h); //rysowanie ramki wokół canvas c.strokeRect(0, 0, w, h); //przesuwanie obiektu x = x + vx; y = y + vy; //rysowanie obiektu c.fillRect(x, y, bok, bok); //rekurencyjne wywołanie kolejnej animacji clearTimeout(czas); czas = setTimeout(animacja, skok); } animacja(); |
Odbijanie
- instrukcja warunkowa
Gdy obiekt dociera do brzegu powinien się „odbić”, tzn. zmienić kierunek, skąd przyleciał, na przeciwny.
Matematycznie wystarczy zmienić znak na przeciwny vx - w poziomie
lub vy - w pionie. Należy uwzględnić również szerokość i wysokość obiektu.
Instrukcje warunkowe służą do podejmowania decyzji, "w którą stronę" ma zmierzać program. Decyzję podejmujemy za pomocą warunku logicznego, którego wynikiem jest zawsze prawda lub fałsz. Jeśli warunek logiczny jest prawdziwy, to wykonywana jest instrukcja. Jeśli warunek logiczny jest fałszywy, to instrukcja nie jest wykonywana. Warunki logiczne mogą być proste (sprawdzamy czy jest równe, różne, mniejsze lub większe) lub złożone (sprawdzamy tzw. sumę lub iloczyn logiczny).
Instrukcje w ramce wstawiamy do środka pętli animacyjnej - po instrukcjach obliczających nowe położenie obiektu.
//odbicia od brzegów if (x < 0) vx=-vx; // lewy if (x+bok > w) vx=-vx; // prawy if (y < 0) vy=-vy;} // górny if (y+bok > h) vy=-vy; // dolny |
Możemy zastosować złożone warunki logiczne i z czterech instrukcji warunkowych zostaną dwie. Zastosowano tzw. sumę logiczną, która oznacza, że nastąpi zmiana kierunku ruchy gdy jeden z dwóch warunków logicznych będzie prawdziwy: pierwszy LUB drugi
if (x+bok > w || x < 0) vx=-vx; if (y+bok > h || y < 0) vy=-vy; |
Obracanie
Jeśli obiekt ma zdefiniowany kąt obrotu, to postępujemy podobnie jak podczas przesuwania – zwiększamy kąt o jakiś elementarny składnik – dK.
Musimy także sprawdzać, kiedy kąt osiągnie wartość graniczną i w odpowiedni
sposób go zmodyfikować.
//początkowy kąt i skok kąta var kat = 0; var vk = 1; //w pętli animacyjnej zwiększamy i sprawdzamy kąt kat = kat + vk; if (kat>=360) {vk=-vk |
Funkcja rysująca kwadrat z możliwością obracania. Wykorzystujemy translację i rotację obszaru canvas.
//obrotowy kwadrat function kwaO(xs,ys,bok,kat,kolor){ c.save(); c.translate(xs-bok/2,ys-bok/2); c.rotate(Math.PI*kat/180); c.fillStyle=kolor; c.fillRect(-bok/2,-bok/2,bok,bok); c.restore(); } |
Zmienione zostaną instrukcje warunkowe - kwadrat po odbiciu od brzegu będzie również zmieniał kierunek obrotu. Ponieważ w instrukcji warunkowej należy wykonać dwie instrukcje, dlatego musimy zastosować instrukcję bloku {}.
if (x > w || x < bok) { vx=-vx; vk=-vk; } if (y > h || y < bok) { vy=-vy; vk=-vk; } // te same instrukcje można zapisać w jednym wierszu if (x>w || x<bok) {vx=-vx;vk=-vk;} if (y>h || y<bok) {vy=-vy;vk=-vk;} |
Sposób, w jaki zapiszemy poszczególne instrukcje (osobne wiersze i wcięcia) nie ma znaczenia dla wykonywanego programu, ale ma ogromne znaczenie dla samego piszącego program - lepiej się "czyta" program i łatwiej go modyfikuje.
Animacja
Cały program realizujący animację - przesuwanie i obracanie kwadratowego
obiektu. Zwróć uwagę na następujące elementy:
<canvas width="400" height="400" id="can"></canvas> <script> var c = can.getContext("2d"); var w = c.canvas.width; var h = c.canvas.height; var skok = 10; var czas; var x = 100; var y = 100; var vx = 2; var vy = 1; var kat = 0; var vk = 1; var bok = 50; function kwaO(xs,ys,bok,kat,kolor){ c.save(); c.translate(xs-bok/2,ys-bok/2); c.rotate(Math.PI*kat/180); c.fillStyle=kolor; c.fillRect(-bok/2,-bok/2,bok,bok); c.restore(); } function animacja() { c.clearRect(0, 0, w, h); c.strokeRect(0, 0, w, h); x = x + vx; y = y + vy; kat = kat + vk; if (x > w || x -bok < 0){vx=-vx; vk=-vk;} if (y > h || y -bok < 0){vy=-vy; vk=-vk;} if (kat >= 360) kat = 0; kwaO(x,y,bok,kat,'red'); clearTimeout(czas); czas = setTimeout(animacja, skok); } animacja(); </script> |
Szablon
<canvas width="400" height="400" id="can"></canvas> <script> var c = can.getContext("2d"); var w = c.canvas.width; var h = c.canvas.height; var skok = 10; var czas; function animacja() { c.clearRect(0, 0, w, h); //rysowanie i przesuwanie obiektu clearTimeout(czas); czas = setTimeout(animacja, skok); } animacja(); </script> |