» 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.

Grafico funzione sinusoide

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.

Grafico funzione cosinusoide

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

Ritieni questo post utile o interessante?
Condividi e Segnala

, , , , , , ,

Leggi anche:

Feed dei commenti dei commenti - lascia un commento - trackback

18 commenti per “Menù 3D in Flash con AS Actionscript 2”

  1. flo

    Troppo diffizile per me, ma il tuo plugin per Wordpress è fantastico ;)
    Ah… ti ho linkato, ciao!

  2. R.A.M. Page

    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!

  3. ale devartstudio

    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

  4. R.A.M.Page

    Piacere di esserti stato d’aiuto :)

  5. Rafael Dourado

    Change if (distance == 5), if (distance == 4), if (distance == 3)…
    for this["blur" + i].blurX = this["blur" + i].blurY = Math.abs(distance – 5);

  6. annamanicomio

    Ma si puo cambiare anche l’angolo di rotazione?

  7. R.A.M.Page

    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

  8. annamanicomio

    Si ti ringranzio, ma sarò più precisa.
    Io voglio inclinare l’asse di rotazione X

  9. R.A.M.Page

    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

  10. annamanicomio

    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?

  11. annamanicomio

    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

  12. annamanicomio
  13. Mars

    Ciao R.A.M.,
    molto bello il menù ed è proprio quello che cercavo per il mio sito.
    Io vorrei però che le sfere che girano, siano oggetti uno diverso dall’altro, (es.una mela, una pesca, un’arancia, un’anguria…) come posso fare?

  14. noemilat

    Ciao a tutti
    finalmente ho trovato quello che cercavo…ho scaricato il file di crescenzo che ho trovato utilissimo per capire un po’ il funzionamento di questo menu….

    PERO’ vorrei capire una cosa…..
    vorrei realizzare un menu tipo questo:

    http://www.ramazzotti.com/ita/home_ita.htm

    ma mi chiedo come faccio a caricare in ogni sfera l’immagine da me scelta?
    e l’effetto dissolvenza delle sfere che ruotano e non sono piu’ in primo piano???????

    grazie di cuore a chi vorra’ aiutarmi

  15. Ciorry

    Poniamo il caso al posto dei link sui bottoni del menù voglio fare in modo che cliccando mi apre una nuova scena…come devo fare ?

  16. Frank

    ciao
    complimenti per il progetto.
    Ho modificato il tuo script per uso didattico e ho fatto un paio di modifiche sui link; ho però un problema nel visualizzare correttamente le immagini “nuove” importate. Mantengono anche le info relative al bordo esterno dell’ immagine stessa (per intenderci l’ area che completa il quadrato. Si può avere un consiglio in merito ? grazie 1000 in anticipo.
    Saluti.

  17. R.A.M.Page

    Ciao Frank,
    puoi provare ad inserire una maschera circolare su ogni movieclip che fa da bottone, così da non avere l’azione ROLLOVER sul PNG quadrato ma solo sulla sfera.

    Per rispondere a Ciorry, basta che sulla funzione associata al rollover aggiungi gotoAndPlay(”NomeScena”)

  18. hily

    ciao
    molto bello lo script
    ma se volessi far fermare le palle con un rallentamento tipo EaseOut?

    impostando il rotating su false si blocca di scatto.

    grazie!

Rispondi al post