AS3: AxisScroller v1.0

View Example
View Documentation
Download Class & Example Files

AxisScroller is a scroller class that can be used in any of your AS3 projects. It's an update to the original AS2 AxisScroller and it is versioned at v1.0. The syntax for usage is almost identical except that I added a first parameter, the stage reference, so that the keyboard would work in AS3 as the keys are bound to the stage. This version also includes all the new stuff that was introduced in v2.0 of AxisScroller for AS2 and will be updated in the future simultaneously.

Actionscript:
  1. /**
  2. * Creates a scroller that allows for scrolling in the x or y axis, using the mouse wheel/arrow keys, different easing functions and types, and some other miscellaneous cool things.
  3. *
  4. * @usage
  5. * <code>
  6. * <pre>
  7. import flash.events.MouseEvent;
  8. import fl.transitions.Tween;
  9. import fl.transitions.easing.*;
  10. import com.reintroducing.ui.AxisScroller;
  11. stop();
  12. var optionalObj:Object = new Object(
  13. {
  14.     scrollType: "easing",
  15.     isTrackClickable: true,
  16.     useArrows: true,
  17.     upArrow: content_mc.up_btn,
  18.     downArrow: content_mc.down_btn,
  19.     continuousScroll: false,
  20.     easeFunc: Regular.easeOut,
  21.     duration: .25,
  22.     arrowMove: 50,
  23.     scaleScroller: true,
  24.     autoHideControls: true
  25. });
  26. var scroller:AxisScroller = new AxisScroller(stage, content_mc, content_mc.scroller_mc, content_mc.movie_mc, content_mc.track_mc, content_mc.mask_mc, "y", optionalObj);
  27. reset_btn.addEventListener(MouseEvent.MOUSE_DOWN, resetScroller);
  28. function resetScroller($evt:MouseEvent):void
  29. {
  30.     scroller.reset();
  31. }
  32. * </pre>
  33. * </code>
  34. *
  35. * @author Matt Przybylski [http://www.reintroducing.com]
  36. * @version 1.0
  37. */
  38.  
  39. package com.reintroducing.ui
  40. {
  41.     import flash.display.MovieClip;
  42.     import flash.display.Stage;
  43.     import flash.events.Event;
  44.     import flash.events.KeyboardEvent;
  45.     import flash.events.MouseEvent;
  46.     import flash.events.TimerEvent;
  47.     import flash.utils.Timer;
  48.    
  49.     import fl.transitions.Tween;
  50.     import fl.transitions.easing.*;
  51.    
  52.     public class AxisScroller
  53.     {
  54. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  55.  
  56.         private var _stage:Stage;
  57.         private var _changeProp:String;
  58.         private var _mouseAxis:String;
  59.         private var _changeScale:String;
  60.         private var _nextPosition:int;
  61.         private var _arrowMove:Number;
  62.         private var _scaleScroller:Boolean;
  63.         private var _autoHideControls:Boolean;
  64.         private var _mouseIsPressedDown:Boolean;
  65.         private var _trackStart:Number;
  66.         private var _trackEnd:Number;
  67.         private var _tween:Tween;
  68.         private var _arrow1Tween:Tween;
  69.         private var _arrow2Tween:Tween;
  70.         private var _scrollerTween:Tween;
  71.         private var _trackTween:Tween;
  72.         private var _easeFunc:Function;
  73.         private var _duration:Number;
  74.         private var _holder:MovieClip;
  75.         private var _scroller:MovieClip;
  76.         private var _toBeScrolled:MovieClip;
  77.         private var _track:MovieClip;
  78.         private var _mask:MovieClip;
  79.         private var _axis:String;
  80.         private var _scrollType:String;
  81.         private var _isTrackClickable:Boolean;
  82.         private var _arrows:Boolean;
  83.         private var _upArrow:MovieClip;
  84.         private var _downArrow:MovieClip;
  85.         private var _continuousScroll:Boolean;
  86.         private var _arrowTimer:Timer;
  87.         private var _arrowPressed:String;
  88.        
  89. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  90.        
  91.         public static const DEFAULT_NAME:String = "com.reintroducing.ui.AxisScroller";
  92.        
  93. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  94.    
  95.         /**
  96.          * Creates a new instance of the AxisScroller class.
  97.          *
  98.          * <p>
  99.          * The $optionalParams parameter takes in a couple of values.
  100.          * <ul>
  101.          * <li>scrollType: A string representing the scroll type, "instant" or "easing" (default: "easing")</li>
  102.          * <li>isTrackClickable: A boolean value that makes the track clickable so that you can scroll directly to a certain spot (default: true)</li>
  103.          * <li>useArrows: A boolean value that allows the use of arrow buttons (default: false)</li>
  104.          * <li>upArrow: If useArrows, a movie clip that represents the up arrow button (default: null)</li>
  105.          * <li>downArrow: If useArrows, a movie clip that represents the down arrow button (default: null)</li>
  106.          * <li>continuousScroll: If useArrows, a boolean that specifies if when pressing the arrows the scrolling should happen continuously or not (default: false)</li>
  107.          * <li>easeFunc: A function representing the ease type you'd like to use, as per the Tween class easing functions (default: Regular.easeOut)</li>
  108.          * <li>duration: An integer (in seconds) representing the time that the scrollable content will take to move when easing is used (default: .25)</li>
  109.          * <li>arrowMove: An integer (in pixels) that the scrollable content will move onMouseWheel/Key/Arrow movement (default: 100)</li>
  110.          * <li>autoHideControls: A boolean value that hides the scroller/track/arrows (if applicable) if the scroll content is too small to scroll (default: false)</li>
  111.          * <li>scaleScroller *: A boolean value that allows automatic scaling of the scroll bar (default: false)</li>
  112.          * </ul>
  113.          * * If you use the scaleScroller optional parameter, please make the size of the scroll bar the same size as the track and this will take care of
  114.          * scaling it automatically for you.  If you AREN'T using this parameter, please size your scroll bar accordingly manually.
  115.          * </p>
  116.          *
  117.          * @usage <pre><code>var scroller:AxisScroller = new AxisScroller($stage, $holder, $scroller, $toBeScrolled, $track, $mask, $axis, $optionalParams);</code></pre>
  118.          *
  119.          * @param $stage The stage object to use for keyboard input
  120.          * @param $holder The movie clip (or timeline) that holds all of the other clips corresponding to the scroller
  121.          * @param $scroller The movie clip to be used as the scroller
  122.          * @param $toBeScrolled The movie clip where the scrollable content resides
  123.          * @param $track The movie clip that is used as the track (measures extremes)
  124.          * @param $mask The movie clip that is used as the mask for the scrollable content area
  125.          * @param $axis A string value of either "x" or "y" that determines what axis the content is scrolled along
  126.          * @param $optionalParams Optional parameters to further control the scroller
  127.          */
  128.        
  129.         public function AxisScroller($stage:Stage, $holder:MovieClip, $scroller:MovieClip, $toBeScrolled:MovieClip, $track:MovieClip, $mask:MovieClip, $axis:String, $optionalParams:Object)
  130.         {
  131.             this._stage      = $stage;
  132.             this._holder                = $holder;
  133.             this._scroller      = $scroller;
  134.             this._toBeScrolled     = $toBeScrolled;
  135.             this._track                     = $track;
  136.             this._mask       = $mask;
  137.             this._axis       = $axis;
  138.            
  139.             this._scrollType             = ($optionalParams.scrollType == null) ? "easing" : $optionalParams.scrollType;
  140.             this._isTrackClickable    = ($optionalParams.isTrackClickable == null) ? true : $optionalParams.isTrackClickable;
  141.             this._arrows                = ($optionalParams.useArrows == null) ? false : $optionalParams.useArrows;
  142.             this._upArrow           = ($optionalParams.upArrow == null) ? null : $optionalParams.upArrow;
  143.             this._downArrow                 = ($optionalParams.downArrow == null) ? null : $optionalParams.downArrow;
  144.             this._continuousScroll      = ($optionalParams.continuousScroll == null) ? false : $optionalParams.continuousScroll;
  145.             this._easeFunc      = ($optionalParams.easeFunc == null) ? Regular.easeOut : $optionalParams.easeFunc;
  146.             this._duration      = ($optionalParams.duration == null) ? .25 : $optionalParams.duration;
  147.             this._arrowMove                 = ($optionalParams.arrowMove == null) ? 100 : $optionalParams.arrowMove;
  148.             this._autoHideControls      = ($optionalParams.autoHideControls == null) ? false : $optionalParams.autoHideControls;
  149.             this._scaleScroller    = ($optionalParams.scaleScroller == null) ? false : $optionalParams.scaleScroller;
  150.            
  151.             this.manageAxis(this._axis);
  152.             this.init();
  153.         }
  154.        
  155. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  156.        
  157.         // initiates listeners and other events
  158.         private function init():void
  159.         {
  160.             this._holder.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
  161.             this._holder.addEventListener(Event.ENTER_FRAME, manageScrolling);
  162.             this._stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);
  163.            
  164.             if (this._continuousScroll)
  165.             {
  166.                 this._arrowTimer = new Timer(80);
  167.                 this._arrowTimer.addEventListener(TimerEvent.TIMER, manageContinuousScroll);
  168.             }
  169.            
  170.             this.activateButtonEvents();
  171.         }
  172.        
  173.         // re-activates the button events
  174.         private function activateButtonEvents():void
  175.         {
  176.             this._scroller.addEventListener(MouseEvent.MOUSE_DOWN, manageMouseDown);
  177.             this._scroller.buttonMode = true;
  178.            
  179.             if (this._isTrackClickable)
  180.             {
  181.                 this._track.addEventListener(MouseEvent.MOUSE_UP, manageTrack);
  182.                 this._track.buttonMode = true;
  183.             }
  184.            
  185.             if (this._arrows)
  186.             {
  187.                 this._upArrow.addEventListener(MouseEvent.MOUSE_DOWN, manageUpArrow);
  188.                 this._upArrow.addEventListener(MouseEvent.MOUSE_UP, resetArrowTimer);
  189.                
  190.                 this._downArrow.addEventListener(MouseEvent.MOUSE_DOWN, manageDownArrow);
  191.                 this._downArrow.addEventListener(MouseEvent.MOUSE_UP, resetArrowTimer);
  192.                
  193.                 this._downArrow.buttonMode = this._upArrow.buttonMode = true;
  194.             }
  195.         }
  196.        
  197.         // destroys the events on the buttons
  198.         private function killButtonEvents():void
  199.         {
  200.             this._scroller.removeEventListener(MouseEvent.MOUSE_DOWN, manageMouseDown);
  201.             this._scroller.buttonMode = false;
  202.            
  203.             if (this._isTrackClickable)
  204.             {
  205.                 this._track.removeEventListener(MouseEvent.MOUSE_UP, manageTrack);
  206.                 this._track.buttonMode = false;
  207.             }
  208.            
  209.             if (this._arrows)
  210.             {
  211.                 this._upArrow.removeEventListener(MouseEvent.MOUSE_UP, manageUpArrow);
  212.                 this._upArrow.removeEventListener(MouseEvent.MOUSE_DOWN, manageUpArrow);
  213.                
  214.                 this._downArrow.removeEventListener(MouseEvent.MOUSE_UP, manageDownArrow);
  215.                 this._downArrow.removeEventListener(MouseEvent.MOUSE_DOWN, manageDownArrow);
  216.                
  217.                 this._downArrow.buttonMode = this._upArrow.buttonMode = false;
  218.             }
  219.         }
  220.        
  221.         // sets the axis at which the scroller will function against
  222.         private function manageAxis($axis:String):void
  223.         {
  224.             if ($axis == "x")
  225.             {
  226.                 this._changeProp          = "width";
  227.                 this._mouseAxis             = "mouseX";
  228.                 this._changeScale         = "scaleX";
  229.             }
  230.             else if ($axis == "y")
  231.             {
  232.                 this._changeProp          = "height";
  233.                 this._mouseAxis             = "mouseY";
  234.                 this._changeScale         = "scaleY";
  235.             }
  236.         }
  237.        
  238.         // calculates values and responds to changes by the scroller
  239.         private function manageScrolling($evt:Event):void
  240.         {
  241.             var trackSize:Number          = this._track[this._changeProp];
  242.             var trackStart:Number       = this._track[this._axis];
  243.             var trackEnd:Number             = this._track[this._axis] + trackSize - (this._scroller[this._changeProp]);
  244.             var trackRange:Number       = trackEnd - trackStart;
  245.             var maskSize:Number             = this._mask[this._changeProp];
  246.             var movieSize:Number          = this._toBeScrolled[this._changeProp];
  247.             var minPosition:Number    = this._mask[this._axis] + 2;
  248.             var maxPosition:Number    = minPosition + movieSize - maskSize + 4;
  249.             var onePercentChange:Number     = (maxPosition - minPosition) / 100;
  250.             var percent:int                 = Math.round(((this._scroller[this._axis] - trackStart) / trackRange) * 100);
  251.             var targetPosition:int     = Math.round(minPosition - (onePercentChange * percent));
  252.            
  253.             this._trackStart             = trackStart;
  254.             this._trackEnd      = trackEnd;
  255.            
  256.             if (this._scrollType == "instant")
  257.             {
  258.                 this._toBeScrolled[this._axis] = targetPosition;
  259.             }
  260.             else if (this._scrollType == "easing")
  261.             {
  262.                 this._toBeScrolled[this._axis] += Math.round((targetPosition - this._toBeScrolled[this._axis]) / 5);
  263.             }
  264.    
  265.             if (movieSize <maskSize)
  266.             {
  267.                 onePercentChange = 0;
  268.             }
  269.            
  270.             if (this._mouseIsPressedDown)
  271.             {
  272.                 this._scroller[this._axis] = Math.round(this._holder[this._mouseAxis] - (this._scroller[this._changeProp] / 2));
  273.             }
  274.            
  275.             if (this._scroller[this._axis] <trackStart)
  276.             {
  277.                 this._scroller[this._axis] = Math.round(trackStart);
  278.             }
  279.             else if (this._scroller[this._axis]> trackEnd)
  280.             {
  281.                 this._scroller[this._axis] = Math.round(trackEnd);
  282.             }
  283.            
  284.             if (this._scaleScroller) this.manageScrollScaling(movieSize, maskSize);
  285.            
  286.             this.manageControls(this._autoHideControls, movieSize, maskSize);
  287.         }
  288.        
  289.         // regulates mouse pressed down
  290.         private function manageMouseDown($evt:MouseEvent):void
  291.         {
  292.             this._mouseIsPressedDown = true;
  293.            
  294.             this._holder.stage.addEventListener(MouseEvent.MOUSE_UP, manageMouseUp);
  295.         }
  296.        
  297.         // regulates mouse released and mouse released outside
  298.         private function manageMouseUp($evt:MouseEvent):void
  299.         {
  300.             this._mouseIsPressedDown = false;
  301.            
  302.             this._holder.stage.removeEventListener(MouseEvent.MOUSE_UP, manageMouseUp);
  303.         }
  304.        
  305.         // regulates the movement of the content based on where the track is clicked, if applicable
  306.         private function manageTrack($evt:MouseEvent):void
  307.         {
  308.             if (this._isTrackClickable)
  309.             {
  310.                 if (this._scrollType == "instant")
  311.                 {
  312.                     if (this._holder[this._mouseAxis] <this._trackStart)
  313.                     {
  314.                         this._scroller[this._axis] = this._trackStart;
  315.                     }
  316.                     else if (this._holder[this._mouseAxis]> this._trackEnd)
  317.                     {
  318.                         this._scroller[this._axis] = this._trackEnd;
  319.                     }
  320.                     else
  321.                     {
  322.                         this._scroller[this._axis] = Math.round(this._holder[this._mouseAxis] - (this._scroller[this._changeProp] / 2));
  323.                     }
  324.                 }
  325.                 else if (this._scrollType == "easing")
  326.                 {
  327.                     if (this._holder[this._mouseAxis] <this._trackStart)
  328.                     {
  329.                         this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._trackStart, this._duration, true);
  330.                     }
  331.                     else if (this._holder[this._mouseAxis]> this._trackEnd)
  332.                     {
  333.                         this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._trackEnd, this._duration, true);
  334.                     }
  335.                     else
  336.                     {
  337.                         this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], Math.round(this._holder[this._mouseAxis] - (this._scroller[this._changeProp] / 2)), this._duration, true);
  338.                     }
  339.                 }
  340.             }
  341.         }
  342.        
  343.         // moves the scroller up when the up arrow is clicked
  344.         private function moveUp():void
  345.         {
  346.             if (this._scrollType == "instant")
  347.             {
  348.                 this._nextPosition = Math.round(this._scroller[this._axis] - this._arrowMove);
  349.                
  350.                 if (this._nextPosition <this._trackStart)
  351.                 {
  352.                     this._scroller[this._axis] = this._trackStart;
  353.                 }
  354.                 else
  355.                 {
  356.                     this._scroller[this._axis] = this._nextPosition;
  357.                 }
  358.             }
  359.             else if (this._scrollType == "easing")
  360.             {
  361.                 this._nextPosition = Math.round(this._scroller[this._axis] - this._arrowMove);
  362.                
  363.                 if (this._nextPosition <this._trackStart)
  364.                 {
  365.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._trackStart, this._duration, true);
  366.                 }
  367.                 else
  368.                 {
  369.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._nextPosition, this._duration, true);
  370.                 }
  371.             }
  372.         }
  373.        
  374.         // moves the scroller down when the down arrow is clicked
  375.         private function moveDown():void
  376.         {
  377.             if (this._scrollType == "instant")
  378.             {
  379.                 this._nextPosition = Math.round(this._scroller[this._axis] + this._arrowMove);
  380.                
  381.                 if (this._nextPosition> this._trackEnd)
  382.                 {
  383.                     this._scroller[this._axis] = this._trackEnd;
  384.                 }
  385.                 else
  386.                 {
  387.                     this._scroller[this._axis] = this._nextPosition;
  388.                 }
  389.             }
  390.             else if (this._scrollType == "easing")
  391.             {
  392.                 this._nextPosition = Math.round(this._scroller[this._axis] + this._arrowMove);
  393.                
  394.                 if (this._nextPosition> this._trackEnd)
  395.                 {
  396.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._trackEnd, this._duration, true);
  397.                 }
  398.                 else
  399.                 {
  400.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._nextPosition, this._duration, true);
  401.                 }
  402.             }
  403.         }
  404.        
  405.         // regulates the movement of the up arrow, if applicable
  406.         private function manageUpArrow($evt:MouseEvent):void
  407.         {
  408.             if (this._continuousScroll)
  409.             {
  410.                 this._arrowPressed = "up";
  411.                 this._arrowTimer.start();
  412.             }
  413.             else
  414.             {
  415.                 this.moveUp();
  416.             }
  417.         }
  418.        
  419.         // regulates the movement of the down arrow, if applicable
  420.         private function manageDownArrow($evt:MouseEvent):void
  421.         {
  422.             if (this._continuousScroll)
  423.             {
  424.                 this._arrowPressed = "down";
  425.                 this._arrowTimer.start();
  426.             }
  427.             else
  428.             {
  429.                 this.moveDown();
  430.             }
  431.         }
  432.        
  433.         // if continuous scroll is on, manages the timer that moves it up and down
  434.         private function manageContinuousScroll($evt:TimerEvent):void
  435.         {
  436.             if (this._arrowPressed == "up")
  437.             {
  438.                 this.moveUp();
  439.             }
  440.             else if (this._arrowPressed == "down")
  441.             {
  442.                 this.moveDown();
  443.             }
  444.         }
  445.        
  446.         // if continuous scroll is on, resets the timer after you release an arrow button
  447.         private function resetArrowTimer($evt:MouseEvent):void
  448.         {
  449.             if (this._continuousScroll)
  450.             {
  451.                 this._arrowTimer.reset();
  452.             }
  453.         }
  454.        
  455.         // auto hides/shows the controls of the scroller
  456.         private function manageControls($isAutoHideEnabled:Boolean, $contentSize:Number, $maskSize:Number):void
  457.         {
  458.             if ($isAutoHideEnabled && $contentSize <= $maskSize)
  459.             {
  460.                 // yes, hide controls
  461.                 this._arrow1Tween   = new Tween(this._upArrow, "alpha", this._easeFunc, this._upArrow.alpha, 0, this._duration, true);
  462.                 this._arrow2Tween   = new Tween(this._downArrow, "alpha", this._easeFunc, this._downArrow.alpha, 0, this._duration, true);
  463.                 this._scrollerTween = new Tween(this._scroller, "alpha", this._easeFunc, this._scroller.alpha, 0, this._duration, true);
  464.                 this._trackTween    = new Tween(this._track, "alpha", this._easeFunc, this._track.alpha, 0, this._duration, true);
  465.                
  466.                 this.killButtonEvents();
  467.             }
  468.             else
  469.             {
  470.                 // no, show controls
  471.                 this._arrow1Tween   = new Tween(this._upArrow, "alpha", this._easeFunc, this._upArrow.alpha, 100, this._duration, true);
  472.                 this._arrow2Tween   = new Tween(this._downArrow, "alpha", this._easeFunc, this._downArrow.alpha, 100, this._duration, true);
  473.                 this._scrollerTween = new Tween(this._scroller, "alpha", this._easeFunc, this._scroller.alpha, 100, this._duration, true);
  474.                 this._trackTween    = new Tween(this._track, "alpha", this._easeFunc, this._track.alpha, 100, this._duration, true);
  475.                
  476.                 this.activateButtonEvents();
  477.             }
  478.         }
  479.        
  480.         // regulates the scaling of the scroller, if applicable
  481.         private function manageScrollScaling($contentSize:Number, $maskSize:Number):void
  482.         {
  483.             var trackPercent:Number = ($maskSize / $contentSize);
  484.            
  485.             if ($contentSize> $maskSize)
  486.             {
  487.                 this._scroller[this._changeScale] = trackPercent;
  488.             }
  489.             else
  490.             {
  491.                 this._scroller[this._changeScale] = 1;
  492.             }
  493.         }
  494.        
  495.         // regulates the movement of the mouse wheel
  496.         private function onMouseWheel($evt:MouseEvent):void
  497.         {
  498.             var delta:int = $evt.delta;
  499.             var multiplier:Number = 10;
  500.            
  501.             if (this._scrollType == "instant")
  502.             {
  503.                 this._nextPosition = Math.round(this._scroller[this._axis] - (delta * multiplier));
  504.                
  505.                 if (this._nextPosition <this._trackStart)
  506.                 {
  507.                     this._scroller[this._axis] = this._trackStart;
  508.                 }
  509.                 else if (this._nextPosition> this._trackEnd)
  510.                 {
  511.                     this._scroller[this._axis] = this._trackEnd;
  512.                 }
  513.                 else
  514.                 {
  515.                     this._scroller[this._axis] = this._nextPosition;
  516.                 }
  517.             }
  518.             else if (this._scrollType == "easing")
  519.             {
  520.                 this._nextPosition = Math.round(this._scroller[this._axis] - (delta * multiplier));
  521.                
  522.                 if (this._nextPosition <this._trackStart)
  523.                 {
  524.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._trackStart, this._duration, true);
  525.                 }
  526.                 else if (this._nextPosition> this._trackEnd)
  527.                 {
  528.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._trackEnd, this._duration, true);
  529.                 }
  530.                 else
  531.                 {
  532.                     this._tween = new Tween(this._scroller, this._axis, this._easeFunc, this._scroller[this._axis], this._nextPosition, this._duration, true);
  533.                 }
  534.             }
  535.         }
  536.        
  537.         // regulates the movement of the up and down keyboard keys
  538.         private function onKeyPressed($evt:KeyboardEvent):void
  539.         {
  540.             if (this._axis == "x")
  541.             {
  542.                 switch($evt.keyCode)
  543.                 {
  544.                     case 37: // left
  545.                         this.moveUp();
  546.                         break;
  547.                        
  548.                     case 39: // right
  549.                         this.moveDown();
  550.                         break;
  551.                 }
  552.             }
  553.             else if (this._axis == "y")
  554.             {
  555.                 switch($evt.keyCode)
  556.                 {
  557.                     case 38: // up
  558.                         this.moveUp();
  559.                         break;
  560.                        
  561.                     case 40: // down
  562.                         this.moveDown();
  563.                         break;
  564.                 }
  565.             }
  566.         }
  567.        
  568. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  569.    
  570.         /**
  571.          * Creates the scroller again if it was deleted using destroy.
  572.          *
  573.          * @usage <pre><code>scroller.create();</code></pre>
  574.          *
  575.          * @return Nothing
  576.          */
  577.        
  578.         public function create():void
  579.         {
  580.             this.init();
  581.         }
  582.        
  583.         /**
  584.          * Resets the position of the scroller and the content movie clip to its initial position.
  585.          *
  586.          * @usage <pre><code>scroller.reset();</code></pre>
  587.          *
  588.          * @return Nothing
  589.          */
  590.        
  591.         public function reset():void
  592.         {
  593.             this._scroller[this._axis] = this._trackStart;
  594.         }
  595.        
  596.         /**
  597.          * Performs garbage collection of events.
  598.          *
  599.          * @usage <pre><code>scroller.destroy();</code></pre>
  600.          *
  601.          * @return Nothing
  602.          */
  603.        
  604.         public function destroy():void
  605.         {
  606.             this._holder.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
  607.             this._holder.removeEventListener(Event.ENTER_FRAME, manageScrolling);
  608.             this._stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);
  609.            
  610.             if (this._continuousScroll)
  611.             {
  612.                 this._arrowTimer.removeEventListener(TimerEvent.TIMER, manageContinuousScroll);
  613.                 this._arrowTimer = null;
  614.             }
  615.            
  616.             this.killButtonEvents();
  617.         }
  618.    
  619. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  620.    
  621.        
  622.    
  623. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  624.    
  625.         /**
  626.          * Gets the value of autoHideControls to see if they are currently being hidden or not.
  627.          *
  628.          * @usage <pre><code>trace(scroller.autoHideControls);</code></pre>
  629.          *
  630.          * @return Boolean
  631.          */
  632.        
  633.         public function get autoHideControls():Boolean
  634.         {
  635.             return this._autoHideControls;
  636.         }
  637.        
  638.         /**
  639.          * Sets the value of autoHideControls "on-the-fly".
  640.          *
  641.          * @usage <pre><code>scroller.autoHideControls = true;</code></pre>
  642.          *
  643.          * @return Nothing
  644.          */
  645.        
  646.         public function set autoHideControls($b:Boolean):void
  647.         {
  648.             this._autoHideControls = $b;
  649.         }
  650.    
  651. //- HELPERS -----------------------------------------------------------------------------------------------
  652.    
  653.         public function toString():String
  654.         {
  655.             return "com.reintroducing.ui.AxisScroller";
  656.         }
  657.    
  658. //- END CLASS ---------------------------------------------------------------------------------------------
  659.     }
  660. }

If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.

34 Comments

Very nice Matt!

Great thanks! I found a bug though. Scroll to the bottom, then click directly at the top. You can notice it better if the movie_mc is only slightly bigger than the mask, but there is always a little bounce as the scroller reaches the top.

http://img502.imageshack.us/img502/2429/examplesl0.jpg

great thanks! Found a bug though. If you scroll all the way down, then click right at the top, there is a little bounce back (if that makes sense). Its more obvious if your movie_mc is smaller, but still visible in the example.

http://img130.imageshack.us/img130/5766/examplepo2.jpg

[...] View Preview Download Example Files Download AxisScroller [...]

I'm just going to repost what I posted in the other post about this for legacy purposes for anyone reading this in the future:

Tomer,
Yeah, I've found this to be true in both versions of the AxisScroller, it is because of the ability to scale the scroller to the content which was introduced in v1.5 of the AS2 version i believe because I had to make the scroller be able to take on other sizes, so now that is not controllable. I've been thinking about how to reduce that and will still consider it, but its not a priority. After all, you can just set the track to not clickable and it won't be a problem πŸ˜›

Hey Matt,

First of all thanks for putting your classes up here, they're a great help!
I've been trying to impliment your axisscroller into a project but everytime I do it gives me a

1137: Incorrect number of arguments. Expected no more than 0.

error... the code works in one fla (built off your example), but not with a new project, I have no idea why it's doing it? If you could give me a pointer, that would be awesome!

Here's the code I'm using

import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.*;
import com.reintroducing.ui.AxisScroller;

var optionalObj:Object = new Object({
scrollType: "easing",
isTrackClickable: true,
useArrows: true,
upArrow: content_mc.up_btn,
downArrow: content_mc.down_btn,
continuousScroll: false,
easeFunc: Regular.easeOut,
duration: .25,
arrowMove: 9,
scaleScroller: true,
autoHideControls: true
});

var scroller:AxisScroller = new AxisScroller(stage, content_mc, content_mc.scroller_mc, content_mc.movie_mc, content_mc.track_mc, content_mc.mask_mc, "y", optionalObj);

//Create the URLLOader instance
var myLoader:URLLoader = new URLLoader()
//the data will come as URL-encoded variables
myLoader.dataFormat = URLLoaderDataFormat.VARIABLES
//Load using an URLRequest, even beeing local
myLoader.load(new URLRequest("http://dev.papertank.net/receipt/products.php"))
//onLoad handler listener
myLoader.addEventListener(Event.COMPLETE, onDataLoad)
//add a listener for the complete event
function onDataLoad(evt:Event){
for(var i:uint=0; i<evt.target.data.entries; i ){
var menu_item:item=new item();
content_mc.movie_mc.addChild(menu_item);
menu_item.y = 40*i;
menu_item.name_txt.text = evt.target.data["product" i];

}
}

Thanks!

Liam

Hey Liam,
I don't think my blog is parsing your code correctly as I think it has removed the signs in your for loop and possibly some other stuff. If you'd like, send me an FLA (preferably with the problem isolated if it is part of a bigger project) that throws the error and I can take a look at it and try and see if I can figure it out. You can send it to matt [at] reintroducing [dot] com. Thanks.

For anyone reading this, apparently you can no longer pass in parameters to the Object constructor (was this always like this? I swear this example worked for me before and many times in the past...)

The solution can be executed in two ways:

1. when creationg the optionalParams object, just do this:

Actionscript:
  1. var optionalParams:Object = {scrollType: "easing", etc...};

2. the other, and longer method, is to create the object and then assign its properties, like so:

Actionscript:
  1. var optionalParams:Object = new Object();
  2. optionalParams.scrollType = "easing";
  3. etc...

Hi Matt i have a problem when this scroll is called with a Loader in swf external this is a message ...

TypeError: Error #1009: No se puede acceder a una propiedad o a un mΓ©todo de una referencia a un objeto nulo.
at com.magiadigital.ingepet::AxisScroller/::manageUpArrow()

Help me please πŸ™

Alexis,
I'm not sure I understand what you are trying to do, nor do I understand spanish πŸ˜›

Hi Matt,
if I set useArrows to false and I omit upArrow and downArrow properties I get this error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.reintroducing.ui::AxisScroller/manageControls()
at com.reintroducing.ui::AxisScroller/manageScrolling()

Is this normal? How can I disable the arrows without getting this error?

Thanks

hmm, that should not be happening. can you paste your code for settings up the scroller?

I have simply modified your example:

import com.reintroducing.ui.AxisScroller;
import gs.easing.Sine;

var optionalObj:Object =
{
scrollType: "easing",
isTrackClickable: true,
useArrows: false,
continuousScroll: false,
easeFunc: Sine.easeOut,
duration: .25,
scaleScroller: true,
autoHideControls: true
};

var scroller:AxisScroller = new AxisScroller(stage, content_mc, content_mc.scroller_mc, content_mc.movie_mc, content_mc.track_mc, content_mc.mask_mc, "y", optionalObj);

I can send you fla file too if you need.

Thanks for help

Riccardo,
I posted a new version (1.1) that doesn't cause this issue. Please read my post on the front page though about other possible issues this may create.

Matt,
I've just ridden your post and I'm trying new version and like you said doesn't cause this issue.

This is the best scrollbar I've ever seen. I'm using it from as2 version and has everything someone can need. Thank you for sharing it Matt.

Thanks for your support Riccardo. I hope to eventually replace this with an even better version but that will have to wait for the time being.

Matt,

I added the AxisScroller to my project today, and I have a couple of questions.

First, when I launch the project, the scrollable content seems to have a Y offset, where the top has blank space above it, and the bottom doesn't completely scroll into view.

