Menù 3D in Flash con AS Actionscript 2
Con questo tutorial vedremo come ottenere un menu 3d in Flash utilizzando le funzione matematiche seno e coseno.
No, non dovremo tornare a studiare trigonometria al liceo..l’utilizzo di questi 2 metodi della classe Math di AS ActionScript 2 è molto semplice e versatile: questo impiego per ricreare un menù apparentemente tridimensionale è solo uno dei molteplici effetti che possiamo ottenere.
L’effetto realizzato qui sopra è spiegato nelle relativamente poche righe di codice a seguire.
Tralascio o spiego in breve l’analisi di altre funzioni volendomi concentrare sull’ellisse creato dalle 2 funzioni matematiche SIN e COS.
import flash.filters.BlurFilter;
var links = new Array();
links[1] = ["http://www.w3facile.com/index.php/css-gallery", "CSS Gallery", "1"];
links[2] = ["http://www.w3facile.com/index.php/easy-bookmarker", "Easy Bookmarker", "2"];
links[3] = ["http://www.w3facile.com/index.php/enciclopedia-actionscript-20", "Enciclopedia Actionscript", "3"];
links[4] = ["http://www.w3facile.com/index.php", "HomePage", "4"];
var posX = Stage.width/2;
var posY = Stage.height/2+40;
var angle = links.length-1;
_global.rotating = true;
var mousePos = ((_root._xmouse-posX)/100);
sphere.swapDepths(999);
In un prossimo articolo vorrei analizzare la classe che gestisce i filtri e provare qualche effetto ma per ora limitiamoci ad importare la classe per il blur dei movieclip quando vanno più in profondità, quindi creiamo un array di elementi, che saranno in questo caso le voci del nostro menù indicando URL, nome e un indice numerico o alfabetico che per ora non ci servirà.
Ho estrapolato questo esempio di codice da un ampio progetto e non mi sono preoccupato di togliere ogni riferimento esterno :)
Inserite le voci dichiariamo le variabili posX e posY, responsabili della centratura del menù al centro dello Stage.
In questo caso specifico faccio riferimento allo Stage perchè qui ho posizionato l’oggetto, nel caso vogliate creare un movieclip per importarlo dove volete ricordatevi di cambiare Stage con il nome del movieclip o con this.
Se dividendo ampiezza e altezza dello stage non doveste ottenere la giusta centratura perchè il menù ha una forma articolata, aggiustate facendo tentativi.
La variabile angle che dichiariamo corrisponde agli indici dell’array, vedremo poi come sarà implementata.
La variabile globale rotating ci serve per capire se la rotazione sta avvenendo o no, mousePos corrisponde alla posizione del mouse in relazione alle voci del menù, ci serve per regolare la velocità di rotazione intorno all’asse.
sphere.swapDepths(999) ci assicura che il livello di profondità del movieclip asse centrale sia quello giusto.
Richiamiamo le voci con questo ciclo:
for (var i = 1; i<angle+1; i++) {
attachMovie("menu", "menu"+i, i);
this["blur"+i] = new BlurFilter(5, 5, 2);
this["menu"+i].txtCover = i;
}
e instanziamo effetti blur per ogni movieclip che andremo poi a regolare in base alla profondità.
Passiamo alla funzione che gestisce il tutto, onEnterFrame:
this.onEnterFrame = function() {
if (rotating) {
mousePos -= ((_root._xmouse-posX)/100);
Se il boolean rotating è true, ovvero sta avvenendo la rotazione, ad ogni frame viene eseguito tutto lo script a seguire, mousePos viene aggiornato secondo la posizione del mouse sull’asse X.
E arriviamo al cuore e alla parte più difficile dello script:
for (var i = 1; i<angle+1; i++) {
depth = ((mousePos+(360/angle*i))*Math.PI)/(180);
this["menu"+i]._x = posX-(Math.sin(depth)*210);
this["menu"+i]._y = posY+(Math.cos(depth)*70);
In questo ciclo, per ogni voce del menù e quindi movieclip, assegniamo la profondità attuale e passandola come parametro (ovvero il grado vero e proprio dell’angolo che in quell’istante sta descrivendo l’orbita del movieclip) alle funzioni sin e cos otteniamo la posizione frame by frame del movieclipsullo stage. La funzione seno l’abbiamo impiegata per calcolare la posizione lungo l’asse X, la coseno per l’Y: provate a commentare la riga con la funzione coseno e vedrete che i movieclip cambiano solo la coordinata X rimanendo sempre sulla stessa Y, descrivendo comunque un cerchio regolare, un bell’effetto che però rende meno l’illusione dello spostamento lungo l’asse Z, quello della tridimensione.
Volendo dire un po’ di più ma consigliandovi comunque un approfondimento su libri specializzati, diciamo che il risultato della funzione seno in base al grado che passiamo restituisce un valore tra il numero massimo 1 e il numero minimo -1, che moltiplicato alla distanza che vogliamo e poi sottratto (o sommato se vogliamo rotazione antioraria) al centro del menù, ci restituisce la posizione lungo l’asse X.
Vi allego il grafico della funzione seno, chiamato in trigonometria sinusoide, per chi volesse capire meglio l’andamento del movieclip lungo l’asse X.

La funzione coseno anch’essa oscilla tra i 1 e -1 ma in modo diverso in base al grado che passiamo e ci è utile per calcolare lo spostamento lungo l’asse Y senza ricalcolare la profondità ovvero il grado: controllare l’andamento nel grafico della cosinusoide qui sotto.

Anche il risultato del coseno viene moltiplicato per la distanza dal centro che scegliamo e poi sommato se vogliamo inclinazione dell’orbita verso il basso o sottratto per l’inclinazione verso l’alto.
this["menu"+i]._xscale = 100+(Math.cos(depth)*50);
this["menu"+i]._yscale = 100+(Math.cos(depth)*50);
this["menu"+i].swapDepths(1000+(Math.cos(depth)*100));
this["menu"+i].smoothing = true;
Per rendere ancora meglio l’effetto della tridimensione scaliamo i movieclip in base al grado e alla profondità, servendoci della funzione coseno per sottrarre o aggiungere valore al metodo x o yscale degli oggetti Flash, ovviamente lo scale dovrà essere lo stesso nello stesso istante e poi calcoliamo il diverso livello di profondità per sovrapporlo o non all’oggetto centrale del menù, in un modo simile a quello con cui calcoliamo lo scale.
Lo smoothing ci serve per nascondere i difetti dell’ingrandimento dei movieclip.
distance = this["menu"+i].getDepth()-900;
distance = Math.round(distance/40);
if (distance == 5) {
this["blur"+i].blurX = 0;
this["blur"+i].blurY = 0;
this["menu"+i].filters = [this["blur"+i]];
}
if (distance == 4) {
this["blur"+i].blurX = 1;
this["blur"+i].blurY = 1;
this["menu"+i].filters = [this["blur"+i]];
}
if (distance == 3) {
this["blur"+i].blurX = 2;
this["blur"+i].blurY = 2;
this["menu"+i].filters = [this["blur"+i]];
}
if (distance == 2) {
this["blur"+i].blurX = 3;
this["blur"+i].blurY = 3;
this["menu"+i].filters = [this["blur"+i]];
}
if (distance == 1) {
this["blur"+i].blurX = 4;
this["blur"+i].blurY = 4;
this["menu"+i].filters = [this["blur"+i]];
}
if (distance == 0) {
this["blur"+i].blurX = 5;
this["blur"+i].blurY = 5;
this["menu"+i].filters = [this["blur"+i]];
}
Quindi calcoliamo la distanza dal livello del centro del menù di ogni singolo movieclip secondo il livello di profondità su cui si trova, in base a questo valorizziamo l’effetto di Blur instanziato in precedenza e assegniamolo all’oggetto.
Questo è il momento giusto per inserire anche effetti diversi, sempre se vogliamo.
this["menu"+i].txtName = links[i][1].toUpperCase();
this["menu"+i].url = links[i][0];
this["menu"+i].onRelease = function() {
getURL(this.url, "_blank");
};
/*this["menu"+i].onRollOver = function():Void {
this["menu"+i].gotoAndPlay(2);
rotating = false;
};
this["menu"+i].onRollOut = function() {
rotating = true;
};*/
}
}
};
stop();
Assegniamo poi il nome del link per ogni singola voce del menù, la sua url e il click per aprire in una nuova finestra l’indirizzo selezionato.
Il codice commentato è un esempio di metodi di rollover e rollout associati ad animazioni all’interno del movieclip menù, dove la rotazione si interromperebbe per permettere una migliore visione della stessa.
Se necessario scaricate il codice sorgente clicca qui
Cerca: as actionscript 2, cos flash, flash 3d, flash actionscript, menu 3d, menu actionscript, menu flash, sin flashRitieni questo post utile o interessante?
Condividi e Segnala
Leggi anche:
- Non ci sono articoli correlati





