În acest tutorial vom face un cronometru de numărătoare reutilizabil, cu o dată dinamică dinamică care poate fi setată prin intermediul XML. Vom anima numerele care se răstoarnă în stilul unui vechi aeroport sau al unei stații de tren. Vom acoperi codul, crearea de imagini și animația.
Tutorial publicatLa fiecare câteva săptămâni, revizuim câteva postări preferate ale cititorului nostru de-a lungul istoriei site-ului. Acest tutorial a fost publicat pentru prima oară în mai 2010.
Creați un nou fișier Flash (Actionscript 3) cu aceste setări: 500x300, fundal negru și 30 fps.
Creați un nou film MovieClip numit "digit_bottom" și desenați un dreptunghi rotunjit în interiorul acestuia, de aproximativ 36px la 50px înălțime. (O modalitate rapidă de a desena un dreptunghi cu dimensiuni precise este să selectați instrumentul dreptunghi și alt clic pe scenă.)
Dați dreptunghiului un gradient de umplere de la # 111111 (de sus) la # 333333 (de jos) și un contur de 2 px color # 333333.
Poziționați dreptunghiul astfel încât punctul de înregistrare al filmului (micul '+') să fie exact la jumătatea distanței dintre partea superioară și cea inferioară și marginea din stânga. Dacă ați făcut dreptunghiul dvs. de 50px înalt, atunci valoarea y ar trebui să fie -25.
Creați un nou strat și adăugați un câmp de text dinamic numit "t_num". Alegeți un font care are un aeroport sau o stație de tren care se simt la el (cum ar fi Helvetica, DIN sau Interstate). Eu folosesc Helvetica Bold.
Setați formatul paragrafului la centrat și nu uitați să încorporați fonturile pentru numerele 0-9.
Poziționați câmpul text astfel încât să fie centrat pe dreptunghiul de fundal.
Vom folosi acest MovieClip ca bază pentru un alt grafic, așa că faceți un moment pentru a vă asigura că arată bine.
Creați un nou strat pe linia temporală a digit_bottom MovieClip și numiți-o "mască". Copiați dreptunghiul rotunjit și Lipiți pe loc pe masca layer (Editare> Lipire în poziție sau Comandă-Shift-V).
Selectați jumătatea superioară a dreptunghiului mască și ștergeți-l.
Faceți clic dreapta pe masca layer, alegeți Mască și asigurați-vă că acoperă toate straturile de sub ea.
Du-te în Bibliotecă, duplicați-l digit_bottom MovieClip și denumirea copiei noi 'digit_top'.
Acest film va fi virtual identic cu digit_bottom clip, cu excepția faptului că masca va afișa jumătatea superioară a graficii în loc de partea inferioară.
Ștergeți graficele aflate în prezent pe masca strat. Copiați dreptunghiul rotunjit și din nou lipiți pe loc pe masca strat. De data aceasta selectați jumătatea inferioară și ștergeți-o.
Singura altă ajustare pe care ați putea dori să o faceți este să ajustați culoarea textului și umbrirea dreptunghiului rotunjit în fundal. Am făcut grafica în mine digit_top clipul este mai întunecat pentru a simula lumina care vine din partea de sus.
Creați un nou film MovieClip numit "Digit". Trageți în digit_top și digit_bottom MovieClips și poziționează-le pe ambele la 0,0. Dați-le numele de instanță "top1" și "bottom1".
Acum copiați ambele filme MovieClips (digit_top și digit_bottom), creați un nou strat și inserați în loc o copie a fiecărui. Denumiți copiile noi "top2" și "bottom2".
Ar trebui să aveți acum 4 filmări în interiorul dvs. Cifră MovieClip: 2 copii de digit_top și 2 copii ale lui digit_bottom. Voi explica de ce am pus-o asa in pasul urmator.
Trebuie să facem un pic de trickery de animație pentru a obține efectul numerelor flipping dorim. Uitați-vă la diagrama de mai jos a noastră Cifră MovieClip (redat-o în 3D doar pentru a putea vedea mai ușor straturile):
Începem cu bottom2 clipul a fost inversat cu susul în jos (utilizând proprietatea scaleY) și plasat în spatele Top2 clamă. În acest moment cele 2 clipuri care sunt vizibile sunt Top2 și bottom1. Numerele de pe aceste două clipuri corespund una cu cealaltă, astfel încât să formeze o cifră completă.
Acum ne răsturnăm Top2 clip în centrul cifrei. În acest moment, scaraY va fi zero, astfel încât clipul nu va fi vizibil. În același timp, suntem, de asemenea, flipping jos bottom2 clip, dar asta o să flipăm până la capăt. Din moment ce este în spate Top2, nu se va arăta până când nu se va depăși jumătatea punctului. Acum sunt cele 2 clipuri vizibile TOP1 și bottom1. Numerele de pe cele două clipuri nu se potrivesc, dar asta e bine deoarece acest pas durează doar pentru un moment scurt.
Top2 clipul rămâne în centru ca bottom2 continuă să coboare până jos. Odată ce au loc numerele de pe clipurile vizibile (TOP1 și bottom2) se potrivesc din nou pentru a forma o cifră completă.
În acest moment vom relayer și resetați pozițiile celor 2 clipuri ascunse pentru a vă pregăti pentru flipul următor. Observați cum clipurile sunt în aceleași poziții ca și Pasul 1, inversate numai.
Acum că avem individul Cifră Setarea filmuletelor MovieClip, să construim ceasul.
Creați un nou filmClip pe scenă numit "Ceas" cu numele de instanță "ceas". În interiorul noului film MovieClip plasați 9 copii ale dvs. Cifră MovieClip; 2 pentru secunde, 2 minute, 2 ore și 3 zile. Dați fiecărei cifre un nume de instanță. De la stânga la dreapta, numiți "digit0", "digit1", "digit2" și așa mai departe.
Adăugați niște coloni pentru a separa filmările și etichetele pentru fiecare secțiune. Designul depinde de tine. Am adăugat un dreptunghi rotund întunecat ca fundal pentru ceasul meu.
În final, adăugați un câmp de text dinamic numit "t_date". Aici vom arăta data țintă la care se numără ceasul. Nu uitați să încorporați fontul pentru acest câmp de text dacă nu utilizați un font de sistem.
Creați un nou fișier Actionscript numit 'Digit.as' și adăugați acest cod pentru a crea caracterele goale pentru clasă:
pachet import flash.display.MovieClip; clasa publică Digit extinde MovieClip private const TOP: int = 0; const const BOTTOM: int = 1; privat var _currentDigit: Array; privat var _nextDigit: Array; privat var _number: String = "0"; Funcția publică CONSTRUCTOR Digit () _currentDigit = Array nou (top1, bottom1); _nextDigit = Array nou (top2, bottom2);
Acest lucru nu face încă multe. Avem două matrice pentru a ține cele 2 seturi de digit_top și digit_bottom MovieClips. Am setat 2 constante, TOP și BOTTOM pentru a ajuta la urmărirea clipurilor de sus și de jos din cadrul acestor tablouri. _număr variabilă va ține respectiva cifră afișată la un moment dat.
(Notă: Folosesc sublinierea în numele variabilelor pentru a indica variabilele private.)
Gaseste-ti Cifră MovieClip din Bibliotecă și să îi atribuiți această clasă în setările de legare.
Vom folosi biblioteca TweenLite pentru a ne anima Cifră MovieClip.
Descărcați versiunea AS3 a bibliotecii TweenLite aici.
Plasați folderul "com" în același director ca fișierul dvs. principal Flash (sau pe calea sursă, dacă ați configurat o altă cale de clasă).
Adăugați aceste două linii în partea de sus a dvs. Cifră , sub importul filmului MovieClip:
import com.greensock. * import com.greensock.easing. *
Abia vom zgâria suprafața a ceea ce TweenLite poate face în acest tutorial. Pentru mai multe informații, consultați documentația TweenLite.
Adăugați această funcție la dvs. Cifră clasă:
funcția publică flipTo (num: String): void _number = num; _nextDigit [TOP] .t_num.text = num; _nextDigit [BOTTOM] .t_num.text = num; // aruncați în partea de sus a cifrei la jumătatea punctului TweenLite.to (_currentDigit [TOP], .15, scaleY: 0, ease: Linear.easeNone); // flip următoarea cifră de jos în jos TweenLite.to (_nextDigit [BOTTOM], .3, scaleY: 1, onComplete: flipComplete, ușurință: Bounce.easeOut);
Iată ce se întâmplă, line-line:
Luați o altă privire la diagrama de la Pasul 8 dacă sunteți confuz în legătură cu animația de aici.
Adăugați această funcție la Cifră clasa chiar sub flipTo funcţie:
funcția privată flipComplete (): void // swap digits var următoarea: Array = _currentDigit; _currentDigit = _nextDigit; _nextDigit = următor; // resetarea întârzierii de întărire ();
După terminarea animației de tip flip vom executa această funcție. Schimbă _currentDigit și _nextDigit matrice. După ce se termină, se apelează o funcție numită "Resetare" pentru a reseta întinderea și poziționarea clipului pentru următorul flip. Să scriem funcția acum.
Adăugați această funcție la Cifră clasă:
resetarea funcției private (): void addChild (_nextDigit [BOTTOM]); addChild (_currentDigit [TOP]); // rotiți următoarea fundătură pentru a fi în spatele curentului de sus _nextDigit [BOTTOM] .scaleY = -1; _nextDigit [TOP] .scaleY = 1;
Primele două rânduri din această funcție sunt: _nextDigit BOTTOM și apoi _currentDigit TOP în partea de sus a listei de afișare. De obicei, folosesc doar addChild () pentru a face acest lucru deoarece necesită mai puțină tastatură decât folosirea setChildIndex ().
După ce clipurile sunt re-stratificate, setăm proprietățile scaleI astfel încât să fie pregătite pentru flipul următor. Aceasta înseamnă schimbarea _nextDigit [BOTTOM] de la 1 la -1 și _nextDigit [TOP] de la 0 la 1.
Din nou, verificați diagrama din pasul 8 dacă vă pierdeți.
Un lucru pe care am uitat să-l facem este să poziționăm clipurile în mod corespunzător pentru prima animație de tip flip. Putem face acest lucru ușor prin adăugarea unui apel către restabili funcționează corect în constructorul de clase Digit:
Funcția publică CONSTRUCTOR Digit () _currentDigit = Array nou (top1, bottom1); _nextDigit = Array nou (top2, bottom2); reset ();
Un ultim lucru de care avem nevoie în clasa noastră Digit este o modalitate de a accesa privat _număr variabilă din afara clasei. Vom adăuga o funcție simplu accesoriu:
funcția publică obține numărul (): String return _number;
Creați un nou fișier ActionScript numit "Clock.as". Inserați în acest cod:
pachet import flash.display.MovieClip; import flash.events.TimerEvent; import flash.media.Sound; import flash.utils.Timer; public class Ceas extinde MovieClip private var _clockTimer: Timer; privat var _targetDate: Data; // Funcția publică CONSTRUCTOR Ceas ()
Nu prea multe aici. Doar importați câteva dintre orele de care avem nevoie. De asemenea, am câteva variabile private. _clockTimer va număra secundele pentru noi și _Data-țintă va deține data la care numărăm.
Adăugați această funcție la clasa de ceas chiar sub constructor:
// setați data țintă și începeți setul funcției publice cu temporizatorul (data: Date): void _targetDate = date; _clockTimer = nou Cronometru (1000) // bifați fiecare secundă (1000 milisecunde) _clockTimer.addEventListener (TimerEvent.TIMER, actualizare); _clockTimer.start (); // afișați data țintă deasupra ceasului t_date.text = _targetDate.toLocaleString () toUpperCase (); // actualizați ceasul o dată aici, astfel încât acesta să înceapă cu actualizarea corectă a timpului ();
Aceasta este funcția pe care o vom folosi pentru a seta data țintă pentru ceas. Acceptă o dată (desigur) și o atribuie acesteia _Data-țintă variabil. Apoi ne instantiateste _clockTimer. _clockTimer va apela Actualizați funcționează o dată pe secundă pentru a actualiza cifrele.
După pornirea timerului, funcția setează t_date text cu data țintă. Funcția toLocaleString () asigură că data este afișată în fusul orar local al utilizatorului.
Se solicită ultima linie a acestei funcții Actualizați o dată pentru a seta ceasul la ora corespunzătoare. În caz contrar, se va afișa "000 00:00:00" pentru o secundă până la primul eveniment de temporizare.
Această funcție este un pic cam lungă, pentru că este locul în care se desfășoară majoritatea lucrărilor. Adăugați-o la clasa Ceas:
actualizarea funcției private (e: TimerEvent = null): void var now: Date = new Date (); // obține timpul curent // găsiți diferența (în ms) între țintă și acum var diff: Number = _targetDate.valueOf () - now.valueOf (); în cazul în care (dif <=0) // TIME'S UP! // do something cool here _clockTimer.stop(); _clockTimer.removeEventListener(TimerEvent.TIMER, update); diff = 0; // convert to seconds diff = Math.round(diff/1000); // number of days var days:int = Math.floor(diff/ (24 * 60 * 60)); diff -= days*(24 * 60 * 60 ); // number of hours var hours:int = Math.floor(diff / (60 * 60)) diff -= hours*60 * 60; // number of minutes var min:int = Math.floor(diff/ 60); diff -= min*60; // seconds are all that remain var sec:int = diff; // create an array of strings to hold the number for each value var diffArr:Array = new Array(String(days), String(hours), String(min), String(sec)); var diffString:String = "" var len:int = 3; // the first value (days) has 3 digits. All the rest have 2 for each(var s:String in diffArr) // pad the string with a leading zero if needed while(s.length < len) s = "0"+s; len = 2; // all the other values are 2 digits in length diffString += s; // add the padded string to the diffString // go through each character in the diffString and set the corresponding digit for(var i:int = 0; i< diffString.length; i++) if(diffString.substr(i, 1) != this["digit"+i].number) this["digit"+i].flipTo(diffString.substr(i, 1));
Această funcție acceptă un parametru TimerEvent. Valoarea implicită pentru acest parametru este nul. Acest lucru ne permite să apelăm funcția fără a trimite un parametru, așa cum facem în a stabilit funcţie.
Prima linie a acestei funcții devine data și ora curente ca un obiect Date. Apoi, găsim diferența dintre data curentă și data țintă (linia 37). Dacă diferența este 0 sau mai mică, atunci este trecută data țintă, așa că oprim _clockTimer (liniile 38-44).
Deoarece diferența de timp dintre acum și țintă este calculată în milisecunde, trebuie să convertim acest lucru într-un afișaj frumos citit de zile, ore, minute și secunde (linii 46-62). Matematica aici este destul de simplă atâta timp cât știți că există 1000 de milisecunde într-o secundă, 60 de secunde într-un minut, 60 de minute într-o oră și 24 de ore pe zi.
Pe linia 65 stocăm toate aceste valori ca elemente într-un matrice. Pornind de la linia 68, bifăm fiecare element și îl adăugăm unui șir de caractere numit "diffString". În timp ce facem acest lucru, adăugăm, de asemenea, zerouri de conducere unde este necesar (linia 71). Deci, dacă valorile noastre pentru ceas au fost 30 de zile, 5 ore, 56 de minute și 6 secunde diffString ar arăta astfel: "030055606".
Ultimul lucru pe care această funcție îl face este prin buclă prin caracterele din diffString (folosind metoda charAt ()). Pentru fiecare caracter din șir, verificăm dacă este diferit de numărul afișat curent pe cifra corespunzătoare. Acest lucru este ușor din cauza modului în care am numit instanțele digitale. Dacă numărul nu este același cu cel afișat, spuneți acea cifră pentru a reveni la numărul din diffString.
Găsiți (sau creați) un sunet bun care va juca de fiecare dată când se actualizează ceasul. Importați-o în biblioteca fișierului dvs. Flash și setați numele clasei la "TickSound" din setările de legare.
Adaugă _tickSound variabilă în partea de sus a clasei de ceas, chiar sub celelalte două variabile:
privat var _clockTimer: Timer; privat var _targetDate: Data; privat var _tickSound: sunet = nou TickSound ();
Și redați sunetul în interiorul lui Actualizați funcţie:
_tickSound.play ();
Timerul nostru de numărătoare inversă este complet, avem nevoie doar de un mod de a seta data țintă. Creați un nou fișier Actionscript numit "Main.as" cu acest cod:
pachet import flash.display.MovieClip; public class Main extinde MovieClip funcția publică principală () // setarea datei țintă pentru ceasul var targetDate: Date = new Date (); targetDate.setTime (Date.UTC (2010, 4, 28, 20, 00)); clock.set (targetDate);
Toate acestea fac setarea datei țintă pentru instanța Ceas din Stadiu. Folosesc setTime () și Date.UTC () pentru a converti data la Timecode universale. În acest fel, data va fi corectă atunci când devine convertită înapoi la ora locală pe computerul utilizatorului. De asemenea, nu uitați că lunile sunt bazate pe zero. Deci, luna 4 este de fapt mai, nu aprilie.
În fișierul dvs. Flash setați clasa Document la "Main".
Dacă aveți nevoie de o actualizare la utilizarea clasei de documente, verificați acest sfat rapid.
Încercați acum filmul și totul ar trebui să funcționeze. Încercați să schimbați data țintă în clasa principală și să vedeți cum se schimbă numărătoarea inversă.
Un potențial dezavantaj al modului în care am stabilit acest lucru este acela că data-țintă este greu codificată în SWF-ul nostru. Este bine, dar ar fi bine dacă am putea încărca dinamic data, astfel încât să putem reutiliza numărătoarea inversă pentru lucruri diferite.
Să vedem ce putem face despre asta ...
Creați un nou fișier XML în același director ca fișierul dvs. Flash denumit 'targetDate.xml' (un fișier XML este doar un fișier text simplu). Adăugați acest lucru în fișierul XML:
2011 3 25 20 21
Folosirea acestui format pentru data-țintă este destul de umflată (există mai mult markup decât există date reale), dar va păstra lucrurile foarte clare în scopul acestui tutorial.
Acum, să facem câteva modificări în clasa noastră de documente principale. Înlocuiți totul în acel fișier cu acest cod:
pachet import flash.display.MovieClip; import flash.net.URLLoader; import flash.net.URLRequest; importul flash.events.Event; public class Main extinde MovieClip // CONSTRUCTOR funcția publică Main () // încărcați XML var xmlLoader: URLLoader = new URLLoader (); xmlLoader.addEventListener (eveniment.COMPLETE, onDataLoaded); xmlLoader.load (noua adresă URLRequest ("targetDate.xml"));
Veți observa că am importat câteva clase suplimentare pentru a ne ajuta să încărăm fișierul XML. În funcția constructor creăm o nouă instanță URLLoader pentru a încărca fișierul pentru noi. Anexăm un ascultător al evenimentului care va apela o funcție numită "onDataLoaded" atunci când fișierul se termină încărcarea.
Adăugați această funcție la clasa principală:
funcția privată onDataLoaded (e: Event): void var xml: XML = nou XML (e.target.data); var targetDate: Data = data nouă (); targetDate.setTime (Date.UTC (int (xml.year), int (xml.month), int (xml.day), int (xml.hour), int (xml.minute))); clock.set (targetDate);
Această funcție creează un nou obiect XML din fișierul pe care l-am încărcat. Apoi vom crea un nou obiect Date din valorile din XML. Din nou, folosim setTime () și Date.UTC () pentru a converti data la Timecode universale. Linia finală este aceeași ca înainte, ci doar trimite data țintă la instanța noastră Ceas.
Asta e destul pentru asta. Există însă câteva îmbunătățiri pe care le-ați putea dori să le faceți:
Mult noroc! Ca întotdeauna, postați un comentariu și spuneți-mi ce credeți.