Lundi 15 novembre 2010
1
15
/11
/Nov
/2010
22:44
J'ai récemment posté sur Mediabox une galerie tout à fait standard
mais qui j'éspère pourra servir à certain. Je détaille ci-dessous quelques classes qui la composent et bien évidement je mets à disposition les sources. Voici le résultat final: exemple
Afin que le projet semble claire, voici son arborescence. A la
racine, (i.e. dans le fichier CLASS FxTilesInfinity), nous trouve le fichier wall.swf autour duquel s'organisent différents dossiers.
Dans le dossier xml nous trouvons le fichier wall3D.xml qui répertorie les chemins d'accès aux différentes images qui composeront la galerie. Chaque noeud contient deux adresses, l'une pour la
miniature de l'image et l'autre pour l'image dans sa taille originelle.
Le dossier gal contient deux sous dossiers, thumbs et tiles, qui sont destinés à contenir respectivement les miniatures et images non modifiées.
Le dossier fx contient l'ensemble des classes nécessaires. Elles sont réparties en deux packages. Le package de Grant Skinner qui sert pour les Tweens et le package bidesign qui sert pour la
galerie.
Le dossier control contient la classe FxTilesInfinity donc le constructeur admet deux paramètres, l'url du xml fournissant la liste des adresses des images et le nombre de lignes sur lesquels les
miniatures sont à répartir. Cela peu permettre, par exemple, d'adapter la hauteur de la galerie en fonction de la taille de l'écran client.
Voici le contenu de la classe document qui montre comment instancier un objet FxTilesInfinity.
package fx.bidesign.document
{
import fx.bidesign.utils.FxStats;
import fx.bidesign.desktop.FxSuperStage;
import fx.bidesign.controls.FxTilesInfinity;
public class Document extends FxSuperStage
{
public function Document()
{
var line:int = Math.floor( FxSuperStage.STAGE.stageHeight / 300 );
var wall:FxTilesInfinity;
wall = new FxTilesInfinity( "xml/wall3D.xml", line );
addChild( wall );
}
}
}
La classe FxTilesInfinity n'est pas spécialement compliquée et peut être améliorée pour intégrer de la 3D. Néanmoins, le contrôle des ressources utilisées devient plus compiqué dans ce cas.
package fx.bidesign.controls
{
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.geom.Point;
import flash.geom.PerspectiveProjection;
import fl.transitions.easing.*;
import fl.motion.easing.Exponential;
import fx.gskinner.motion.GTween;
import fx.bidesign.controls.FxTile;
import fx.bidesign.controls.FxTileDisplay;
import fx.bidesign.events.FxTileEvent;
import fx.bidesign.desktop.FxSuperStage;
public class FxTilesInfinity extends Sprite
{
private var tile:FxTile;
private var screen:FxTileDisplay;
//
private var end:int;
private var tileMax:int;
private var celerity:int;
private var rows:int;
private var spread:Number;
private var tileW:Number;
private var tileH:Number;
private var filter:Boolean;
private var reflect:Boolean;
private var smoothing:Boolean;
private var dimension:Boolean;
private var zoom:Number;
private var zoomMax:Number;
private var zoomMin:Number;
//
private var offset:Number;
private var allowMove:Boolean;
//
private var xml:XML;
private var list:XMLList;
private var loader:URLLoader;
//
private var url:String;
public function FxTilesInfinity( pUrl:String, pRows:int = 3 )
{
url = pUrl;
rows = pRows;
//
FxSuperStage.STAGE.align = StageAlign.TOP_LEFT;
FxSuperStage.STAGE.scaleMode = StageScaleMode.NO_SCALE;
//
open();
}
private function open():void
{
//
loader = new URLLoader( new URLRequest( url ) );
loader.addEventListener( Event.COMPLETE, complete );
}
private function params():void
{
/*
/
/ Let you modify params
/
*/
//rows = 3;
spread = 10;
celerity = 3500;
end = list.length();
tileW = 200;
tileH = 200;
filter = true;
reflect = true;
smoothing = true;
dimension = false;
zoom = 0;
zoomMax = -500;
zoomMin = 1500;
/*
/
/ end params
/
*/
//
draw();
}
private function draw():void
{
//
tileMax = Math.ceil( ( FxSuperStage.STAGE.stageWidth ) / ( tileW + spread ) ) * rows;
for( var i:int = 0; i < tileMax; i++ )
{
tile = new FxTile( i, rows, tileW, tileH, spread, list[i].@src, list[i].@url, filter, reflect, smoothing );
tile.addEventListener( FxTileEvent.LEFT, outByLeft );
tile.addEventListener( FxTileEvent.RIGHT, outByRight );
addChild( tile );
}
//
this.transform.perspectiveProjection = new PerspectiveProjection();
this.transform.perspectiveProjection.projectionCenter = new Point ( this.width / 2, this.height / 2 );
//
move();
}
private function drawNow( index:int ):void
{
tile = new FxTile( index, rows, tileW, tileH, spread, list[index].@src, list[index].@url, filter, reflect, smoothing );
tile.addEventListener( FxTileEvent.LEFT, outByLeft );
tile.addEventListener( FxTileEvent.RIGHT, outByRight );
addChild( tile );
}
private function move():void
{
this.allowMove = true;
this.doubleClickEnabled = true;
this.addEventListener( Event.REMOVED_FROM_STAGE, removeAll );
FxSuperStage.STAGE.addEventListener( MouseEvent.DOUBLE_CLICK, click );
FxSuperStage.STAGE.addEventListener( MouseEvent.MOUSE_DOWN, mouseDown );
}
/*
/
/ Event
/
*/
private function removeAll( pEvt:Event ):void
{
for( var j:int = 0; j < numChildren - 1; j++ )
{
( getChildAt( j ) as FxTile ).removeAll();
}
}
private function complete( pEvt:Event ):void
{
//
xml = new XML( pEvt.target.data );
list = xml.item;
//
params();
//
loader.removeEventListener( Event.COMPLETE, complete );
}
private function outByLeft( pEvt:FxTileEvent ):void
{
//
drawNow( pEvt.id + tileMax );
//
pEvt.target.removeEventListener( FxTileEvent.LEFT, outByLeft );
pEvt.target.removeEventListener( FxTileEvent.RIGHT, outByRight );
pEvt.target.removeAll();
}
private function outByRight( pEvt:FxTileEvent ):void
{
//
drawNow( pEvt.id - tileMax );
//
pEvt.target.removeEventListener( FxTileEvent.LEFT, outByLeft );
pEvt.target.removeEventListener( FxTileEvent.RIGHT, outByRight );
pEvt.target.removeAll();
}
private function click( pEvt:MouseEvent ):void
{
if( pEvt.target is FxTile && allowMove )
{
allowMove = !allowMove;
//
screen = new FxTileDisplay( pEvt.target.source, FxSuperStage.STAGE.stageWidth, FxSuperStage.STAGE.stageHeight, false,
false, true );
addChild( screen );
addEventListener( MouseEvent.CLICK, click );
}
else
{
allowMove = !allowMove;
//
removeChild( screen );
removeEventListener( MouseEvent.CLICK, click );
}
}
private function mouseDown( pEvt:MouseEvent ):void
{
offset = mouseX;
if( allowMove ) FxSuperStage.STAGE.addEventListener( MouseEvent.MOUSE_UP, mouseUp );
if( allowMove ) FxSuperStage.STAGE.addEventListener( MouseEvent.MOUSE_MOVE, mouseMove );
}
private function mouseUp( pEvt:MouseEvent ):void
{
//
FxSuperStage.STAGE.removeEventListener( MouseEvent.MOUSE_UP, mouseUp );
FxSuperStage.STAGE.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMove );
//
if( dimension ) var rotateY:GTween = new GTween( this, 5, { rotationY: 0 },{ ease:Exponential.easeOut } );
}
private function mouseMove( pEvt:MouseEvent ):void
{
//
var speed:Number = ( mouseX - offset ) / FxSuperStage.STAGE.stageWidth;
/*if( speed < 0 ) speed = ( speed > - 0.7 ) ? speed : - 0.7;
else speed = ( speed < 0.7 ) ? speed : 0.7;*/
var moveX:GTween = new GTween( this, 5, { x: this.x + ( speed * celerity ) },{ ease:Exponential.easeOut } );
moveX.addEventListener( Event.INIT, check );
//
if( dimension ) var rotateY:GTween = new GTween( this, 1, { rotationY: this.rotationY + ( speed * 10 ) },{ ease:Elastic.easeOut } );
pEvt.updateAfterEvent();
}
private function check( pEvt:Event ):void
{
var pos:Number = ( end - tileMax ) * ( tileW + spread ) / 3;
if( pEvt.target.getProperty( "x" ) > - 10 ) pEvt.target.setProperty( "x", 10 );
else if( pEvt.target.getProperty( "x" ) < - pos ) pEvt.target.setProperty( "x", - pos );
pEvt.target.removeEventListener( Event.INIT, check );
}
}
}
Les paramètres utiles à la gestions de la galerie sont regroupés dans la fonction params() et sont essentiellement les à la vitesse de défilement (celerity), l'écart entre les miniatures
(spread), la dimension des miniatures (tileW et tileH) et le rendu. Du rendu, va dépendre la fluidité de l'animation. Ainsi, si chaque miniature est lissée (smoothing), encadré (filter) et
embarque un effet de reflet (reflect) l'animation pourra ne pas être fluide sur tout les postes clients.
Télécharger les sources