JavaScript-animation som fungerar (del 2 av 4)

I det sista inlägget introducerade vi idén om spriting, ett enkelt sätt att animera i JavaScript som fungerar i alla webbläsare. Vi gick också igenom hur du konfigurerar sprite som en bakgrundsbild för en div och använd sedan en rad JavaScript för att ändra bakgrundsläget så att det verkar som om bilden har flyttats.

I det här inlägget använder vi denna teknik för att animera både löpande och hoppande rörelser. För att skapa animationen måste vi snabbt ändra bakgrundspositionen med jämna mellanrum. Ta en titt igen på sprite vi använder.


Möt J, mascot för mitt företag, Joust Multimedia.

I vårt exempel har vi tio totalt bilder: en av J står inför höger, tre av J kör till höger och en av J hoppar medan de vetter mot höger (med samma antal av varje ram mot vänster). Låt oss börja med att få honom att springa till höger. För att få vår bild att se ut som den kör, måste vi göra två saker: ändra sprite till en annan bild och flytta div till höger.


Running to the right animation

Vi vill verkligen inte fastna med att klicka på olika knappar för att cykla genom spritesna, så vi måste skapa några funktioner som gör det automatiskt.

För vår löpande funktion vill vi:

  1. Flytta div mot höger något
  2. Flytta till nästa animationsram
  3. Paus i en bråkdel av en sekund (för att bevara visionen "persistens av vision")
  4. Gå till funktionen igen

Lyckligtvis finns det ett enkelt sätt att slingra med funktioner. Ett inbyggt kommando i JavaScript kallas setTimeout tillåter oss att skapa en tidsbegränsad fördröjning, varefter vi kommer att ringa till funktionen igen (från insidan av funktionen).

 funktion run_right () // Flytta något till höger ... // Ändra till nästa animationsram ... // det här kallas 'run_right' igen efter 200 millisekunder setTimeout (funktion () run_right ();, 200); 

Så nu har vi en funktion som kallar sig igen fem gånger i sekundet (vilket kommer att vara tillräckligt snabbt för att skapa animering för våra ändamål). Kom ihåg att webbläsare inte är väldigt korrekta med sina timers. Du kan ange timing till millisekunden, men det betyder inte att ditt skript kommer att köras vid den tidpunkten exakt!

Vårt nästa problem att ta itu med är hur går vår funktion att veta vilken sprite som ska byta till? I vårt exempel måste vi cykla fram och tillbaka genom våra tre bilder (för att ha fyra totala animationsramar). För att göra detta kommer vi att skicka vår funktion lite information för att berätta vilken bild som ska bytas till. En gång i funktionen gör vi ett test som kontrollerar vilken bild vi ska vara på, och byt sedan bakgrundspositionen till rätt sprite. När vi kallar funktionen igen, kommer vi att passera nästa bild som argumentet.

 funktion run_right (slide) // Flytta något till höger ... byt (slide) // den här inställningen kontrollerar olika möjligheter för "slide" fall 1: // om "slide" är lika med "1" ... document.getElementById ( 'j'). style.backgroundPosition = "-40px 0px"; setTimeout (funktion () run_right (2);, 200); ha sönder; fall 2: // om "slide" är lika med "2" ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (funktion () run_right (3);, 200); ha sönder; fall 3: // om "slide" är lika med "3" ... document.getElementById ('j'). style.backgroundPosition = "-120px 0px"; setTimeout (funktion () run_right (4);, 200); ha sönder; fall 4: // om "slide" är lika med "4" ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (funktion () run_right (1);, 200); ha sönder; 

Och nu när vi kallar funktionen för första gången, måste vi se till att vi passerar startdia.

 

På samma sätt, för att flytta vårt div till höger lite kan vi passera det ursprungliga vänstra attributet för div, flytta sedan div något varje gång funktionen heter.

 funktion run_right (bild, vänster) vänster = vänster + 15; // Öka hans vänstra attribut med 15px document.getElementById ('j'). Style.left = left + "px"; switch (slide) // den här växlingsuppsättningen kontrollerar olika möjligheter för "slide" case 1: // om "slide" är lika med "1" ... document.getElementById ('j'). style.backgroundPosition = "-40px 0px" ; setTimeout (funktion () run_right (2, vänster);, 200); ha sönder; fall 2: // om "slide" är lika med "2" ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (funktion () run_right (3, vänster);, 200); ha sönder; fall 3: // om "slide" är lika med "3" ... document.getElementById ('j'). style.backgroundPosition = "-120px 0px"; setTimeout (funktion () run_right (4, vänster);, 200); ha sönder; fall 4: // om "slide" är lika med "4" ... document.getElementById ('j'). style.backgroundPosition = "-80px 0px"; setTimeout (funktion () run_right (1, vänster);, 200); ha sönder; 

Och när vi först kallar funktionen, måste vi se till att vi passerar den nuvarande vänstra positionen hos vår div.

 

Stoppar animationen

Så, nu har vi en funktion som, när den kallas, kommer att animera J att springa till höger. Tyvärr har vi inget sätt att stoppa det. Först av allt måste vi göra funktionen sluta ringa sig själv om J går till kanten av vårt stadium. För att göra det, varje gång funktionen körs, kontrollerar vi en om uttalande för att se om J har utrymme att fortsätta springa. Om så är fallet kommer vi att köra funktionen som normal. Om inte, kommer vi sluta ringa funktionen och returnera honom till stående sprite.

 funktion run_right (slide, left) // Om vi ​​kan lägga till 15 pixlar till vänster och har Js högra kant inte vid scenens högra kant ... om ((vänster + 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";  

Slutligen vill vi ha ett sätt att stoppa funktionen, när det behövs. Vi kan ställa in setTimeout () kommandot till en variabel, stoppa sedan den med cleartimeout () kommando. För att göra detta måste vi förklara den variabeln utanför funktionen, så att vi kommer att kunna hänvisa till det senare. För nu kommer vi att förklara det som en global variabel. Det här är hemskt kodande övning, men vi kommer att korrigera detta i nästa inlägg. Så här ser vår funktion ut.

 var timer; funktion run_right (slide, left) if ((vänster + 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";  

Och vi kan skapa en annan funktion för att stoppa körtiden och returnera sprite till den stående bilden.

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

Running till vänster Animation

Nu genom att låna koden från vår run_right funktion kan vi skapa en annan funktion för att göra en run_left funktion, med några få modifieringar.

 funktion run_left (steg, vänster) om ((vänster - 15)> 0) vänster = vänster - 15; document.getElementById ('j'). style.left = left + "px"; switch (scen) case 1: document.getElementById ('j'). style.backgroundPosition = "-40px -50px"; timer = setTimeout (funktion () run_left (2, vänster);, 200); ha sönder; fall 2: document.getElementById ('j'). style.backgroundPosition = "-80px -50px"; timer = setTimeout (funktion () run_left (3, vänster);, 200); ha sönder; fall 3: document.getElementById ('j'). style.backgroundPosition = "-120px -50px"; timer = setTimeout (funktion () run_left (4, vänster);, 200); ha sönder; fall 4: document.getElementById ('j'). style.backgroundPosition = "-80px -50px"; timer = setTimeout (funktion () run_left (1, vänster);, 200); ha sönder;  else document.getElementById ('j'). style.backgroundPosition = "0px -50px"; 

Hoppning Animation

Slutligen måste vi skapa en hoppfunktion. Vi kommer att skicka två argument till den här funktionen, en som kommer att spåra om div För närvarande flyttas upp eller ner och en annan som spårar den aktuella toppattributet för div. Mellan de två bestämmer vi vilken riktning div måste flytta nästa och hur långt (vi kommer att flytta div mindre avstånd nära bågens båge för att simulera acceleration med tyngdkraften).

 funktionshopp (uppåt) / * * Vi ändrar J till hans hoppsprit ... * / document.getElementById ('j'). style.backgroundPosition = "-160px 0px"; / * * Här måste vi bestämma om han ska resa upp eller ner ... * / if (up && (document.getElementById ('j'). OffsetTop> 20)) // om han för närvarande flyttar han är mer än 20 pixlar från toppen av scenen ... topp = topp - (topp * .1); // Detta ger oss en liten båge i hoppet, snarare än en konstant rörelse som att köra document.getElementById ('j'). Style.top = top + "px"; // Ändra sin positionstimer = setTimeout (funktion () hoppa (uppåt);, 60); // Då kallas funktionen igen annars om (upp) // om han för närvarande flyttar upp, men han är nästan överst i scenen och behöver komma tillbaka ner ... upp = false; // vi byter upp-variabeln så att han kommer att falla i nästa loop timer = setTimeout (funktion () hoppa (upp, topp);, 60);  annars om (! 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 kan vi sätta alla fyra av våra funktioner i knappar och ha en fungerande prototyp av en löpande och hoppande animation! Vänligen kolla källkoden för den här sidan med kommentarer och ladda ner spritarket som jag använde, om du skulle vilja.


Slutsats

Nu, även om vi har en fungerande prototyp här, kanske du märker att det är en liten buggy. När du klickar på mer än en knapp i taget försöker skriptet köra både på en gång. Eller, om du klickar på hopp-knappen igen på vägen ner kommer J att fortsätta att falla för alltid. Också, som jag nämnde tidigare, har vi globala variabler i vårt skript, vilket innebär att det kan vara svårt att lägga till den här koden i en befintlig sida utan att krascha annan JavaScript (vilket varför jag försökte inte köra den här koden i den här bloggen sida). I vårt nästa inlägg kommer vi att rensa alla dessa buggar och prata om konceptet inkapsling och varför det är viktigt att skriva bra kod i den verkliga världen.