In questo tutorial creeremo un timer per il conto alla rovescia riutilizzabile con una data di destinazione dinamica che può essere impostata tramite XML. Animeremo i numeri abbattuti nello stile di un vecchio aeroporto o della stazione ferroviaria. Copriremo il codice, la creazione grafica e l'animazione.
Tutorial ripubblicatoOgni poche settimane, rivisitiamo alcuni dei post preferiti del nostro lettore da tutta la cronologia del sito. Questo tutorial è stato pubblicato per la prima volta nel maggio del 2010.
Crea un nuovo file Flash (Actionscript 3) con queste impostazioni: 500x300, sfondo nero e 30 fps.
Crea un nuovo Movie Clip chiamato 'digit_bottom' e traccia un rettangolo arrotondato al suo interno di circa 36 px di larghezza per 50 px di altezza. (Un modo rapido per disegnare un rettangolo con dimensioni precise è selezionare lo strumento rettangolo e Alt-clic sul palcoscenico.)
Assegna al rettangolo un riempimento sfumato da # 111111 (in alto) a # 333333 (in basso) e un contorno di 2 px colorato # 333333.
Posiziona il rettangolo in modo che il punto di registrazione di MovieClip (il piccolo '+') sia esattamente a metà tra il bordo superiore e inferiore e il bordo sinistro. Se hai reso il tuo rettangolo di 50 px di altezza, il valore di y dovrebbe essere -25.
Crea un nuovo livello e aggiungi un campo di testo dinamico chiamato 't_num'. Scegli un font che abbia un aeroporto o una stazione ferroviaria (come Helvetica, DIN o Interstate). Sto usando Helvetica Bold.
Imposta il formato del paragrafo su centrato e ricorda di incorporare i caratteri per i numeri da 0 a 9.
Posiziona il campo di testo in modo che sia centrato sul rettangolo dello sfondo.
Useremo questo Movie Clip come base per un altro grafico, quindi prenditi un momento per assicurarti che abbia un bell'aspetto.
Crea un nuovo livello sulla timeline del digit_bottom MovieClip e chiamalo 'maschera'. Copia il rettangolo arrotondato e incolla in posizione sul maschera livello (Modifica> Incolla in posizione o Comando-Maiusc-V).
Seleziona la metà superiore del rettangolo della maschera ed eliminalo.
Fare clic con il tasto destro del mouse su maschera livello, selezionare Maschera e assicurarsi che copra tutti i livelli sottostanti.
Vai nella Libreria, duplica il digit_bottom MovieClip e nominare la nuova copia 'digit_top'.
Questo MovieClip sarà praticamente identico al digit_bottom clip, tranne che la maschera mostrerà la metà superiore della grafica anziché la parte inferiore.
Elimina la grafica attualmente sul maschera strato. Copia il rettangolo arrotondato e di nuovo Paste in Place sul maschera strato. Questa volta seleziona la metà inferiore e cancellala.
L'unica altra regolazione che potresti voler fare qui è regolare il colore del testo e l'ombreggiatura del rettangolo arrotondato dello sfondo. Ho realizzato la grafica nella mia digit_top clip un po 'più scuro per simulare la luce proveniente dall'alto.
Crea un nuovo MovieClip chiamato 'Digit'. Trascina nel digit_top e digit_bottom MovieClip e posizionale entrambi a 0,0. Assegna loro i nomi di istanza 'top1' e 'bottom1'.
Ora copia entrambi i MovieClip (digit_top e digit_bottom), crea un nuovo livello e Incolla in posizione una copia di ciascuno. Assegna un nome alle nuove copie 'top2' e 'bottom2'.
Ora dovresti avere 4 Movie Clip all'interno del tuo cifra MovieClip: 2 copie di digit_top e 2 copie di digit_bottom. Spiegherò perché lo stiamo configurando in questo modo nel prossimo passaggio.
Dobbiamo fare un po 'di trucchetti di animazione per ottenere l'effetto dei numeri flipping che vogliamo. Dai uno sguardo allo schema qui sotto del nostro cifra MovieClip (lo sto visualizzando in 3D solo per vedere più facilmente la stratificazione):
Iniziamo con il bottom2 clip capovolto (utilizzando la proprietà scaleY) e posizionato dietro il top2 clip. A questo punto i 2 clip che sono visibili sono top2 e bottom1. I numeri su queste due clip corrispondono tra loro, quindi formano una cifra completa.
Ora capovolgiamo il top2 clip al centro della cifra. A questo punto la scalaY sarà zero, quindi la clip non sarà visibile. Allo stesso tempo, stiamo anche abbattendo il bottom2 clip, ma questo gireremo fino in fondo. Poiché è dietro top2, non verrà mostrato fino a quando non oltrepassa il punto a metà strada. Ora i 2 clip visibili sono TOP1 e bottom1. I numeri su queste due clip non corrispondono, ma va bene perché questo passaggio dura solo per un breve momento.
Il top2 la clip rimane al centro come bottom2 continua a cadere fino in fondo. Una volta posizionato, i numeri sui clip visibili (TOP1 e bottom2) di nuovo corrisponde per formare una cifra completa.
A questo punto ci relazioneremo e ripristineremo le posizioni delle 2 clip nascoste per prepararci al prossimo lancio. Notare come i clip si trovano nelle stesse posizioni del passaggio 1, solo invertiti.
Ora che abbiamo l'individuo cifra MovieClip impostato, creiamo l'orologio.
Crea un nuovo MovieClip sul palco chiamato 'Orologio' con il nome di istanza 'orologio'. All'interno del nuovo MovieClip inserire 9 copie del tuo cifra Un filmato; 2 per secondi, 2 per minuti, 2 per ore e 3 per giorni. Assegna a ogni cifra un nome di istanza. Da sinistra a destra chiamali "digit0", "digit1", "digit2" e così via.
Aggiungi alcuni due punti per separare i MovieClip e le etichette per ogni sezione. Il design dipende da te. Ho aggiunto un rettangolo arrotondato scuro come sfondo per il mio orologio.
Infine, aggiungi un campo di testo dinamico chiamato 't_date'. Qui è dove mostreremo la data di arrivo a cui l'orologio sta contando. Ricorda di incorporare il carattere per questo campo di testo se non stai utilizzando un font di sistema.
Crea un nuovo file Actionscript chiamato "Digit.as" e aggiungi questo codice per creare la shell vuota per la classe:
package import flash.display.MovieClip; public class Digit estende MovieClip private const TOP: int = 0; const privato BOTTOM: int = 1; private var _currentDigit: Array; private var _nextDigit: Array; private var _number: String = "0"; // Funzione pubblica CONSTRUCTOR Digit () _currentDigit = new Array (top1, bottom1); _nextDigit = new Array (top2, bottom2);
Questo non fa ancora molto Abbiamo un paio di matrici per contenere i 2 set di digit_top e digit_bottom MovieClip. Ho impostato 2 costanti, TOP e BOTTOM per tenere traccia delle clip in alto e in basso all'interno di tali array. Il _numero variabile terrà la cifra che è in mostra in un dato momento.
(Nota: sto usando il trattino basso nei miei nomi variabili per indicare variabili private).
Trova il tuo cifra MovieClip nella Libreria e assegna questa classe ad esso nelle impostazioni del Concatenamento.
Utilizzeremo la libreria TweenLite per animare i nostri cifra Un filmato.
Scarica qui la versione AS3 della libreria TweenLite.
Inserisci la cartella 'com' nella stessa directory del tuo file Flash principale (o nel tuo percorso di origine, se hai impostato un percorso di classe diverso).
Aggiungi queste due linee nella parte superiore del tuo cifra classe, appena sotto l'importazione MovieClip:
import com.greensock. * import com.greensock.easing. *
A malapena riusciremo a scalfire la superficie di ciò che TweenLite può fare in questo tutorial. Per ulteriori informazioni, consultare la documentazione di TweenLite.
Aggiungi questa funzione al tuo cifra classe:
funzione pubblica flipTo (num: String): void _number = num; _nextDigit [TOP] .t_num.text = num; _nextDigit [BOTTOM] .t_num.text = num; // capovolgere la parte superiore della cifra fino a metà TweenLite.to (_currentDigit [TOP], .15, scaleY: 0, facilità: Linear.easeNone); // capovolge la successiva cifra in basso TweenLite.to (_nextDigit [BOTTOM], .3, scaleY: 1, onComplete: flipComplete, ease: Bounce.easeOut);
Ecco cosa sta succedendo, riga per riga:
Dai un altro sguardo al diagramma al punto 8 se sei confuso sull'animazione qui.
Aggiungi questa funzione al cifra classe appena sotto il flipTo funzione:
funzione privata flipComplete (): void // swap digits var next: Array = _currentDigit; _currentDigit = _nextDigit; _nextDigit = next; // reset layering reset ();
Una volta completata l'animazione flip, eseguiremo questa funzione. Scambia il _currentDigit e _nextDigit array. Fatto questo, chiama una funzione chiamata 'reset' per ripristinare la stratificazione e le posizioni del clip per il successivo flip. Scriviamo ora quella funzione.
Aggiungi questa funzione al cifra classe:
funzione privata reset (): void addChild (_nextDigit [BOTTOM]); addChild (_currentDigit [TOP]); // capovolge il fondo successivo per essere dietro al corrente superiore _nextDigit [BOTTOM] .scaleY = -1; _nextDigit [TOP] .scaleY = 1;
Le prime due righe in questa funzione pop _nextDigit BASSO e poi il _currentDigit TOP in cima alla lista di visualizzazione. Di solito uso solo addChild () per fare questo perché richiede meno battitura rispetto all'uso di setChildIndex ().
Dopo che i clip sono stati riposizionati, impostiamo le proprietà scaleY in modo che siano pronti per il prossimo lancio. Questo significa cambiare _nextDigit [FONDO] da 1 a -1 e _nextDigit [TOP] da 0 a 1.
Di nuovo, controlla il diagramma al punto 8 se ti stai perdendo.
Una cosa che abbiamo dimenticato di fare è posizionare correttamente le clip per la prima animazione di flip. Possiamo farlo facilmente aggiungendo una chiamata al reset funzione proprio nel costruttore della classe Digit:
// Funzione pubblica CONSTRUCTOR Digit () _currentDigit = new Array (top1, bottom1); _nextDigit = new Array (top2, bottom2); reset();
Un'ultima cosa di cui avremo bisogno nella nostra classe Digit è un modo per accedere al privato _numero variabile dall'esterno della classe. Aggiungeremo una semplice funzione di accesso:
funzione pubblica get numero (): String return _number;
Crea un nuovo file ActionScript denominato "Clock.as". Incolla in questo codice:
package import flash.display.MovieClip; import flash.events.TimerEvent; import flash.media.Sound; import flash.utils.Timer; public class Clock estende MovieClip private var _clockTimer: Timer; private var _targetDate: Date; // Orologio di funzione pubblica CONSTRUCTOR ()
Non c'è ancora molto. Importa solo alcune delle classi di cui avremo bisogno. Ho anche un paio di variabili private. _clockTimer farà il conto alla rovescia dei secondi per noi, e _targetDate terremo la data che stiamo contando.
Aggiungi questa funzione alla classe Clock appena sotto il costruttore:
// imposta la data di destinazione e avvia il set di funzioni pubbliche del timer per il conto alla rovescia (data: data): void _targetDate = date; _clockTimer = new Timer (1000) // tick ogni secondo (1000 millisecondi) _clockTimer.addEventListener (TimerEvent.TIMER, aggiornamento); _clockTimer.start (); // mostra la data di destinazione sopra l'orologio t_date.text = _targetDate.toLocaleString (). toUpperCase (); // aggiorna l'orologio una volta qui, quindi inizia con l'aggiornamento dell'ora corretto ();
Questa è la funzione che useremo per impostare la data di destinazione per l'orologio. Accetta una data (ovviamente) e la assegna al _targetDate variabile. Quindi istanzia il nostro _clockTimer. Il _clockTimer chiamerà il aggiornare funzione una volta al secondo per aggiornare le cifre.
Dopo aver avviato il timer, la funzione imposta il t_date testo con la data di destinazione. La funzione toLocaleString () assicura che la data sia visualizzata nel fuso orario locale dell'utente.
L'ultima riga di questa funzione chiama aggiornare una volta per impostare l'orologio al momento giusto. Altrimenti verrebbe visualizzato "000 00:00:00" per un secondo fino al primo evento del timer.
Questa funzione è un po 'lunga perché è dove viene eseguita la maggior parte del lavoro. Aggiungilo alla tua classe Clock:
aggiornamento della funzione privata (e: TimerEvent = null): void var now: Date = new Date (); // ottiene l'ora corrente // trova la differenza (in ms) tra il target e ora var diff: Number = _targetDate.valueOf () - now.valueOf (); if (diff <=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));
Questa funzione accetta un TimerEvent come parametro. Il valore predefinito per questo parametro è nullo. Questo ci permette di chiamare la funzione senza inviare un parametro, come stiamo facendo nel impostato funzione.
La prima riga di questa funzione ottiene la data e l'ora correnti come oggetto Date. Successivamente, troviamo la differenza tra la data corrente e la data di destinazione (riga 37). Se la differenza è 0 o meno, allora ha superato la data di destinazione, quindi fermiamo il _clockTimer (righe 38-44).
Poiché la differenza di tempo tra ora e obiettivo viene calcolata in millisecondi, è necessario convertirla in una visualizzazione leggibile di giorni, ore, minuti e secondi (righe 46-62). La matematica qui è piuttosto semplice purché tu sappia che ci sono 1000 millisecondi in un secondo, 60 secondi in un minuto, 60 minuti in un'ora e 24 ore in un giorno.
Sulla linea 65 memorizziamo tutti quei valori come elementi in una matrice. A partire dalla riga 68 passiamo in rassegna ogni elemento e lo aggiungiamo a una stringa di caratteri chiamata "diffString". Facendo ciò aggiungiamo anche zeri iniziali ove necessario (riga 71). Quindi se i nostri valori per l'orologio erano 30 giorni, 5 ore, 56 minuti e 6 secondi il diffString sarebbe simile a questo: "030055606".
L'ultima cosa che fa questa funzione è scorrere i caratteri nel file diffString (usando il metodo charAt ()). Per ogni carattere nella stringa controlliamo se è diverso dal numero attualmente visualizzato sulla cifra corrispondente. Questo è facile a causa del modo in cui abbiamo chiamato le nostre istanze di cifre. Se il numero non è lo stesso di quello attualmente visualizzato, diamo a quella cifra di passare al numero nel file diffString.
Trova (o crea) un buon suono ticchettante che suonerà ogni volta che l'orologio si aggiorna. Importalo nella Libreria del tuo file Flash e imposta il nome della classe su "TickSound" nelle impostazioni di Linkage.
Aggiungi il _tickSound variabile in cima alla tua classe Clock appena sotto le altre due variabili:
private var _clockTimer: Timer; private var _targetDate: Date; private var _tickSound: Sound = new TickSound ();
E suona il suono dentro il aggiornare funzione:
_tickSound.play ();
Il nostro conto alla rovescia è completo, abbiamo solo bisogno di un modo per impostare la data di destinazione. Crea un nuovo file Actionscript chiamato "Main.as" con questo codice:
package import flash.display.MovieClip; public class Main extends MovieClip public function Main () // imposta la data di destinazione per l'orologio var targetDate: Date = new Date (); targetDate.setTime (Date.UTC (2010, 4, 28, 20, 00)); clock.set (targetDate);
Tutto ciò è impostato sulla data di destinazione per l'istanza di Clock sullo stage. Sto usando setTime () e Date.UTC () per convertire la data in Universal Timecode. In questo modo la data sarà corretta quando viene convertita all'ora locale sul computer dell'utente. Inoltre, ricorda che i mesi sono a base zero. Quindi, il mese 4 è in realtà maggio, non aprile.
Nel file Flash imposta la classe Documento su "Principale".
Se hai bisogno di un aggiornamento sull'uso della Document Class, consulta questo suggerimento rapido.
Metti alla prova il tuo film ora e tutto dovrebbe funzionare. Prova a cambiare la data del target nella classe Main e vedi come cambia il conto alla rovescia.
Un potenziale svantaggio di come abbiamo impostato questo è che la data di destinazione è hard-coded nel nostro SWF. Va bene, ma sarebbe bello se potessimo caricare dinamicamente la data in modo da poter riutilizzare il conto alla rovescia per cose diverse.
Vediamo cosa possiamo fare a riguardo ...
Crea un nuovo file XML nella stessa cartella del tuo file Flash chiamato 'targetDate.xml' (un file XML è solo un file di testo). Aggiungi questo al file XML:
2011 3 25 20 21
L'uso di questo formato per la nostra data obiettivo è piuttosto gonfio (c'è più markup che dati reali), ma manterrà le cose molto chiare per gli scopi di questo tutorial.
Ora facciamo alcune modifiche alla nostra classe di documento principale. Sostituisci tutto in quel file con questo codice:
package import flash.display.MovieClip; import flash.net.URLLoader; import flash.net.URLRequest; import flash.events.Event; public class Main estende MovieClip // Funzione pubblica CONSTRUCTOR Main () // carica XML var xmlLoader: URLLoader = new URLLoader (); xmlLoader.addEventListener (Event.COMPLETE, onDataLoaded); xmlLoader.load (new URLRequest ("targetDate.xml"));
Noterai che abbiamo importato alcune classi aggiuntive per aiutarci a caricare il file XML. Nella funzione di costruzione stiamo creando una nuova istanza URLLoader per caricare il file per noi. Alleghiamo un listener di eventi che chiamerà una funzione chiamata 'onDataLoaded' al termine del caricamento del file.
Aggiungi questa funzione alla classe Main:
funzione privata onDataLoaded (e: Event): void var xml: XML = new XML (e.target.data); var targetDate: Date = new Date (); targetDate.setTime (Date.UTC (int (xml.year), int (xml.month), int (xml.day), int (xml.hour), int (xml.minute))); clock.set (targetDate);
Questa funzione crea un nuovo oggetto XML dal file che abbiamo caricato. Quindi creiamo un nuovo oggetto Date dai valori nell'XML. Stiamo ancora utilizzando setTime () e Date.UTC () per convertire la data in Universal Timecode. La linea finale è la stessa di prima, invia semplicemente la data di destinazione alla nostra istanza di Clock.
Questo è praticamente per questo. Ci sono un paio di miglioramenti che potresti voler realizzare:
In bocca al lupo! Come sempre, pubblica un commento e fammi sapere cosa ne pensi.