Ciao a tutti !
Vi è mai capitato di voler creare un menu in Flash che riesca a gestire le sezioni del vostro sito ?
Ho notato che i Flash designers e webmasters con nozioni Actionscript pressochè inesistenti,
hanno difficoltà nel gestire gli eventi dei menu associati a delle MovieClip che sono anidate sulla timeline principale.
Faccio un esempio, abbiamo un menu con 5 bottoni o MovieClip e vorremmo che al click di uno di questi,
oltre ad eseguire una determinata azione sulla timeline di una MovieClip, l' animazione rimanesse sullo stato attivo, in modo che rimanga chiaro all' utente in che sezione si trova in quel momento.
Dopo aver visto insieme come
creare un sito caricando degli SWF esterni,
con questo tutorial invece vedremo come gestire un menu e le sezioni del nostro sito Flash dalla Document Class.
Innanzitutto voglio già sottolineare il fatto che è meglio non eseguire mai animazioni sulla timeline principale.
Inoltre, una cosa molto importante è il fatto che con Flash CS3 non possiamo più scrivere codice sulle MovieClip ( per fortuna ) e quindi per gestire un menu multiplo come quello che stiamo per creare,
bisogna per forza utilizzare cicli e array, per cui consiglio a chi di voi avesse ancora dei dubbi su come si usano di andare a leggersi i seguenti tutorials:
- array di Actionscript
- cicli di Actionscript
Creo un FLA che salvo con nome ' main.fla '.
Al suo interno, creo 6 livelli dei quali il primo in alto lo chiamo menu e gli altri a scendere: section5, section4, section3, section2, section1.
Creo il menu:
- Creo una MovieClip che chiamo mc_menu ( nome in libreria ).
- Creo altre 5 nuove MovieClip che fungeranno da bottoni per il nostro menu e gli assegno i nomi ( in libreria ): mc_menu1, mc_menu2, mc_menu3, mc_menu4, md_menu5.
- All' interno di ognuna delle 5 MovieClip creo altri 2 keyframe ( in modo da averne 3 in totale ) e cambio il colore del bottone. In questo modo potremo gestire con Actionscript gli eventi del mouse sulla MovieClip spostando la sua stessa timeline.
- Inoltre, ognuna di queste 5 MoiveClip ha 2 livelli, uno nei quali ci sono le grafiche di gni keyframe e quindi di ogni stato e nell' altro livello inseriamo il testo della voce di menu.
- Inserisco le 5 MovieClip dentro a mc_menu.
- Trascino mc_menu sullo stage e gli assegno nome istanza menu_mc.
- Entro dentro a menu_mc e assegno i nomi istanza alle 5 MovieClip: menu1_mc. menu2_mc, menu3_mc, menu4_mc, menu5_mc.
Creo le sezioni:
- Creo 5 MovieClip con nome in libreria mc_section1, mc_section2, mc_section3, mc_section4, mc_section5
- Ognuna di queste MovieClip ha un' animazione al suo interno di 60 frames ( keyframe a 1,30 e 60 ). Nei primi 30 frames l' animazione esegue un fadeIn mentre da frame 30 a 60 esegue un fadeOut, in questo modo gestiremo gli ingressi e le relative uscite delle nostre sezioni.
- Al keyframe 30 e al keyframe 60 apro il pannello azioni ed inserisco un stop in questo modo: stop();
- Trascino dalla libreria allo stage le cinque MovieClip ognuna nel proprio livello ed assegno a loro i corrispettivi nomi istanza: section1_mc, section2_mc, section3_mc, section4_mc, section5_mc.
Adesso creo la Document Class, un file AS che salvo con nome ' Main.as ', implementata in questo modo:
Code:
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip
{
private var menu_array:Array;
private var section_array:Array;
private var currentSection:int=0;
private var nextSection:int;
public function Main()
{
init();
}
private function init():void
{
menu_array=new Array(menu_mc.menu1_mc,menu_mc.menu2_mc,menu_mc.menu3_mc,menu_mc.menu4_mc,menu_mc.menu5_mc);
section_array=new Array(section1_mc,section2_mc,section3_mc,section4_mc,section5_mc);
stage.frameRate=31;
stopAll();
addMenuEvents();
hideCurrentSection();
}
private function stopAll():void
{
for(var i:int=0;i < menu_array.length;i++)
{
menu_array[i].stop();
section_array[i].stop();
}
}
private function addMenuEvents():void
{
for(var i:int=0;i < menu_array.length;i++)
{
menu_array[i].mouseChildren=false;
menu_array[i].buttonMode=true;
menu_array[i].id=i;
menu_array[i].isPressed=false;
menu_array[i].addEventListener(MouseEvent.MOUSE_OVER,setOver);
menu_array[i].addEventListener(MouseEvent.MOUSE_OUT,setOut);
menu_array[i].addEventListener(MouseEvent.MOUSE_DOWN,setDown);
menu_array[i].addEventListener(MouseEvent.MOUSE_UP,setUp);
}
}
private function setOver(evt:MouseEvent):void
{
if(evt.target.isPressed==false)
evt.target.gotoAndStop(2);
}
private function setOut(evt:MouseEvent):void
{
if(evt.target.isPressed==false)
evt.target.gotoAndStop(1);
}
private function setDown(evt:MouseEvent):void
{
nextSection=evt.target.id;
checkState(evt.target.id);
evt.target.gotoAndStop(3);
hideCurrentSection();
currentSection=evt.target.id;
}
private function setUp(evt:MouseEvent):void
{
if(evt.target.isPressed==false)
evt.target.gotoAndStop(1);
}
private function checkState(n:int):void
{
for(var i:int=0;i < menu_array.length;i++)
{
if(i==n)
menu_array[i].isPressed=true;
else
{
menu_array[i].isPressed=false;
menu_array[i].gotoAndStop(1);
}
}
}
private function hideCurrentSection():void
{
section_array[currentSection].gotoAndPlay(31);
showSection();
}
private function showSection():void
{
section_array[nextSection].gotoAndPlay(2);
}
}
}
Analizziamo il codice
Importo le classi che mi occorrono
import flash.display.MovieClip;
import flash.events.MouseEvent;
Proprietà
i due Array nei quali inserisco le MovieClip del menu e le MovieClip delle sezioni
private var menu_array:Array;
private var section_array:Array;
una variabile numerica in cui inserisco il numero della sezione correntemente attiva
private var currentSection:int=0;
una variabile numerica in cui inserisco il numero della sezione che al click del menu corrispondente verrà azionata con un play
private var nextSection:int;
Funzione Costruttrice
chiamo il metodo init
init();
Metodi
init();
popolo gli array con i nomi delle MovieClip che ho sullo stage. Rispettivamente inserisco le MovieClip del menu dentro menu_array e le MovieClip delle sezioni in section_array
menu_array=new Array(menu_mc.menu1_mc,menu_mc.menu2_mc,menu_mc.me nu3_mc,menu_mc.menu4_mc,menu_mc.menu5_mc);
section_array=new Array(section1_mc,section2_mc,section3_mc,section4 _mc,section5_mc);
imposto una velocità di frame rate
stage.frameRate=31;
chiamo il metodo stopAll che fermerà tutte le MovieClip che ho sullo stage
stopAll();
chiamo il metodo addMenuEvents che gestirà i listeners e gli eventi di ogni MovieClip del menu
addMenuEvents();
chiamo il metodo hideCurrentSection che visualizerà la prima sezione
hideCurrentSection();
stopAll();
tramite un
ciclo dico stop sia alle MovieClip del menu che alle MovieClip delle sezioni
for(var i:int=0;i < menu_array.length;i++)
{
menu_array[i].stop();
section_array[i].stop();
}
addMenuEvents();
sempre tramite un
ciclo Actionscript comunico alle MovieClip una serie di azioni:
for(var i:int=0;i < menu_array.length;i++)
{
dico alle MC del menu di disattivare gli eventi del mouse associati a qualsiasi oggetto si trovi al suo interno. Questo perchè altrimenti se non lo facessi la manina del mouse non comparirebbe se sono nell' area del campo di testo che si trova all' interno appunto di ogni MC del menu ( vedere questo articolo:
trucco del giorno - mouseChildren )
menu_array[i].mouseChildren=false;
utilizzo mouseButton = true per ogni MC, in modo che si veda la manina del mouse al passaggio sulle stesse MC
menu_array[i].buttonMode=true;
creo una proprietà ad ogni MC che chiamo id e gli assegno il valore della i in quel momento durante l' iterazione del ciclo, in questo modo quando l' utente agirà sulle MC saprò quale sezione chiamare utilizzando appunto l' id delle MovieClip come indice dell' array section_array
menu_array[i].id=i;
creo un' altra proprietà per ogni MC che chiamo isPressed e gli assegnerò il valore false. Diventerà true quando l' utente cliccherà tale MC e mi permetterà di muovere la sua timeline in base alla verifica di isPressed se sarà true o false
menu_array[i].isPressed=false;
aggiungo i listeners necessari in ascolto dei 4 eventi principali del mouse: MOUSE_OVER, MOUSE_OUT, MOUSE_DOWN, MOUSE_UP che chiameranno le corrispettive funzioni: setOver, setOut, setDown e setUp
menu_array[i].addEventListener(MouseEvent.MOUSE_OVER,setOver);
menu_array[i].addEventListener(MouseEvent.MOUSE_OUT,setOut);
menu_array[i].addEventListener(MouseEvent.MOUSE_DOWN,setDown);
menu_array[i].addEventListener(MouseEvent.MOUSE_UP,setUp);
}
setOver();
controllo la MC che è stata cliccata ( che la recupero con evt.target ), se la sua proprietà isPressed è false. Ecco il perchè utilizzo isPressed, se la MC è stata cliccata non deve spostare la sua timeline in quanto non deve cambiare colore, deve rimanere del colore ' attivo '
if(evt.target.isPressed==false)
se è false muovo la sua timeline al frame 2
evt.target.gotoAndStop(2);
setOut();
stessa cosa del setOver, controllo isPressed della MC cliccata e se è false
if(evt.target.isPressed==false)
muovo la sua timeline al frame 1
evt.target.gotoAndStop(1);
setDown();
imposto il valore della variabile nextSection uguale al valore id della MC che è stata cliccata
nextSection=evt.target.id;
chiamo la funzione checkState passandogli il valore id della stessa MC cliccata che gestirà le timeline delle altre MC del menu in quanto se questa MC è stata cliccata, tutte le altre devono muovere la loro timeline allo stato ' normale '
checkState(evt.target.id);
muovo la sua timeline al frame 3 ( lo stato attivo )
evt.target.gotoAndStop(3);
chiamo la funzione hideCurrentSection che farà scomparire la sezione in corso ed apparire la nuova sezione
hideCurrentSection();
imposto il valore della variabile currentSection uguale al valore id di questa MC cliccata
currentSection=evt.target.id;
setUp();
anche quì controllo isPressed della MC cliccata e se è false
if(evt.target.isPressed==false)
sposto la sua timeline al frame 1
evt.target.gotoAndStop(1);
checkState(n:int):void
tramite un ciclo che controlla le MC del menu, se la i dell' iterazione del momento è uguale alla id della MC che ho pasato dalla funzione setDown, allora imposto isPressed = true dell' elemento i dell' array menu_array ( che appunto è una delle MC del menu, esattamente quella che è stata cliccata )
for(var i:int=0;i < menu_array.length;i++)
{
if(i==n)
menu_array[i].isPressed=true;
altrimenti se la i non è uguale a n, allora imposto isPressed = false della MC che sta nell' array menu_array all' indice i e riporto allo stato normale la timeline
else
{
menu_array[i].isPressed=false;
menu_array[i].gotoAndStop(1);
}
}
hideCrentSection();
faccio partire l' animazione della MC della sezione che deve scomparire
section_array[currentSection].gotoAndPlay(31);
chiamo il metodo showSection
showSection();
showSection();
faccio partire l' animazione della MC della sezione che deve apparire
section_array[nextSection].gotoAndPlay(2);
Allego i files sorgente: