¿Quieres registrarte?

Crear ScrollBar con Easing en Actionscript 3

Por: penHolder
18 de Noviembre del 2008
2905 de clabLevel
Otros artículos de penHolder
10,461 visitas

Esta clase de componentes con efecto de suavizado son de las mas buscadas, aquí en cristalab tenemos varios ejemplos de ello, sin embargo ya era hora de uno hecho para actionscript 3.

Este componente ha sido posible, una vez mas, gracias a la inmensa sabiduría del Gran Maestro Z, que con su gracia e iluminación ha hecho posible la optimización de esta clase, por los que ha sido bautizada como Zscrollez.as



Este componente consta de dos clases. La primera es una clase simple que dibuja un objeto de cuatro lados rectos, que usaremos para cada una de las partes (scroll, mascara, etc.); la segunda es la clase principal y es la que arma todo el componente.

Como bien dijimos la primer clase solamente dibuja un rectángulo que extiende de Sprite, y recibe como parámetros: el ancho, el alto, y el color de fondo.

RectScuare.as

Código :

package ph.graphic{
                //
   import flash.display.Sprite;
   import flash.display.Graphics;
   //
   public class RectScuare extends Sprite {
      //
      private var clip    :Sprite;
      private var wd      :uint;
      private var hg      :uint;
      private var bgColor :uint;
      //
      public function RectScuare(_wd:uint, _hg:uint, _bgColor:uint):void {
         //
         wd      = _wd;
         hg      = _hg;
         bgColor = _bgColor;
         //
         drawRectScuare();
      }
      //
      private function drawRectScuare():void {
         //
         clip = new Sprite();
         clip.graphics.beginFill(bgColor);
         clip.graphics.drawRect(0, 0, wd, hg);
         addChild(clip);
      }
   }// class
}// package

Una vez lista esta clase, empecemos con lo divertido: Zscrolez.as
Primero declaremos la variables a usar:

Código :

private var holder       :MovieClip;  // clip contenedor
private var clip         :MovieClip;  // contenido
private var clipMask     :RectScuare; // máscara
private var dragger      :RectScuare; // barra del scroll
private var slider       :RectScuare; // guía del scroll
private var hg           :uint;       // alto total del componente
private var scrolled     :uint;       // distancia desplazada
private var friction     :uint;       // aceleracion
private var currentY     :int;        // la posicion inmediata del contenido
private var fade         :Tween;      // alpha de la barra del scroll
private var fadeAmount   :Number;     // valor de alpha
private var wheel        :Boolean;    // hace falta aclaracion?

El constructor de la clase recibirá 4 parámetros, dos de ellos preseteados:

Código :

Zscrollez (_clip:MovieClip, _hg:uint, _friction:uint = 5, _wheel:Boolean = false)

donde:

Entonces quedaría así:

Código :

public function Zscrollez(_clip:MovieClip, _hg:uint, _friction:uint = 5, _wheel:Boolean = false):void {
   //
   clip       = _clip;
   hg         = _hg;
   friction   = _friction;
   wheel      = _wheel;
   //
   if (clip.height > hg) {
      //
      createHolder();
      createMask();
      createSrollBar();
      addListeners();
   }
}

Ahí ya vemos las funciones que usaremos, el if() evalúa si el contenido es lo suficientemente largo para ser scrolleado.

Vamos con la primera función; simplemente crearemos un objeto que contendrá todos los elementos:

Código :

private function createHolder():void {
   //
   holder = new MovieClip();
   holder.x = clip.x;
   holder.y = clip.y;
   clip.x = clip.y = 0;
   holder.addChild(clip);
   addChild(holder);
}


Bien, una vez echo esto empecemos por enmascarar al clip que contiene el contenido (redundancia?), lo que haremos será usar la clase que previamente creamos para crear un rectángulo:

Código :

private function createMask():void {
   //
   clipMask = new RectScuare(clip.width, hg, 0x000000);
   clip.mask = clipMask;
   holder.addChild(clipMask);
}


Ahora crearemos la barra, que serán dos objetos uno llamado slider, que será la guía por donde se va a mover la barra propiamente dicha llamada dragger. La clase tendrá los valores del alto del dragger (dH), y los colores del slider (sC) y del dragger (dC), ya preseteados.

Código :

private function createSrollBar(dH:uint = 30, dC:uint = 0x000000, sC:uint = 0xCCCCCC):void {
   //
   draggerHg    = dH;
   draggerColor = dC;
   sliderColor  = sC;
   //
   slider = new RectScuare(10, hg, sliderColor);
   dragger = new RectScuare(10, dH, draggerColor);
   slider.x = dragger.x = clip.width + 5;
   holder.addChild(slider);
   holder.addChild(dragger);
}


Como ya hemos creado la barra, ahora vamos a crear los eventos de startDrag y stopDrag, mas un evento para cuando el release del mouse se efectúe fuera del área del dragger, que no es otra cosa que el onReleaseOutside de AS2.

Código :

private function dragOn(e:Event):void {
   //
   dragger.startDrag(false, new Rectangle(dragger.x, 0, 0, slider.height - dragger.height));
   dragOnOutSide();
}
private function dragOff(e:Event):void {
   //
   dragger.stage.removeEventListener(MouseEvent.MOUSE_UP, dragOff);
   dragger.stopDrag();
}
private function dragOnOutSide():void {
   //
   dragger.stage.addEventListener(MouseEvent.MOUSE_UP, dragOff);
}

Bien, ya que estamos creando efectos para la barra añadamos un efecto rollover:

Código :

private function fadeIn(e:Event):void {
   //
   e.type == "rollOver" ? fadeAmount = 0.5 : fadeAmount = 1;
   fade = new Tween(e.target, "alpha", Strong.easeOut, e.target.alpha, fadeAmount, 0.5, true);
}

Esta extraña sintaxis la explica el maestro perfectamente en una clase majistral a cerca de como obtener parámetros en eventos de Actionscript 3

Entonces necesitaríamos una función que nos mueva el contenido acorde con el movimiento de la barra, y que lo haga de forma suavizada.

Código :

private function easeIn(e:Event):void 
   //
   {if (friction >= 5) friction = 5; 
   /* 
   cuidamos que no se pase de 5 ya de lo contrario 
   el calculo dispara el contenido realmente al carajo
   */

   // calculamos el porcentaje del dragger que se ha movido
   scrolled = dragger.y / (hg - dragger.height) * 100;

   // ahora hacemos lo mismo con respecto al contenido
   currentY = -(clip.height - hg) * scrolled / 100;

   // y asignamos la posición con respecto al valor de fricción
   clip.y += (currentY - clip.y) / friction;
}


Para ir terminando crearemos la función para aplicar el uso del scroll wheel:

Código :

private function aplyScrollWheel(e:MouseEvent):void {
   //
   dragger.y += e.delta * -4;
   //
   if (dragger.y < 0) {
      //
      dragger.y = 0;
      } else if (dragger.y > (slider.height - dragger.height)) {
      //
      dragger.y = slider.height - dragger.height;
   }
}

(el valor de -4 asignado al movimiento puede ser cambiado según prefieran un movimiento mas pausado o mas rápido, claro que también se podría crear alguna especie de setter)

Finalmente tenemos que asignar todos los eventos para ello yo he hecho una función aparate:

Código :

private function addListeners():void {
   //
   dragger.addEventListener(MouseEvent.ROLL_OVER, fadeIn);
   dragger.addEventListener(MouseEvent.ROLL_OUT, fadeIn);

   dragger.addEventListener(MouseEvent.MOUSE_DOWN, dragOn);
   dragger.addEventListener(MouseEvent.MOUSE_UP, dragOff);
   dragger.addEventListener(Event.ENTER_FRAME, easeIn);
   //
   if (wheel == true) {
      clip.addEventListener(MouseEvent.MOUSE_WHEEL, aplyScrollWheel);
   }
}


Con todo nuestra clase ya funciona perfectamente:


Pero claro, como vemos, no es muy personalizable, por lo que vamos a añadirle unas cuantas funciones públicas.
Primero unos setters para acceder directamente al valor de wheel, y para habilitar la opción de buttonMode:

Código :

public function set scrollWheel(b:Boolean):void {
   //
   wheel = b;
   addListeners();
}
//
public function set handCursor(h:Boolean):void {
   //
   dragger.buttonMode = h;
}


Ahora crearemos una función para asignarle nuevos valores al color y el tamaño de la barra:

Código :

public function scrollBarProperties(_draggerHg:uint, _draggerC:uint, _sliderC:uint):void {
   //
   draggerHg    = _draggerHg;
   draggerColor = _draggerC;
   sliderColor  = _sliderC;
   //
   createSrollBar(draggerHg, draggerColor, sliderColor);
   addListeners();
}


Y, finalmente, una función para añadir un fondo, ya que es posible que el texto se encuentra sobre alguna imagen y dificulte su lectura:

Código :

public function backGround(_bgColor:uint = 0xFFFFFF, _bgAlpha:Number = 1):void {
   //
   bgColor = _bgColor;
   bgAlpha = _bgAlpha;
   //
   bGround = new RectScuare(clip.width, hg, bgColor);
   bGround.x = bGround.y = 0;
   bGround.alpha = bgAlpha;
   holder.addChild(bGround);
   holder.swapChildren(bGround, clip);
}


Como vemos vamos a necesitar algunas variables más, por lo que finalmente nuestra clase completa quedaría así:
Zscrollez.as

Código :

package ph.component{
   //
   import flash.display.*;
   import flash.events.*;
   import flash.geom.Rectangle;
   import fl.transitions.Tween;
   import fl.transitions.easing.*;
   import ph.graphic.RectScuare;
   //-----------------------------------------------
   public class Zscrollez extends Sprite {
      //
      private var holder       :MovieClip;
      private var clip         :MovieClip;
      private var clipMask     :RectScuare;
      private var dragger      :RectScuare;
      private var slider       :RectScuare;
      private var bGround      :RectScuare;
      private var bgAlpha      :Number;
      private var bgColor      :uint;
      private var hg           :uint;
      private var scrolled     :uint;
      private var friction     :uint;
      private var currentY     :int;
      private var draggerHg    :uint;
      private var draggerColor :uint;
      private var sliderColor  :uint;
      private var fade         :Tween;
      private var fadeAmount   :Number;
      private var wheel        :Boolean;
      //------------------------------------------------------------------------
      public function Zscrollez(_clip:MovieClip, _hg:uint, _friction:uint = 5, _wheel:Boolean = false):void {
         //
         clip       = _clip;
         hg         = _hg;
         friction   = _friction;
         wheel      = _wheel;
         //
         if (clip.height > hg) {
            //
            createHolder();
            createMask();
            createSrollBar();
            addListeners();
         }
      }
      //---------------------------------------------------------------------------
      public function set scrollWheel(b:Boolean):void {
         //
         wheel = b;
         addListeners();
      }
      //
      public function set handCursor(h:Boolean):void {
         //
         dragger.buttonMode = h;
      }
      //---------------------------------------------------------------------------
      public function scrollBarProperties(_draggerHg:uint, _draggerC:uint, _sliderC:uint):void {
         //
         draggerHg    = _draggerHg;
         draggerColor = _draggerC;
         sliderColor  = _sliderC;
         //
         createSrollBar(draggerHg, draggerColor, sliderColor);
         addListeners();
      }
      //---------------------------------------------------------------------------
      public function backGround(_bgColor:uint = 0xFFFFFF, _bgAlpha:Number = 1):void {
         //
         bgColor = _bgColor;
         bgAlpha = _bgAlpha;
         //
         bGround = new RectScuare(clip.width, hg, bgColor);
         bGround.x = bGround.y = 0;
         bGround.alpha = bgAlpha;
         holder.addChild(bGround);
         holder.swapChildren(bGround, clip);
      }
      //---------------------------------------------------------------------------
      private function createHolder():void {
         //
         holder = new MovieClip();
         holder.x = clip.x;
         holder.y = clip.y;
         clip.x = clip.y = 0;
         holder.addChild(clip);
         addChild(holder);
      }
      //---------------------------------------------------------------------------
      private function createMask():void {
         //
         clipMask = new RectScuare(clip.width, hg, 0x000000);
         clip.mask = clipMask;
         holder.addChild(clipMask);
      }
      //---------------------------------------------------------------------------
      private function createSrollBar(dH:uint = 30, dC:uint = 0x000000, sC:uint = 0xCCCCCC):void {
         //
         draggerHg    = dH;
         draggerColor = dC;
         sliderColor  = sC;
         //
         slider = new RectScuare(10, hg, sliderColor);
         dragger = new RectScuare(10, dH, draggerColor);
         slider.x = dragger.x = clip.width + 5;
         holder.addChild(slider);
         holder.addChild(dragger);
      }
      //--------------------------------------------------------------------------
      private function dragOn(e:Event):void {
         //
         dragger.startDrag(false, new Rectangle(dragger.x, 0, 0, slider.height - dragger.height));
         dragOnOutSide();
      }
      private function dragOff(e:Event):void {
         //
         dragger.stage.removeEventListener(MouseEvent.MOUSE_UP, dragOff);
         dragger.stopDrag();
      }
      private function dragOnOutSide():void {
         //
         dragger.stage.addEventListener(MouseEvent.MOUSE_UP, dragOff);
      }
      //---------------------------------------------------------------------------
      private function fadeIn(e:Event):void {
         //
         e.type == "rollOver" ? fadeAmount = 0.5 : fadeAmount = 1;
         fade = new Tween(e.target, "alpha", Strong.easeOut, e.target.alpha, fadeAmount, 0.5, true);
      }
      //---------------------------------------------------------------------------
      private function easeIn(e:Event):void {
         //
         if (friction >= 5) friction = 5;
         //
         scrolled = dragger.y / (hg - dragger.height) * 100;
         currentY = -(clip.height - hg) * scrolled / 100;
         clip.y += (currentY - clip.y) / friction;
      }
      //---------------------------------------------------------------------------
      private function aplyScrollWheel(e:MouseEvent):void {
         //
         dragger.y += e.delta * -4;
         //
         if (dragger.y < 0) {
            //
            dragger.y = 0;

         } else if (dragger.y > (slider.height - dragger.height)) {
            //
            dragger.y = slider.height - dragger.height;
         }
      }
      //--------------------------------------------------------------------------
      private function addListeners():void {
         //
         dragger.addEventListener(MouseEvent.ROLL_OVER, fadeIn);
         dragger.addEventListener(MouseEvent.ROLL_OUT, fadeIn);
         dragger.addEventListener(MouseEvent.MOUSE_DOWN, dragOn);
         dragger.addEventListener(MouseEvent.MOUSE_UP, dragOff);
         dragger.addEventListener(Event.ENTER_FRAME, easeIn);
         //
         if (wheel == true) {
            clip.addEventListener(MouseEvent.MOUSE_WHEEL, aplyScrollWheel);
         }
      }
      //-------------------------------------------------------------------------

   }// class
}// package


y para obtener un scroll como el que se encuentra al principio haríamos lo siguiente:

Código :

import ph.component.Zscrollez;
//-----------------------------------------------
var textoClip:Clip = new Clip();
var eScroll:Zscrollez = new Zscrollez(textoClip, 300);
eScroll.scrollBarProperties(60, 0xFB761E, 0x666666);
eScroll.backGround(0xFFFFFF, 0.5);
eScroll.scrollWheel = true;
eScroll.handCursor = true;
eScroll.x = eScroll.y = 15;
addChild(eScroll);


Bien eso es todo, espero haya servido de algo.

Descargate aqui el archivo .FLA ;)

Enviar a twitter Enviar a facebook


También te interesa


Etiquetas actionscript_3 componente

Comentarios | Enviar un comentario
el texto desaparece enseguida apenas se hace click en la barra.
Por: Mariux
A mi me falla rotundamente el scroll, imagino que es el mismo problema que el de Mariux... Ademas como consejo podrías agregar un listener para cuando gires la rueda del mouse y unos botones para que puedas subirlo o bajarlo...

Ojalá puedas arreglarlo !
Por: M@U
:? raro eso sucede con flash player 10, no tengo idea de porque lo hace? con fl player 9 funciona bien :cry:
Por: penHolder
y en IE se ve perfectamente... porque nadie me quiere T_T
Por: penHolder

FIXED!

:cool:

PenHolder, PenHolder... ejem... definiste como uint una variable (currentY) que ha de tener valores negativos.. tiene que estar definida como int.. U_U

PD. No me preguntes por que en player 9 funcionaba U.U

Por: Zguillez
Mmmm... Interesante ahora que funciona mejor, aunque el MOUSE_WHEEL esta algo raro...
:o
Por: M@U
El scroll con el wheel no va fino, baja y corre la pagina al mismo tiempo :S
Por: Bleend
Creo, y solamente creo que el problema escinde en que utilizas una condicional para hacer uso de MOUSE_WHEEL...

Código :

if (wheel == true) {
      clip.addEventListener(MouseEvent.MOUSE_WHEEL, aplyScrollWheel);
   }


Igual no tengo NPI de AS POO y demás, pero no funciona mejor si; ¿dejas la condicional vacía, y añades el Listener directamente al stage

Código :

stage.addEventListener(MouseEvent.MOUSE_WHEEL, aplyScrollWheel);

Por: M@U
Zks Z! ...es raro que tambien funcionaba con IE... en fin, el tip quedaria asi:

* Editado y actualizado *


Por: penHolder

M@U :

Creo, y solamente creo que el problema escinde en que utilizas una condicional para hacer uso de MOUSE_WHEEL...

Código :

if (wheel == true) {
      clip.addEventListener(MouseEvent.MOUSE_WHEEL, aplyScrollWheel);
   }


Igual no tengo NPI de AS POO y demás, pero no funciona mejor si; ¿dejas la condicional vacía, y añades el Listener directamente al stage

Código :

stage.addEventListener(MouseEvent.MOUSE_WHEEL, aplyScrollWheel);

Ese condicional es para habilitar o no el listener del scroll del mouse (puede que te interese un scroll no controlado por la rueda del mouse). Por eso tiene un setter para la propiedad _wheel en la que al asignarle un valor reinicias los listeners.
Por: Zguillez
Para los que queráis usar el MouseWheel podéis añadir esta clase, cosa que agradecerán muchos "Makeros": http://blog.pixelbreaker.com/flash/as30-mousewheel-on-mac-os-x/
Por: Andros
sólo con afán de tocar un poco los coj..., ¿por qué la Clase RectScuare hace un addChild? ¿no sería mejor que devolviera sólo el sprite en lugar de hacer un addChild? Eso evitaría que tuviéramos sprites dentro de sprites dentro de sprites dentro de sprites dentro de ...
Por: Eliseo-blog

Eliseo-blog :

sólo con afán de tocar un poco los coj..., ¿por qué la Clase RectScuare hace un addChild? ¿no sería mejor que devolviera sólo el sprite en lugar de hacer un addChild? Eso evitaría que tuviéramos sprites dentro de sprites dentro de sprites dentro de sprites dentro de ...

Ciertamente, al extender RectScuare de Sprite no es necesario crear otro sprite dentro, podia haberse dejado asi:

Código :

private function drawRectScuare():void { 
    this.graphics.beginFill(bgColor); 
    this.graphics.drawRect(0, 0, wd, hg); 
}

