Parfois, vous voulez juste être très moderne sur votre site web. Et comment mieux montrer aux gens à quel point vous êtes cool en tant que programmeur flash que de leur faire en faire l'expérience eux-mêmes? Dans ce tutoriel, je vais vous montrer comment créer un menu moderne avec des boutons à ressort. Nous allons même le rendre personnalisable à partir du xml!
Jetons un coup d'œil à ce sur quoi nous travaillons:
Créez un nouveau fichier flash ActionScript 3 et définissez les dimensions sur 600 x 200 pixels. Nous définissons ces dimensions afin de permettre aux boutons de suivre la souris. Définissez le nombre d'images par seconde sur 25 et le paramètre DocumentClass sur ElasticMenu, une classe que nous allons créer après la conception.
Faisons un dégradé de fond qui servira de base à notre bouton. Créez un rectangle et faites-le 150 x 40px. La taille importe peu pour l'instant, car nous redimensionnerons le rectangle pour qu'il corresponde à la taille du texte du bouton..
Je peux vous entendre demander: pourquoi ne pas créer un rectangle par programmation avec Sprite.graphics.drawRectangle ()? Je vais vous montrer pourquoi j'ai choisi ce chemin. La raison de faire un MovieClip sur la scène est que nous pouvons réellement couper à travers le rectangle pour créer un bouton de découpe cool comme dans cet aperçu:
Je ne vais pas vous expliquer comment faire cet exemple ici, mais cette méthode est préférable au cas où vous voudriez pimenter l'arrière-plan du bouton. C'est juste un pourboire.
Sélectionnez le rectangle que vous venez de créer et appuyez sur F8 (Modification> Convertir en symbole) pour créer le graphique d'arrière-plan et cochez la case Exporter pour ActionScript. Donnez à ce MovieClip le nom de classe "GradBackground". Nous allons utiliser ce nom de classe à partir d'ActionScript.
Nous allons maintenant créer le fichier XML pour contenir notre configuration. À partir de ce fichier, l'animation flash recevra le nom du bouton, l'emplacement du lien et la couleur. Créez un nouveau fichier à côté de la source .fla et nommez-le menu.xml avec ce qui suit:
Que se passe t-il ici? Nous créons un
Passons maintenant à la construction du menu flash actuel. Créez un nouveau fichier ActionScript et nommez-le. ElasticMenu.as. Pour plus de rapidité, j'ai utilisé le caractère générique * pour importer toutes les classes du paquet. Une fois le menu flash terminé, vous pouvez modifier les importations pour n’inclure que ce dont vous avez besoin, afin de réduire la taille du fichier. Créez le paquet habituel et le nom de la classe ElasticMenu avec les variables requises:
package import flash.display. *; importer flash.text. *; importer flash.net. *; importer flash.events. *; import flash.utils.Timer; La classe publique ElasticMenu étend MovieClip var xml: XML; boutons var: Array; var tm: minuterie; var maxdist: Number = 50;
le xml variable tiendra le xml réel chargé à partir du menu.xml fichier. le boutons variable est un tableau qui contiendra les références des boutons.
le tm est une minuterie qui prend en charge la vérification réelle de la distance.
le maxdist variable définira à quelle distance le bouton se séparera de la souris et reviendra à sa place.
Ok, créons la fonction constructeur, ajoutons les opérations de chargement et traitons le XML:
fonction publique ElasticMenu () var req = new URLLoader (); req.addEventListener (Event.COMPLETE, xml_loaded); req.load (new URLRequest ('menu.xml')); boutons = nouveau tableau (); tm = nouveau temporisateur (40); tm.addEventListener (TimerEvent.TIMER, check_buttons); fonction privée xml_loaded (e: événement) xml = XML (e.target.data); createButtons ();
Qu'est-ce qu'il se passe ici? Nous créons un objet URLRequest et ajoutons un gestionnaire d'événements complet qui déclenchera la fonction xml_loaded lorsque le xml est chargé..
Nous initialisons le boutons tableau et la minuterie, et nous lions l'événement TIMER à la check_buttons () une fonction. C'est la fonction qui vérifiera la distance des boutons. Une fois le fichier XML chargé, nous le transmettons à xml variable et construire les boutons avec le createButtons () fonction que nous créerons ensuite.
Continuez en créant les boutons et positionnez-les sur la scène par programmation:
fonction publique createButtons () var sectw = (stage.stageWidth / (xml… button.length () + 1)); pour (var i = 0; i< xml… button.length(); i++) var m = new ElasticButton(); m.x = sectw + (sectw*i); m.y = stage.stageHeight/2; m.init( xml… button[i] ); addChild( m ); buttons.push( m ); tm.start();
Ok, nous définissons le sectw variable, qui est la phase divisée en le nombre de boutons plus un. Pourquoi? Parce que nous allons organiser les boutons pour qu'ils soient exactement à la même distance et occupent toute la largeur de la scène. Pour mieux comprendre cela, regardez l'image suivante:
Parce que nous centrons les boutons sur les axes x et y, ils seront à égale distance les uns des autres. Ensuite, nous créons une boucle for, à l'intérieur de laquelle nous définissons chaque bouton comme un nouveau. ElasticButton classe, que nous allons coder sous peu. Nous plaçons chaque bouton à sectw éloigner les uns des autres et régler leur y sur la moitié de la scène pour les centrer. Ensuite, nous les ajoutons à la scène et les poussons dans le tableau de boutons, pour une utilisation ultérieure. Mais il y a une autre fonction que nous appelons sur le bouton que nous définirons dans la classe ElasticButton, à laquelle nous passons le nœud du bouton xml actuel..
Continuons avec la fonction principale déclenchée toutes les 40 millisecondes par le minuteur:
fonction privée check_buttons (e: TimerEvent) for (boutons var b in) if (boutons [b] .dragging) boutons [b] .x = mouseX; boutons [b] .y = mouseY; if (boutons [b] .getDistance ()> maxdist) boutons [b] .reset ();
Ok, expliquons rapidement ce qui se passe ici pour pouvoir passer à la classe ElasticButton:
Tout d'abord, nous parcourons tous les boutons du tableau et nous vérifions pour chacun s'ils ont une propriété de type dragging avec la valeur "true". Fondamentalement, si la souris est au-dessus du bouton et si "oui", nous vérifions si le getDistance () méthode du ElasticButton la classe est supérieure à la maxdist variable. Si c'est plus haut, on appelle un réinitialiser() fonction sur le bouton. Nous ne savons encore rien de ces fonctions.
OK, enfin la classe que nous attendions tous, la classe des boutons. C’est là que toutes les choses importantes se passent: déterminer la distance, créer le texte, l’arrière-plan et appeler réinitialiser() pour ramener le bouton à son emplacement.
package import flash.display. *; importer flash.text. *; importer flash.net. *; importer flash.events. *; import flash.geom.ColorTransform; import fl.transitions.Tween; import fl.transitions.TweenEvent; import fl.transitions.easing. *; importer fl.motion.Color; Classe publique ElasticButton étend MovieClip var origin: Object; var textfield: TextField; var tf: TextFormat; var dragging: Boolean = false; var bg: Sprite; var url: String; var twx: Tween; var twy: Tween; padding var: Nombre = 8; var couleur: uint; var msk: Sprite; fonction publique ElasticButton () // ne rien faire
Laissez-moi expliquer les lignes:
Vous constaterez qu'en dehors de l'importation des classes normales, nous importons également les classes fl.transitions.Tween et TweenEvent, easing et fl.motion.Color. Nous avons besoin des classes d'interpolation pour associer le film à son origine et de la classe de couleur pour teinter l'arrière-plan à la couleur du fichier xml..
Nous avons quelques variables ici:
le origine objet est un objet qui tiendra les positions x et y du bouton. J'aurais pu en faire un objet flash.geom.Point mais je suis trop paresseux pour inclure une autre classe pour 2 variables!
Nous avons un champ de texte variable qui tiendra le champ de texte de l’étiquette du bouton, le tf variable qui est un objet TextFormat pour le style de texte, le connu traînant propriété, un bg var qui sera le MovieClip de fond, une chaîne avec l'URL du bouton, deux variables pour contenir les tweens, un rembourrage variable qui rendra le bouton un peu plus gros, le Couleur objet et un msk var qui sera un masque pour le MovieClip. Nous en avons besoin pour faire le coin arrondi que vous avez vu dans l'aperçu!
Faisons la fonction init, déclenchée par notre classe parent:
fonction publique init (node) textfield = new TextField (); tf = new TextFormat (); tf.size = 14; tf.font = '_sans'; tf.bold = true; tf.color = 0xffffff; tf.align = TextFormatAlign.CENTER; textfield.defaultTextFormat = tf; textfield.text = noeud… nom; textfield.width = 65; textfield.height = 20; textfield.x = - (textfield.width / 2); textfield.y = - (textfield.height / 2); textfield.mouseEnabled = false; addChild (textfield); origine = nouvel objet (); origin.x = this.x; origine.y = this.y; couleur = noeud… couleur; createBG (); url = noeud… url; glisser = faux; this.buttonMode = true; this.addEventListener (MouseEvent.MOUSE_OVER, mouse_over); this.addEventListener (MouseEvent.CLICK, mouse_click);
Il y a déjà beaucoup!
Nous créons le champ de texte, lui affectons un format de texte avec certaines propriétés (je n’entrerai pas dans les détails ici), définissons la couleur en blanc, car les arrière-plans auront tendance à être plus sombres, nous lui donnons le texte du nœud passé en paramètre. . Assez standard.
Il est préférable de créer une largeur et d'aligner le texte au centre afin que différents mots soient parfaitement alignés. Assurez-vous de ne pas inclure un mot très long, sinon le bouton aura l'air laid!
Nous avons ensuite un positionnement intéressant du champ de texte. Nous définissons le x sur moins la moitié de la largeur et le y sur la moitié de la hauteur du champ de texte, alignant ainsi le champ de texte exactement au centre. Nous en avons besoin pour obtenir un calcul uniforme de la distance maximale.
Nous fixons mouseEnabled false pour le champ de texte, pour désactiver la souris en désactivant le bouton. J'ai cherché cette propriété pour un toute la journée quand j'ai commencé AS3 :)
le origine Ensuite, l'objet est initialisé et nous créons les propriétés x et y avec les x et y du MovieClip actuel (la classe ElasticButton). Lorsque le bouton dépasse la maxdist, nous allons renvoyer le bouton à ces points d'origine.
Il se passe encore quelques choses ici: nous tenons la couleur du noeud xml dans le répertoire Couleur var, nous tenons l’url du bouton dans le url var amd nous appelons un createBG () fonction que nous sommes encore à coder.
Nous définissons glisser sur false, buttonMode pour le ElasticButton actuel sur true et créons les gestionnaires de souris au-dessus de la souris..
Cette fonction s'occupera de faire le fond et de le teinter en fonction de la couleur dans le xml:
fonction publique createBG () bg = new GradBackground (); var dbpad = padding * 2; bg.width = textfield.width + dbpad; bg.height = textfield.height + dbpad; bg.x = - ((textfield.width + dbpad) / 2); bg.y = - ((textfield.height + dbpad) / 2); addChild (bg); var col = nouvelle couleur (1,1,1,1); col.setTint (couleur, 0,4); bg.transform.colorTransform = col; setChildIndex (bg, 0);
Ici, nous faisons une classe GradBackground, qui est le MovieClip que nous avons créé dans le source FLA et lui donnons le nom de classe GradBackground. Nous définissons la largeur et la hauteur du MovieClip sur la largeur du champ de texte plus une variable dbpad. Vous remarquerez que j'ai défini cette variable pour la vitesse, de sorte que je ne tape pas (padding * 2). Définir une nouvelle variable avec le double remplissage précalculé est plus rapide que d'appeler cette opération plusieurs fois. Nous devons aussi nous occuper de la CPU!
Pourquoi est-ce que j'ajoute une variable de remplissage? Alors que le bouton est plus gros que le champ de texte. Regardez cette image pour mieux comprendre:
Je centre aussi le movieclip bg comme je l'ai fait avec le champ de texte: je règle le x moins la moitié de la hauteur et moins la moitié de la largeur du movglip bg.
Ensuite, je crée une nouvelle couleur avec les attributs par défaut (rgb et alpha 1), puis j'utilise le setTint() pour en faire une nuance de la couleur xml. Comme la classe Color est une sous-classe de la classe ColorTransform, nous pouvons passer cette couleur directement à l'objet movieclip transform.colorTransform..
Enfin, nous définissons la profondeur 0 sur le bg movieclip, afin que tout soit au-dessus de l'arrière-plan.
Je vais rapidement passer en revue les gestionnaires d'événements:
fonction privée mouse_over (e: MouseEvent) glissant = vrai; fonction privée mouse_click (e: MouseEvent) browseToURL (new URLRequest (url));
Les gestionnaires d'événements sont assez simples: je règle le glissement sur true lorsque la souris survole le bouton. J'utilise le gestionnaire de clic browseToURL () fonction pour aller à l'URL demandée. Si vous construisez un site flash, c'est ici que l'action pour le changement de page irait.
C'est la fonction la plus importante du menu. Rappelez-vous, nous appelons le getDistance fonction pour voir si elle est plus grande que la maxdist var afin que nous puissions réinitialiser le bouton. Nous utilisons l'équation algébrique de Pitagora pour trouver la distance entre 2 points:
fonction publique getDistance () return Math.sqrt ((this.x-origin.x) * (this.x-origin.x) + (this.y-origin.y) * (this.y-origin.y) )
Cela nous donnera la distance entre les boutons x et y et l'origine x et y. C'est pourquoi nous tenons la variable d'origine.
Cette fonction est déclenchée lorsque la distance par rapport à l'origine est trop élevée. À ce stade, nous interpolons le bouton à son origine:
fonction publique reset () dragging = false; twx = new Tween (this, 'x', Elastic.easeOut, this.x, origin.x, 0.4, true); twy = new Tween (this, 'y', Elastic.easeOut, this.y, origin.y, 0.4, true);
Nous définissons le dragging sur false et créons deux tweens; un pour le x et un pour le y. Nous aurions pu utiliser une autre bibliothèque d'interpolation, utiliser une seule interpolation et transmettre un tableau à la fonction d'interpolation, mais la classe Tween intégrée de AS3 ne prend pas en charge plusieurs propriétés, à ma connaissance..
Laissez-moi vous montrer, en prime, comment créer le premier et le dernier bouton, comme vous l'avez vu dans l'aperçu. Nous créons une nouvelle fonction makeStartButton () où nous allons construire le masque arrondi:
fonction publique makeStartButton () msk = new Sprite (); msk.graphics.beginFill (0x000000,1); msk.graphics.moveTo (0, remplissage); msk.graphics.curveTo (0, 0, remplissage, 0); msk.graphics.lineTo ((padding * 2) + textfield.width, 0); msk.graphics.lineTo ((padding * 2) + textfield.width, (padding * 2) + textfield.height); msk.graphics.lineTo (0, (padding * 2) + textfield.height); msk.graphics.lineTo (0, remplissage); msk.graphics.endFill (); msk.x = bg.x; msk.y = bg.y; addChild (msk); bg.mask = msk;
Ok, cela doit être expliqué:
Nous créons un nouveau Sprite et utilisons la classe du graphique beginFill () pour faire un remplissage, la couleur n'a pas d'importance. Pour comprendre ce qui se passe, regardons cette image:
Nous construisons le masque d’arrière-plan arrondi et l’ajoutons à la liste displayList en le configurant comme masque pour bg MovieClip
Nous utilisons la même procédure, maintenant avec la courbe à droite:
fonction publique makeEndButton () var dbpad = padding * 2; msk = nouveau Sprite (); msk.graphics.beginFill (0x000000,1); msk.graphics.lineTo (textfield.width + padding, 0); msk.graphics.curveTo (textfield.width + dbpad, 0, textfield.width + dbpad, remplissage); msk.graphics.lineTo (dbpad + textfield.width, dbpad + textfield.height); msk.graphics.lineTo (0, dbpad + textfield.height); msk.graphics.lineTo (0, remplissage); msk.graphics.endFill (); msk.x = bg.x; msk.y = bg.y; addChild (msk); bg.mask = msk;
Vous verrez que c’est la même technique, il suffit de faire la courbe à droite et d’ajouter le masque à la bg MovieClip.
Nous devons modifier la classe ElasticMenu pour appeler ces deux fonctions sur les premier et dernier boutons. Dans les createButtons (), nous apportons les modifications suivantes (lignes 8 à 13):
fonction publique createButtons () var sectw = (stage.stageWidth / (xml… button.length () + 1)); pour (var i = 0; i< xml… button.length(); i++) var m = new ElasticButton(); m.x = sectw + (sectw*i); m.y = stage.stageHeight/2; m.init( xml… button[i] ); if( i == 0 ) m.makeStartButton(); if( i == xml… button.length()-1) m.makeEndButton(); addChild( m ); buttons.push( m ); tm.start();
Donc, si la variable je est 0 (si c'est le premier bouton) ou si je est le xml… button.length () - 1 (si c'est le dernier) on appelle la fonction respective.
N'oubliez pas, si vous rencontrez une erreur, que les fonctions que nous appelons depuis la classe parente, ElasticMenu être public dans le ElasticButton classe, sinon vous obtiendrez une erreur indiquant que la fonction n'existe pas!
C'est tout! Voici le code complet de la classe ElasticMenu:
package import flash.display. *; importer flash.text. *; importer flash.net. *; importer flash.events. *; import flash.utils.Timer; La classe publique ElasticMenu étend MovieClip var xml: XML; boutons var: Array; var tm: minuterie; var maxdist: Number = 50; ligne var: Sprite; fonction publique ElasticMenu () var req = new URLLoader (); req.addEventListener (Event.COMPLETE, xml_loaded); req.load (new URLRequest ('menu.xml')); boutons = nouveau tableau (); tm = nouveau temporisateur (40); tm.addEventListener (TimerEvent.TIMER, check_buttons); fonction privée xml_loaded (e: événement) xml = XML (e.target.data); createButtons (); fonction publique createButtons () var sectw = (stage.stageWidth / (xml… button.length () + 1)); pour (var i = 0; i< xml… button.length(); i++) var m = new ElasticButton(); m.x = sectw + (sectw*i); m.y = stage.stageHeight/2; m.init( xml… button[i] ); if( i == 0 ) m.makeStartButton(); if( i == xml… button.length()-1) m.makeEndButton(); addChild( m ); buttons.push( m ); tm.start(); private function check_buttons( e:TimerEvent ) for( var b in buttons ) if( buttons[b].dragging ) buttons[b].x = mouseX; buttons[b].y = mouseY; if( buttons[b].getDistance() > maxdist) buttons [b] .reset ();
Et pour la classe ElasticButton:
package import flash.display. *; importer flash.text. *; importer flash.net. *; importer flash.events. *; import flash.geom.ColorTransform; import fl.transitions.Tween; import fl.transitions.TweenEvent; import fl.transitions.easing. *; importer fl.motion.Color; Classe publique ElasticButton étend MovieClip var origin: Object; var textfield: TextField; var tf: TextFormat; var dragging: Boolean = false; var bg: Sprite; var url: String; var twx: Tween; var twy: Tween; padding var: Nombre = 8; var couleur: uint; var msk: Sprite; fonction publique ElasticButton () // ne rien faire fonction publique init (noeud) textfield = new TextField (); tf = new TextFormat (); tf.size = 14; tf.font = '_sans'; tf.bold = true; tf.color = 0xffffff; tf.align = TextFormatAlign.CENTER; textfield.defaultTextFormat = tf; textfield.text = noeud… nom; textfield.width = 65; textfield.height = 20; textfield.x = - (textfield.width / 2); textfield.y = - (textfield.height / 2); textfield.mouseEnabled = false; addChild (textfield); origine = nouvel objet (); origin.x = this.x; origine.y = this.y; couleur = noeud… couleur; createBG (); url = noeud… url; glisser = faux; this.buttonMode = true; this.addEventListener (MouseEvent.MOUSE_OVER, mouse_over); this.addEventListener (MouseEvent.CLICK, mouse_click); fonction publique createBG () bg = new GradBackground (); var dbpad = padding * 2; bg.width = textfield.width + dbpad; bg.height = textfield.height + dbpad; bg.x = - ((textfield.width + dbpad) / 2); bg.y = - ((textfield.height + dbpad) / 2); addChild (bg); var col = nouvelle couleur (1,1,1,1); col.setTint (couleur, 0,4); bg.transform.colorTransform = col; setChildIndex (bg, 0); fonction publique getDistance () return Math.sqrt ((this.x-origin.x) * (this.x-origin.x) + (this.y-origin.y) * (this.y-origin.y )); fonction publique reset () dragging = false; twx = new Tween (this, 'x', Elastic.easeOut, this.x, origin.x, 0.4, true); twy = new Tween (this, 'y', Elastic.easeOut, this.y, origin.y, 0.4, true); fonction privée mouse_over (e: MouseEvent) glissant = vrai; fonction privée mouse_click (e: MouseEvent) browseToURL (new URLRequest (this.url)); fonction publique makeStartButton () msk = new Sprite (); msk.graphics.beginFill (0x000000,1); msk.graphics.moveTo (0, remplissage); msk.graphics.curveTo (0, 0, remplissage, 0); msk.graphics.lineTo ((padding * 2) + textfield.width, 0); msk.graphics.lineTo ((padding * 2) + textfield.width, (padding * 2) + textfield.height); msk.graphics.lineTo (0, (padding * 2) + textfield.height); msk.graphics.lineTo (0, remplissage); msk.graphics.endFill (); msk.x = bg.x; msk.y = bg.y; addChild (msk); bg.mask = msk; fonction publique makeEndButton () var dbpad = padding * 2; msk = nouveau Sprite (); msk.graphics.beginFill (0x000000,1); msk.graphics.lineTo (textfield.width + padding, 0); msk.graphics.curveTo (textfield.width + dbpad, 0, textfield.width + dbpad, remplissage); msk.graphics.lineTo (dbpad + textfield.width, dbpad + textfield.height); msk.graphics.lineTo (0, dbpad + textfield.height); msk.graphics.lineTo (0, remplissage); msk.graphics.endFill (); msk.x = bg.x; msk.y = bg.y; addChild (msk); bg.mask = msk;
Maintenant, c'était un très long tutoriel! J'espère que je n'ai ennuyé personne. Si vous avez des idées sur la façon dont nous pourrions améliorer le menu, ajoutez-les aux commentaires..
!