La Brigade des Tuts :beta

Flash, ActionScript 3.0

Introduction

Ce tuto vous explique comment créer une barre de défilement verticale en ActionScript 3.0.

Barre de défilement destinée à n'importe quel contenu Flash (MovieClip, TextField, composants).

Difficulté : Moyen.

Dernière modification : 24 Janvier 2009.

Sommaire

  1. Préparation de la classe

  2. Création des éléments graphiques

  3. Dimensionnement

  4. Positionnement

  5. Evénement « drag and drop »

  6. Evénement de la mollette

1. Préparation de la classe

L'objectif est de créer une classe entièrement autonome (sans fichier *.fla) capable de s'intégrer dans n'importe quel projet Flash.

Nommons cette classe : « maScrollbar ».

Toute classe qui se confond se trouve dans un fichier qui porte le même nom qu'elle et qui a pour extension .as (pour document ActionScript).

Ainsi, notre classe doit se trouver dans un document ActionScript nommé « maScrollbar.as ».

Voici notre document initial comportant les bases de la classe « maScrollbar » :


package

{

import flash.display.Sprite;

public class maScrollbar extends Sprite

{

     public function maScrollbar ()

     {

// Je suis initialisée !

     };

}

}

 

Notre classe va nécessiter deux paramètres pour fonctionner correctement.

D'abord une hauteur maximale « maxHeight », permettant de définir la hauteur de la zone sur laquelle le contenu défilera.

Ensuite une cible « target », définissant quel est le contenu qui doit défiler verticalement.

Pour créer des paramètres dans une classe, on utilise de simples variables. Elles sont déclarées « publiquement » pour pouvoir être modifié « de l'extérieur » à la manière des coordonnées X et Y pour un clip.

La déclaration publique des variables « maxHeight » et « target » :

 

package

{

import flash.display.Sprite;

public class maScrollbar extends Sprite

{

public var target:Sprite;

public var maxHeight:Number;

 

    public function maScrollbar ()

    {

// Je suis initialisée !

};

}

}

 

Ultérieurement et pour utiliser la classe « maScrollbar », vous procéderez ainsi :

 

/// Import du fichier « maScrollbar.as »

/// Ne pas mettre l'extension .as !

 

    import maScrollbar;

 

/// Création d'une scrollbar dans un conteneur Sprite

/// Nommons-la « barre_de_defilement »

 

var barre_de_defilement:maScrollbar = new maScrollbar();

 

/// Définition coordonnées « x » et « y » et des paramètres

/// « maxHeight », hauteur à 500 pixels, et « target », un clip de la scène

 

    barre_de_defilement.x = 500;

    barre_de_defilement.y = 20;

    barre_de_defilement.maxHeight = 500;

    barre_de_defilement.target = nom_du_movieclip;

2. Création des éléments graphiques

Voyons à présent comment créer les éléments graphiques de notre barre de défilement.

Une barre de défilement basique est constituée de deux éléments : Un fond avec une hauteur fixe et un bouton de contrôle permettant de faire défiler le contenu. Le bouton change de hauteur en fonction de la hauteur du contenu à faire défiler. Nommons ces éléments « BACKGROUND » pour le fond et « HANDLER » pour le bouton de contrôle. 

Ces éléments doivent être de type « Sprite » afin de contenir des objets graphiques. Objets qui seront générés en ActionScript dans une nouvelle fonction, que nous nommerons « init() ».

Déclaration et création de ces éléments par une nouvelle fonction « init() » :

 

package

{

import flash.display.Sprite;

 

public class maScrollbar extends Sprite

{

 

public var target:Sprite;

public var maxHeight:Number;

private var BACKGROUND:Sprite;

private var HANDLER:Sprite;

 

    public function maScrollbar ()

    { ... };

 

public function init():void

{

    BACKGROUND = new Sprite();

    BACKGROUND.graphics.beginFill( 0x999999, 1 );

    BACKGROUND.graphics.drawRect( 0, 0, 20, 20 );

    BACKGROUND.graphics.endFill();

    addChild( BACKGROUND );

 

    HANDLER = new Sprite();

    HANDLER.graphics.beginFill( 0x444444, 1 );

    HANDLER.graphics.drawRect( 0, 0, 20, 20 );

    HANDLER.graphics.endFill();

    addChild( HANDLER );

};

}

}

3. Dimensionnement

La hauteur du bouton de contrôle peut se calculer en fonction de la hauteur de la cible et du paramètre « maxHeight ». Analysons la situation :

Alternative content

Get Adobe Flash player

Nous pouvons en tirer le tableau suivant et appliquer la règle de trois :

 


A l’échelle de la cible :
A l’échelle de la scrollbar :
BACKGROUND.height
target.height
maxHeight
HANDLER.height
maxHeight
?

HANDLER.height = maxHeight * maxHeight / target.height;

 

Imaginons une fonction « render() » qui appliquerait ce dimensionnement. Décidons égalemment de l'appeller dans la fonction « init() » pour afficher les éléments correctement dès le départ :

 

package

{

import flash.display.Sprite;

 

public class maScrollbar extends Sprite

{

 

public var target:Sprite;

public var maxHeight:Number;

private var BACKGROUND:Sprite;

private var HANDLER:Sprite;

 

    public function maScrollbar ()

    { ... };

 

public function init():void

{ ...

 

render( 0 );

};

 

public function render():void

{

 

    BACKGROUND.height = maxHeight;

    HANDLER.height = maxHeight * maxHeight / target.height;

 

 

};

 

}

}

4. Positionnement

Voyons comment positionner les éléments aux bons endroits. Comme vous le voyez dans l'animation précédente, ce sont les positions du « HANDLER » et de la cible « target » qui évoluent.

Généralement, elles sont identiques au départ. Après, c'est à nous de gérer les actions du visiteurs sur le bouton de contrôle. 

Imaginons une fonction qui s'exécuterait à chaque action du visiteur et qui aurait pour paramètre le déplacement demandé en pixels. Et pourquoi pas la fonction « render() » ?

Ajoutons le paramètre « delta » à la fonction « render() ». Ce paramètre étant destiné à contenir un nombre positif ou négatif, du fait des deux directions « vers le haut » et « vers le bas ». 

Il nous faut au préalable vérifier avec « if » si la valeur « delta » n'est pas trop grande positivement et négativement, pour éviter les bugs d'affichage.

La fonction « render() », dimensionnant et positionnant les éléments :

 

package

{

import flash.display.Sprite;

 

public class maScrollbar extends Sprite

{

 

public var target:Sprite;

public var maxHeight:Number;

private var BACKGROUND:Sprite;

private var HANDLER:Sprite;

 

    public function maScrollbar ()

    { ... };

 

public function init():void

{ ... };

 

public function render( delta:int ):void

{

 

    BACKGROUND.height = maxHeight;

    HANDLER.height = maxHeight * maxHeight / target.height;

 

    if( (HANDLER.y + delta) < 0 )

{

        delta = -HANDLER.y;

    }

    if( (HANDLER.y + delta) > (maxHeight - HANDLER.height) )

{

        delta = (maxHeight - HANDLER.height) - HANDLER.y;

    }

 

    HANDLER.y = HANDLER.y + delta;

    target.y = this.y -((HANDLER.y * (target.height -maxHeight) / (maxHeight -HANDLER.height)));

 

};

 

}

}

5. Evénement « drag and drop »

Il est temps de s'attaquer aux événements. Commençons par le « glisser / déposer », s'appliquant au bouton de contrôle, l'élément « HANDLER ».

Un « glisser / déposer » démarre au moment où le visiteur commence à cliquer sur le bouton de la souris (événement « MOUSE_DOWN ») et termine au moment où il relâche le bouton (événement « MOUSE_UP »). Entre-temps, le visiteur effectue des déplacement vers le haut ou vers le bas (événement « MOUSE_MOVE »).

Il nous faut donc un moyen de capturer au mieux ces trois événements. Observons l'action dans le temps :

A noter qu'à l'instant « t1 », le visiteur commence à enfoncer le bouton gauche de la souris. Observons que le curseur quitte la zone du « HANDLER » en rouge à l'instant « t3 ». Et qu'à l'instant « t5 », le curseur sort carrément de la scène voire de la fenêtre du navigateur !

Il nous sera difficile de suivre le curseur en écoutant uniquement les événements du « HANDLER ». Comparons alors ces événements avec ceux de la scène « stage » (fond blanc) :

 

Instant
Description
Événements sur HANDLER
Événements sur stage
t0
Le curseur s’approche au dessus du HANDLER
MOUSE_MOVE
ROLL_OVER
MOUSE_MOVE
t1
Le curseur démarre un clic
MOUSE_DOWN
MOUSE_MOVE
t2
Le curseur se déplace au dessus du HANDLER
MOUSE_MOVE
MOUSE_MOVE
t3
Le curseur sort de la zone du HANDLER
ROLL_OUT
MOUSE_MOVE
t4
Le curseur se déplace au dessus de la scène
?
MOUSE_MOVE
t5
Le curseur sort de la scène, voire du navigateur
?
MOUSE_LEAVE
t(n)
Le curseur relâche enfin le clic
?
MOUSE_UP

 

Il serait alors plus judicieux, d'après ce tableau, de suivre le curseur au niveau de la scène plutôt qu'à partir du bouton de contrôle, car cela nous permettrait de le suivre plus longtemps.

Voici donc les événements qui vont nous intéresser, avec leur type de classe :

  • MouseEvent . MOUSE_DOWN sur l'élément « HANDLER »
  • MouseEvent . MOUSE_MOVE sur l'élément « stage »
  • MouseEvent . MOUSE_UP sur l'élément « stage »
  • Event . MOUSE_LEAVE sur l'élément « stage »

Et pour faire encore mieux, nous allons déclarer ces événements intélligement.

Puisque les trois derniers événements listés ne sont utiles qu'après la survenance du premier, nous pouvons alors dire à ce premier de déclarer lui-même les autres.

Pendant l'événement « MOUSE_MOVE », il va nous falloir calculer « delta » et appeler la fonction « render() » (pour effectuer un re-positionnement des éléments).

Remarquons sur le schéma précédent que « delta » peut se calculer à partir d'un simple calcul de différence :

 

delta = (Coordonnée « y » actuelle) MOINS (Coordonnée « y » à l'instant précédent)

 

Pour connaître la position du curseur à l'instant précédent, il nous suffit de l'enregistrer dans une variable. Déclarons alors une nouvelle variable « VAR_stageY » au début de notre classe.

« stageY » est le nom d'une propriété de l'événement « MOUSE_MOVE » qui indique la position du curseur sur l'axe des coordonnées (l'axe vertical).

Ainsi « delta » se calculera comme suit :

 

delta = MouseEvent.stageY - VAR_stageY;

 

Déclaration intélligente des événements et de la variable « VAR_stageY » :

 

package

{

import flash.display.Sprite;

import flash.events.Event;

import flash.events.MouseEvent;

 

public class maScrollbar extends Sprite

{

 

public var target:Sprite;

public var maxHeight:Number;

private var BACKGROUND:Sprite;

private var HANDLER:Sprite;

private var VAR_stageY:int;

 

    public function maScrollbar ()

    { ... };

 

public function init():void

{ ...

HANDLER.addEventListener( MouseEvent.MOUSE_DOWN, mouseDown );

};

 

public function render( delta:int ):void

{ ... };

 

 

public function mouseDown( e:MouseEvent ):void

{

    VAR_stageY = e.stageY;

    e.target.stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMove );

    e.target.stage.addEventListener( MouseEvent.MOUSE_UP, mouseUp );

    e.target.stage.addEventListener( Event.MOUSE_LEAVE, mouseLeave );

 

};

 

public function mouseMove( e:MouseEvent ):void

{

    var coordonnee_y_actuelle = e.stageY;

    render( coordonnee_y_actuelle - VAR_stageY );

    VAR_stageY = coordonnee_y_actuelle;

};

 

public function mouseUp( e:MouseEvent ):void

{

    e.target.stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUp );

    e.target.stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMove );

    e.target.stage.removeEventListener( Event.MOUSE_LEAVE, mouseLeave );

};

 

public function mouseLeave( e:Event ):void

{

    e.target.stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUp );

    e.target.stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMove );

    e.target.stage.removeEventListener( Event.MOUSE_LEAVE, mouseLeave );

};

 

}

}

 

6. Evénement de la mollette

Il n'y a rien de plus facile que de configurer la mollette. Sauf pour les portables Macintosh !

L'événement qui nous intéresse se nomme « MOUSE_WHEEL ». Nous avons la possibiliter de l'écouter sur deux éléments : la cible « target » ou plus largement la scène « stage ». Nous ferons présentemment le choix numéro 2.

Cet événement possède une propriété « delta » qui correspond à la valeur du scroll (entier positif ou négatif). Il correspond entièrement avec notre « delta » à nous, qui se veut être un entier positif ou négatif. Il faut néammoins multiplier la valeur par « -6 » pour correspondre avec notre classe.

La déclaration de l'écouteur de l'événement « MOUSE_WHEEL » sur la scène « stage » :

 

package

{

import flash.display.Sprite;

import flash.events.Event;

import flash.events.MouseEvent;

 

public class maScrollbar extends Sprite

{

 

public var target:Sprite;

public var maxHeight:Number;

private var BACKGROUND:Sprite;

private var HANDLER:Sprite;

private var VAR_stageY:int;

 

    public function maScrollbar ()

    { ... };

 

public function init():void

{ ...

this.stage.addEventListener( MouseEvent.MOUSE_WHEEL, mouseWheel );

};

 

public function render( delta:int ):void

{ ... };

 

public function mouseDown( e:MouseEvent ):void

{ ... };

 

public function mouseMove( e:MouseEvent ):void

{ ... };

 

public function mouseUp( e:MouseEvent ):void

{ ... };

 

public function mouseLeave( e:Event ):void

{ ... };

 

public function mouseWheel( e:MouseEvent ):void

{

render( e.delta * (-6) );

};

 

}

}

 

 

Sur les Macintosh, l'obstacle à surmonter est de capturer l'événement du dénommé « TouchPad » (surface tactile qui remplace la souris).

Pour ce faire, il nous faut accepter deux contraintes :

  • Premièrement utiliser la méthode « SWFObject » pour afficher notre animation Flash sur une page HTML. Ce qui revient à utiliser un script en JavaScript pour afficher notre SWF (un bon procédé actuellement) ;
  • Deuxièmement, ajouter un autre code JavaScript « SWFMacMouseWheel » afin de capturer la surface tactile.

La partie JavaScript sur notre page HTML :

 

 

Exemple

La fonction « SWFMacMouseWheel » est désactivée car elle empêcherait les utilisateurs de Macintosh de faire défiler la page actuelle.

Voir l'exemple dans une nouvelle fenêtre

Alternative content

Get Adobe Flash player

Sources

« maScrollbar.as »

 

 

package

{

import flash.display.Sprite;

 

public class maScrollbar extends Sprite

{

 

public var target:Sprite;

public var maxHeight:Number;

private var BACKGROUND:Sprite;

private var HANDLER:Sprite;

private var VAR_stageY:int;

 

    public function maScrollbar ()

    {

// Je suis initialisée !

};

 

public function init():void

{

    BACKGROUND = new Sprite();

    BACKGROUND.graphics.beginFill( 0x999999, 1 );

    BACKGROUND.graphics.drawRect( 0, 0, 20, 20 );

    BACKGROUND.graphics.endFill();

    addChild( BACKGROUND );

 

    HANDLER = new Sprite();

    HANDLER.graphics.beginFill( 0x444444, 1 );

    HANDLER.graphics.drawRect( 0, 0, 20, 20 );

    HANDLER.graphics.endFill();

    addChild( HANDLER );

 

 

render( 0 );

 

HANDLER.addEventListener( MouseEvent.MOUSE_DOWN, mouseDown );

this.stage.addEventListener( MouseEvent.MOUSE_WHEEL, mouseWheel );

};

 

public function render( delta:int ):void

{

 

    BACKGROUND.height = maxHeight;

    HANDLER.height = maxHeight * maxHeight / target.height;

 

    if( (HANDLER.y + delta) < 0 )

{

        delta = -HANDLER.y;

    }

    if( (HANDLER.y + delta) > (maxHeight - HANDLER.height) )

{

        delta = (maxHeight - HANDLER.height) - HANDLER.y;

    }

 

    HANDLER.y = HANDLER.y + delta;

    target.y = this.y -((HANDLER.y * (target.height -maxHeight) / (maxHeight -HANDLER.height)));

 

};

 

 

public function mouseDown( e:MouseEvent ):void

{

    VAR_stageY = e.stageY;

    e.target.stage.addEventListener( MouseEvent.MOUSE_MOVE, mouseMove );

    e.target.stage.addEventListener( MouseEvent.MOUSE_UP, mouseUp );

    e.target.stage.addEventListener( Event.MOUSE_LEAVE, mouseLeave );

 

};

 

public function mouseMove( e:MouseEvent ):void

{

    var coordonnee_y_actuelle = e.stageY;

    render( coordonnee_y_actuelle - VAR_stageY );

    VAR_stageY = coordonnee_y_actuelle;

};

 

public function mouseUp( e:MouseEvent ):void

{

    e.target.stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUp );

    e.target.stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMove );

    e.target.stage.removeEventListener( Event.MOUSE_LEAVE, mouseLeave );

};

 

public function mouseLeave( e:Event ):void

{

    e.target.stage.removeEventListener( MouseEvent.MOUSE_UP, mouseUp );

    e.target.stage.removeEventListener( MouseEvent.MOUSE_MOVE, mouseMove );

    e.target.stage.removeEventListener( Event.MOUSE_LEAVE, mouseLeave );

};

 

public function mouseWheel( e:MouseEvent ):void

{

render( e.delta * (-6) );

};

 

}

}