pero bueno, al quedar la clase encapsulada tampoco es gran problema tener un sprite de más..
Por: Zguillez
buenas tardes a todos, interesante este tipo de scroll, soy nuevo en esto del flash CS3 manejaba el flash 5. Por un, tiempo me dedique a diseñar revistas y ese tiempo se hizo muy largo y al ver el nuevo cs3, quede loco no entiendo nada... me gustaria saber como hago que ese tipo de scroll lo pueda utilazar en mi proyecto varias veces o sera mucha molestia quedo pendiente a su respuesta
Por: AnGeLCoL

AnGeLCoL-blog :

buenas tardes a todos, interesante este tipo de scroll, soy nuevo en esto del flash CS3 manejaba el flash 5. Por un, tiempo me dedique a diseñar revistas y ese tiempo se hizo muy largo y al ver el nuevo cs3, quede loco no entiendo nada... me gustaria saber como hago que ese tipo de scroll lo pueda utilazar en mi proyecto varias veces o sera mucha molestia quedo pendiente a su respuesta


...de flash 5 hasta ahora han pasado muchas cosas, en fin estas queriendo saltar de AS1 basico a AS3 y POO, antes de querer usar este componente sin ni siquiera enenderlo, mejor empieza por aprender algo de POO y sus fundamentos, usando AS2; luego, si empieza con AS3
Por: penHolder
muy gentil por su respuesta, se que esta a años luz del 5 pase por el mx y ahora el cs3 aunquen ya salio cs4 baje un tutor de as3 lo estado estudiando, pero para un proyecto me era urgente saber el scroll que planteo, a lo que me refiero ese mismo no lo puedo incluir en un trabajo ya que sale en toda la pelicula, mas que entenderlo, considero es que hay que acostumbrarme a la nueva forma de plantearlo en un scrip a hacerlo todo en el area de trabajo de flash, pero le estoy agradecido por la respuesta y ya estoy aprendiendo analizarlo gracias.
Por: AnGeLCoL
Yo también estoy aprendiendo con el as3. Vengo de mal aprender con cs2, y este cambio tan grande en ocasiones me supera.

Estoy en la misma encrucijada que AnGeLCol, yo lo meto en mi web, y me funciona muy bien, es más he trabajado algunos cambios propios. Pero... el problema aparece cuando quiero meterlo en varios mc distintos. Creo que el fallo está en que usa un sólo ENTER_FRAME pero como hago para diferenciar en él que objeto quiero scrollar??

Gracias por la ayuda, y por la web. Me está salvando de muchas.
Por: FalcoTi-blog
lo siento por ser tan noob, pero como puedo cambiar el ancho de texto?
Por: Lorem-IP-zum-blog
eso no es un componente de flash... SWC
Por: cruzexx-blog
Saludos, tengo la duda de como evitar que se mueva toda la pagina cuando se hace uso de la rueda del raton, es decir, que solo haga scroll en el clip de pelicula y no se mueva la barra de desplazamiento del navegador
Por: Prottodied-blog
hola bueno la verdad es que le aplique el scroll a un docuemnto que me lee mysql y ni un problema todo perfecto pero el tema es que el width del scroll no puedo cambiarselo me gustaria que estuviera un poco mas grueso
bueno si alguien sabe me avisa muchisimas gracias saludos desde chile
Por: spoot-blog
Alguien sabe alguna pagina que te explique paso a paso indicando donde esta todo bien, sin saltarse pasos, desde el principio, sin tener que importar nada de otro sitio ni nada???? Explicarlo partiendo del documento en blanco...para los que sabemos menos y no somos tan listos.
Por: Smeik-blog
Deja un comentario
IMPORTANTE

Recuerda ser respetuoso, no insultes a otras personas, ni uses palabrotas, hay una persona al otro lado de la pantalla.

Habla bien, NO ESCRIBAS EN MAYUSCULA TODO, no escribas como en un SMS, evita cosas como "ke", "x q" y demás abreviaciones.

Aquí funcionan las etiquetas de los foros, puedes usar [b] para negrita, [img] para las imágenes, [url] para los enlaces, etc.

Si tienes preguntas técnicas, envíalas mejor al foro.