Comunidad de diseño web y desarrollo en internet

Crear ScrollBar con Easing en Actionscript 3

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:
  • _clip: es el objeto a scrollear, el contenido que será un MovieClip que tendremos en el escenario o en la biblioteca.
  • _hg: es el height del componente el área visible total (el ancho lo toma automáticamente del contenido).
  • _friction (valor por defecto: 5): es el valor de aceleración que tendrá el movimiento.
  • _weel (valor por defecto: false): es un valor boleano que decide si queremos o no usar la cosita del medio del mouse (para que lo entienda Julero)

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 ;)

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate