Uno degli effetti grafici più diffusi nel design di siti web, attualmente, è quello di immagini e icone riflesse.
Creare un effetto di riflessione "manualmente"
Per prima cosa importiamo un'immagine sullo stage, la selezioniamo, la copiamo e la incolliamo in modo da ottenere una copia dell'immagine principale. Ruotiamo la copia di 180 gradi e posizioniamola sotto la foto originale.
Ora non ci resta che creare l'effetto di riflessione sull'immagine ruotata. Per prima cosa creiamo un nuovo livello sulla linea temporale, quindi disegniamoci sopra un rettangolo bianco che occupi indicativamente la stessa area dell'immagine riflessa.
Dobbiamo fare in modo che sotto questo rettangolo appaia l'immagine riflessa, in maniera sfumata: utilizziamo quindi un riempimento di tipo gradiente. Selezioniamo il rettangolo, apriamo il pannello Colors ed impostiamo come tipo di riempimento un gradiente lineare. Settiamo quindi il colore iniziale come bianco con una trasparenza dello 0% e quello finale bianco con trasparenza 100%.
Se avessimo impostato un colore di sfondo per lo stage, invece di utilizzare il bianco scegliamo il colore corrispondente allo sfondo.
Di default il riempimento gradiente andrà da sinistra a destra.
Per ruotare il riempimento secondo le nostre esigenze selezioniamo lo strumento trasformazione gradiente, accessibile dalla barra degli strumenti (si trova nella stessa casella dello strumento trasformazione libera), oppure premiamo il tasto F. Con questo strumento possiamo variare la rotazione e l'ampiezza del riempimento gradiente, così da poter regolare la sfumatura: ruotiamo il riempimento fino ad ottenere un risultato di nostro gradimento.
Con pochi semplici passaggi abbiamo realizzato un effetto di riflessione per un'immagine, tuttavia questa soluzione è poco personalizzabile e soprattutto, se dovessimo applicare lo stesso effetto a più immagini, il procedimento andrebbe ripetuto ogni volta.
Creare un effetto di riflessione con Actionscript
Vediamo allora come far eseguire automaticamente al filmato il procedimento di copia, rotazione e posizionamento dell'immagine e la creazione della forma con riempimento gradiente, il tutto grazie ad Actionscript 3.
Creiamo un nuovo file Actionscript, all'interno del quale scriveremo la nostra classe. È necessario importare i package che utilizzeremo nel nostro codice.
In Actionscript dobbiamo avere dei movieclip come riferimento per poter effettuare delle operazioni di copia e di creazione, per cui andremo ad importare il package flash.display.MovieClip
; per copiare l'immagine ci serviranno le classi BitmapData
e Bitmap
, quindi importeremo anche flash.display.BitmapData
e flash.display.Bitmap
; per creare il riempimento gradiente alla clip che crea l'effetto dovremo invece sfruttare i package flash.display.GradientType
, flash.geom.Matrix
e flash.display.SpreadMethod
.
Quindi la prima parte di codice della nostra classe sarà la seguente:
Listato 1. Prima parte del codice
package{
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.GradientType;
import flash.display.SpreadMethod;
import flash.geom.Matrix;
public class rifletti extends MovieClip{
}
}
Utilizzeremo in totale 4 elementi: la clip originale, la clip duplicata, la copia dell'immagine contenuta nella clip originale ed infine la clip colorata con il riempimento gradiente. Possiamo quindi dichiarare inizialmente 4 variabili, inoltre impostiamo la funzione in modo che la clip da "riflettere" sia passata come parametro:
Listato 2. Dichiarazione delle variabili
public class rifletti extends MovieClip{
private var sorgente:MovieClip
private var duplicato:BitmapData
private var riflesso:Bitmap
private var maschera:DisplayObject
public function rifletti(mc){
}
}
Con questo codice abbiamo impostato le basi della nostra classe e possiamo ora concentrarci sul codice interno alla funzione rifletti, che rappresenterà la trasposizione in Actionscript 3 dei passaggi compiuti manualmente.
Procedendo con ordine, il primo passaggio è creare e disporre la copia della clip originale.
Listato 3. Crea e dispone la copia della clip
public function rifletti(mc){
// Memorizzo il riferimento alla clip originale
sorgente = mc
// Ricavo altezza e larghezza della clip
var altezza:Number = sorgente.height
var larghezza:Number = sorgente.width
trace(altezza,larghezza)
// Preparo un oggetto bitmapData con la copia dell'immagine
duplicato = new BitmapData(larghezza, altezza, true,0xFFFFFF);
duplicato.draw(sorgente);
// Creo la copia dell'immagine originale
riflesso = new Bitmap(duplicato);
// La inverto (corrisponde alla rotazione di 180 gradi)
riflesso.scaleY = -1
// e la posiziono al di sotto del movieclip originale
riflesso.y = sorgente.height*2 + 10
// Quindi la aggiungo all'interno della clip originale
sorgente.addChild(riflesso)
I commenti al codice dovrebbero essere abbastanza esaustivi; teniamo presente che la copia dell'immagine verrà inserita dentro alla clip originale ruotata di 180 gradi, per questo è necessario moltiplicare per 2 l'altezza del clip sorgente per posizionare correttamente la copia.
Tramite l'oggetto BitmapData
prepariamo i dati per la creazione della copia dell'immagine originale, copia che viene creata con l'oggetto riflesso che è poi di fatto quello che inseriamo nello stage.
Testiamo questa prima parte di codice: apriamo un nuovo progetto Actionscript 3, importiamo un'immagine e convertiamola in movieclip: diamo a questo movieclip nome istanza mc, quindi sul primo fotogramma della linea temporale inseriamo il seguente codice
import rifletti
var rifl:rifletti = new rifletti(mc)
Testando il filmato avremo questo risultato:
Non ci resta che aggiungere nel codice i passaggi per creare il clip con riempimento gradente sfumato.
Listato 4. Crea il clip con riempimento gradente sfumato
// Creo la clip da utilizzare con riempimento gradiente
maschera = new MovieClip()
// Imposto lo riempimento gradiente lineare di colore bianco, con alpha da 0 ad 1 e che influenzi
// circa metà clip
var riempimento:String = GradientType.LINEAR;
var colori:Array = [0xFFFFFF, 0xFFFFFF];
var trasparenza:Array = [0, 1];
var influenza:Array = [0, 150];
// Imposto lo stile del gradiente
var spreadMethod:String = SpreadMethod.PAD;
// Creo la matrice per il riempimento
var matr:Matrix = new Matrix();
// Creo lo riempimento gradiente
matr.createGradientBox(larghezza, altezza,(90/180)*Math.PI, 0, 0);
maschera.graphics.beginGradientFill(riempimento, colori,trasparenza, influenza, matr, spreadMethod);
// Disegno la clip, con dimensioni pari a quelle del clip sorgente
maschera.graphics.drawRect(0,0,larghezza,altezza);
// Posiziono la clip gradiente sopra alla clip riflessa
maschera.y = sorgente.getChildByName("riflesso").y- sorgente.getChildByName("riflesso").height;
sorgente.addChild(maschera)
La creazione di un riempimento gradiente tramite Actionscript è abbastanza elaborata poiché ricca di parametri: in questo caso abbiamo usato due colori (infatti i vari array hanno solo due elementi), uno è un bianco con alpha 0 e l'altro è un bianco con alpha 1, con l'effetto influenzato per agire fino a circa metà immagine (influenza da 0 a 150, su un range massimo da 0 a 255).
Lo spreadMethod
corrisponde ai settaggi per la ripetizione del riempimento nel pannello Colori, precisamente PAD corrisponde al metodo di default.
Utilizzando questi valori abbinati ad una matrice è possibile creare praticamente qualsiasi tipo di riempimento gradiente; nel nostro caso ne abbiamo creato uno pressoché identico a quello realizzato manualmente.
Applicare l'effetto a più clip
Lo svantaggio principale della soluzione manuale era la necessità di ripetere ogni volta il procedimento per applicare l'effetto a diverse clip: con la classe che abbiamo creato basterà invece aggiungere delle righe di codice, ad esempio, per applicare l'effetto a 4 clip utilizziamo:
Listato 5. Applica l'effetto a 4 clip
import rifletti
var r1:rifletti = new rifletti(mc)
var r2:rifletti = new rifletti(mc2)
var r3:rifletti = new rifletti(mc3)
var r4:rifletti = new rifletti(mc4)
Rendere personalizzabile l'effetto
Altro vantaggio, derivato dall'utilizzo di Actionscript, è la possibilità di rendere versatile e personalizzabile l'effetto; supponiamo di lasciare la possibilità di scegliere il colore, la distanza tra la clip originale e il riflesso e l'area di influenza del riflesso.
Listato 6. Rende personalizzabile l'effetto
package{
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Matrix;
import flash.display.GradientType;
import flash.display.SpreadMethod;
public class rifletti extends MovieClip{
private var sorgente:MovieClip
private var duplicato:BitmapData
private var riflesso:Bitmap
private var maschera:MovieClip
public function rifletti(mc,distanza,colore,influ){
// Memorizzo il riferimento alla clip originale
sorgente = mc
// Ricavo altezza e larghezza della clip
var altezza:Number = sorgente.height
var larghezza:Number = sorgente.width
// Preparo un oggetto bitmapData con la copia dell'immagine
duplicato = new BitmapData(larghezza, altezza, true,0xFFFFFF);
duplicato.draw(sorgente);
// Creo la copia dell'immagine originale
riflesso = new Bitmap(duplicato);
// La inverto (corrisponde alla rotazione di 180 gradi)
riflesso.scaleY = -1
// e la posiziono al di sotto del movieclip originale
riflesso.y = sorgente.height*2 + distanza
riflesso.name = "riflesso"
// Quindi la aggiungo all'interno della clip originale
sorgente.addChild(riflesso)
// Creo la clip da utilizzare con riempimento gradiente
maschera = new MovieClip()
// Imposto uno riempimento gradiente lineare di colore bianco, con alpha da 0 ad 1 e che influenzi
// circa metà clip
var riempimento:String = GradientType.LINEAR;
var colori:Array = [colore,colore];
var trasparenza:Array = [0, 1];
var influenza:Array = [0, influ];
// Imposto lo stile del gradiente
var spreadMethod:String = SpreadMethod.PAD;
// Creo la matrice per il riempimento
var matr:Matrix = new Matrix();
// Creo il riempimento gradiente
matr.createGradientBox(larghezza, altezza,(90/180)*Math.PI, 0, 0);
maschera.graphics.beginGradientFill(riempimento, colori,trasparenza, influenza, matr, spreadMethod);
// Disegno la clip, con dimensioni pari a quelle del clip sorgente
maschera.graphics.drawRect(0,0,larghezza,altezza);
// Posiziono la clip gradiente sopra alla clip riflessa
maschera.y = sorgente.getChildByName("riflesso").y- sorgente.getChildByName("riflesso").height;
sorgente.addChild(maschera)
}
}
}
Mentre il codice per il richiamo diventerà:
import rifletti
var rifl:rifletti = new rifletti(mc,10,0xFFFFFF,150)