Tạo Scroller tương tác 2 chiều trong AS3

Scroller tương tác 2 chiều nghĩa là scroller có thể kéo để điều khiển được 1 MovieClip chạy lên, xuống theo vị trí của thanh kéo và ngược lại, khi người dùng kéo MovieClip lên xuống thì thanh kéo trên scrollbar cũng chạy theo sự thay đổi vị trí của MovieClip. Ngoài ra thanh kéo còn thay đổi độ dài tùy theo độ dài của nội dung.

Để hiểu rõ hơn về ví dụ này bạn hãy click vào tấm hình dưới đây để xem hoạt động của scroller này. Bạn có thể kéo thanh trượt, hoặc click vào 2 buttons lên xuống để điều khiển MovieClip chạy. Và ngược lại, bạn cũng có thể kéo MovieClip lên xuống, khi đó thanh trượt cũng sẽ chạy theo.

Để hoàn thành bài này chúng ta cần có 2 buttons “up_btn” và “down_btn“, thanh kéo “scrollFace_mc” và “scrollTrk_mc” là MC nằm dưới thanh kéo là phạm vi mà thanh kéo sẽ trượt trong đó. Tiếp theo, phần nội dung tôi đặt là “contentMain_mc“. Và cuối cùng là ta cần 1 mask tên là “mask_mc“, mask này là của phần nội dung để xác định vùng nhìn nội dung.

1. Đầu tiên là phần thanh kéo “scrollFace_mc” và 2 buttons điều khiển MC nội dung “contentMain_mc”.

ActionScript

Đặt các biến:

var scrollHeight:Number = scrollTrk_mc.height;
var contentHeight:Number = contentMain_mc.height;
var barRatio:Number = contentHeight / scrollHeight;
//đóng dòng dưới lại nếu không muốn chiều cao thanh trượt thay đổi
scrollFace_mc.height = scrollHeight / barRatio;
var scrollFaceHeight:Number = scrollFace_mc.height
var maskHeight:Number = mask_mc.height;
var initPosition:Number = scrollFace_mc.y = scrollTrk_mc.y;
var initContentPos:Number = contentMain_mc.y;
var finalContentPos:Number = maskHeight - contentHeight + initContentPos;
var left:Number = scrollTrk_mc.x;
var top:Number = scrollTrk_mc.y;
var right:Number = 0;
var bottom:Number = scrollTrk_mc.height - scrollFaceHeight;
var bottom2:Number = scrollTrk_mc.height - scrollFaceHeight + scrollTrk_mc.y;
var dy:Number = 0;
var speed:Number = 10;
var moveVal:Number = (contentHeight-maskHeight)/(scrollHeight-scrollFaceHeight);
var currPos:Number;
var rect1:Rectangle = new Rectangle(left,top,right,bottom);

Các listeners

scrollFace_mc.addEventListener(MouseEvent.MOUSE_DOWN, scrollMouseDown);
scrollFace_mc.addEventListener(MouseEvent.MOUSE_UP, scrollMouseUp);
up_btn.addEventListener(MouseEvent.MOUSE_DOWN, up_btnPress);
up_btn.addEventListener(MouseEvent.MOUSE_UP, up_btnRelease);
up_btn.addEventListener(MouseEvent.MOUSE_OUT, up_btnOut);
down_btn.addEventListener(MouseEvent.MOUSE_DOWN, down_btnPress);
down_btn.addEventListener(MouseEvent.MOUSE_UP, down_btnRelease);
down_btn.addEventListener(MouseEvent.MOUSE_OUT, down_btnOut);

Các functions

function scrollMouseDown(event:MouseEvent){
   currPos = this.scrollFace_mc.y;
   scrollFace_mc.startDrag(false, rect1);
   scrollFace_mc.addEventListener(Event.ENTER_FRAME, scrollMove);
   stage.addEventListener(MouseEvent.MOUSE_UP, releaseOut);
}
function scrollMove(event:Event){
   dy = Math.abs(initPosition - scrollFace_mc.y);
   contentMain_mc.y = Math.round(dy * -1 * moveVal + initContentPos);
}
function scrollMouseUp(event:MouseEvent){
   scrollFace_mc.stopDrag();
   scrollFace_mc.removeEventListener(Event.ENTER_FRAME, scrollMove);
}
function releaseOut(event:MouseEvent){
   if (event.target == scrollFace_mc){
      trace("nnnnn");
   }
   else{
      scrollFace_mc.stopDrag();
      scrollFace_mc.removeEventListener(Event.ENTER_FRAME, scrollMove);
   }
   stage.removeEventListener(MouseEvent.MOUSE_UP, releaseOut);
}
function up_btnPress(event:MouseEvent){
   up_btn.addEventListener(Event.ENTER_FRAME, up_btnEnterFrame);
}
function up_btnEnterFrame(event:Event){
   if (contentMain_mc.y >= initContentPos || scrollFace_mc.y < = top){
      scrollFace_mc.y = top;
   }
   else{
      scrollFace_mc.y -=  speed / moveVal;
      contentMain_mc.y +=  speed;
   }
}
function up_btnRelease(event:MouseEvent){
   up_btn.removeEventListener(Event.ENTER_FRAME, up_btnEnterFrame);
}
function up_btnOut(event:MouseEvent){
   up_btn.removeEventListener(Event.ENTER_FRAME, up_btnEnterFrame);
}
function down_btnPress(event:MouseEvent){
   down_btn.addEventListener(Event.ENTER_FRAME, down_btnEnterFrame);
}
function down_btnEnterFrame(event:Event){
   if (contentMain_mc.y <= finalContentPos || scrollFace_mc.y >= bottom){
      scrollFace_mc.y = bottom2;
   }
   else{
      scrollFace_mc.y +=  speed / moveVal;
      contentMain_mc.y -=  speed;
   }
}
function down_btnRelease(event:MouseEvent){
   down_btn.removeEventListener(Event.ENTER_FRAME, down_btnEnterFrame);
}
function down_btnOut(event:MouseEvent){
   down_btn.removeEventListener(Event.ENTER_FRAME, down_btnEnterFrame);
}

if (contentHeight < maskHeight){
   scrollFace_mc.visible = false;
   up_btn.enabled = false;
   down_btn.enabled = false;
}
else{
   scrollFace_mc.visible = true;
   up_btn.enabled = true;
   down_btn.enabled = true;
   //
   contentMain_mc.addEventListener(MouseEvent.MOUSE_DOWN, startMove);
   contentMain_mc.addEventListener(MouseEvent.MOUSE_UP, stopMove);
}

2. Phần tiếp theo là MC nội dung “contentMain_mc” điều khiển thanh kéo “scrollFace_mc”.

ActionScript

var initPosition2:Number = contentMain_mc.y = mask_mc.y;
var initContentPos2:Number = scrollFace_mc.y;
var moveVal2:Number = (scrollHeight-scrollFaceHeight)/(contentHeight-maskHeight);
var leftMC:Number = mask_mc.x;
var topMC:Number = mask_mc.y;
var rightMC:Number = 0;
var contentMain_mcHeight:Number = contentMain_mc.height;
var bottomMC:Number = mask_mc.height - contentMain_mcHeight;
var rectMC:Rectangle = new Rectangle(leftMC,topMC,rightMC,bottomMC);
var dy2:Number = 0;
//
function startMove(evt:MouseEvent):void{
   contentMain_mc.startDrag(false, rectMC);
   contentMain_mc.addEventListener(MouseEvent.MOUSE_MOVE, mcMove);
}
function stopMove(evt:MouseEvent):void{
   contentMain_mc.stopDrag();
   contentMain_mc.removeEventListener(MouseEvent.MOUSE_MOVE, mcMove);
}
function mcMove(evt:MouseEvent):void{
   dy2 = Math.abs(initPosition2 - contentMain_mc.y);
   scrollFace_mc.y = Math.round(dy2 * moveVal2 + initContentPos2);
}

Dowload Source Code CS5: scroller_as3.zip