August 28th, 2007, 4:08 pm
Troppo diffizile per me, ma il tuo plugin per Wordpress è fantastico ;)
Ah… ti ho linkato, ciao!
September 2nd, 2007, 1:19 pm
Ti ho linkato anch’io :)
Il plug-in l’ho ottimizzato e ci ho aggiunto altre cosette utili, poi quando ci risentiamo te lo passo
Ciao!
January 13th, 2008, 8:07 pm
ciao
complimenti…era proprio quello di cui avevo bisogno.
Ho modificato il tuo script per fare una gallery dinamica da xml,
e ho fatto un paio di modifiche, con il movimento del mouse allargo in entrambe le coordinate la larghezza della circonferenza creata!
Terrò più d’occhio il tuo sito!
Grazie
January 13th, 2008, 8:46 pm
Piacere di esserti stato d’aiuto :)
April 4th, 2008, 3:22 pm
Change if (distance == 5), if (distance == 4), if (distance == 3)…
for this[”blur” + i].blurX = this[”blur” + i].blurY = Math.abs(distance - 5);
September 15th, 2008, 10:13 am
Ma si puo cambiare anche l’angolo di rotazione?
September 16th, 2008, 8:04 pm
Certo che si può cambiare.
Basta modificare i valori in queste 2 rige
this[”menu”+i]._x = posX-(Math.sin(depth)*210);
this[”menu”+i]._y = posY+(Math.cos(depth)*70);
rispettivamente per l’asse delle X e l’asse delle Y
September 17th, 2008, 7:51 pm
Si ti ringranzio, ma sarò più precisa.
Io voglio inclinare l’asse di rotazione X
September 18th, 2008, 10:48 pm
Credo di aver capito cosa intendi.
Prova a sostituire la riga
this[”menu”+i]._y = posY+(Math.cos(depth)*70);
con
this[”menu”+i]._y = posY+(Math.sin(depth)*70);
e variare il valore numerico finchè non ottieni l’angolo desiderato
September 19th, 2008, 11:01 am
Grazie mille R.A.M.
Scusami se chiedo ancora..
Ok l’angolo si inclina, però se volessi lo stesso effetto in prospettiva della posizione iniziale?
September 19th, 2008, 11:24 am
Ciao R.A.M.,
io vorrei creare un menu a 6 pulsanti.
Ogni due pulsanti devono avere un orbita con un angolo di inclinazione diverso
September 26th, 2008, 5:38 pm
Vorrei fare un menu cosi:
http://www.mrlewis.it/test/flash/menu/menu_3d_rotation.html