Abbiamo visto come
dichiarare la Document Class al FLA.
Abbiamo studiato a fondo
cosa è la document class.
Abbiamo visto come interagiscono la
timeline e la Document Class.
E' giunto il momento di affrontare il problema di una eventuale doppia Document Class. L' idea di scrivere questo articolo mi è venuta rispondendo ad una discussione sul
forum Flash CS3 di FlepStudio, nella quale un utentechiedeva spiegazione su come risolvere il problema di caricare un SWF esterno che a sua volta ha una Document Class. In questo caso, ci ritroveremmo con il nostro FLA principale e la sua Document Class che carica una altro SWF il cui FLA a sua volta ha una Document Class. Siccome, per la DC dell' SWF caricato cambia la root, tutte le path/percorsi utilizzati nella sua DC rusulterebbero impropri per cui avremmo una bella lista di errori.
Vediamo come risolvere questa tragedia...
In un' applicazione Object Oriented la classe principale è una sola, in Flash è appunto stata nominata come Document Class mentre in Java rimane la Main Class.
Non possiamo avere 2 Document Class in un' applicazione Flash. Anche perchè a rigor di logica è una classe sola che fa partire tutta l'applicazione invocando un metodo cha a sua volta istanzierà le altri classi o invocherà metodi e proprietà delle altre classi.
Detto questo, non possiamo caricare un SWF esterno ( con Document Class ) all'interno dell' SWF principale ricordandoci che il FLA principale della nostra applicazione non è altro che unaistanza della sua Document Class.
Per cui, bisogna sempre lavorare da una Document Class e tramite lei accedere all' SWF caricato. In questo tutorial vedremo che utilizzando la Document Class, ci mettiamo in una situazione privilegiata e cioè da ogni punto della nostra applicazione in cui noi vogliamo recuperare o assegnare o chiamare del codice possiamo farlo tranquillamente perchè c'è come un filo conduttore che lega ogni classe dell' applicazione stessa.
I files che utilizzo in questo tutorial:
main.fla ( il FLA principale dell'applicazione )
Main.as ( la Document Class associata a main.fla )
Loading.as ( una classe istanziata dalla Document Class che caricherà un SWF esterno )
my_swf.fla ( il FLA che crea l' SWF da caricare )
my_swf.swf ( l' SWF esterno che viene caricato in main.swf )
Main2.as ( la classe che interagisce completamente sia con l' SWF caricato che con quello principale, un po come se fosse la Document Class di my_swf.fla )
main.fla
creo in libreria una MovieClip con nome ' mc_prova ' e la istanzio sullo Stage assegnandoli il nome istanza ' prova_mc '.
assegno a questo FLA la Document Class Main.as
my_swf.fla
creo in libreria una MovieClip con nome ' mc_test ' e la istanzio sullo Stage assegnandoli il nome istanza ' test_mc '. Poi gli creo una interpolazione di forma della durata che voglio e sul primo keyframe aggiungo uno stop(); ( questo perchè vedremo come chiamare il play() di questa MovieClip dalla classe Main2 una volta che l' SWF è stato caricato ).
Main.as
la Document Class di tutta l' applicazione, implementata in questo modo:
Code:
package
{
import flash.display.MovieClip;
public class Main extends MovieClip
{
private var loading:Loading;
public var trovami:Number=10;
public function Main()
{
stage.frameRate=31;
loadSWF();
}
private function loadSWF():void
{
loading=new Loading(this);
}
}
}
Proprietà
una istanza della classe Loading.as che si prenderà il compito di caricare l' SWF esterno
private var loading:Loading;
una variabile numerica con valore 10, ci servirà per vedere comepoter recuperare quel valore da qualsiasi punto della nostra applicazione. Con la frase ' qualsiasi punto ' intendo dire che questa variabile è recuperabile da ogni file dell' applicazione se l' applicazione stessa segue i canoni di una ' buona ed educata ' Object Oriented Programming.
public var trovami:Number=10;
Metodi
funzione costruttrice:
public function Main()
{
imposto una velocità di frame rate
stage.frameRate=31;
chiamo il metodo loadSWF
loadSWF();
}
loadSWF();
istanzio la classe Loading e gli passo il valore della main root, della root del fla principale ( main.fla )
loading=new Loading(this);
Loading.as
la classe che caricherà l' SWF esterno ( my_swf.swf )
Code:
package
{
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.text.TextField;
import flash.display.Loader;
import flash.events.*;
import flash.net.URLRequest;
public class Loading extends MovieClip
{
private var _fla:MovieClip;
private var url:String;
private var loader:Loader;
public function Loading(fla:MovieClip)
{
_fla=fla;
init();
}
private function init():void
{
url='my_swf.swf';
var request:URLRequest=new URLRequest(url);
loader=new Loader();
initListeners(loader.contentLoaderInfo);
loader.load(request);
}
private function initListeners(dispatcher:IEventDispatcher):void
{
dispatcher.addEventListener(Event.COMPLETE,completato);
}
private function completato(event:Event):void
{
_fla.addChild(loader);
loader.y=_fla.prova_mc.y+_fla.prova_mc.height+10;
loader.y=10;
var main2:Main2;
main2=new Main2(_fla,MovieClip(loader.content));
}
}
}
Proprietà
una variabile MovieClip a cui assegnerò il valore della root che mi passa Main.as ( la Document Class )
private var _fla:MovieClip;
una variabile stringa che conterrà l' url dell' SWF esterno da caricare ( my_swf.swf )
private var url:String;
una istanza della classe Loader per caricare my_swf.swf
private var loader:Loader;
Metodi
funzione costruttrice:
public function Loading(fla:MovieClip)
{
assegno alla variabile _fla la root che mi passa Main.as ( la Document Class )
_fla=fla;
chiamo il metodo init
init();
}
init();
assegno alla variabile url, l'url dell' SWF da caricare
url='my_swf.swf';
faccio richiesta url a Flash
var request:URLRequest=new URLRequest(url);
istanzio il Loader
loader=new Loader();
chiamo il metodo initListeners
initListeners(loader.contentLoaderInfo);
carico l' SWF
loader.load(request);
initListeners();
aggiungo un listener in ascolto dell' evento COMPLETE in mododa intercettare quando l' SWF è stato interamente caricato. Quando lo sarà, verrà chiamato il metodo ' completato '
dispatcher.addEventListener(Event.COMPLETE,complet ato);
completato();
questo è il punto cruciale di questo tutorial. Faccio un addChild di loader in modo che sia visibile
_fla.addChild(loader);
posiziono il loader
loader.y=10;
istanzio la classe Main2 e gli passo come primo parametro la root che a sua volta mi era stata passata dalla Document Class e come secondo parametro il contenuto di loader ( l' SWF caricato )
var main2:Main2;
main2=new Main2(_fla,MovieClip(loader.content));
PS: nella riga sopra utilizzo un'altra forma di un trucchetto che abbiamo già visto nell' articolo
Trucco del giorno - Loader.content
Main2.as
Code:
package
{
import flash.display.MovieClip;
public class Main2 extends MovieClip
{
private var _fla:MovieClip;
private var mia_root:MovieClip;
public function Main2(fla:MovieClip,m:MovieClip)
{
_fla=fla;
mia_root=m;
callClip();
}
private function callClip():void
{
mia_root.test_mc.play();
trace(_fla.prova_mc.name);
trace(_fla.trovami);
}
}
}
Proprietà
una variabile di tipo MovieClipa cui assegnerò il valore della root che mi è passata da Loading.as che a sua volta l' ha ricevuta dalla Document Class ( Main.as )
private var _fla:MovieClip;
una variabile MovieClip a cui assegno il valore della root dell'SWF caricato che mi passa la classe Loading.as, che se ricordate era loader.content. In questo modo possorifrirmi all' SWF principale oppure all' SWF caricato quando e come voglio.
private var mia_root:MovieClip;
Metodi
funzione costrutrice
public function Main2(fla:MovieClip,m:MovieClip)
{
assegno alla varibile _fla ilvalore della root principale dell' applicazione
_fla=fla;
assegno alla variabile mia_root, il valore della root dell' SWF caricato
mia_root=m;
chiamo il metodo callClip
callClip();
}
callClip();
eseguo un play su test_mc che se ben ricordate si trova in my_sw.fla, quindi l' SWF caricato ( da notare il percorso: mia_root.test_mc )
mia_root.test_mc.play();
faccio un trace della propietà name di prova_mc, la MovieClip nell' SWF principale ( da notare il percorso: _fla.prova_mc )
trace(_fla.prova_mc.name);
recupero inoltre il valore di una proprietà dellaDocument Class ( la variabile ' trovami ' )
trace(_fla.trovami);
In sostanza, in questo momento abbiamo tutto sotto estremamente sotto controllo.
Se volessi agire sull' SWF principale, potrei farlo sia dalla Document Class, dalla classe Loading.as e da Main2.as .
Se volessi inoltre agire sull' SWF caricato, potrei farlo da Loading.as come da Main2.as .
Allego i files sorgente: