Una delle novità del FlashMX, anche se all'apparenza di importanza minore, è l'introduzione dell'oggetto Stage
. L'oggetto si riferisce proprio allo stage del filmato, e possiede alcune proprietà interessanti che, abbinate all'evento onResize
, permettono di gestirne più in profondità l'aspetto quando viene ridimensionato il proiettore o la pagina HTML che lo contengono.
Cominciamo con le proprietà, per poi passare all'applicazione pratica.
Align
Stage.align = "X";
dove a X bisogna sostituire uno dei seguenti valori:
Valore | Verticale | Orizzontale |
T | in alto | al centro |
B | in basso | al centro |
L | al centro | a sinistra |
R | al centro | a destra |
TL | in alto | a sinistra |
TR | in alto | a destra |
BL | in basso | a sinistra |
BR | in basso | a destra |
Se quindi vogliamo che il filmato sia allineato in basso a destra, nel primo frame della timeline principale scriveremo:
Stage.align = "BR";
Cambiando durante la riproduzione il valore della proprietà align
, cambierà di conseguenza anche la posizione del filmato. Se quindi al frame 100 scriviamo:
Stage.align = "TL";
il filmato si allineerà in alto a sinistra. Lasciando vuoto lo spazio tra le virgolette, il filmato sarà allineato al centro in entrambe le dimensioni.
È importante da notare che le impostazioni settate nella sezione HTML dei Publish Settings, prevalgono su quelle del filmato, quando questo viene guardato all'interno del browser. Quindi, se ad esempio settiamo lo Stage
.align
per allineare in basso a destra, ma nei Publish Settings usiamo come Dimension il "Match Movie", il filmato sarà comunque allineato in alto a sinistra.
Al contrario, nel proiettore hanno valore solo le impostazioni dell'oggetto Stage
, quindi vedremmo il filmato ridimensionarsi proporzionalmente, ma rispettando l'allineamento settato con l'align
.
ShowMenu
Stage.showMenu = flag;
dove a flag va sostituito true
o false
. L'effetto è lo stesso dell' fscommand
("showmenu", flag);, ma il comportamento del filmato, in relazione ai Publish Settings, è diverso da quello precedente. Se nel proiettore, naturalmente, vale quanto settato con lo Stage
.showMenu
, nella pagina html, perchè il menu sia visibile, deve essere settato come tale in entrambi (o omesso in entrambi, come di default). Se invece anche solo una delle due impostazioni è settata come falsa, il menu non sarà visibile.
Ad esempio, se nei Publish Settings, come in figura, abbiamo settato il "Display Menu", ma nel primo frame del filmato scriviamo:
Stage.showMenu = false;
il menu contestuale del mouse non sarà visibile ne nel proiettore, ne nella pagina html.
.scaleMode
Stage.scaleMode = "modalità";
dove a modalità bisogna sostituire uno dei seguenti valori:
Valore | Significato |
showAll | il filmato si ridimensiona, rispettando proporzioni e allineamento quando possibile |
exactFit | il filmato si ridimensiona, deformandosi per riempire l'area visibile, e quindi rendendo nulle le impostazioni sull'allineamento |
noBorder | il filmato si ridimensiona mantenendo le proporzioni, ma uscendo dall'area visibile quando in un senso ha più spazio che nell'altro |
noScale | il filmato non si ridimensiona, mantenendo sempre le dimensioni iniziali e l'allineamento impostato |
Queste impostazioni hanno sempre valore nel proiettore, mentre vengono ignorate nel browser quando, come nel caso dell'align, nei Publish Settings usiamo il Match Movie.
Se invece impostiamo come Dimension l'opzione "Percent" al 100% allora anche nel browser, avranno valore sia la proprietà align
, che lo scaleMode
. (tutti gli esempi sono settati con l'opzione Dimension Percent al 100% e Stage
.align
= "TL")
esempio1 - Stage.scaleMode = "showAll"
esempio2 - Stage.scaleMode = "exactFit"
esempio3 - Stage.scaleMode = "noBorder"
esempio4 - Stage.scaleMode = "noScale"
Width e Height
Stage
.width
e Stage
.height
sono delle proprietà di sola lettura, che restituiscono le dimensioni del filmato. Bisogna subito fare delle distinzioni sui valori che restituiscono, a seconda della modalità e del media adottato.
Nel proiettore:
- quando lo
scaleMode
è omesso, oppure è uguale a "showAll", "exactFit" e "noBorder", le due proprietà restituiscono le dimensioni originali del filmato, comunque venga ridimensionato il proiettore. - quando lo
scaleMode
è uguale a "noScale", le proprietà restituiscono le dimensioni del proiettore (le dimensioni del filmato restano quelle impostate in fase di authoring, dal momento che il contenuto non viene ridimensionato).
Nel browser:
- qualunque sia lo
scaleMode
, se le Dimension sono settate come "Match Movie", "No Border", o "Exact Fit", le proprietà restituiscono le dimensioni originali del filmato. - se le Dimension sono settate come Percent al 100%, e lo
Stage
.scaleMode
è uguale a "noScale", il contenuto del filmato non viene ridimensionato, ma le proprietà restituiscono le dimensioni dell'area visibile del browser occupata dal filmato (non le dimensioni del browser stesso).
esempio5 - Dimension "Percent" al 100%, e Stage
.scaleMode
= "noScale"
Lo script che determina la scrittura dei due valori è un semplice:
Stage.align = "TL";
Stage.scaleMode = "noScale";
this.onEnterFrame = function(){
testo.html = true;
testo.htmlText = "Stage.width = " + Stage.width + "<br>Stage.height = " + Stage.height;
};
Terminate le proprietà, passiamo all'unico evento previsto per l'oggetto Stage
, l'onResize
.
OnResize
Stage.onResize = function(){
// - istruzioni - //
}
dove al posto di // - istruzioni - // vanno inseriti i comandi da eseguire quando viene ridimensionato lo Stage
. Perchè la funzione possa essere eseguita, bisogna creare un oggetto che "ascolti" il ridimensionamento dello Stage
, e operi una chiamata alla funzione. Vediamo quindi i due metodi disponibili per questa operazione.
AddListener e RemoveListener
Stage.addListener(oggetto);
Stage.removeListener(oggetto);
Supponiamo di voler eseguire una funzione quando lo Stage
viene ridimensionato. Solo in quel momento, non continuamente come nell'esempio della pagina precedente (onEnterFrame
).
Creeremo allora un oggetto, che ascolti il ridimensionamento:
mioOggetto = new Object();
quindi definiremo una funzione da eseguire "al ridimensionamento":
mioOggetto.onResize = function (){...};
e infine assoceremo l'oggetto allo Stage:
Stage.addListener(mioOggetto);
Un modo per semplificare le cose, senza la creazione di un nuovo oggetto, è usare la timeline principale come Listener:
this.onResize = function(){
// - istruzioni - //
};
Stage.addListener(this);
Rimanendo invece all'uso di un oggetto creato appositamente, possiamo riscrivere l'esempio precedente:
Stage.align = "TL";
Stage.scaleMode = "noScale";
mioOggetto = new Object();
mioOggetto.onResize = function(){
testo.html = true;
testo.htmlText = "Stage.width = " + Stage.width + "<br>Stage.height = " + Stage.height;
};
Stage.addListener(mioOggetto);
rimuovi.onRelease = function(){
Stage.removeListener(mioOggetto);
};
In fondo allo script, ho aggiunto una funzione associata ad un pulsante il cui nome di istanza è "rimuovi". La funzione, con il removeListener
, rimuove l'oggetto creato per chiamare la funzione onResize
. Cliccando il pulsante nell'esempio, infatti, ai successivi ridimensionamenti i valori del campo di testo non saranno modificati.
esempio6 - uso dell'evento onResize
e del metodo addListener
Quali sono i vantaggi rispetto all'uso del onEnterFrame
? Innanzitutto, la funzione per l'aggiornamento del campo di testo con i dati non viene chiamata alla velocità del frame rate, ma solo quando effettivamente viene ridimensionato il filmato. Poi, abbiamo la possibilità di rimuovere l'aggiornamento dei dati con il removeListener
, che ci evita anche di usare una variabile solo per rendere vera o falsa una condizione per il richiamo della funzione.
Fino ad adesso non si può certo dire che le proprietà e i metodi sembrino molto utili. Ma proviamo a vedere le cose da un altro punto di vista.
Vediamo lo script, che poi spiegherò passo passo.
vis = 1;
scala = false;
Button.prototype.useHandCursor = false;
Stage.align = "";
Stage.scaleMode = "showAll";
wdth = Stage.width;
hght = Stage.height;
Stage.scaleMode = "noScale";
controllo = new Object();
controllo.onResize = function(){
w = Stage.width
h = Stage.height
cx = (w-wdth)/2;
cy = (h-hght)/2;
vis = (w < wdth || h < hght) ? 0 : 1;
scritta._visible = (w < wdth || h < hght) ? 1 : 0;
fascia._width = w;
for(var i = 1; i < 5; i++){
_root["freccia" + i]._visible = vis;
}
logo._visible = barra._visible = larg._visible = alt._visible = vis;
scaler = scala ? 100+cx/1.5 : 100;
alt._x = Math.round(wdth+cx);
larg._y = Math.round(5-cy);
larg.testo.text = "LARGHEZZA: " + w;
alt.testo.text = "ALTEZZA: " + h;
};
Stage.addListener(controllo);
MovieClip.prototype.move = function(x,y){
this._x += (x-this._x)/4;
this._y += (y-this._y)/4;
};
barra.pulsante.onRelease = function(){
_root.scala = !_root.scala;
controllo.onResize();
};
this.onEnterFrame = function(){
logo._xscale = logo._yscale = logo._yscale + (scaler-logo._yscale)/3;
barra.move(wdth/2,hght-2+cy)
freccia1.move(2-cx,2-cy);
freccia2.move(wdth-2+cx,2-cy);
freccia3.move(wdth-2+cx,hght-2+cy);
freccia4.move(2-cx,hght-2+cy);
};
controllo.onResize();
Le quattro frecce puntano ciascuna ad un angolo dell'area visibile del browser (il filmato riempie l'area, essendo settato come Dimension percentuale al 100%, anche se lo stage originale non viene deformato, vista la proprietà Stage.scaleMode = "noScale").
La fascia grigio chiaro centrale (un movieclip), viene ridimensionata in orizzontale seguendo le dimensioni dell'area visibile, mentre in verticale resta delle dimensioni iniziali. Il pulsante, è settato in modo da rimanere sempre vicino al bordo inferiore del browser, e il logo rimane delle dimensioni originali, se non quando si preme il pulsante, e segue una scala proporzionata in base alla larghezza.
Quando l'area visibile diventa più piccola delle dimensioni originali, tutti gli oggetti vengono nascosti.
Prima della spiegazione del codice, è meglio chiarire come prendere i riferimenti per la posizione degli oggetti nel filmato. Nella "figura" seguente vediamo lo schema di come ci appare nel browser. Lo stage originale è in arancione, ma nel filmato le dimensioni originali sono invisibili (non ci sono contorni a delimitarlo), gli oggetti "vivono" di vita propria, e il filmato si allarga con lo sfondo a riempire l'area visibile, in bianco.
Come si deduce dalla figura, il punto di origine del filmato, allineato centralmente, rimane quello originale, cioè il vertice superiore sinistro del rettangolo arancione, e non il vertice superiore sinistro dell'area visibile. Quindi la posizione del punto indicato dall'asterisco non è lo Stage.width, ma molto di meno (assegnando alla _x dell'asterisco il valore di Stage.width, il punto esce abbondantemente dal browser sulla destra, rimanendo nascosto).
Quindi noi assegniamo a "w" il valore dello Stage.width, e a "wdth" il valore della larghezza originale dello stage. A "w" sottraiamo "wdth", e dividiamo per due, ottenendo "cx" che è la larghezza di una delle due fasce che servono a raggiungere il limite del browser. Quindi, la posizione del punto è determinata dalle dimensioni originali dello stage più quest'ultimo valore, "wdth" più "cx".
// assegniamo alla variabile "vis", che determinerà la visibilità degli
// oggetti, il valore 1 (oggetti visibili)
vis = 1;
// assegniamo alla variabile "scala", che determinerà quando il logo sarà
// da ridimensionare, il valore false (il logo non si ridimensiona)
scala = false;
// eliminiamo la manina da tutti i pulsanti del filmato
Button.prototype.useHandCursor = false;
// lasciamo vuota la proprietà align, che ci da un filmato centrato
// sia in verticale che in orizzontale, a qualunque dimensione
Stage.align = "";
// settiamo lo scaleMode come "showAll". questo ci permette di prendere
// tramite le proprietà width ed height, le dimensioni originali del
// filmato ( a qualunque dimensione, sempre quelle)
Stage.scaleMode = "showAll";
// associamo a due variabili il valori originali delle dimensioni
wdth = Stage.width;
hght = Stage.height;
// adesso che abbiamo i valori originali, possiamo portare lo "scaleMode"
// al valore "noScale", che ci permette di recuperare tramite width ed
// height le dimensioni dell'area del browser occupata dal filmato
Stage.scaleMode = "noScale";
// creiamo un nuovo oggetto, chiamato "controllo", che sarà il listener
// della funzione onResize
controllo = new Object();
// definiamo la funzione onResize relativa all'oggetto controllo, che
// verrà chiamata solo quando il browser (il filmato) viene ridimensionato
controllo.onResize = function(){
// assegniamo a "w" il valore della larghezza del filmato
w = Stage.width
// assegniamo a "h" il valore dell'altezza del filmato
h = Stage.height
// assegniamo a due variabili, rispettivamente il valore della metà
// della parte di area visibile oltre al filmato originale in larghezza, e
// il valore della metà della parte visibile oltre al filmato in altezza
cx = (w-wdth)/2;
cy = (h-hght)/2;
// assegniamo a "vis" (la visibilità), il valore di 0 se una delle
// dimensioni è inferiore a quelle originali, e 1 se è maggiore
vis = (w < wdth || h < hght) ? 0 : 1;
// determiniamo la visibilità della scritta in base all'opposto
// del valore detto sopra (la scritta apparirà quando
// scompariranno gli altri oggetti)
scritta._visible = (w < wdth || h < hght) ? 1 : 0;
// determiniamo la larghezza della fascia grigia centrale in base alla
// larghezza dell'area visibile
fascia._width = w;
// con un ciclo for, determiniamo la visibilità delle 4 frecce
// sulla base del valore di "vis"
for(var i = 1; i < 5; i++){
_root["freccia" + i]._visible = vis;
}
// determiniamo sul valore di "vis" la visibilità degli altri oggetti
logo._visible = barra._visible = larg._visible = alt._visible = vis;
// assegniamo a "scaler" (fattore di scala del logo) il valore di
// 100+cx/1.5 se "scala" è vera, e 100 se "scala" è falsa
scaler = scala ? 100+cx/1.5 : 100;
// posizioniamo i due movieclip che ci dicono le dimensioni dello stage
// vicino ai limiti destro e superiore
alt._x = Math.round(wdth+cx);
larg._y = Math.round(5-cy);
// scriviamo nei campi di testo dinamici all'interno dei movieclip, i
// valori della larghezza e dell'altezza attuale del filmato
larg.testo.text = "LARGHEZZA: " + w;
alt.testo.text = "ALTEZZA: " + h;
};
// aggiungiamo allo Stage l'oggetto "controllo" come Listener
Stage.addListener(controllo);
// creiamo una funzione universale per i movieclip, che sfrutta la nota
// formula del moto uniformemente decelerato per spostare un oggetto
// verso i due punti finali determinati da x e y
MovieClip.prototype.move = function(x,y){
this._x += (x-this._x)/4;
this._y += (y-this._y)/4;
};
// assegniamo al pulsante "pulsante" dentro "barra", il cambiamento
// del valore booleano di "scala", che determina il ridimensionamento
// del logo centrale, e richiamiamo la funzione onResize
barra.pulsante.onRelease = function(){
_root.scala = !_root.scala;
controllo.onResize();
};
// associamo alla timeline principale una funzione da eseguire ad ogni
// riproduzione del frame
this.onEnterFrame = function(){
// sempre secondo la formula, il logo viene scalato verso il valore
// di scaler (se "scala" è falsa, scaler è uguale a 100, e il logo
// resta delle dimensioni originali).
logo._xscale = logo._yscale = logo._yscale + (scaler-logo._yscale)/3;
// muoviamo la barra secondo la funzione universale per i movieclip, passando
// come parametri la larghezza dello stage divisa per due, e l'altezza
// originale meno una delle fascie verticali (resta vicino al limite
// inferiore dell'area visibile)
barra.move(wdth/2,hght-2+cy)
// allo stesso modo posizioniamo le 4 frecce ai 4 angoli dell'area visibile
freccia1.move(2-cx,2-cy);
freccia2.move(wdth-2+cx,2-cy);
freccia3.move(wdth-2+cx,hght-2+cy);
freccia4.move(2-cx,hght-2+cy);
};
// chiamiamo la prima volta la funzione onResize
controllo.onResize();