La classe Matrix, introdotta in Flash 8, utilizzata insieme alla classe Transform, permette non solo di scalare e spostare un movieclip, ma anche di inclinarlo dinamicamente; risulta quindi possibile applicare tramite Actionscript tutte le trasformazioni ottenibili manualmente con la trasformazione libera.
Sia la classe Transform che la classe Matrix apparengono al package Flash.geom e sono disponibili in Flash 8 e in Flash CS3.
Struttura della matrice
I valori u, v e w
non sono modificabili da Flash e quindi hanno valori fissi (rispettivamente 0,0,1), mentre agendo sugli altri valori possiamo modificare l'aspetto grafico del movieclip. La corrispondenza è la seguente:
- a: agisce sulla rotazione e sulla dimensione orizzontale del clip
- b: agisce sulla rotazione e sulla inclinazione verticale del clip
- c: agisce sulla rotazione e sulla dimensione verticale del clip
- d: agisce sulla rotazione e sulla inclinazione orizzontale del clip
- tx: agisce sulla posizione orizzontale del clip
- ty: agisce sulla posizione verticale del clip
Ogni movieclip ha una sua matrice di trasformazione predefinita, impostata in questo modo:
(a=1, b=0, c=0, d=1, tx=0, ty=0)
In questo caso la clip è posizionata sulle coordinate 0,0 non è ruotata (ha valore _rotation
uguale a 0), non è ridimensionata (ha i valori _xscale
e _yscale
corrispondenti a 100) e non è inclinata.
Modificare la matrice
Come detto, ogni movieclip ha una sua matrice; essa è accessibile usando la sintassi nomeistanza.transform.matrix
. Tale matrice, però, non può essere modificata direttamente; per essere più chiari, possiamo usare il seguente comando per leggere solo i valori a e b della matrice del clip mc:
trace(mc.transform.matrix.a)
trace(mc.transform.matrix.b)
Ma non possiamo usare il seguente codice per cambiare aspetto al suddetto clip.
mc.transform.matrix.a = 2
mc.transform.matrix.b = .5
È invece necessario creare una copia della matrice, applicare le modifiche alla copia e poi associarla al movieclip, in questo modo:
Listato 1. Codice per cambiare aspetto al clip
var nuova_matrice:Object = mc.transform.matrix;
matrice.a = 2;
matrice.b = .5;
mc.transform.matrix = matrice;
È possibile associare una nuova matrice ad un movieclip, ma non è possibile modificarla direttamente.
Per quanto riguarda rotazione, spostamenti e ridimensionamenti non è comunque fondamentale modificare direttamente i valori della matrice: quando utilizziamo i comandi rotation
, xscale
, yscale
, x
ed y
andiamo a modificare la matrice del movieclip. Possiamo verificarlo ad esempio con questo codice:
Listato 2. Modifica della matrice di un movieclip
import flash.geom.Matrix;
var mc:MovieClip = _root.createEmptyMovieClip("mc", 1);
mc.beginFill(0xFF0000);
mc.lineTo(0, 50);
mc.lineTo(50, 50);
mc.lineTo(50, 0);
mc.lineTo(0, 0);
trace(mc.transform.matrix)
mc.onPress = function(){
this._rotation = 45
trace(this.transform.matrix)
}
Il risultato che otterremo nella finestra di output dopo aver cliccato sul movieclip sarà il seguente:
Listato 3. Risultato dell'esecuzione del codice
(a=1, b=0, c=0, d=1, tx=0, ty=0)
(a=0.707107543945313, b=0.707107543945313, c=-0.707107543945313, d=0.707107543945313, tx=0, ty=0)
Avremmo ottenuto un risultato analogo anche usando le proprietà accennate in precedenza.
Inclinare un movieclip
Per l'inclinazione non c'è un comando "skew" o simili, né direttamente per i movieclip né per le matrici: l'unico modo per inclinare dinamicamente un movieclip è quello di agire direttamente sulle variabili b e c di una matrice e associarla al movieclip desiderato.
Listato 4. Inclinare un movieclip
var matrice = mc.transform.matrix
matrice.b = 1
matrice.c = .5
mc.transform.matrix = matrice
È singolare la mancanza di un comando specifico per l'inclinazione, dato che aggiunta agli altri controlli consente un controllo pressoché completo sull'aspetto di un clip filmato. Altrettanto curioso il fatto che per spostamento, ridimensionamento e rotazione oltre ai già citati comandi che agiscono direttamente sul clip ci sono dei metodi specifici della classe Matrix. Ad esempio il comando matrice.translate(x,y)
permette di impostare le posizioni x ed y da far assumere a un clip, e si occupa di agire automaticamente sulle variabili tx
e ty
della matrice.
Analogamente il comando matrice.rotation(gradi)
permette di controllare la rotazione dalla matrice e matrice.scale(xscale,yscale)
agisce sulle variabili della matrice relative al ridimensionamento.
Sfruttare la matrice per memorizzare modifiche
Abbiamo visto come la matrice in 6 sole variabili contenga quasi tutte le informazioni sull'aspetto grafico di un movieclip: questo vuol dire che possiamo facilmente memorizzare diversi aspetti di un movieclip, che magari è modificabile dall'utente, in modo da rendere possibile una sorta di "annulla operazione" tipico dei programmi di grafica. Per esempio potremmo memorizzare, ad ogni modifica, la precedente matrice di trasformazione e tenerla come riferimento per consentire di annullare un'operazione, inoltre potremmo anche inserire un tasto di reset che reimposti la matrice al suo valore iniziale.
Con il seguente codice quando l'utente clicca sul movieclip ne aumenta dimensione e inclinazione, ma quando porta il puntatore fuori dal movieclip questo ritorna al suo stato originario.
Listato 5. Aumenta dimensioni e inclinazione in base all'interazione con l'utente
import flash.geom.Matrix
var matrice_orig = mc.transform.matrix
var matrice_mod = mc.transform.matrix
mc.onPress = function(){
matrice_mod.a += 1
matrice_mod.b += .3
matrice_mod.c += .2
mc.transform.matrix = matrice_mod
}
mc.onRollOut = function(){
mc.transform.matrix = matrice_orig
matrice_mod = mc.transform.matrix
}
Notiamo l'utilizzo di due matrici, quella originale (matrice_orig) che non verrà modificata ma solo utilizzata per riportare la clip al suo stato iniziale, e matrice_mod che invece viene sfruttata per variare l'aspetto del movieclip mc.
Esiste anche un metodo apposito della classe Matrix per resettare una matrice, si tratta di identity()
. Questo comando però resetta completamente la matrice.
Listato 6. Resetta la matrice
import flash.geom.Matrix
var matrice_mod = mc.transform.matrix
mc.onPress = function(){
matrice_mod.a += 1
matrice_mod.b += .3
matrice_mod.c += .2
mc.transform.matrix = matrice_mod
}
mc.onRollOut = function(){
matrice_mod.identity()
mc.transform.matrix =matrice_mod
}
Usando questo codice al rollout
il clip non solo torna alle sue dimensioni originali, ma viene anche spostato nel punto 0,0 dello stage. Con il codice visto in precedenza invece siamo sicuri che la clip assume l'aspetto che ha ad inizio filmato, perché abbiamo preso la sua matrice come riferimento e la riassegniamo quando necessario.
Metodi della classe Matrix
Oltre al citato metodo identity
, che come detto resetta completamente una matrice, la classe Matrix offre alcuni metodi utili per sveltire alcune operazioni.
- clone: crea una copia esatta della matrice;
- concat: unisce due matrici, combinando l'effetto geometrico delle due;
- invert: crea la trasformazione inversa della matrice selezionata;
- rotate: imposta la matrice in modo da usarla per una rotazione;
- scale: imposta la matrice in modo da usarla per un ridimensionamento;
- toString: restituisce le proprietà della matrice sotto forma di stringa;
- transformPoint: applica le trasformazioni impostate nella matrice ad un punto;
- translate: imposta la matrice in modo da usarla per una traslazione.
Abbiamo visto in precedenza la corrispondenza di questi comandi coi classici metodi dei movieclip.
L'inclinazione non trova metodi ma può essere applicata solo agendo direttamente sulla matrice di trasformazione.
Le matrici di trasformazione possono essere molto utili per creare strumenti grafici, dato che in una sola matrice troviamo immagazzinati i dati relativi alla quasi totalità dell'aspetto di una clip (eccetto la trasparenza), mentre per ottenere lo stesso risultato senza le matrici dovremmo ricavare i valori di _rotation
, _xscale
, _yscale
, _y
ed _x
in variabili separate, aumentando quindi notevolmente il codice.
Actionscript 3: la classe MatrixTransformer
Se per quanto riguarda la classe Matrix, non vi sono variazioni particolari in Actionscript 3 vi è più in generale una novità piuttosto rilevante, ed è la classe MatrixTransformer. Questa classe permette di modificare una matrice: innanzitutto introduce i comandi per regolare l'inclinazione (non dovremo quindi modificare direttamente la matrice) e soprattutto innalza il livello di controllo della rotazione, dato che sarà possibile impostare con degli appositi comandi la rotazione su punti interni o esterni alla matrice (e quindi al movieclip) in maniera molto intuitiva.
La classe MatrixTransformer segue maggiormente i dettami della programmazione ad oggetti e prevede pertanto diverse proprietà, sia "set" (per impostare un valore) che "get" (per ricavarlo). Ecco l'elenco dei metodi a disposizione per la classe MatrixTransformer ed una breve spiegazione degli stessi.
- getRotation: restituisce il valore (in gradi) corrispondente alla rotazione;
- getRotationRadians: restituisce il valore (in radianti) corrispondente alla rotazione;
- getScaleX: restituisce il fattore di ridimensionamento orizzontale;
- getScaleY: restituisce il fattore di ridimensionamento verticale;
- getSkewX: restituisce il valore (in gradi) di inclinazione orizzontale;
- getSkewXRadians: estituisce il valore (in radianti) di inclinazione orizzontale;
- getSkewY: restituisce il valore (in gradi) di inclinazione verticale;
- getSkewYRadians: restituisce il valore (in radianti) di inclinazione verticale;
- matchInternalPointWithExternal: ruota una matrice su un punto specifico;
- rotateAroundExternalPoint: ruota una matrice intorno ad un punto esterno alla matrice;
- rotateAroundInternalPoint: ruota una matrice intorno ad un punto interno alla matrice;
- setRotation: imposta l'angolo di rotazione;
- setScaleX: imposta il fattore di ridimensionamento orizzontale;
- setScaleY: imposta il fattore di ridimensionamento verticale;
- setSkewX: imposta il fattore di inclinazione orizzontale;
- setSkewRadians: imposta il fattore di inclinazione orizzontale, in radianti;
- setSkewY: imposta il fattore di inclinazione verticale;
- setSkewYRadians: imposta il fattore di inclinazione verticale, in radianti.
Nota: questi metodi agiscono su di una matrice. È comunque necessario impostare una matrice di trasformazione che agisca poi a sua volta sul movieclip. Ad esempio per ruotare un clip intorno ad un punto esterno ad esso dovremmo usare il seguente codice:
Listato 7. Ruota il clip intorno a un punto esterno
import flash.geom.Matrix
import fl.motion.MatrixTransformer
var matrice_mod = mc.transform.matrix
mc.addEventListener(MouseEvent.CLICK,modifica)
function modifica(evt:MouseEvent){
MatrixTransformer.rotateAroundExternalPoint(matrice_mod,0,0,35)
evt.target.transform.matrix = matrice_mod
}
Notiamo come il parametro del metodo rotateAroundExternalPoint
sia la matrice, e non il movieclip. Con la classe MatrixTransformer, possiamo modificare la matrice di trasformazione che andremo in seguito ad associare ad un clip.
Prima di Actionscript 3, per impostare la rotazione su un punto esterno al movieclip, o comunque diverso dal suo centro, dovevamo agire direttamente sui valori a, b, c e d della matrice e comunque non avremmo mai raggiunto la precisione ottenibile con i comandi rotateAroundExternalPoint
e rotateAroundInternalPoint
.
Per inclinare un clip senza agire direttamente sui valori della matrice in Actionscript 3 possiamo fare in questo modo:
Listato 8. Inclina un clip senza agire sui valori della matrice
import flash.geom.Matrix
import fl.motion.MatrixTransformer
var matrice_mod = mc.transform.matrix
mc.addEventListener(MouseEvent.CLICK,modifica)
function modifica(evt:MouseEvent){
MatrixTransformer.setSkewX(matrice_mod,20)
evt.target.transform.matrix = matrice_mod
}
In modo più rapido e intuitivo rispetto ad agire direttamente sui valori b e c.
La possibilità di specificare le trasformazioni in radianti consente un maggior controllo, mentre la capacità di specificare un punto di riferimento per la rotazione diverso dal centro del movieclip da una libertà maggiore per gli spostamenti e per diversi effetti fisici o di "reazione" ad input del mouse.
Compatibilità tra Actionscript 2 ed Actionscript 3
I metodi della classe Matrix non vedono variazioni tra Actionscript 2 e Actionscript 3, questo consente una migrazione molto più comoda di un progetto. Invece, se usiamo i classici comandi _rotation
, _xscale
, _yscale
, _x
ed _y
in Actionscript 2, qualora fosse necessario un porting in Actionscript 3 dovremmo modificarli in rotation
, xscale
, yscale
, x
ed y
, rischiando di perdere diverso tempo.