Dans ce tutoriel, nous allons créer un compte à rebours réutilisable avec une date cible dynamique pouvant être définie via XML. Nous animerons les chiffres à la manière d’un ancien tableau de statut d’aéroport ou de gare. Nous couvrirons le code, la création graphique et l'animation.
Tutoriel republiéToutes les quelques semaines, nous revoyons certains des articles préférés de nos lecteurs tout au long de l'histoire du site. Ce tutoriel a été publié pour la première fois en mai 2010.
Créez un nouveau fichier Flash (Actionscript 3) avec les paramètres suivants: 500x300, fond noir et 30 ips..
Créez un nouveau MovieClip appelé "digit_bottom" et tracez un rectangle arrondi à l'intérieur d'environ 36 pixels de large par 50 pixels de haut. (Un moyen rapide de dessiner un rectangle avec des dimensions précises consiste à sélectionner l'outil Rectangle et à cliquer sur la scène en maintenant la touche Alt enfoncée.)
Donnez au rectangle un dégradé de # 111111 (en haut) à # 333333 (en bas) et un contour en 2 px de couleur # 333333.
Positionnez le rectangle de sorte que le point d'alignement du MovieClip (le petit '+') soit exactement à mi-chemin entre le bord supérieur et inférieur et le bord gauche. Si vous avez créé un rectangle de 50 pixels de haut, la valeur y devrait être -25.
Créez un nouveau calque et ajoutez un champ de texte dynamique appelé "t_num". Choisissez une police qui ressemble à un aéroport ou à une gare (comme Helvetica, DIN ou Interstate). J'utilise Helvetica Bold.
Définissez le format de paragraphe sur Centré et n'oubliez pas d'intégrer les polices pour les chiffres de 0 à 9..
Positionnez le champ de texte de sorte qu'il soit centré sur le rectangle d'arrière-plan.
Nous allons utiliser ce MovieClip comme base pour un autre graphique, alors prenez un moment pour vous assurer qu'il est beau.
Créer un nouveau calque sur la timeline du digit_bottom MovieClip et appelez-le 'masque'. Copiez le rectangle arrondi et Coller en place sur le masque calque (Édition> Coller à la place ou Commande-Maj-V).
Sélectionnez la moitié supérieure du rectangle de masque et supprimez-le..
Faites un clic droit sur le masque couche, choisissez Masque et assurez-vous qu'il masque toutes les couches en dessous.
Allez dans la bibliothèque, dupliquez le digit_bottom MovieClip et nommez la nouvelle copie 'digit_top'.
Ce MovieClip sera pratiquement identique à la digit_bottom clip, sauf que le masque montrera la moitié supérieure du graphique au lieu du bas.
Supprimer les graphiques actuellement sur le masque couche. Copiez le rectangle arrondi et à nouveau Coller en place sur le masque couche. Cette fois, sélectionnez la moitié inférieure et supprimez-la.
Le seul autre ajustement que vous puissiez faire ici est de régler la couleur du texte et l'ombrage du rectangle arrondi. J'ai fait les graphiques dans mon digit_top clip un peu plus sombre pour simuler la lumière venant du haut.
Créez un nouveau MovieClip nommé 'Digit'. Faites glisser dans le digit_top et digit_bottom MovieClips et positionnez-les tous les deux à 0,0. Donnez-leur les noms d'instance 'top1' et 'bottom1'.
Maintenant, copiez les deux MovieClips (digit_top et digit_bottom), créer un nouveau calque et coller en place une copie de chacun. Nommez les nouvelles copies 'top2' et 'bottom2'.
Vous devriez maintenant avoir 4 MovieClips dans votre Chiffre MovieClip: 2 copies de digit_top et 2 copies de digit_bottom. Je vais expliquer pourquoi nous mettons en place comme ça dans la prochaine étape.
Nous devons faire quelques trucs d’animation pour obtenir l’effet de retournement voulu. Regardez le schéma ci-dessous de notre Chiffre MovieClip (je le rends en 3D pour que vous puissiez voir plus facilement la superposition):
Nous commençons avec le bas2 clip renversé (à l'aide de la propriété scaleY) et placé derrière le top2 agrafe. À ce stade, les 2 clips visibles sont top2 et bas1. Les numéros sur ces deux clips se correspondent, ils forment donc un chiffre complet.
Maintenant nous baissons la top2 clip au centre du chiffre. A ce stade, scaleY sera nul et le clip ne sera pas visible. Dans le même temps, nous baissons aussi les bas2 clip, mais celui-ci nous allons tout le chemin vers le bas. Depuis c'est derrière top2, il ne sera pas montré jusqu'à ce qu'il passe au-delà du point à mi-chemin. Maintenant, les 2 clips visibles sont Top 1 et bas1. Les chiffres sur ces deux clips ne correspondent pas, mais c'est correct car cette étape ne dure qu'un bref moment..
le top2 le clip reste au centre comme bas2 continue de tomber tout en bas. Une fois en place, les numéros sur les clips visibles (Top 1 et bas2) à nouveau correspondre pour former un chiffre complet.
À ce stade, nous allons relancer et réinitialiser les positions des 2 clips cachés pour nous préparer au prochain retournement. Notez que les clips se trouvent dans les mêmes positions que l’étape 1 et ne sont inversés..
Maintenant que nous avons la personne Chiffre MovieClip mis en place, construisons l'horloge.
Créez un nouveau MovieClip sur la scène appelé "Clock" avec le nom d'occurrence "clock". Dans le nouveau MovieClip, placez 9 copies de votre Chiffre MovieClip; 2 pour les secondes, 2 pour les minutes, 2 pour les heures et 3 pour les jours. Donnez à chaque chiffre un nom d'instance. De gauche à droite, nommez-les 'digit0', 'digit1', 'digit2', etc..
Ajoutez des deux points pour séparer les MovieClips et les étiquettes de chaque section. La conception est à vous. J'ai ajouté un rectangle arrondi foncé comme fond d'écran pour mon horloge.
Enfin, ajoutez un champ de texte dynamique appelé 't_date'. C'est ici que nous allons montrer la date cible à laquelle compte l'horloge. N'oubliez pas d'intégrer la police pour ce champ de texte si vous n'utilisez pas de police système..
Créez un nouveau fichier Actionscript appelé 'Digit.as' et ajoutez ce code pour créer le shell vide pour la classe:
package import flash.display.MovieClip; public class Digit extend MovieClip private const TOP: int = 0; const privé BOTTOM: int = 1; private var _currentDigit: Array; private var _nextDigit: Array; private var _number: String = "0"; // fonction publique CONSTRUCTOR Digit () _currentDigit = new Array (top1, bottom1); _nextDigit = new Array (top2, bottom2);
Cela ne fait pas beaucoup encore. Nous avons deux tableaux pour contenir les 2 ensembles de digit_top et digit_bottom MovieClips. J'ai configuré 2 constantes, TOP et BOTTOM pour vous aider à garder une trace des clips supérieurs et inférieurs dans ces tableaux. le _nombre variable tiendra le chiffre qui est affiché à un moment donné.
(Remarque: j'utilise le trait de soulignement dans mes noms de variables pour indiquer les variables privées.)
Trouver votre Chiffre MovieClip dans la bibliothèque et lui attribuer cette classe dans les paramètres de liaison.
Nous allons utiliser la bibliothèque TweenLite pour animer notre Chiffre MovieClip.
Téléchargez la version AS3 de la bibliothèque TweenLite ici.
Placez le dossier "com" dans le même répertoire que votre fichier Flash principal (ou dans votre chemin source si vous avez configuré un chemin de classe différent)..
Ajoutez ces deux lignes en haut de votre Chiffre classe, juste en dessous de l'importation MovieClip:
importer com.greensock. * importer com.greensock.easing. *
Nous allons à peine effleurer la surface de ce que TweenLite peut faire dans ce tutoriel. Pour plus d'informations, consultez la documentation TweenLite.
Ajoutez cette fonction à votre Chiffre classe:
fonction publique flipTo (num: String): void _number = num; _nextDigit [TOP] .t_num.text = num; _nextDigit [BOTTOM] .t_num.text = num; // retourne le haut du chiffre jusqu'au point médian TweenLite.to (_currentDigit [TOP], .15, scaleY: 0, easy: Linear.easeNone); // retourne le chiffre suivant en bas TweenLite.to (_nextDigit [BOTTOM], .3, scaleY: 1, onComplete: flipComplete, easy: Bounce.easeOut);
Voici ce qui se passe, ligne par ligne:
Jetez un autre coup d'œil au diagramme de l'étape 8 si l'animation est compliquée..
Ajouter cette fonction au Chiffre classe juste en dessous de la flipTo une fonction:
fonction privée flipComplete (): void // swap digits var next: Array = _currentDigit; _currentDigit = _nextDigit; _nextDigit = next; // réinitialiser la superposition reset ();
Une fois l'animation terminée, nous allons exécuter cette fonction. Il échange le _currentDigit et _nextDigit tableaux. Une fois cela fait, il appelle une fonction nommée 'reset' pour réinitialiser la superposition de clips et les positions pour le prochain retournement. Écrivons cette fonction maintenant.
Ajouter cette fonction au Chiffre classe:
fonction privée reset (): void addChild (_nextDigit [BOTTOM]); addChild (_currentDigit [TOP]); // retourne le prochain bas derrière le sommet actuel _nextDigit [BOTTOM] .scaleY = -1; _nextDigit [TOP] .scaleY = 1;
Les deux premières lignes de cette fonction font apparaître le _nextDigit BAS puis le _currentDigit HAUT en haut de la liste d'affichage. D'habitude, j'utilise simplement addChild () parce que cela nécessite moins de frappe que d'utiliser setChildIndex ().
Une fois les clips ré-superposés, nous définissons les propriétés de scaleY afin qu'elles soient prêtes pour le prochain retournement. Cela signifie changer _nextDigit [BAS] de 1 à -1 et _nextDigit [TOP] de 0 à 1.
Encore une fois, vérifiez le diagramme à l'étape 8 si vous vous perdez.
Une chose que nous avons oublié de faire est de positionner correctement les clips pour la première animation de retournement. Nous pouvons le faire facilement en ajoutant un appel au réinitialiser fonction dans le constructeur de la classe Digit:
// fonction publique CONSTRUCTOR Digit () _currentDigit = new Array (top1, bottom1); _nextDigit = new Array (top2, bottom2); réinitialiser();
Une dernière chose dont nous aurons besoin dans notre classe Digit est un moyen d’accéder au privé _nombre variable en dehors de la classe. Nous allons ajouter une fonction d'accesseur simple:
fonction publique get number (): String return _number;
Créez un nouveau fichier ActionScript nommé 'Clock.as'. Coller dans ce code:
package import flash.display.MovieClip; import flash.events.TimerEvent; import flash.media.Sound; import flash.utils.Timer; public class Clock s'étend sur MovieClip private var _clockTimer: Timer; private var _targetDate: Date; // CONSTRUCTOR fonction publique Clock ()
Pas beaucoup ici pour l'instant. Importer juste certaines des classes dont nous aurons besoin. J'ai aussi quelques variables privées. _clockTimer comptera les secondes pour nous, et _targetDate tiendra la date à laquelle nous comptons jusqu'à.
Ajoutez cette fonction à la classe Clock juste en dessous du constructeur:
// définit la date cible et démarre la fonction publique du compte à rebours (date: date): void _targetDate = date; _clockTimer = new Timer (1000) // coche toutes les secondes (1000 millisecondes) _clockTimer.addEventListener (TimerEvent.TIMER, update); _clockTimer.start (); // affiche la date cible au-dessus de l'horloge t_date.text = _targetDate.toLocaleString (). toUpperCase (); // met à jour l'horloge une fois ici pour qu'elle commence par l'heure correcte update ();
C’est la fonction que nous utiliserons pour définir la date cible de l’horloge. Il accepte une date (bien sûr) et l'assigne à la _targetDate variable. Il instancie ensuite notre _clockTimer. le _clockTimer appellera le mettre à jour fonctionne une fois par seconde pour mettre à jour les chiffres.
Après avoir démarré la minuterie, la fonction règle le t_date texte avec la date cible. La fonction toLocaleString () garantit que la date est affichée dans le fuseau horaire local de l'utilisateur..
La dernière ligne de cette fonction appelle mettre à jour une fois pour régler l'horloge au bon moment. Sinon, il afficherait "000 00:00:00" pendant une seconde jusqu'au premier événement du minuteur..
Cette fonction est un peu longue car c’est là que se fait le plus gros du travail. Ajoutez-le à votre classe d'horloge:
mise à jour de fonction privée (e: TimerEvent = null): void var now: Date = new Date (); // récupère l'heure actuelle // trouve la différence (en ms) entre la cible et maintenant var diff: Number = _targetDate.valueOf () - now.valueOf (); si (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));
Cette fonction accepte un paramètre TimerEvent. La valeur par défaut pour ce paramètre est nul. Cela nous permet d’appeler la fonction sans envoyer de paramètre, comme nous le faisons dans le ensemble une fonction.
La première ligne de cette fonction récupère la date et l'heure actuelles en tant qu'objet Date. Ensuite, nous trouvons la différence entre la date actuelle et la date cible (ligne 37). Si la différence est égale ou inférieure à 0, la date cible étant passée, nous arrêtons la _clockTimer (lignes 38 à 44).
Puisque la différence de temps entre maintenant et la cible est calculée en millisecondes, nous devons la convertir en un bel affichage lisible des jours, des heures, des minutes et des secondes (lignes 46 à 62). Le calcul est assez simple dans la mesure où vous savez qu’il ya 1000 millisecondes en une seconde, 60 secondes en une minute, 60 minutes en une heure et 24 heures en une journée..
À la ligne 65, nous stockons toutes ces valeurs en tant qu’éléments d’un tableau. À partir de la ligne 68, nous parcourons chaque élément et l’ajoutons à une chaîne de caractères appelée «diffString». Ce faisant, nous ajoutons également des zéros au début (ligne 71). Donc, si nos valeurs pour l’horloge étaient de 30 jours, 5 heures, 56 minutes et 6 secondes, diffString ressemblerait à ceci: "030055606".
La dernière chose que fait cette fonction est de parcourir en boucle les caractères du diffString (en utilisant la méthode charAt ()). Pour chaque caractère de la chaîne, nous vérifions s'il est différent du nombre actuellement affiché sur le chiffre correspondant. C'est facile à cause de la façon dont nous avons nommé nos instances de chiffres. Si le numéro n’est pas le même que celui actuellement affiché, nous indiquons à ce chiffre de passer au numéro de la liste. diffString.
Trouvez (ou créez) un bon son de tick qui sera joué à chaque mise à jour de l'horloge. Importez-le dans la bibliothèque de votre fichier Flash et définissez le nom de la classe sur 'TickSound' dans les paramètres de liaison..
Ajouter le _tickSound variable en haut de votre classe Clock juste en dessous des deux autres variables:
private var _clockTimer: Minuterie; private var _targetDate: Date; private var _tickSound: Sound = new TickSound ();
Et jouez le son à l'intérieur du mettre à jour une fonction:
_tickSound.play ();
Notre compte à rebours est terminé, nous avons juste besoin d’un moyen de définir la date cible. Créez un nouveau fichier Actionscript appelé 'Main.as' avec ce code:
package import flash.display.MovieClip; classe publique Main étend MovieClip fonction publique Main () // définit la date cible pour l'horloge var targetDate: Date = new Date (); targetDate.setTime (Date.UTC (2010, 4, 28, 20, 00)); clock.set (targetDate);
Tout ce que cela fait est de définir la date cible pour l'instance Clock sur la scène. J'utilise setTime () et Date.UTC () pour convertir la date en code temporel universel. Ainsi, la date sera correcte lorsqu’elle sera reconvertie en heure locale sur l’ordinateur de l’utilisateur. De plus, rappelez-vous que les mois sont basés sur zéro. Donc, le mois 4 est en fait mai, pas avril.
Dans votre fichier Flash, définissez la classe Document sur 'Main'.
Si vous avez besoin d'un rappel sur l'utilisation de la classe de document, consultez ce conseil rapide..
Testez votre film maintenant et tout devrait fonctionner. Essayez de changer la date cible dans la classe principale et voyez comment le compte à rebours change.
Un inconvénient potentiel de la manière dont nous avons mis cela en place est que la date cible est codée en dur dans notre fichier SWF. C'est bien, mais ce serait bien si nous pouvions charger dynamiquement la date afin de pouvoir réutiliser le compte à rebours pour différentes choses..
Voyons ce que nous pouvons faire à ce sujet…
Créez un nouveau fichier XML dans le même dossier que votre fichier Flash appelé "targetDate.xml" (un fichier XML est simplement un fichier de texte brut). Ajoutez ceci au fichier XML:
2011 3 25 20 21
L'utilisation de ce format pour notre date cible est assez lourde (il y a plus de balises que de données réelles), mais cela gardera les choses très claires pour les besoins de ce tutoriel..
Modifions maintenant notre classe de documents principale. Remplacez tout le contenu de ce fichier par ce code:
package import flash.display.MovieClip; import flash.net.URLLoader; import flash.net.URLRequest; import flash.events.Event; classe publique Main étend MovieClip // CONSTRUCTOR fonction publique Main () // charge le code XML var xmlLoader: URLLoader = new URLLoader (); xmlLoader.addEventListener (Event.COMPLETE, onDataLoaded); xmlLoader.load (new URLRequest ("targetDate.xml"));
Vous remarquerez que nous avons importé quelques classes supplémentaires pour nous aider à charger le fichier XML. Dans la fonction constructeur, nous créons une nouvelle instance d'URLLoader pour charger le fichier pour nous. Nous attachons un écouteur d'événement qui appellera une fonction nommée 'onDataLoaded' une fois le chargement du fichier terminé..
Ajoutez cette fonction à la classe principale:
fonction privée onDataLoaded (e: Event): void var xml: XML = nouveau 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);
Cette fonction crée un nouvel objet XML à partir du fichier que nous avons chargé. Nous créons ensuite un nouvel objet Date à partir des valeurs du code XML. Nous utilisons à nouveau setTime () et Date.UTC () pour convertir la date en code temporel universel. La dernière ligne est la même que précédemment, elle envoie simplement la date cible à notre instance Clock.
C'est à peu près tout pour celui-ci. Il y a quelques améliorations que vous aimeriez peut-être faire:
Bonne chance! Comme toujours, postez un commentaire et dites-moi ce que vous en pensez.