Content Scrollbar (Revised)

Hi everyone,
Here is something that I worked on earlier today. Basically, it is a simplified scrollbar that scrolls whatever content you place into a movie clip.

From my initial testing, the scrollbar seems easy to use for beginners. The code automatically adjusts for varying heights in the content, scrollbar, and dragger button so that the scrolling boundaries remain consistent.

Cheers!
Kirupa :beam:

How do I modify the code if I want to remove the up/down buttons and just have the scrollbar?

Hi guys
I was just wondering if this has happened before:
When I start my movie everything works fine except for the start position of my contentMain. It has an offset causing the content to be displayed near the bottom of the mask. When I scroll I cannot reach the bottom of the contentMain. I already added the + XX as stated in an earlier post and can scroll all the way down now but still there is the offset at the start position of contentMain.

Any ideas?

Thanks

tdi just replace the image of the up/down buttons with an alpha=0% movieclip?

I’ve used the easing code with external data. every xml record will create an extra movieclip with the duplicate movieclip code. But the scroller never get’s to the bottom.

an example at http://www.dri360.com/flash_main.php then press “nieuws” at the menu. after the scroller comes there will follow even two extra records. But the scroller does not reach the bottom. This is my code:


scrolling = function (easing)
{
	var moveSpeed:Number = 20;
	var easingSpeed:Number = 10;
	var scrollHeight:Number = scrollTrack._height;
	var contentHeight:Number = contentMain._height;
	var scrollFaceHeight:Number = scrollFace._height;
	var maskHeight:Number = maskedView._height;
	var initPosition:Number = scrollFace._y = scrollTrack._y;
	var initContentPos:Number = contentMain._y;
	var finalContentPos:Number = maskHeight - contentHeight + initContentPos;
	var left:Number = scrollTrack._x;
	var top:Number = scrollTrack._y;
	var right:Number = scrollTrack._x;
	var bottom:Number = scrollTrack._height - scrollFaceHeight + scrollTrack._y;
	var dy:Number = 0;
	var speed:Number = 20;
	var moveVal:Number = (contentHeight - maskHeight) / (scrollHeight - scrollFaceHeight);
	scrollFace.onPress = function ()
	{
		var currPos:Number = this._y;
		startDrag (this, false, left, top, right, bottom);
		this.onMouseMove = function ()
		{
			dy = Math.abs (initPosition - this._y);
			contentMain.newY = Math.round (dy * -1 * moveVal + initContentPos);
		};
	};
	contentMain.onEnterFrame = function ()
	{
		if (!easing || easing == undefined)
		{
			this._y = this.newY;
		}
		else
		{
			this._y += (this.newY - this._y) / easingSpeed;
		}
	};
	scrollFace.onMouseUp = function ()
	{
		stopDrag ();
		delete this.onMouseMove;
	};
	if (contentHeight < maskHeight)
	{
		scrollFace._visible = false;
	}
	else
	{
		scrollFace._visible = true;
	}
};
scrolling (true);

Does someone have any solution? is it even possible?
i red a reply from kirupa and does it says it’s not possible?

umm why not just make an holderMc and let that scroll with an ease based on the percentage of the dragbar y pos?

I wrote a tutorial for this and will be up soon

Ok i’ll wait for that then. I mad a holderMc but it’s normally only about 20 or 30 px high. only after the data loaded dynamicly the holderMc is larger and it will not be recornized by the scrollbar. :bounce:

Ok i’ll wait for that then. I mad a holderMc but it’s normally only about 20 or 30 px high. only after the data loaded dynamicly the holderMc is larger and it will not be recornized by the scrollbar. :bounce::eye:

Remember:

The scrolling is based on the Stagewidth, if you want the scroller to be related to “scroll window” simply add a mask to your content and replace

var sHeight = Stage.height;

with

var sHeight = myMask._height;

To add dynamic text simply put a dynamic textbox in the holder MC.
Load your text. Activate “Multiline”, and add this code;

holder.myText.autoSize = “left”;

enjoy.

EDIT

sorry for the stopDrag not workin.


replace “stopDrag;” with “stopDrag();”


with dynamicly loaded text

Greggeh,

dank.

But my file already uses a mask.,

Check my file here it’s maybe easyer when you see how it’s build.

Greggeh,

dank.

But my file already uses a mask.,

Check my file here it’s maybe easyer when you see how it’s build.

K but you problem was you scroller didnt scroll down to the bottom.
i think i know why that is… because there are apaces between the textfield.
which do not add up to the holder._height.

make an mc (prolly square) and make the alpha to 0. then write something so the background mc is the total height of all the textfields + the spaces. something like

backGroundMC._height = latestTextField._y + latestTextField._height;

maybe thatll work.

I’ll try that this evening and let it know in the morning if it worked…

Thanks Greggeh

I had a problem with these and many other scrollers when loading dynamic content.
I fixed it by placing an alpha=0 mc at the top of the field and then placing one at the bottom of the field directly after I loaded text.

i dont know why the scroller didnt work properly without this.
happy though to solve the problem i was havin

I tried it but it doesn’t matter. i’ll keep on working on it but for every record there will be another Mc. with dynamic content within.

maybe if i add another movieclip in the timeline before the duplicate mc
i the height of the scroller.

Howdy,

I’m on the newer side of Actionscripting and I’m working with a project where I need to scroll through the frames (about 50) of a movie clip rather than masking a one-frame movie clip. The tutorials I’ve seen in this thread are the closest to what (I think) I’m looking for but it’s doesn’t seem quite right. Does anyone have a suggestion?

Borcho

i’m not a actionscript guru either far from that but maybe you can try something like:
give the scollbutton the next script.
If someone thinks i’m totally wrong let me know :rap:


onPress {
	this.startDrag._x
	play();
}

onRelease {
	this.stopDrag();
	stop();
}

Hey guys, I’ve been away from this thread for a while, been really busy with work. After thinking about the “not showing the bottom of the scroll” situation, I figured out what it was and came up with a solution.

The math that is used in the Easing Equation deals with proportional movement. The value never quite makes it all the way, this is because we are doing floating point division, we could easily achieve a smooth easing effect using integer division.

Again the problem is that currently we are ALWAYS approaching the end position, but never quite make it there. This is where our integer division comes in to play, we utilize integer division with the bit shift operator, we will bit-shift the value to the right by 3 binary digits.

I have composed a class and an example file…

This class only works with Flash 8, so I have posted the class code so that you can look through it.

The only reason it is specific to Flash 8 is because I use a Rectangle as the viewable property, again this is for my personal use, if you’d like to use it and are not running Flash 8 you will need to convert it yourself.

MyScrollbar.as

import flash.geom.Rectangle;
/*
 *  This is a generic scrollbar class, it has some requirements that have
 *  to be met in order for it to work.
 *  Requirements:
 *    - a dragger movieclip (instance name = dragger)
 *    - a track movieclip (instance name = track)
 *    - both up and down buttons (instance names = up,down)
 *
 *  Notes:
 *    - At the moment this is only meant to work with scrolling on the y axis.
 *
 *@author: Michael Avila (MichaelxxOA)
 *@version: 1.0
*/
class MyScrollbar
{
   // the content we will be scrolling
   private var content:MovieClip;
   // the movieclip that represents the viewable area of our content, most likely a mask
   private var viewable:Rectangle;

   // elements in the scrollbar
   public var dragger:MovieClip;
   private var track:MovieClip;
   private var up:MovieClip;
   private var down:MovieClip;

   // the limits as to how far the dragger can move in any direction
   public var left:Number;
   public var top:Number;
   public var right:Number;
   public var bottom:Number;
   // how fast the dragger will move
   public var move_speed:Number = 3;


   /*
    * Scrolling equation values
   */
   
   // how much of our content can be scrolled, defaults at 0
   private var scrollable:Number = 0;
   // where our content will sit when it is at 0% scrolled, defaults at 0.
   // it is likely that we will set this to be the initial position of our content, before any scrolling is applied
   private var top_scroll:Number = 0;

   /* Constructor */
   public function MyScrollbar()
   {
      
      // initialize all boundaries
      left = track._x;
      top = track._y;
      right = track._x;
      bottom = track._y + (track._height - dragger._height);

      // Register this object to receive events from the Mouse class
      Mouse.addListener( this );
   }

