une slidebar AS3 sans les composants
En développant un player de vidéo, je me suis rendu compte que l'utilisation du composant slidebar (fl.controls.Slider) posait pas mal de problèmes .. surtout , bien qu'on puisse le skinner comme on veut, c'est à priori impossible d'en skinner deux différent, bien que normalement la fonction setStyle("..) devrait le permettre..
Je me suis bien cassé les dents sur ce problème lorsque j'ai voulu ajouté une barre de volume en plus d'une barre de progression en utilisant ce composant. Impossible de changer l'apparence du "trackSkin" une fois qu'il était affecté dans le .fla. Etrange car l'affectation de l'apparence du bouton (les skins ThumbUp, ThumbDown , ou encore ThumbOver ) fonctionnait correctement lui .
Autre solution que finalement j'ai choisi : créer ma propre classe pour un slider .
Pour interagir avec l'application dans laquelle l'objet se trouve, j'utilise des écouteurs d'évènement, évènements déclenchés par mon slider. Ainsi ma classe "player" a un addEventListener à l'écoute d'un type particulier d'évènement déclenché uniquement par le slider.
Ce fla est surtout là pour illustrer cette façon pratique de programmer via des "écouteurs d'évènements",ce qui permet de rendre totalement indépendants deux objets qui doivent interagir. On évite ainsi d'implémenter tout un tas de fonctions publiques pour que les objets commmuniquent.
Pour passer une valeur particulière dans un évènement (en l'occurence ici, un niveau de 0 à 100 ) , on ne peut pas utiliser nativement un Event ou un MouseEvent (en plus le probleme se poserait au niveau de l'écouteur qui réagirait à chaque event générique ). Aussi , j'ai créer une classe SliderEvent, qui hérite de la classe Events, que j'ai implémenté d'une variable dite publique (c'est à dire accessible à toute l'application ) .
Le slider :
// class AS3 of a vertical Slider
//
// @author Benjamin PETIT
// december 2009
package com.sensue {
import flash.display.Sprite ;
import flash.events.MouseEvent ;
import flash.geom.Rectangle ;
import fl.transitions.*;
import fl.transitions.easing.*;
import fl.transitions.Tween;
import com.sensue.events.SliderEvent ;
public class Slider extends Sprite {
// Public Properties:
// Private Properties:
// You need 2 MovieClip/graphics on your scene to have this slider working :
// 1 . the "track" for the knob
// 2 . the knob
// For easier manipulation of movieclip, i always place them on x=0 and y=0
// make them exportable trough Flash and give them the right name class aka Knob and TrackSkin
private var _track:TrackSkin = new TrackSkin();
private var _knob:Knob = new Knob();
// Initialization:
public function Slider () {
addChild(_track);
addChild(_knob);
// knob initial position
var initPos:int = 80 ;
// vertical bar
_knob.buttonMode = true ;
_knob.y = (_track.height * (100-initPos))/ 100 ;
// center the knob clip : all clips set to 0 , the formula :
_knob.x = _track.x + _track.width/2 - _knob.width/2 ;
_knob.addEventListener(MouseEvent.MOUSE_DOWN,beginDragVol);
_knob.addEventListener(MouseEvent.MOUSE_UP,endDragVol);
// the additionnal Mouse up is necessary when still MOUSE_DOWN but not actually anymore on the knob
_knob.addEventListener(MouseEvent.MOUSE_OUT,endDragVol);
}
// Public Methods: set the slider to a position
public function resetSlider(vol:Number):void{
_knob.y = (_track.height * (100 - vol))/ 100 ;
dispatchEvent(new SliderEvent('SliderEvent.VALUE_CHANGED', vol ));
}
// Protected Methods:
private function beginDragVol(e:MouseEvent):void{
// limit the startdrag on a 'rectangle' along the track height
e.currentTarget.startDrag(false, new Rectangle( _knob.x, _track.y,0 ,_track.height-_knob.height)) ;
_knob.addEventListener(MouseEvent.MOUSE_MOVE,addListenerMove);
}
private function addListenerMove(e:MouseEvent):void{
//calculate the new position compared to the track height
var newratio:Number = Math.abs ((e.currentTarget.y*100)/_track.height) ;
var vol:Number = Math.round((100*newratio)/(_track.height-_knob.height)) ;
dispatchEvent(new SliderEvent('SliderEvent.VALUE_CHANGED', vol ));
}
private function endDragVol(e:MouseEvent):void{
e.currentTarget.stopDrag();
_knob.removeEventListener(MouseEvent.MOUSE_MOVE,addListenerMove);
}
}
}
La classe SliderEvent :
package com.sensue.events {
import flash.events.Event ;
public class SliderEvent extends Event{
// Constants:
// Public Properties:
public static const VALUE_CHANGED:String = 'valueChanged' ;
public var newValue:Number ;
// Private Properties:
// Initialization:
public function SliderEvent(type:String,newVal:Number) {
//bubbles and cancellable set to true
newValue = newVal ;
super(type, true, true);
}
override public function clone() : Event
{
return new SliderEvent(this.type, this.newValue);
}
}
}
Enfin, l'objet "player" (qui ne contient que le slider, un ecouteur des évenements qu'il émet et un champ texte)
package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.text.TextFormat;
import com.sensue.events.SliderEvent ;
import com.sensue.Slider;
public class Player extends MovieClip {
// UI elements
private var _slider:Slider ;
private var _tf:TextField ;
private var _tformat:TextFormat = new TextFormat();
// Constructor
public function Player():void {
_slider = new Slider() ;
_tf = new TextField() ;
_tformat.color = 0x999999;
_tformat.font = "Verdana"
_tformat.size = 13;
addChild(_slider) ;
addChild(_tf) ;
_tf.width = 200 ;
_tf.y = 150 ;
_slider.y = 40 ;
_slider.x = 40;
addEventListener('SliderEvent.VALUE_CHANGED',doSomething) ;
return ;
}
private function doSomething(e:SliderEvent){
// potentially , you change the volume Here with the value
_tf.text = "capture : "+e.newValue ;
_tf.setTextFormat(_tformat);
}
}
}
| Fichier attaché | Taille |
|---|---|
| Player.zip | 12.64 Ko |
