Wednesday, November 5, 2008

AS3: Scrollbar class

Origion source from http://www.flashscaper, I optimize to make it better.

All you need is :

+ a movie clip contains : scrollermc, trackmc, (upmc and downmc are optional), this movie has a linkage with utils.Scrollbar class.

+ how to use: call init function like : scrollbar.init(movieNeedScrollbar);

Scrollbar function :
  • dragable, up, down
  • click on track
  • mouse wheel
------------------------------------------

package utils { //utils.Scrollbar
import caurina.transitions.Tweener;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;

/**
* ...
* @author binhdocco
*/
public class Scrollbar extends MovieClip {

private var content: MovieClip;
private var transition: String;
private var transitionTime: Number;
private var hasArrow: Boolean;
private var dragRect: Rectangle;

public var scrollermc: MovieClip;
public var trackmc: MovieClip;
public var upmc: MovieClip;
public var downmc: MovieClip;
public var contentY: Number;
private var range: Number;
private var top: Number;
private var bottom: Number;
private var isUp: Boolean = false;
private var isDown: Boolean = false;
private var speedScroll: Number = 3;
private var ratio:Number;

public function Scrollbar() {

}

public function init(content: MovieClip, transition: String = "linear", transitionTime: Number = 0.15, hasArrow: Boolean = true, hasWheel: Boolean = true):void {
this.content = content;
this.transition = transition;
this.transitionTime = transitionTime;
this.hasArrow = hasArrow;

if (this.content.height <= this.height) {
this.visible = false;
}
contentY = this.content.y;
if (!this.hasArrow) {
if (upmc) {
this.trackmc.y = 0;
this.scrollermc.y = 0;
this.trackmc.height += this.upmc.height;
this.removeChild(upmc);
}
if (downmc) {
this.trackmc.height += this.downmc.height;
this.removeChild(downmc);
}
}

//dragRect
top = this.trackmc.y;
bottom = top + this.trackmc.height - this.scrollermc.height;
dragRect = new Rectangle(this.trackmc.x, top, 0, bottom - top);
range = this.height - 5;
ratio = (content.height - range)/(this.trackmc.height - scrollermc.height);
//create mask
var mask: Sprite = new Sprite();
mask.graphics.beginFill(0xFF0000);
mask.graphics.drawRect(content.x, content.y, content.width + 5, this.height);
mask.graphics.endFill();
this.parent.addChild(mask);
this.content.mask = mask;

this.scrollermc.addEventListener(MouseEvent.MOUSE_DOWN, onScrollerMouseDown);
this.stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
this.trackmc.addEventListener(MouseEvent.CLICK, onTrackClick);

if (hasWheel) {
this.content.addEventListener(MouseEvent.MOUSE_WHEEL, onContenMouseWheel);
this.addEventListener(MouseEvent.MOUSE_WHEEL, onContenMouseWheel);
}

if (this.hasArrow) {
this.upmc.addEventListener(MouseEvent.MOUSE_DOWN, onArrowMouseDown);
this.downmc.addEventListener(MouseEvent.MOUSE_DOWN, onArrowMouseDown);
}
}

public function update():void {
this.content.y = contentY;
if (this.content.height <= this.height) {
this.visible = false;
} else {
this.visible = true;
}
ratio = (content.height - range)/(this.trackmc.height - scrollermc.height);
}

public function gotoTop():void {
Tweener.addTween(this.scrollermc, { y: top, time: 0.5, onStart: addEnterFrame, onComplete: stopScroll} );
}

public function gotoEnd():void {
Tweener.addTween(this.scrollermc, { y: bottom, time: 0.5, onStart: addEnterFrame, onComplete: stopScroll} );
}
//EVENTS HANDLER

private function onTrackClick(e:MouseEvent):void {
var mouseY: Number = this.mouseY;
var scrollY: Number = this.scrollermc.y;
var destY: Number = mouseY - this.scrollermc.height / 2;
if (destY >= bottom) {
destY = bottom;
}
if (destY <= top) {
destY = top;
}
Tweener.addTween(this.scrollermc, { y: destY, time: 0.5, onStart: addEnterFrame, onComplete: stopScroll} );

}

private function onContenMouseWheel(event:MouseEvent):void {
if (event.delta < 0) {
if (this.scrollermc.y < bottom) {
this.scrollermc.y += Math.abs(event.delta)*2;
if (this.scrollermc.y >= bottom) {
this.scrollermc.y = bottom;
}
startScroll();
}
} else {
if (this.scrollermc.y > top) {
this.scrollermc.y -= event.delta*2;
if (this.scrollermc.y <= top) {
this.scrollermc.y = top;
}
startScroll();
}
}
}


private function onArrowMouseDown(e:MouseEvent):void {
if (e.target.name == this.upmc.name) {
isUp = true;
this.upmc.addEventListener(Event.ENTER_FRAME, onUpEnterFrame);
} else if (e.target.name == this.downmc.name) {
isDown = true;
this.downmc.addEventListener(Event.ENTER_FRAME, onDownEnterFrame);
}
}

private function onUpEnterFrame(e:Event):void {
if (isUp) {
if (this.scrollermc.y > top) {
this.scrollermc.y -= speedScroll;
if (this.scrollermc.y <= top) {
this.scrollermc.y = top;
}
startScroll();
}
}
}

private function onDownEnterFrame(e:Event):void {
if (isDown) {
if (this.scrollermc.y < bottom) {
this.scrollermc.y += speedScroll;
if (this.scrollermc.y >= bottom) {
this.scrollermc.y = bottom;
}
startScroll();
}
}
}

private function onStageMouseUp(e:MouseEvent):void {
if (isUp) {
this.upmc.removeEventListener(Event.ENTER_FRAME, onUpEnterFrame);
isUp = false;
}
if (isDown) {
this.downmc.removeEventListener(Event.ENTER_FRAME, onDownEnterFrame);
isDown = false;
}
this.scrollermc.stopDrag();
stopScroll();
}

private function onScrollerMouseDown(e:MouseEvent):void {
stopScroll();
this.scrollermc.startDrag(false, dragRect);
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function addEnterFrame():void {
stopScroll();
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function onEnterFrame(e:Event = null):void {
startScroll();
}

// FUNCTIONS
private function stopScroll():void {
this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}

private function startScroll():void {
var sPos: Number = ratio*(this.trackmc.y - scrollermc.y ) + contentY;
Tweener.removeTweens(this.content);
Tweener.addTween(this.content, { y: sPos, time:transitionTime, transition:transition } );
}
}

}
}