   /*
    * PUBLIC API
    *
    *    - Two of these methods have to be invoked before our scrollbar will work
    *      We will need to call, setContent() and setViewable().  The others are optional.
   */
   public function setContent( content:MovieClip ):Void
   {
      this.content = content;
      setScrollProps();
   }
   public function setViewable( viewable:Rectangle ):Void
   {
      this.viewable = viewable;
      setScrollProps();
   }
   // set easing either true/false
   public function setEasing( value:Boolean, speed:Number ):Void
   {
      content.isEasing = value;
      
      
      if (speed > 0 && value)
      {
         content.speed = speed;
      }
   }
   /*
    * Private Methods
    *
    * Probably the single most important function in our class, this will set our contents newY property to 
    * it's proper value
   */
   // public for the event handlers.. still not considered part of the API
   public function updateContentPos():Void
   {
		var percent_scrolled:Number = (dragger._y-track._y)/(track._height-dragger._height);
		// instead of setting the _y property directly, we simple set newY
		// that way we can adjust how we handle the new Y coordinate we'd like to move to
		content.newY = Math.round(top_scroll - (percent_scrolled * scrollable));
   }

   
   private function setScrollProps():Void
   {
      // if either viewable or content hasn't been set we cannot successfully set our scroll properties
      // so return out of the function
      if (viewable == undefined || content == undefined) return;

      // if not then set properties
      scrollable = content._height - viewable.height;
      top_scroll = content._y;

      initElements();
      checkScrollability();
   }
   // checks whether or not our content is scrollable, if it is not than we hide the dragger and disable the
   // other elements
   private function checkScrollability():Void
   {
      if (scrollable < 0)
      {
         dragger._visible = false;
         up._alpha = 50;
         down._alpha = 50;
         track._alpha = 50;
      }
   }

   /**
    * Executes when the mouse wheel is scrolled.
    */
   private function onMouseWheel ( delta:Number ) : Void
   {
      var speed:Number =  (delta > 0) ? move_speed : -move_speed;
      dragger._y = Math.min( bottom, Math.max(top, dragger._y-speed));
      updateContentPos();
   }

   /*
    *  This function might be a little messy as it is created to initialize all elements and their event handlers.
    *  The only thing that we are doing odd in this method is the fact that we are setting a src property on each
    *  element.  We do this so that we can make calls to functions in the MyScrollbar class.
    *
    *  Another thing about our src property is that in order for the compiler to not throw an error we have to
    *  declare it with a null value, our declared src property is not the src property that we will be accessing
    *  in our elements event handlers.
   */
   private function initElements():Void
   {
      var src;// trick compiler.

      // set src properties on all elements
      dragger.src = this;
      track.src = this;
      up.src = this;
      down.src = this;

      // CONTENTS EVENT HANDLERS
      var newY; // trick compiler
      var isEasing;
      var speed; // trick the compiler

      content.speed = move_speed;

      content.onEnterFrame = function()
      {
         if (this.isEasing)
         {
            this._y += (this.newY-this._y) >> this.speed;
            return;
         }
         this._y = this.newY;
      }

      // DRAGGERS EVENT HANLDERS
      dragger.onPress = function()
      {
         this.startDrag(false, this.src.left, this.src.top, this.src.right, this.src.bottom);
         
         this.onMouseMove = function()
         {
            this.src.updateContentPos();
         }
      }
      dragger.onMouseUp = function()
      {
         stopDrag();
         delete this.onMouseMove;
      }
      
      // UP BUTTONS EVENT HANDLERS
      up.onPress = function()
      {
         this.onEnterFrame = function()
         {
            this.src.dragger._y = Math.max(this.src.top, this.src.dragger._y-this.src.move_speed);
		   	this.src.updateContentPos();
         }
      }
      up.onDragOut = up.onRelease =  function()
	   {
		   delete this.onEnterFrame;
	   }

      // DOWN BUTTONS EVENT HANDLERS
      down.onPress = function()
	   {
		   this.onEnterFrame = function()
		   {
			   this.src.dragger._y = Math.min(this.src.bottom, this.src.dragger._y+this.src.move_speed);
		   	this.src.updateContentPos();
		   }
	   }
	   down.onDragOut = down.onRelease = function()
	   {
		   delete this.onEnterFrame;
	   }

   }
}



Take Care.

_Michael

Michael,

Maybe i miss understood your post but i thought your scroller is for dynamic data. Or just not? I’m using an XML file for every record but the scroller does not appear when loaded. Because it doesn’t recorgnize all the data but only the given Mc, wich is only 20 or 30 pixels high

Is it just not possible to add dynamic data from an xml file to this scroller?

Jos