JavaScript-animatie die werkt (deel 2 van 4)

In het laatste bericht hebben we het idee geïntroduceerd spriting, een eenvoudige manier om te animeren in JavaScript die in alle browsers werkt. We hebben ook doorlopen hoe je de sprite als achtergrondafbeelding voor een kunt instellen div en gebruik vervolgens een regel JavaScript om de achtergrondpositie te wijzigen zodat deze lijkt alsof de afbeelding is verplaatst.

In deze post zullen we deze techniek gebruiken om zowel rennende als springende bewegingen te animeren. Om de animatie te maken, moeten we de achtergrondpositie snel met een regelmatig interval wijzigen. Kijk opnieuw naar de sprite die we gebruiken.


Ontmoet J, de mascotte voor mijn bedrijf, Joust Multimedia.

In ons voorbeeld hebben we tien totaalbeelden: een van J staat met de voorkant naar rechts, drie van de J naar rechts en een van J springt naar rechts (met hetzelfde aantal van elk frame naar links gericht). Laten we beginnen met hem naar rechts te laten rennen. Om onze afbeelding er uit te laten zien dat deze in werking is, moeten we twee dingen doen: de sprite wijzigen in een andere afbeelding en de afbeelding verplaatsen div naar rechts.


Running to Right Animation

We zullen zeker niet willen vastlopen op verschillende knoppen om door de sprites te bladeren, dus we zullen een aantal functies moeten creëren die dit automatisch doen.

Voor onze hardloopfunctie willen we:

  1. Verplaats de div naar rechts iets
  2. Ga naar het volgende frame van de animatie
  3. Pauzeer een fractie van een seconde (om de illusie van "volharding van het zicht" te behouden)
  4. Loop de functie opnieuw

Gelukkig is er een eenvoudige manier om functies te gebruiken. Een native commando in JavaScript genoemd setTimeout stelt ons in staat om een ​​getimede vertraging aan te maken, waarna we de functie opnieuw oproepen (vanuit de functie).

 function run_right () // Verplaats iets naar rechts ... // Ga naar het volgende animatievenster ... // dit roept opnieuw 'run_right' op na 200 milliseconden setTimeout (function () run_right ();, 200); 

Dus nu hebben we een functie die zichzelf vijf keer per seconde opnieuw zal noemen (die snel genoeg zal zijn om animatie te maken voor onze doeleinden). Onthoud hier dat browsers niet erg accuraat zijn met hun timers. U kunt timing opgeven voor de milliseconde, maar dat betekent niet dat uw script precies op die timing wordt uitgevoerd!

Ons volgende probleem dat moet worden aangepakt, is hoe onze functie gaat weten naar welke sprite te veranderen? In ons voorbeeld moeten we heen en weer fietsen door onze drie afbeeldingen (om vier totale frames van animatie te hebben). Om dit te doen, gaan we onze functie een beetje informatie doorgeven om aan te geven naar welke dia we willen overschakelen. Eenmaal in de functie zullen we een test doen die controleert op welke dia we zouden moeten staan ​​en vervolgens de achtergrondpositie naar de juiste sprite schakelen. Wanneer we de functie opnieuw aanroepen, zullen we de volgende dia als het argument doorgeven.

 function run_right (slide) // Beweeg iets naar rechts ... switch (slide) // deze switch-opdracht controleert verschillende mogelijkheden voor 'slide' case 1: // als 'slide' gelijk is aan '1' ... document.getElementById ( 'j'). style.backgroundPosition = "-40px 0px"; setTimeout (function () run_right (2);, 200); breken; case 2: // als 'slide' gelijk is aan '2' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (3);, 200); breken; case 3: // als 'slide' gelijk is aan '3' ... document.getElementById ('j'). style.backgroundPosition = "-120px 0px"; setTimeout (function () run_right (4);, 200); breken; case 4: // als 'slide' gelijk is aan '4' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (1);, 200); breken; 

En nu we de functie voor de eerste keer aanroepen, moeten we ervoor zorgen dat we de startdia passeren.

 

Evenzo, om onze te verplaatsen div rechts iets, we kunnen het aanvankelijke linkerattribuut van de div, verplaats dan de div elke keer dat de functie wordt aangeroepen.

 functie run_right (dia, links) links = links + 15; // Verhoog zijn linkerattribuut met 15px document.getElementById ('j'). Style.left = links + "px"; switch (slide) // deze switch-opdracht controleert verschillende mogelijkheden voor 'slide' case 1: // als 'slide' gelijk is aan '1' ... document.getElementById ('j'). style.backgroundPosition = "-40px 0px" ; setTimeout (function () run_right (2, left);, 200); breken; case 2: // als 'slide' gelijk is aan '2' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (3, left);, 200); breken; case 3: // als 'slide' gelijk is aan '3' ... document.getElementById ('j'). style.backgroundPosition = "-120px 0px"; setTimeout (function () run_right (4, left);, 200); breken; case 4: // als 'slide' gelijk is aan '4' ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (function () run_right (1, left);, 200); breken; 

En wanneer we in eerste instantie de functie aanroepen, moeten we ervoor zorgen dat we de huidige linkerpositie van onze passeren div.

 

De animatie stoppen

Dus nu hebben we een functie die, wanneer deze wordt opgeroepen, J zal animeren om naar rechts te rennen. Helaas kunnen we het niet stoppen. Allereerst moeten we ervoor zorgen dat de functie zichzelf niet meer roept als J naar de rand van onze fase rent. Om dat te doen, controleren we elke keer dat de functie wordt uitgevoerd een als verklaring om te zien of J ruimte heeft om te blijven werken. Als dat zo is, zullen we de functie als normaal uitvoeren. Zo niet, dan stoppen we met het oproepen van de functie en keren hem terug naar de staande sprite.

 function run_right (slide, left) // Als we links van links 15 pixels kunnen toevoegen en J's rechterkant niet aan de rechterrand van de stage staat ... 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";  

Ten slotte willen we een manier hebben om de functie te stoppen, wanneer nodig. We kunnen de setTimeout () commando naar een variabele, stop dan met de clearTimeout () commando. Om dit te doen, moeten we die variabele buiten de functie declareren, zodat we er later naar kunnen verwijzen. Voorlopig verklaren we het als een globale variabele. Dit is een verschrikkelijke codeermethode, maar we zullen dit in de volgende post corrigeren. Dit is hoe onze functie eruit ziet.

 var timer; functie run_right (dia, links) if ((links + 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";  

En we kunnen een andere functie maken om de draaitimer te stoppen en de sprite terug te zetten naar de staande afbeelding.

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

Rennen naar links Animatie

Nu door de code van onze te lenen run_right functie, kunnen we een andere functie maken om een ​​te maken run_left functie, met slechts een paar wijzigingen.

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

Jumping Animation

Ten slotte moeten we een jump-functie maken. We zullen twee argumenten doorgeven aan deze functie, een die zal volgen of het div is momenteel omhoog of omlaag en een andere die het huidige bovenste attribuut van de. zal volgen div. Tussen de twee, zullen we bepalen welke richting de div moet volgende gaan, en hoe ver (we zullen de div minder afstand nabij de boog van de sprong om versnelling met zwaartekracht te simuleren).

 functie jump (boven, boven) / * * We veranderen J in zijn springende sprite ... * / document.getElementById ('j'). style.backgroundPosition = "-160px 0px"; / * * Hier moeten we beslissen of hij omhoog of omlaag moet reizen ... * / if (up && (document.getElementById ('j'). OffsetTop> 20)) // als hij momenteel omhoog gaat, en hij is meer dan 20 pixels van de bovenkant van het podium ... top = top - (top * .1); // Dit geeft ons een lichte boog in de sprong, in plaats van een constante beweging zoals het uitvoeren van document.getElementById ('j'). Style.top = top + "px"; // Verander zijn positie timer = setTimeout (function () jump (up, top);, 60); // Roep vervolgens de functie opnieuw aan else if (up) // als hij momenteel omhoog gaat, maar hij staat bijna aan de top van het podium en moet weer naar beneden komen ... up = false; // we schakelen de variabele 'op' zodat hij in de volgende lus timer valt = setTimeout (function () jump (up, top);, 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  

Nu kunnen we alle vier onze functies in knoppen plaatsen en een werkend prototype hebben van een rennende en springende animatie! Bekijk de broncode voor deze pagina met opmerkingen en download het sprite-blad dat ik heb gebruikt, als je dat wilt.


Conclusie

Nu, hoewel we hier een werkend prototype hebben, merk je misschien dat het een kleine buggy is. Wanneer u op meer dan één knop tegelijk klikt, probeert het script beide tegelijk uit te voeren. Of, als u op de terugweg nogmaals op de springknop klikt, blijft J voor altijd vallen. Ook, zoals ik al eerder zei, hebben we globale variabelen in ons script, wat betekent dat het moeilijk kan zijn om deze code aan een bestaande pagina toe te voegen zonder andere JavaScript te laten crashen (wat ook de reden is waarom ik deze code niet binnen deze blog probeerde uit te voeren pagina). In onze volgende post zullen we al deze bugs opruimen en praten over het concept van inkapseling en waarom het belangrijk is om goede code te schrijven in de echte wereld.