I also need to have an alternate way of scrolling the content. It would be best if I could modify or extend AxisScroller.as to accept absolute or relative offsets. What would be the best value to change to achieve this?

Other than that, I think this is great! exactly what I needed. I was referred to it by someone on the #Papervision3D IRC channel.

Craig,
I think the first problem you are having has to do with how your clips are set up as i've never had that issue before.

as for the second one, it is possible but it's kind of hard to control with the way this was coded, hence why i've been wanting to re-write it for a while now. that kind of stuff is not easily done with this version and it's something i've been wanting to add because i've wanted that kind of control in the past as well.

i apologize because those are probably not answers you wanted to hear but unfortunately i don't really have better ones at this time :\

Matt,

Thanks, I have my problems figured out for now...

The first "fix" was to add a variable...

private var _offsetHack:Number;

and add it to the optionalParams object...

this._offsetHack = ($optionalParams.offsetHack == null) ? 0 : $optionalParams.offsetHack;

then in the private function manageScrolling, I changed the targetPosition to this:

var targetPosition:int = Math.round(minPosition - (onePercentChange * percent)+_offsetHack);

and then all I had to do was pass a non-zero offset, and that "fixed" it.

For the scrolling via code, I added this function:

public function scrollBy(increment:Number):void
{
this._scroller[this._axis] += increment;
this._scroller[this._axis] = Math.max(Math.min(this._scroller[this._axis] ,this._trackEnd),this._trackStart);
}

if I call that function and send it a percentage of scroll (positive or negative) it will move the scroller (and then the content) by that amount, and limit it to the top/bottom via the second line. Yay!

(I hope all those formatting tags work, otherwise this comment will be kind of a jumble.)

thanks again!

Craig

Craig,
glad you got it figured out. the code in this class is kind of a mess when i go back and look at it but if its working for you then by all means keep using it. like i said, i do plan on redoing it when i get some free time.

Hey Matt,
Thanks for the great work but I am having a small problem.

I have the scroll bar sitting in a movieclip that has a MOUSE_OVER and MOUSE_OUT events attached to it. For some reason when I scroll with the mouse wheel over the content I'd like to scroll, it scrolls properly but when it is done scrolling the scroller immediately snaps back to the top of the scroll bar.

As well when I roll over the scroller it fires the parent clips MOUSE_OUT event. This is obvious enough and is the expected behavior, I need to write a solution myself but I thought I'd mention it in case you thought it would be related.

Thanks again.
Phil

@Phil: I have not experienced problems like this. My assumption is that it has something to do with other code in your file and there are some things getting intertwined that probably shouldnt.

@Matt: I manged to resolve the problem by setting autoHideControls = true;

I do not know why this would make a difference but it did thankfully.

Hey Matt.

Just found your class and was keen to view the example fla, however it doesn't work on CS3 mac. I just get a "Failed to load" message.

Any ideas?

Crunchie,
I have no idea why thats happening. That's not a CS4 to CS3 error (plus these files were made with CS3 on a mac). I tried googling that error and it seems there could be a problem with your ActiveX controls, but I'm not sure what else to tell you. Is anyone else getting this error or can you possibly have someone else you know test it?

Hi Matt.

Possibly i didn't explain correctly. The .fla will not load into the IDE. I found another example of your double axis one and the fla works fine on that. I thought i best let you know.

All the best.

hmm, maybe I did re-save this in CS4. I saved it out as a CS3 FLA now so please test again and let me know if that works. Thanks Crunchie.

Hi Matt.
I just downloaded from http://evolve.reintroducing.com/_source/classes/as3/AxisScroller/AxisScroller.zip

Still fails to load for me πŸ™

try clearing your cache and re-downloading. it may be downloading a cached version.

[...] In the example we use AxisScroller which is available at EVOLVE.Β  But this method should work with any scrollbar class. Share the [...]

I am using GAIA framework with multiple scrollers (one on each page) On my transition out I need to destroy the scroller.. because every page I goto my memory is jumping 2 megs per page. Its only happening on your scroller pages... if I click the same 2 pages back and forth I can essentially boost the memory +2 megs everytime until my flash crashes. How do I use destroy??? my scroller is called ffxscroller

public var ffxscroller:AxisScroller;

would it be ffxscroller.destroy();

its throwing errors TypeError: Error #1009: Cannot access a property or method of a null object reference.

so where is the .destroy(); linking too? or am I not even close??? please help.. I have to have this site done in 2 weeks and at this point the memory leaks are going to kill someone looking at the page for more than 10 minutes.. πŸ™‚ your scroller is great besides me not being able to clear the garbage out on each page.

@zurie: I apologize for the delayed reply but I was on vacation and am only now catching up. Anyway, I would not bank on bank on this scroller for the cleanest coding. I'm actually going to be re-writing it from scratch so I can have more control over some of the new options I'm going to be adding to it so feel free to cut this thing up as you see fit as I'm not really supporting it anymore or encouraging users to use it because it just got wacky when I started to add stuff to it. It's old code written a long time ago and just needs a rewrite to function better, unfortunately.

Hey Matt, I solved my issue. Using VarCentral class I made a var for ffxscroller like
VarCentral().var.ffxscroller = ffxscroller

then later on I called

VarCentral().var.ffxscroller.destroy(); and it worked fine. SO thank you for the reply, everything is great. and I look forward to seeing your new class.

Nice post. I learn something totally new and challenging on
sites I stumbleupon on a daily basis. It's always exciting to read articles from other authors and use something from other sites.

Leave a comment

(required)

(required)