Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Quelques classes utiles

Compatible ActionScript 2. Cliquer pour en savoir plus sur les compatibilités.

Ce mini tutorial vous présente quelques class qui vous seront trés utile dans vos travaux.

mx.utils.Delegate

La class mx.utils.Delegate vous permet de palier au probleme de scopage, problème courant dans certaines fonctions asynchrones :

class MaClass 
{
	private var _sText : String;
	public function MaClass (sURL : String)
	{
		var oLv : LoadVars = new LoadVars ();
		oLv.onData = function (s : String) : Void 
		{
			// Ceci ne fonctionnera pas:
			// MaClass._sText ne sera pas affécté par s
			// car _sText ne peut sortir du scope de oLv
			_sText = s;
		};
		oLv.load (sURL);
	}
}

Ainsi, pour résoudre cette difficulté, il suffit d'utiliser mx.utils.Delegate :

class MaClass 
{
	private var _sText : String;
	public function MaClass (sURL : String)
	{
		var oLv : LoadVars = new LoadVars ();
		oLv.onData = mx.utils.Delegate.create(this, setText);
		oLv.load (sURL);
 
	}
	private function setText(sText:String):Void {
		_sText = sText;
	}
}

Le seul défaut de cette class, c'est le fait de ne pouvoir faire passer qu'un seul argument à la fois dans la fonction appelée, ce qui peut parfois se réveler problématique, la seule méthode de contournement c'est l'utilisation de arguments.caller pour faire passer d'autres informations :

class MaClass 
{
	private var _sText : String;
	public function MaClass (sURL : String)
	{
		var oLv : LoadVars = new LoadVars ();
		var fCustomDelegate : Function = mx.utils.Delegate.create (this, setText);
		fCustomDelegate._bChargement = true;
		oLv.onData = fCustomDelegate;
		oLv.load (sURL);
	}
	private function setText (sText : String) : Void 
	{
		_sText = sText;
		trace ("Chargement : "+arguments.caller._bChargement);
	}
}

Le problème étant que parfois la fonction a appeler doit faire passer plusieurs arguments, nous allons donc voir comment faire cela avec la class Proxy, mais tout d'abord, voici le code de la class mx.utils.Delegate :

//****************************************************************************
//Copyright (C) 2003-2004 Macromedia, Inc. All Rights Reserved.
//The following is Sample Code and is subject to all restrictions on
//such code as contained in the End User License Agreement accompanying
//this product.
//****************************************************************************
 
/**
The Delegate class creates a function wrapper to let you run a function in the context
of the original object, rather than in the context of the second object, when you pass a
function from one object to another.
*/
 
class mx.utils.Delegate extends Object
{
	/**
	Creates a functions wrapper for the original function so that it runs 
	in the provided context.
	@parameter obj Context in which to run the function.
	@paramater func Function to run.
	*/
	static function create(obj:Object, func:Function):Function
	{
		var f = function()
		{
			var target = arguments.callee.target;
			var func = arguments.callee.func;
 
			return func.apply(target, arguments);
		};
 
		f.target = obj;
		f.func = func;
 
		return f;
	}
 
	function Delegate(f:Function)
	{
		func = f;
	}
 
	private var func:Function;
 
	function createDelegate(obj:Object):Function
	{
		return create(obj, func);
	}
}

ascb.utils.Proxy

Cette classe permet de palier aux défauts de mx.utils.Delegate, on peut ainsi envoyer plusieurs arguments à la fois :

class MaClass 
{
	private var _sText : String;
	public function MaClass (sURL : String)
	{
		var oLv : LoadVars = new LoadVars ();
		oLv.onData = ascb.utils.Proxy.create(this, setText, true);
		oLv.load (sURL);
	}
	private function setText (sText : String, b : Boolean) : Void 
	{
		_sText = sText;
		trace (b);
	}
}

Voici la class ascb.util.Proxy

class ascb.util.Proxy 
{
	public static function create (oTarget : Object, fFunction : Function) : Function 
	{
		// Create an array of the extra parameters passed to the method. Loop
		// through every element of the arguments array starting with index 2,
		// and add the element to the aParameters array.
		var aParameters : Array = new Array ();
		for (var i : Number = 2; i < arguments.length; i ++)
		{
			aParameters [i - 2] = arguments [i];
		}
		// Create a new function that will be the proxy function.
		var fProxy : Function = function () : Void 
		{
			// The actual parameters to pass along to the method called by proxy
			// should be a concatenation of the arguments array of this function
			// and the aParameters array.
			var aActualParameters : Array = arguments.concat (aParameters);
			// When the proxy function is called, use the apply( ) method to call
			// the method that is supposed to get called by proxy. The apply( )
			// method allows you to specify a different scope (oTarget) and pass
			// the parameters as an array.
			fFunction.apply (oTarget, aActualParameters);
		};
		// Return the proxy function.
		return fProxy;
	}
}

mx.events.EventDispatcher

L'interet de cette classe c'est de pouvoir s'affranchir complement des problèmes de scopage pour l'appel de méthode lors d'un événement donné.

Voici une classe pas trés utile, qui donne des informations supplémentaires lors du chargement d'un fichier, elle va nous permettre de voir ces problémes de scopage, et la manière dont les méthodes sont appelées avec EventDispatcher :

import mx.events.EventDispatcher;
class PreLoader
{
	private var _oMcLoader : MovieClipLoader;
	private var _oMcLoaderEcoute : Object;
	private var _mcCible : MovieClip;
	private var _sSource : String;
	private var _init : Object;
	//
	private var _nStart : Number;
	private var _nEnd : Number;
	private var _nDebit : Number;
	private var _nPourcent : Number;
	private var _nLoaded : Number;
	private var _nTotal : Number;
	private var _nMin : Number;
	private var _nSec : Number;
	private var _sErreur : String;
	// déclaration de méthodes pour EventDispatcher
	private var dispatchEvent : Function;
	private var addEventListener : Function;
	private var removeEventListener : Function;
	// Constructeur
	public function PreLoader (mc : MovieClip, s : String, o : Object)
	{
		_mcCible = mc;
		_sSource = s;
		_init = o;
		// initialisation de EventDispatcher pour cette occurence de PreLoader
		EventDispatcher.initialize (this);
		// préparation des événements
		addEventListener ("onLoadComplete", this);
		addEventListener ("onLoadError", this);
		addEventListener ("onLoadInit", this);
		addEventListener ("onLoadProgress", this);
		addEventListener ("onLoadStart", this);
		_load ();
	}
	private function _load ()
	{
		_oMcLoader = new MovieClipLoader ();
		_oMcLoaderEcoute = new Object ();
		// on donne une reference à PreLoader, pour pouvoir cibler correctement les variables de PreLoader
		_oMcLoaderEcoute.path = this;
		_oMcLoaderEcoute.onLoadStart = function (mc : MovieClip)
		{
			var p = this.path;
			p._nLoaded = 0;
			p._nEnd =0;
			p._nTotal = 0;
			p._nPourcent = 0;
			p._nDebit = 0;
			p._nMin = 0;
			p._nSec = 0;
			p._sErreur = "";
			p._nStart = int (getTimer () / 1000);
			// on lance un événement
			this.path.dispatchEvent ( 
			{
				type : "onLoadStart", target : this.path
			});
			// initialisation des variables
 
		}
		_oMcLoaderEcoute.onLoadProgress = function (mc : MovieClip, nLoad : Number, nTotal : Number)
		{
			var p = this.path;
			p._nLoaded = nLoad;
			p._nTotal = nTotal;
			// calcul du pourcentage
			p._nPourcent = Math.round (p._nLoaded / p._nTotal * 100);
			// calcul du débit
			var nTime : Number = getTimer () / 1000;
			var nBps : Number = nLoad / nTime;
			p._nDebit = Math.round (nBps / 1024 );
			// calcul du temps restants
			var nTempsRestant = Math.ceil (Number (nTotal - nLoad) / nBps);
			p._nMin = Math.floor (nTempsRestant / 60);
			if (p._nMin >= 1)
			{
				nTempsRestant -= Math.floor (p._nMin * 60);
			} else
			{
				p._nMin = 0;
			}
			p._nSec = nTempsRestant;
			// on lance un événement
			this.path.dispatchEvent ( 
			{
				type : "onLoadProgress", target : this.path
			});
		}
		_oMcLoaderEcoute.onLoadComplete = function (mc : MovieClip)
		{
			// on lance un événement
			this.path.dispatchEvent ( 
			{
				type : "onLoadComplete", target : this.path
			});
		}
		_oMcLoaderEcoute.onLoadError = function (mc : MovieClip, s : String)
		{
			this.path._sErreur = s;
			// on lance un événement
			this.path.dispatchEvent ( 
			{
				type : "onLoadError", target : this.path
			});
		}
		_oMcLoaderEcoute.onLoadInit = function (mc : MovieClip)
		{
			this.path._nEnd = int (getTimer () / 1000);
			// on assigne les proprietes de l'objet init au mc
			for (var i in this.path._init)
			{
				mc [i] = this.path._init [i];
			}	
			// on lance un événement
			this.path.dispatchEvent ( 
			{
				type : "onLoadInit", target : this.path
			});
		}
		_oMcLoader.addListener (_oMcLoaderEcoute);
		_oMcLoader.loadClip (_sSource, _mcCible);
	}
	// getter
	public function get cible () : MovieClip
	{
		return _mcCible;
	}
	public function get source () : String
	{
		return _sSource;
	}
	public function get init () : Object
	{
		return _init;
	}
	public function get start () : Number
	{
		return _nStart;
	}
 
	public function get debit () : Number
	{
		return _nDebit;
	}
	public function get pourcent () : Number
	{
		return _nPourcent;
	}
	public function get loaded () : Number
	{
		return _nLoaded;
	}
	public function get total () : Number
	{
		return _nTotal;
	}
	public function get minute () : Number
	{
		return _nMin;
	}
	public function get seconde () : Number
	{
		return _nSec;
	}
	public function get minTotal () : Number
	{
 
		var n : Number = Math.floor (_nEnd - _nStart);
		var nMin : Number = Math.floor (n / 60)
		return nMin;
 
	}
	public function get secTotal () : Number
	{
		var n : Number = _nEnd - _nStart;
		var nMin : Number = Math.floor (n / 60);
		if (nMin>1)
		{
			n -= Math.floor (nMin * 60);
		}
		return n;
	}
	public function get erreur () : String
	{
		return _sErreur;
	}
	// déclaration des méthodes pour EventDispatcher
	public function onLoadStart () : Void
	{
	}
	public function onLoadComplete () : Void
	{
	}
	public function onLoadProgress () : Void
	{
	}
	public function onLoadError () : Void
	{
	}
	public function onLoadInit () : Void
	{
	}
}

Usage :

import PreLoader;
this.createEmptyMovieClip("mc", 1);
this.createTextField("tx", 2, 0, 0, 250, 250);
var o:PreLoader = new PreLoader(this.mc, "http://niko.informatif.org/fichiers/IMG_0032.jpg?"+Math.random(), {_alpha:50});
o.onLoadStart = function() {
	trace("Chargement de "+this.source+" sur le clip "+this.cible);
};
o.onLoadComplete = function() {
	_root.tx.text = "";
};
o.onLoadProgress = function() {
	if (this.pourcent>0) {
		var path = _root.tx;
		path.text = Math.round(this.loaded/1024)+"/"+Math.round(this.total/1024)+" Ko > "+this.pourcent+" %";
		path.text += "\nDebit : "+this.debit+" Ko/s";
		path.text += "\nTemps restant : ";
		if (this.minute<10) {
			path.text += "0";
		}
		path.text += this.minute+":";
		if (this.seconde<10) {
			path.text += "0";
		}
		path.text += this.seconde;
	}
};
o.onLoadError = function() {
	_root.tx.text = "Erreur de chargement : \n"+this.erreur;
};
o.onLoadInit = function() {
	_root.tx.text = "Chargement éfféctué en : \n";
	_root.tx.text += this.minTotal+" minute(s) et ";
	_root.tx.text += this.secTotal+" seconde(s)";
};

GDispatcher

à faire

voir GSkinner