SCOPO
Modificare la posizione e il contenuto di un layer html da un filmato Flash
STRUMENTI
Metodi Javascript
SetVariable
GetVariable
Richiamo funzioni Javascript da Flash
METODO
Attraverso la spiegazione di quest'esempio, riprenderemo in mano la maggior parte degli argomenti trattati in questa guida: il settaggio e il recupero di variabili in Flash tramite Javascript, il richiamo di funzioni contenute nella pagina, la sovrapposizione di layer html.
Prima di cominciare, bisogna notare come l'esempio funzioni al 100% solo con due Browser tra quelli provati, Internet Explorer e Mozilla. Gli altri:
• Netscape 7: l'unico difetto è uno sfarfallio dei layer durante il movimento
• Netscape 6: non implementa la comunicazione Javascript > Flash
• K-Meleon: problemi di ogni tipo, con i layer, con Javascript, con i tag di incorporamento
• Opera: come per K-Meleon
LA PAGINA HTML
<html>
<head>
<title>Trascinamento di un layer e scrittura del contenuto</title>
<script language="JavaScript1.2" type="text/JavaScript" src="dragLayer.js">
</script>
</head>
<body bgcolor="#EEEEEE">
<div
id="dragged" style="position:absolute; left:400px; top:15px;
width:200px; height:200px; z-index:1;"></div>
<div
id="flashMovie" style="position:absolute; left:15px; top:15px;
width:300px; height:200px; z-index:2;">
<OBJECT
classid="[...]" codebase="[...]"
WIDTH="300" HEIGHT="200" ID="mainMovie">
<PARAM NAME=movie VALUE="menu.swf">
<PARAM NAME=quality VALUE=best>
<PARAM NAME=bgcolor VALUE=#EEEEEE>
<PARAM NAME=wmode VALUE=opaque>
<EMBED
src="menu.swf"
quality=best
bgcolor=#EEEEEE
swLiveConnect="true"
name="mainMovie"
WIDTH="300"
HEIGHT="200"
TYPE="[...]" PLUGINSPAGE="[...]">
</EMBED>
</OBJECT>
</div>
</body>
</html>
Da notare:
• all'interno dei tag <script> dentro l'head della pagina html, il richiamo al file dragLayer.js, contenente il codice Javascript utilizzato
• nel corpo della pagina, due layer html: il primo, con z-index minore (e quindi nascosto da quelli con z-index maggiore), ha dragged come identificativo, ed è privo di contenuto. Il secondo, con z-index maggiore, contiene il filmato flash che comanda lo spostamento e la scrittura dell'altro layer, e ha flashmovie come id.
• all'interno del layer flashmovie, il filmato menu.swf: per questo filmato, sono definiti i tag html per la comunicazione Javascript > Flash (id, name e swLiveConnect). Il filmato viene identificato nella pagina come mainMovie
IL CODICE JAVASCRIPT
Il codice Javascript utilizzato in quest'esempio è contenuto nel file dragLayer.js, a cui si collega la pagina html tramite i tag <script>. Vediamo le singole funzioni una ad una così come sono definite nel file, per poi vederne l'utilizzo secondo la sequenza operativa.
.Browser
Browser = function()
{
this.N4 = (document.layers) ? true : false;
this.IE = (document.all) ? true : false;
this.N6 = (document.getElementById) ? true : false;
};
( non entrando nei dettagli della programmazione ad oggetti )
È la funzione di costruzione della Classe Browser. Serve a creare istanze della classe alle quali vengono assegnate automaticamente tre proprietà, N4, IE e N6: ciascuna delle proprietà, tramite la valutazione del tipo di browser, avrà il valore true o false. In base a questi valori, potremo agire sui layer in maniera differente.
.whichLayer
Browser.prototype.whichLayer = function(id)
{
if (this.N4){
return document.layers[id];
} else if (this.IE){
return document.all[id].style;
} else if (this.N6){
return document.getElementById(id).style;
}
};
È un metodo della Classe Browser: è utilizzato dalle istanze create sul modello della funzione di costruzione, e serve ad identificare un layer in maniera differente a seconda del browser utilizzato. Si serve delle tre proprietà definite alla creazione dell'istanza, il cui ordine di valutazione, in questo caso, non è casuale.
Al metodo/funzione viene passato un argomento, id
, vale a dire una stringa contenente il nome del layer da identificare ( gli id dei due layer della pagina sono "dragged" e "flashmovie" ), e questa restituisce un oggetto che ne contiene il riferimento.
.getLayerXpos
Browser.prototype.getLayerXpos = function(id)
{
return parseInt(this.whichLayer(id).left);
};
Un altro metodo della Classe Browser: passando l'identificativo di un layer, ne restituisce la posizione sull'asse delle X all'interno della pagina HTML. Il metodo chiama whichLayer
, che restituisce l'opportuno riferimento al layer, quindi ne estrae la proprietà left
: la tramuta in un numero interno (parseInt), e la restituisce alla funzione chiamante.
.getLayerYpos
Browser.prototype.getLayerYpos = function(id)
{
return parseInt(this.whichLayer(id).top);
};
Stessa cosa del metodo getLayerXpos(), solo che restituisce la posizione del layer sull'asse delle Y.
.setLayerPos
Browser.prototype.setLayerPos = function(id, left, top)
{
var lay = this.whichLayer(id);
lay.left = left;lay.top = top;
};
Il metodo riceve tre parametri, id, left e top. Il primo è l'identificativo del layer, gli altri due sono le coordinate alle quali posizionarlo.
Invoca il metodo whichLayer passandogli l'identificativo id, e riceve un riferimento al layer corrispondente: quindi ne modifica le proprietà left e top
.
.moveLayer
Browser.prototype.moveLayer = function(id)
{
var IE = navigator.appName.indexOf("Microsoft") != -1;
var filmato = IE ? window.mainMovie : window.document.mainMovie;
var xmov=parseInt(filmato.GetVariable("/dragger:xmov"))+this.getLayerXpos(id);
var ymov=parseInt(filmato.GetVariable("/dragger:ymov"))+this.getLayerYpos(id);
this.setLayerPos(id, xmov, ymov);
this.sendLayerPos(id);
};
Il metodo riceve un parametro, id
, cioè l'identificativo del layer da spostare. Quindi:
• identifica il filmato all'interno della pagina come spiegato qui
• tramite il GetVariable recupera dal filmato il valore delle variabili xmov e ymov che, come vedremo più avanti, indicano di quanto spostare i layer. A questi valori vengono aggiunti quelli recuperati dall'invocazione dei metodi getLayerXpos e getLayerYpos, ottenendo quindi la nuova posizione per il layer ( vecchia posizione + spostamento = nuova posizione).
• i valori ottenuti vengono convertiti in interi (parseInt), e salvati nelle variabili locali xmov e ymov, omonime di quelle estratte dal filmato.
• id, xmov e ymov vengono usati come parametri per richiamare il metodo setLayerPos che, come visto in precedenza, modifica la posizione del layer.
• viene invocato il metodo sendLayerPos, cui viene passato l'identificativo del layer.
.sendLayerPos
Browser.prototype.sendLayerPos = function(id)
{
var IE = navigator.appName.indexOf("Microsoft") != -1;
var filmato = IE ? window.mainMovie : window.document.mainMovie;
filmato.SetVariable("/dragger:xpos", this.getLayerXpos(id));
filmato.SetVariable("/dragger:ypos", this.getLayerYpos(id));
};
Il metodo identifica il filmato all'interno della pagina html, e setta le variabili xpos e ypos dentro il movieclip _root.dragger (/dragger nella notazione del Flash4), assegnando come valori rispettivamente la posizione del layer sull'asse delle X e sull'asse delle Y.
.writeToLayer
Browser.prototype.writeToLayer = function(id, obj)
{
if (this.N4) {
document.layers[id].document.close();
document.layers[id].document.write(obj);
document.layers[id].document.close();
} else {
if (this.IE) {
eval("document.all." + id + ".innerHTML='" + obj + "'");
} else {
document.getElementById(id).innerHTML = obj;
}
}
};
Al metodo vengono passati due parametri, id e obj
: il primo è l'identificativo del layer nel quale scrivere (dove), il secondo è il contenuto (cosa). Anche in questo caso, vengono valutate le tre proprietà iniziali per stabilire in quale modo scrivere nel layer.
.init
function init(){
objSWF = '[codice html del filmato]';
objGIF = '<img src="image.gif" width="200" height="200" alt="">';
bw = new Browser();
bw.writeToLayer('dragged', objSWF);
tempo = setInterval("bw.moveLayer('dragged')", 20)
}
init() non è un metodo della classe Browser, ma una comune funzione procedurale. Viene invocata dal filmato stesso al termine del suo caricamento, e serve ad inizializzare il processo di identificazione e spostamento del layer.
Alla sua chiamata, viene settato come valore delle variabili objSWF (omessa per ragioni di spazio) e objGIF
una stringa contenente rispettivamente il codice di incorporamento di un filmato e di una immagine gif ( verranno utilizzate come contenuto del layer da spostare ).
Viene quindi creata un'istanza della Classe Browser, chiamata bw
: all'istanza, viene applicato il metodo writeToLayer che scrive il codice del filmato nel layer dragged
( quello inizialmente vuoto ).
Infine, viene settato un intervallo di 20 millisecondi per l'esecuzione ciclica del metodo moveLayer, applicato sempre all'istanza bw e relativo al layer dragged.
Proviamo a vedere cosa accade ad ogni ciclo in relazione all'istanza bw:
• viene chiamato il metodo moveLayer per spostare il layer dragged
• il metodo moveLayer:
• recupera la posizione del layer chiamando getLayerXpos e getLayerYpos
• recupera il valore dello spostamento dal filmato
• passa questi valori al metodo setLayerPos
• chiama il metodo sendLayerPos
• il metodo setLayerPos sposta il layer alle coordinate indicate
• il metodo sendLayerPos passa al filmato la posizione del layer
• il ciclo ricomincia dopo 20 millisecondi
IL FILMATO FLASH
• richiama la funzione init() per l'inizalizzazione
• passa alla pagina html i valori dello spostamento del layer sui due assi
• riceve dalla pagina html i valori della nuova posizione del layer
Nella timeline principale del filmato abbiamo due pulsanti, che richiamano il metodo writeToLayer
. Al metodo vengono passati due parametri: il primo indica il layer sul quale operare, il secondo il nuovo contenuto ( nel caso, la variabile objGIF od objSWF ).
Lo script associato:
on(release){
getURL("javascript:bw.writeToLayer('dragged', objGIF)");
}
on(release){
getURL("javascript:bw.writeToLayer('dragged', objSWF)");
}
Sono inoltre presenti quattro campi di testo dinamici, associati alle variabili xpos, ypos, xmov e ymov: serviranno a mostrarci la posizione del layer, e la sua velocità di spostamento in orizzontale e verticale.
Infine, oltre ad alcuni movieclip con esclusive funzioni grafiche, è presente il movieclip dragger
( il più piccolo cerchietto sfumato, in basso a destra in figura ):
Dentro il movieclip c'è un pulsante, con associato il seguente script:
on(press){
this.dragged = true;
}
on(release){
this.dragged = false;
}
on(releaseOutside){
this.dragged = false;
}
Alla pressione sul pulsante, la variabile dragged
diventa vera, al rilascio diventa falsa.
Al movieclip è invece associato:
onClipEvent(load){
this.rag = this._parent.base._width / 2 - 20;
this.xct = this._parent.base._x;
this.yct = this._parent.base._y;
function rotate(){
var compx = _root._xmouse - this.xct;
var compy = _root._ymouse - this.yct;
var ang = Math.atan2(compy, compx);
this._x = Math.cos(ang) * this.rag + this.xct;
this._y = Math.sin(ang) * this.rag + this.yct;
this.xmov = compx / 10;
this.ymov = compy / 10;
}
function showInfo(){
this._parent.xpos = parseInt(this.xpos);
this._parent.ypos = parseInt(this.ypos);
this._parent.xmov = Math.round(this.xmov);
this._parent.ymov = Math.round(this.ymov);
}
getURL("javascript:init()");
}
onClipEvent(enterFrame){
if(this.dragged){
this.rotate();
} else {
this.xmov = this.ymov = 0;
}
this.showInfo();
}
Al caricamento del movieclip, vengono definite tre variabili per il trascinamento in circolo (rag
, il raggio, xct
, la coordinata x del centro, yct
, la coordinata y del centro ), quindi due funzioni:
• rotate
- gestisce la rotazione del movieclip e trova i valori xcomp e ycomp che serviranno a determinare lo spostamento del layer sull'asse delle X e sull'asse delle Y
• showInfo
- passa 4 valori ai campi di testo sulla timeline principale
e infine viene richiamata la funzione Javascript init()
.
Ad ogni riproduzione del movieclip (enterFrame), se il pulsante è stato premuto, e quindi il movieclip viene trascinato, viene richiamata la funzione rotate
(), altrimenti a xmov
e ymov
viene assegnato 0 come valore: poi viene richiamata la funzione showInfo
().
Quando, tramite la funzione rotate(), abbiamo trovato xcomp e ycomp, li dividiamo per 10, e li assegniamo alle variabili xmov e ymov. Queste due variabili sono quelle che vengono recuperate dalla funzione Javascript moveLayer()
, e utilizzate per spostare il layer html.
Dal momento che la funzione moveLayer viene richiamata ciclicamente, quando non trasciniamo il movieclip ne azzeriamo il valore, in modo che il layer si fermi.
La funzione showInfo
copia questi valori, assieme ad xpos e ypos (passati al filmato dalla funzione sendLayerPos()
), sulla _root, in modo che appaiano nei campi di testo.
// al caricamento del movieclip
onClipEvent(load){
// definiamo il raggio in cui deve ruotare il movieclip
this.rag = this._parent.base._width / 2 - 20;
// stabiliamo le coordinate del centro del cerchio
this.xct = this._parent.base._x;
this.yct = this._parent.base._y;
// definiamo la funzione rotate
function rotate(){
// troviamo il valore di compx e compy in base alla
// posizione del mouse rispetto al centro del cerchio
var compx = _root._xmouse - this.xct;
var compy = _root._ymouse - this.yct;
// tramite xcompe ycomp determiniamo l'ampiezza
// del'angolo ang
var ang = Math.atan2(compy, compx);
// in base a quest'angolo, al raggio del cerchio ed al
// suo centro, posizioniamo il movieclip
this._x = Math.cos(ang) * this.rag + this.xct;
this._y = Math.sin(ang) * this.rag + this.yct;
// assegniamo alle variabili xmov e ymov il valore
// di xcomp e ycomp fratto 10
// i valori vengono recuperati dalla pagina html
// per spostare il layer
this.xmov = compx / 10;
this.ymov = compy / 10;
}
// definiamo la funzione showInfo
function showInfo(){
// assegniamo alle variabili xpos, ypos, xmov e ymov
// sulla timeline principale il valore intero delle
// variabili corrispondenti nel movieclip
this._parent.xpos = parseInt(this.xpos);
this._parent.ypos = parseInt(this.ypos);
this._parent.xmov = Math.round(this.xmov);
this._parent.ymov = Math.round(this.ymov);
}
// chiamiamo la funzione Javascript init per l'inizializzazione
getURL("javascript:init()");
}
// ad ogni riproduzione del movieclip
onClipEvent(enterFrame){
// se la variabile dragged è vera
if(this.dragged){
// invochiamo la funzione rotate
this.rotate();
// altrimenti
} else {
// azzeriamo il valore di xmov e ymov
this.xmov = this.ymov = 0;
}
// richiamiamo la funzione showInfo
this.showInfo();
}