Animazione JavaScript che funziona (parte 2 di 4)

Nell'ultimo post, abbiamo introdotto l'idea di sprite, un modo semplice per animare in JavaScript che funziona in tutti i browser. Abbiamo anche spiegato come impostare lo sprite come immagine di sfondo per a div e quindi utilizzare una riga di JavaScript per modificare la posizione dello sfondo in modo che appaia come se l'immagine fosse stata spostata.

In questo post, useremo questa tecnica per animare sia i movimenti di corsa che quelli di salto. Per creare l'animazione, sarà necessario modificare rapidamente la posizione dello sfondo a intervalli regolari. Dai un'occhiata di nuovo allo sprite che stiamo usando.


Incontra J, la mascotte della mia azienda, Joust Multimedia.

Nel nostro esempio, abbiamo dieci immagini totali: una di J in piedi rivolta a destra, tre di J in esecuzione a destra e una di J che salta mentre è rivolta a destra (con lo stesso numero di ciascun riquadro rivolto a sinistra). Iniziamo a farlo correre verso destra. Per rendere l'immagine come se fosse in esecuzione, dovremo fare due cose: cambiare lo sprite in un'immagine diversa e spostare il div verso la destra.


Correndo verso l'animazione giusta

Di certo non vorremmo essere bloccati facendo clic su pulsanti diversi per scorrere gli sprite, quindi avremo bisogno di creare alcune funzioni che lo facciano automaticamente.

Per la nostra funzione di corsa, vogliamo:

  1. Muovi il div verso la destra leggermente
  2. Passa al fotogramma successivo di animazione
  3. Pausa per una frazione di secondo (per preservare l'illusione della "persistenza della visione")
  4. Loop di nuovo la funzione

Fortunatamente, esiste un modo semplice per eseguire il ciclo con le funzioni. Un comando nativo in JavaScript chiamato setTimeout ci permetterà di creare un ritardo temporizzato, dopo di che chiameremo di nuovo la funzione (dall'interno della funzione).

 function run_right () // Spostamento leggermente a destra ... // Passa al fotogramma successivo di animazione ... // questo chiamerà di nuovo 'run_right' dopo 200 millisecondi setTimeout (function () run_right ();, 200); 

Quindi ora abbiamo una funzione che si chiamerà di nuovo cinque volte al secondo (che sarà abbastanza veloce da creare l'animazione per i nostri scopi). Ricorda qui che i browser non sono eccessivamente accurati con i loro timer. Puoi specificare i tempi al millisecondo, ma ciò non significa che lo script verrà eseguito esattamente in quel momento!

Il nostro prossimo problema da affrontare è: in che modo la nostra funzione saprà a quale sprite cambiare? Nel nostro esempio, avremo bisogno di andare avanti e indietro tra le nostre tre immagini (per avere quattro fotogrammi totali di animazione). Per fare questo, passeremo alla nostra funzione un po 'di informazioni per dirgli in quale diapositiva passare. Una volta nella funzione, eseguiremo un test che controllerà su quale diapositiva dovremmo essere posizionati, quindi commuterà la posizione dello sfondo sullo sprite corretto. Quando chiamiamo di nuovo la funzione, passeremo la diapositiva successiva come argomento.

 function run_right (slide) // Sposta leggermente a destra ... switch (slide) // questa istruzione switch controlla le diverse possibilità per il caso 'slide' 1: // se 'slide' è uguale a '1' ... document.getElementById ( 'j'). style.backgroundPosition = "-40px 0px"; setTimeout (function () run_right (2);, 200); rompere; caso 2: // se 'slide' è uguale a '2' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (3);, 200); rompere; caso 3: // se 'slide' è uguale a '3' ... document.getElementById ('j'). style.backgroundPosition = "-120px 0px"; setTimeout (function () run_right (4);, 200); rompere; caso 4: // se 'slide' è uguale a '4' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (1);, 200); rompere; 

E ora quando chiamiamo la funzione per la prima volta, dovremo assicurarci di passare la diapositiva iniziale.

 

Allo stesso modo, per spostare il nostro div leggermente a destra, possiamo passare l'attributo iniziale sinistro del div, quindi sposta il div leggermente ogni volta che viene chiamata la funzione.

 function run_right (slide, left) left = left + 15; // Aumenta il suo attributo di sinistra di 15px document.getElementById ('j'). Style.left = left + "px"; switch (slide) // questa istruzione switch controlla le diverse possibilità per il caso 'slide' 1: // se 'slide' è uguale a '1' ... document.getElementById ('j'). style.backgroundPosition = "-40px 0px" ; setTimeout (function () run_right (2, left);, 200); rompere; caso 2: // se 'slide' è uguale a '2' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (3, left);, 200); rompere; caso 3: // se 'slide' è uguale a '3' ... document.getElementById ('j'). style.backgroundPosition = "-120px 0px"; setTimeout (function () run_right (4, left);, 200); rompere; caso 4: // se 'slide' è uguale a '4' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (1, left);, 200); rompere; 

E quando inizialmente chiamiamo la funzione, dobbiamo assicurarci di passare la posizione sinistra corrente del nostro div.

 

Fermare l'animazione

Quindi, ora abbiamo una funzione che, quando chiamata, animerà J per correre a destra. Sfortunatamente, non abbiamo modo di fermarlo. Prima di tutto, dovremo fare in modo che la funzione smetta di chiamarsi se J corre fino al limite del nostro stadio. Per fare ciò, ogni volta che la funzione viene eseguita, controlleremo un Se dichiarazione per vedere se J ha spazio per continuare a correre. Se è così, eseguiremo la funzione normalmente. Altrimenti, smetteremo di chiamare la funzione e restituiremo lo sprite in piedi.

 function run_right (slide, left) // Se possiamo aggiungere 15 pixel a sinistra e avere il lato destro di J non essere sul lato destro dello stage ... if ((left + 15) < (document.getElementById('stage').offsetWidth - document.getElementById('j').offsetWidth)) // We have room! Continue like normal here  else  // if we are on the right edge, we need to stop calling the function and return to standing document.getElementById('j').style.backgroundPosition = "0px 0px";  

Infine, vorremmo avere un modo per fermare la funzione, quando necessario. Possiamo impostare il setTimeout () comando a una variabile, quindi fermarlo con il clearTimeout () comando. Per fare ciò, dovremo dichiarare tale variabile al di fuori della funzione, in modo tale che saremo in grado di riferirci successivamente. Per ora, lo dichiareremo come variabile globale. Questa è una pratica di codice terribile, ma la correggeremo nel prossimo post. Questo è come appare la nostra funzione.

 var timer; function run_right (slide, left) if ((sinistra + 15) < (document.getElementById('stage').offsetWidth - document.getElementById('j').offsetWidth)) left = left + 15; // Increase his left attribute by 15px document.getElementById('j').style.left = left+"px"; switch (slide) // this switch statement checks for different possibilities for 'slide' case 1: // if 'slide' equals '1'… document.getElementById('j').style.backgroundPosition = "-40px 0px"; setTimeout(function()run_right(2, left);, 200); break; case 2: // if 'slide' equals '2'… document.getElementById('j').style.backgroundPosition = "-80px 0px"; setTimeout(function()run_right(3, left);, 200); break; case 3: // if 'slide' equals '3'… document.getElementById('j').style.backgroundPosition = "-120px 0px"; setTimeout(function()run_right(4, left);, 200); break; case 4: // if 'slide' equals '4'… document.getElementById('j').style.backgroundPosition = "-80px 0px"; setTimeout(function()run_right(1, left);, 200); break;   else  document.getElementById('j').style.backgroundPosition = "0px 0px";  

E possiamo creare un'altra funzione per fermare il timer in esecuzione e restituire lo sprite all'immagine in piedi.

 function stop_running () document.getElementById ('j'). style.backgroundPosition = "0px 0px"; clearTimeout (timer); 

In esecuzione verso l'animazione a sinistra

Ora prendendo in prestito il codice dal nostro run_right funzione, possiamo creare un'altra funzione per fare a run_left funzione, con poche modifiche.

 function run_left (stage, left) if ((left - 15)> 0) left = left - 15; document.getElementById ('j'). style.left = left + "px"; switch (stage) case 1: document.getElementById ('j'). style.backgroundPosition = "-40px -50px"; timer = setTimeout (function () run_left (2, left);, 200); rompere; caso 2: document.getElementById ('j'). style.backgroundPosition = "-80px -50px"; timer = setTimeout (function () run_left (3, left);, 200); rompere; caso 3: document.getElementById ('j'). style.backgroundPosition = "-120px -50px"; timer = setTimeout (function () run_left (4, left);, 200); rompere; case 4: document.getElementById ('j'). style.backgroundPosition = "-80px -50px"; timer = setTimeout (function () run_left (1, left);, 200); rompere;  else document.getElementById ('j'). style.backgroundPosition = "0px -50px"; 

Animazione di salto

Infine, dobbiamo creare una funzione di salto. Passeremo due argomenti a questa funzione, una che traccerà se il div è attualmente in movimento verso l'alto o verso il basso e un altro che traccerà l'attuale attributo superiore del div. Tra i due, determineremo in quale direzione div ha bisogno di muoversi dopo, e quanto lontano (ci sposteremo il div meno distanza vicino all'arco del salto per simulare l'accelerazione con la gravità).

 function jump (up, top) / * * Modifichiamo J sul suo jump sprite ... * / document.getElementById ('j'). style.backgroundPosition = "-160px 0px"; / * * Qui, dobbiamo decidere se deve viaggiare o scendere ... * / if (up && (document.getElementById ('j'). OffsetTop> 20)) // se sta attualmente salendo, e è più di 20 pixel dalla parte superiore dello stage ... top = top - (top * .1); // Questo ci dà un leggero arco nel salto, piuttosto che un movimento costante come eseguire document.getElementById ('j'). Style.top = top + "px"; // Cambia il suo position timer = setTimeout (function () jump (su, sopra);, 60); // Quindi chiama di nuovo la funzione else if (up) // se sta attualmente salendo, ma è quasi in cima allo stage e ha bisogno di tornare indietro ... up = false; // cambiamo la variabile 'up' in modo che cada nel ciclo successivo timer = setTimeout (function () jump (su, sopra);, 60);  else if (! up && (document.getElementById ('j'). offsetTop < 115)) // if he is moving down, but is more than 5px from the ground, he will continue to fall… top = top + (top * .1); // His fall will slightly accelerate document.getElementById('j').style.top = top+"px"; timer = setTimeout(function()jump(up, top);, 60);  else  // If he is moving down, and he is within 5px of the ground… document.getElementById('j').style.top = "120px"; // Place him on the ground document.getElementById('j').style.backgroundPosition = "0px 0px"; // return to standing sprite // We do not call the loop anymore since he is standing still at this point  

Ora possiamo mettere tutte e quattro le nostre funzioni in pulsanti e avere un prototipo funzionante di un'animazione in esecuzione e in salto! Si prega di controllare il codice sorgente per questa pagina con commenti e scaricare il foglio sprite che ho usato, se lo desideri.


Conclusione

Ora, anche se qui abbiamo un prototipo funzionante, potresti notare che è un po 'buggato. Quando fai clic su più di un pulsante alla volta, lo script proverà ad eseguire entrambi contemporaneamente. Oppure, se si fa nuovamente clic sul pulsante di salto mentre si scende, J continuerà a cadere per sempre. Inoltre, come ho detto prima, abbiamo variabili globali nel nostro script, il che significa che potrebbe essere difficile aggiungere questo codice in una pagina esistente senza bloccare altri JavaScript (che è anche il motivo per cui non ho provato a eseguire questo codice all'interno di questo blog pagina). Nel nostro prossimo post, puliremo tutti questi bug e parleremo del concetto di incapsulamento e perché è importante scrivere un buon codice nel mondo reale.