The NpScrollingPanel is a ActionScript 3 Implementation of a scrolling panel. Pretty common place stuff.
The NpScrollingPanel Class is designed to create a scrolling pane of content. The Class itself does not handle any loading in of content. You must provide the class with DisplayObjects for it to scroll. I wanted it to be completely content independent.
There’s actually two versions of the class in the download. One, which uses a mask for the scrolling area and another which uses a scrollRect. The mask performs better when you are scrolling with the blur filter enabled. Where as the scrollRect performs marginally better when just scrolling content. The scrollRect implementation also tends to keep memory useage slightly lower. One thing that using a scrollRect will cause is a slight jump in the scrolling as Flash clears the temp bitmapData it creates when creating the bitmap representation of the scrolled content. The advantage of the scrollRect approach is that you can use the blur filter when your scrolled content is larger than Flash’s 2880 px bitmapData limit, which you will come up against in the mask version. The reason for the scrollRect being slightly slower when using the blur is that it must iterate across each content item being scrolled and blur each one, rather than blurring the entire NpScrollingPanel instance. The reason for the iteration is that if you blur the entire instance, it blurs out past the boundaries of the clipped area, which can look cool or bad, depending on your point of view. I took the the bad view.
Anyway, you can use whatever version you like. They are functionally equivalent.
Let me know if there are bugs etc..
Class Features
- Scroll x and y
- Fixed or stage width / height scrolling area
- Create columns / rows of scrolling content
- Scroll via mouse movement, or via external sources
- Scrolls any DisplayObject
- Adjust content item padding on the fly
- Remove content items on the fly
- Use lots of cpu with a blur scroll mode
- Simple internal easing engine
- Control scroll speed and easing
- Enable / Disable scrolling
- Target individual content items
View Example
Here is an example. It’s using external XML content and the vertical scroller is pulling in two bitmaps from the library; http://www.noponies.com/dev/as3_scrollingpanel/
Source Files
Here are the relevant source file; http://www.blog.noponies.com/wp-content/uploads/npscrollingpanel.zip
Dependencies
The .fla’s use the Memory and Framerate monitoring component from Grant Skinner, which you can get here: http://www.gskinner.com/blog/archives/2008/04/simple_componen.html, otherwise, there are no dependencies.
Class ActionScript (just the main Scroller Class)
*Copyright 2008 noponies.
*/
package noponies.ui{
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.DisplayObject;
import flash.net.URLRequest;
import flash.events.*;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.filters.*;
import noponies.events.NpScrollingPanelEvent;
import noponies.display.NpScrollingPanelItem;
/**
* <strong>NpScrollingPanel</strong>
* <p>The NpScrollingPanel Class is designed to create a scrolling pane of content. The Class itself does not handle any loading in of content. You must
* provide the class with DisplayObjects for it to scroll.</p>
* <p>The Class supports scrolling in response to mouse movement over the panel, or via a public method.</p>
* <p>It also suppors creating rows or columns of content and scrolling that. The Class also supports scaling its mask to browsers dimensions
* or you can simply set it to a fixed size. You are also able to remove individual content items and the class will update the position
* of the content items to accomodate items being removed.</p>
* <p>Each content item is wrapped in a NpScrollingPanelItem Instance, which dispatches various custom mouse events. You can use these events to
* track what content item has been clicked etc. Useful for using this class as part of a gallery etc.</p>
* <br /><br />
* <b>Author:</b> noponies - <a href="http://www.blog.noponies.com/" target="_blank">www.blog.noponies.com</a><br />
* <b>Class version:</b> 1<br />
* <b>Actionscript version:</b> 3.0 Player Version 9.0.28<br />
* <b>Copyright:</b>
* Creative Commons AttCreative Commons Attribution 3.0 New Zealand License<br />
* <a href="http://creativecommons.org/licenses/by/3.0/nz/" target="_blank">http://creativecommons.org/licenses/by/3.0/nz/</a><br />
* <em>You can use this class how you like, except as a base for Flash Components or for Flash Template sites.</em><br />
* <br />
* <b>Date:</b> 03 September 2008<br />
*/
public class NpScrollingPanel extends Sprite {
//--------------------------------------
// PRIVATE INSTANCE PROPERTIES
//--------------------------------------
private var maskWidth:int;
private var maskHeight:int;
private var counter:int;
private var padding:int = 10;
private var thumbYpos:int
private var thumbXpos:int
private var thumbMask:Sprite;
private var thumbsHolder:Sprite;
private var thumbsHolderBg:Sprite;
private var itemArray:Array
private var hitRect:Rectangle
private var drawBg:Boolean = true
private var bgColour:uint = 0xFFFFFF
private var blurScroll:Boolean = false
private var blurQual:int = 3
//scroller variables
private var useMouseScroll:Boolean = true;
private var clipHalf:int;
private var scrollSpeed:Number = .2
private var pos:Number = 0;
private var panelDirection:String = "horizontal";
private var useStageDim:Boolean = true;
private var mPos:int
private var targPos:Number
private var scrollingEnabled:Boolean
private var mX:int
private var mY:int
private var cachePanelAsBit:Boolean = true
private var blurAmount:Number = .4
private var panelSnap:int = 3
//--------------------------------------
// GETTERS / SETTERS
//--------------------------------------
/**
* Get / Set the spacing between each content item within the NpScrollingPanel.
* <p><em>This is a Class Instantiation Property. But you can use the <code>adjustPadding()</code> method to change padding at runtime!</em></p>
* @default 10
* @return int
*/
public function get contentPadding():int {
return padding;
}
/**
* @private
*/
public function set contentPadding(newThumbPadding:int):void {
padding = newThumbPadding;
}
/**
* Get / Set the <code>y</code> position of each thumbnail in within the NpScrollingPanel. The purpose of this property is to enable you to
* create mulit rows of content within the NpScrollingPanel.
* <p>To create a extra row of thumbnails within the NpScrollingPanel you would set both the <code>thumbYposition</code> and the <code>thumbXposition</code>
* properties. For instance, if you are wanting to scroll content horizontally, with two rows after say the 10th element, you would reset the <code>thumbXposition</code> to <code>0</code>
* as this property increments with each new thumbnail addition as well as changin the <code>thumbYposition</code> to reflect the new <code>y</code> value of the next row of content.</p>
* <p><em>This is a Class Instantiation Property</em></p>
* @default 0
* @return int
*/
public function get contentYposition():int {
return thumbYpos;
}
/**
* @private
*/
public function set contentYposition(newThumbYpos:int):void {
thumbYpos = newThumbYpos;
}
/**
* Get / Set the <code>x</code> position of each thumbnail in within the NpScrollingPanel. The purpose of this property is to enable you to
* create mulit columns of content within the NpScrollingPanel.
* <p>To create a extra row of thumbnails within the NpScrollingPanel you would set both the <code>thumbXposition</code> and the <code>thumbYposition</code>
* properties. For instance, if you are wanting to scroll content vertically, with two rows after say the 10th element, you would reset the <code>thumbYposition</code> to <code>0</code>
* as this property increments with each new thumbnail addition as well as changin the <code>thumbXposition</code> to reflect the new <code>X</code> value of the next column of content.</p>
* <p><em>This is a Class Instantiation Property</em></p>
* @default 0
* @return int
*/
public function get contentXposition():int {
return thumbXpos;
}
/**
* @private
*/
public function set contentXposition(newThumbXpos:int):void {
thumbXpos = newThumbXpos;
}
/**
* Get / Set the buffer that occurs at the start and end of the scrolling panel where the mouses positional value is rounded up or down depending on if its at the far left (down) or far right(up)
* of the scrolling panel. This setting makes it less fiddly to scroll to the very edges of the scrolled content. In effect it offsets the mouses position as it approaches the top-left, bottom-right of
* the scrolling panel. Setting a large value for this property will cause the panel to "snap" into position as the mouse reaches either of these positions.
* <p>This property has no effect on scrolling operations other than the via mouse movement.</p>
* <p><em>This is a Class Instantiation & run time Property</em></p>
* @default 3
* @return int
*/
public function get panelSnapPoint():int {
return panelSnap;
}
/**
* @private
*/
public function set panelSnapPoint(newPanelSnap:int):void {
panelSnap = newPanelSnap;
}
/**
* Get / Set the visible width of the thumbs track. This value is sets the width of the mask that that thumbs scroll behind. Has no effect if
* the <code>resizeThumbMaskToStage</code> property is enabled and you are scrolling content in the <code>horizontal</code> direction.
* @default 0
* @return int
* @see #resizePanelMaskToStage
*/
public function get panelMaskWidth():int {
return maskWidth;
}
/**
* @private
*/
public function set panelMaskWidth(newMaskWidth:int):void {
maskWidth = newMaskWidth;
}
/**
* Get / Set the visible height of the thumbs track. This value is sets the height of the mask that that thumbs scroll behind. Has no effect if
* the <code>resizePanelMaskToStage</code> property is enabled and you are scrolling content in the <code>vertical</code> direction.
* <p><em>You can set this property at runtime</em></p>
* @default 0
* @return int
* @see #resizePanelMaskToStage
*/
public function get panelMaskHeight():int {
return maskHeight;
}
/**
* @private
*/
public function set panelMaskHeight(newMaskHeight:int):void {
maskHeight = newMaskHeight;
}
/**
* Get / Set the whether or not the thumb track stretches to match either the stages width, or stages height, depending on what orientation the NpScrollingPanel happens to be in.
* <p><em>Make sure you set the opposite track dimension value to the NpScrollingPanels orientation. So, if you are creating a horizontal thumb track, make sure you set the <code>maskHeight</code> property.</em></p>
* <p><em>You can set this property at runtime</em></p>
* @default 0 or stage.stageWidth
* @return Boolean
*/
public function get resizePanelMaskToStage():Boolean {
return useStageDim;
}
/**
* @private
*/
public function set resizePanelMaskToStage(newUseStageDim:Boolean):void {
useStageDim = newUseStageDim;
}
/**
* Get / Set whether or not the thumb scrolling is controlled by a user moving their mouse over the NpScrollingPanel.
* <p><em>You can set this property at runtime</em></p>
* @default true
* @return Boolean
*/
public function get mouseScrolling():Boolean {
return useMouseScroll;
}
/**
* @private
*/
public function set mouseScrolling(newUseMouseScroll:Boolean):void {
useMouseScroll = newUseMouseScroll;
}
/**
* Get / Set the easing for scrolling of the NpScrollingPanels scrolling.
* <p><em>You can set this property at runtime</em></p>
* @default .2
* @return Number
*/
public function get scrollEase():Number {
return scrollSpeed;
}
/**
* @private
*/
public function set scrollEase(newScrollMaxSpeed:Number):void {
scrollSpeed = newScrollMaxSpeed;
}
/**
* Get / Set the position of the thumbsTrack as a <code>percentage!</code> of the NpScrollingPanels mask (visible area) width. Valid value range is within the <code>0-1</code> range.
* <p>Use this property to scroll the thumbsTrack via external means, such as a slider bar or a mouse Click on a button</p>
* <p><em>You can set this property at runtime</em></p>
* @default 0
* @return Number
*/
public function get panelScrollPos():Number {
if (panelDirection=="horizontal") {
return - thumbsHolder.x / (thumbsHolder.width - thumbMask.width);
} else {
return - thumbsHolder.y / (thumbsHolder.height - thumbMask.width);
}
}
/**
* @private
*/
public function set panelScrollPos(newTrackPos:Number):void {
if(!scrollingEnabled){
return
}
//test thumbsHolder bounds against thumbMask, thumbsHolder must be larger than mask
if((panelDirection=="horizontal" && thumbsHolder.width<=thumbMask.width)||(panelDirection=="vertical" && thumbsHolder.height<=thumbMask.height)){
return
}
//check to see if we have an enterframe event running, if not add it
if (! this.willTrigger(Event.ENTER_FRAME)) {
this.addEventListener(Event.ENTER_FRAME,entFrameScroll);
}
panelDirection=="horizontal" ? scrollThumbsX(newTrackPos) : scrollThumbsY(newTrackPos)
}
/**
* Get / Set if you want to blur the scrolled content as it scrolls. The amount of blur depends on how far the content has to scroll. Bigger distances
* equate to bigger blurs. Content is blurred in the direction it is scrolling in.
* <p><strong>Blurring will not work if your content is larger in any dimension that 2880 pixels. This is a Flash limit for bitmapData.</strong></p>
* <p><em>Be aware that this can affect peformance</em></p>
* <p><em>You can set this property at runtime</em></p>
* @default false
* @return Boolean
* @see #panelBlurQuality
*/
public function get panelScrollBlur():Boolean {
return blurScroll
}
/**
* @private
*/
public function set panelScrollBlur(newBlur:Boolean):void {
blurScroll = newBlur
}
/**
* Get / Set the quality of the blur if you have enabled the <code>panelScrollBlur</code> property. Higher numbers set higher quality blurs but degrade performance!
* <p><em>Be aware that this high will affect peformance</em></p>
* <p><em>You can set this property at runtime</em></p>
* @default 3
* @return int
* @see panelScrollBlur
*/
public function get panelBlurQuality():int {
return blurQual
}
/**
* @private
*/
public function set panelBlurQuality(newBlurQual:int):void {
blurQual = newBlurQual
}
/**
* Get / Set the amount of the blurring if you have enabled the <code>panelScrollBlur</code> property. Higher numbers create greater amounts of blur!
* <p>Blurring is a proportion of the distance the panel has to travel. The effect of this property is to divide that amount to arrive at the level of blur.
* So, if you set a amount of <code>.5</code> then the blur will be calculated as .5 of that distance.</p>
* <p><em>You can set this property at runtime</em></p>
* @default .4
* @return Number
* @see panelScrollBlur
*/
public function get panelBlurAmount():Number {
return blurAmount
}
/**
* @private
*/
public function set panelBlurAmount(newBlurAmount:Number):void {
blurAmount = newBlurAmount
}
/**
* Get / Set whether or not to cache the scrolling content as a whole as a bitmap. This increases performance, but you will suffer a performance hit if your content
* visually changes etc.
* <p>If you have enabled the <code>panelScrollBlur</code> property, the scrolling content will be bitmap cached when it is blurred, and returned to is previous cache state
* when the blur has finished.</p>
* <p><em>This property is tested each time the <code>enableScrolling</code> method is called.</em></p>
* @default true
* @return Boolean
*/
public function get renderPanelAsBitmap():Boolean {
return cachePanelAsBit
}
/**
* @private
*/
public function set renderPanelAsBitmap(newCachePanelAtBit:Boolean):void {
cachePanelAsBit = newCachePanelAtBit
}
//--------------------------------------
// CONSTRUCTOR
//--------------------------------------
/**
* <strong>NpScrollingPanel</strong>
* The NpScrollingPanel Class Constructor takes one argument. A string representing the direction you want to scroll your content within.
* <p>To add content to this scrollingPanel use the <code>addContentItem()</code> method. When you have finished adding in your content that you wish
* to scroll, call the <code>enableScrolling()</code> method.</p>
* <p>Set the <code>mouseScrolling, scrollEase, resizeThumbMaskToStage, panelMaskWidth, panelMaskHeight, contentPadding</code> properties before you call the <code>addContentItem()</code> method!</p>
* <p>Use the <code>contentYposition</code> and <code>contentYposition</code> properties as you add content to the NpScrollingPanel class </em>if</em> you want to create multiple rows and columns</p>
* <p>If you need to access individual contentItems, you can access their various dispatched events, and from those events, hook into the event.target property. You can also simply query the
* <code>accessThumb()</code> method.
* @param String (Optional) Representing the direction you want to scroll in. The default scrolling direction is <code>horizontal</code>!.
* @see #mouseScrolling
* @see #scrollEase
* @see #resizeThumbMaskToStage
* @see #panelMaskHeight
* @see #panelMaskWidth
* @see #contentPadding
* @see #renderPanelAsBitmap
* @see #panelScrollBlur
* @see enableScrolling()
* @see #noponies.events.NpScrollingPanelEvent
* @return
* <br>
* @example Example Useage
* <listing version="3.0">
* //Create a new instance of NpScrollingPanel Class and populate it with bitmaps from the library.
*
* var thumbsContainer:NpScrollingPanel = new NpScrollingPanel();
* thumbsContainer.resizePanelMaskToStage = true
* thumbsContainer.panelMaskHeight = 200
* addChild(thumbsContainer);
*
* var libraryItem:Bitmap;
*
* function createNewPanel():void {
* for (var i:int = 0; i< 15; i++) {
* var n:int=i%2;
* if (n==0) {
* var FireybreathData:Fireybreath = new Fireybreath(0, 0);
* libraryItem = new Bitmap(FireybreathData);
* } else {
* var StrawberryData:Strawberry = new Strawberry(0, 0);
* libraryItem = new Bitmap(StrawberryData);
* }
* thumbsContainer.addContentItem(libraryItem)
* //when we have finished adding content, turn on scrolling
* if(i==15){
* thumbsContainer.enableScrolling()
* }
* }
* }
*
* createNewPanel()
*
* </listing>
*/
public function NpScrollingPanel(panelDirection:String = "horizontal") {
switch (panelDirection.toLowerCase()) {
case "horizontal" :
this.panelDirection = panelDirection.toLowerCase();
break;
case "vertical" :
this.panelDirection = panelDirection.toLowerCase();
break;
default :
throw new Error("Problem :The direction parameter passed "+"\""+ panelDirection+"\"" + " does not match the allowed orientation modes, which are: \"horizontal\", \"vertical\"");
};
init();
}
//--------------------------------------
//
// PUBLIC METHODS
//
//--------------------------------------
//--------------------------------------
// ADD CONTENT ITEM
//--------------------------------------
/**
* <p>The <code>addContentItem()</code> public method adds DisplayObjects to the NpScrollingPanel.
* @param DisplayObject Representing the DisplayObject you want to add to the NpScrollingPanel
* @see #contentPadding
* @see #contentXposition
* @see #contentYposition
* @return
*/
public function addContentItem(thumbContent:DisplayObject):void {
var newThumb:NpScrollingPanelItem= new NpScrollingPanelItem(thumbContent, counter, panelDirection);
thumbsHolder.addChild(newThumb);
if (panelDirection=="horizontal") {
newThumb.x = thumbXpos;
newThumb.y = thumbYpos;
} else {
newThumb.x = thumbXpos;
newThumb.y = thumbYpos;
}
//create the mask
if (counter==0) {
if (useStageDim&&panelDirection=="horizontal") {
maskWidth = stage.stageWidth;
}
if (useStageDim&&panelDirection=="vertical") {
maskHeight = stage.stageHeight;
}
//create the mask sprite for the thumbs track
thumbMask = new Sprite();
thumbMask.graphics.beginFill(0xFFFFFF);
thumbMask.graphics.drawRect(0, 0, maskWidth, maskHeight);
thumbMask.graphics.endFill();
thumbMask.x = 0;
thumbMask.y = 0;
addChild(thumbMask);
this.mask = thumbMask;
//set the bg of the thumbs track which is needed to create a smooth scrolling experience to match
//the heights and widths of the first instance of the loaded in content
//this sprite is resized again, as the content loads
thumbsHolderBg.height = thumbContent.height;
thumbsHolderBg.width = thumbContent.width;
}
//increment the positional counter for the thumbs positions
if (panelDirection=="horizontal") {
thumbsHolderBg.width = thumbsHolder.width;
thumbsHolderBg.height = maskHeight;
thumbXpos+=thumbContent.width+padding;
} else {
thumbsHolderBg.height = thumbsHolder.height;
thumbsHolderBg.width = maskWidth;
thumbYpos+=thumbContent.height+padding;
}
//create the counter
counter++;
itemArray.push(newThumb)
}
//--------------------------------------
// ENABLE SCROLLING
//--------------------------------------
/**
* <p>The <code>enableScrolling()</code> public method will enable both mouse movement (Depending on if you have enabled the <code>mouseScrolling</code> property.</code>) based and setter based scrolling.
* @see #mouseScrolling
* @see disableScrolling()
* @return
*/
public function enableScrolling():void {
//enable mouse based scrolling, if it desired. Note the slight inflation of the rectangle. We need to offset it slightly as Flash tests
//for less than when running a rectangle.contains() method.
panelDirection=="horizontal" ? hitRect = new Rectangle(0, 0, maskWidth+1, maskHeight) : hitRect = new Rectangle(0, 0, maskWidth, maskHeight+1)
if (useMouseScroll) {
addScrollListeners();
}
scrollingEnabled = true
//check to see if we are cacheing the content
cachePanelAsBit ? thumbsHolder.cacheAsBitmap = true : thumbsHolder.cacheAsBitmap = false
}
//--------------------------------------
// DISABLE SCROLLING
//--------------------------------------
/**
* <p>The <code>disableScrolling()</code> public method will disable both mouse movement based and setter based scrolling.
* @see enableScrolling()
* @return
*/
public function disableScrolling():void {
if (this.willTrigger(Event.ENTER_FRAME)) {
this.removeEventListener(Event.ENTER_FRAME, entFrameScroll);
}
scrollingEnabled = false
}
//--------------------------------------
// REMOVE A PARTICULAR THUMB
//--------------------------------------
/**
* <p>The <code>removeContentItem()</code> public method will remove a contentItem from the NpScrollingPanel. ContentItems with either a
* greater x or y (depending on scrolling direction) than the removed item will move their positions to fill the 'gap' left my deleting
* the contentItem.</p>
* <p>!! Removing content items when you have multi row or column scrollable content will possibly cause errors</p>
* <p>Pass in the ID of the thumbnail you want to delete. When thumbs are added to the thumbsTrack they are allocated an ID, which corresponds
* to the order they are added in.</p>
* @param int Representing the ID of the thumbnail you want to delete from the thumbsTrack.
* @return
*/
public function removeContentItem(id:int):void {
var thumbToDeleteDim:Number
panelDirection=="horizontal" ? thumbToDeleteDim = itemArray[id].thumbWidth : thumbToDeleteDim = itemArray[id].thumbHeight
thumbsHolder.removeChild(itemArray[id])
itemArray.splice(id,1)
//iterate through elements contained in our itemArray
var len:int = itemArray.length
for (var i:int = 0; i< len; i++) {
itemArray[i].removeClip(i, -thumbToDeleteDim-padding)
}
if(drawBg){
thumbsHolderBg.width -= thumbToDeleteDim+padding;
}
}
//--------------------------------------
// ADJUST THUMB PADDING
//--------------------------------------
/**
* <p>The <code>adjustPadding()</code> public method will adjust the padding between each content item at runtime. Calling this method will
* result in the content items tweening in unison to their new positions.</p>
* @param int Representing the amount of padding you would like between each thumbnail.
* @see enableScrolling()
* @return
*/
public function adjustPadding(newPadding:int):void {
var len:int = itemArray.length
//iterate through elements contained in our itemArray
for (var i:int = 0; i< len; i++) {
itemArray[i].adjustPadding(newPadding)
}
if(drawBg){
panelDirection=="horizontal" ? thumbsHolderBg.width+= (newPadding*itemArray.length)-newPadding : thumbsHolderBg.height+= (newPadding*itemArray.length)-newPadding;
}
}
//--------------------------------------
// UNLOAD ALL THUMBS
//--------------------------------------
/**
* <p>The <code>removeAllContent()</code> public method will unload any thumbnails currently loaded. It will also reset the heights and widths
* of the NpScrollingPanel. Any mouse event listeners registered with the NpScrollingPanel will also be removed.</p>
* <p>You would use this method if you wanted to repopulate the class with a new set of content.</p>
* @return
*/
public function removeAllContent():void {
//deal with listeners first
if (this.willTrigger(Event.ENTER_FRAME)) {
this.removeEventListener(Event.ENTER_FRAME, entFrameScroll);
}
if (useMouseScroll) {
this.removeEventListener(MouseEvent.ROLL_OVER, mouseScroll);
}
//clear thumbs
if (thumbsHolder.numChildren >1) {
while (thumbsHolder.numChildren >1) {
thumbsHolder.removeChildAt(1);
}
}
//reset internal props
counter=0;
thumbsHolder.width = thumbsHolder.height = 0;
if(drawBg){
thumbsHolderBg.width = thumbsHolderBg.height = 0;
}
thumbYpos = thumbXpos = 0
this.mask = null;
removeChild(thumbMask);
itemArray = []
}
//--------------------------------------
// REFERENCE A PARTICULAR THUMB
//--------------------------------------
/**
* <p>The <code>accessThumb()</code> public method is a means of gaining access to a particular thumbNail within the thumbsTrack.</p>
* <p>You would use this method if you wanted to manipulate individual thumbNails.</p>
* @return Object representing the thumbNail ID requested.
*/
public function accessThumb(id:int):Object{
return(itemArray[id])
}
//--------------------------------------
//
// PRIVATE METHODS
//
//--------------------------------------
//--------------------------------------
// INIT HANDLER - CALLED FROM CONSTRUCTOR
//--------------------------------------
//create thumbs holder sprite here, just do this once
private function init():void {
itemArray = []
thumbsHolder = new Sprite();
addChild(thumbsHolder);
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
//--------------------------------------
// ADDED TO STAGE HANDLER
//--------------------------------------
private function addedToStageHandler(event:Event):void {
if(drawBg){
thumbsHolderBg = new Sprite();
thumbsHolderBg.graphics.beginFill(bgColour,1);
thumbsHolderBg.graphics.drawRect(0, 0, 1, 1);
thumbsHolderBg.graphics.endFill();
thumbsHolder.addChildAt(thumbsHolderBg,0);
thumbsHolderBg.cacheAsBitmap = true
}
//add the stage resize listener if its required
if(useStageDim){
stage.addEventListener(Event.RESIZE, resizeHandler);
}
addEventListener(Event.REMOVED_FROM_STAGE, handleRemovedFromStage)
}
//--------------------------------------
// RESIZE HANDLER
//--------------------------------------
private function resizeHandler(event:Event):void {
if (useStageDim) {
if (panelDirection=="horizontal") {
if (thumbsHolder.x+thumbsHolder.width<stage.stageWidth) {
thumbsHolder.x = stage.stageWidth-thumbsHolder.width;
}
//test for when the stage is resized when the thumbs are loading
if(thumbsHolder.width<=stage.stageWidth){
thumbsHolder.x = 0
}
thumbMask.width = stage.stageWidth;
thumbMask.height = maskHeight
hitRect = new Rectangle(1, 0, thumbMask.width-1, maskHeight)
} else {
if (thumbsHolder.y+thumbsHolder.height<stage.stageHeight) {
thumbsHolder.y = stage.stageHeight-thumbsHolder.height;
}
//test for when the stage is resized when the thumbs are loading
if(thumbsHolder.height<=stage.stageHeight){
thumbsHolder.x = 0
}
thumbMask.height = stage.stageHeight;
thumbMask.width = maskWidth
hitRect = new Rectangle(1, 0, maskWidth, thumbMask.height-1)
}
}
}
//--------------------------------------
//
// MOUSESCROLLING FUNCTIONS
//
//--------------------------------------
//function that simply adds the event listeners to our scroll track
//we call this when we have loaded in all the thumbs, as this stops a user from being
//able to scroll a half empty thumbnails track, which would look crap.
private function addScrollListeners():void {
addEventListener(MouseEvent.ROLL_OVER, mouseScroll);
}
//handlers that either add or delete the scroll enterframe event
private function mouseScroll(event:MouseEvent = null):void {
if(!scrollingEnabled){
return
}
//test thumbsHolder bounds against thumbMask, thumbsHolder must be larger than mask
if((panelDirection=="horizontal" && thumbsHolder.width<=thumbMask.width)||(panelDirection=="vertical" && thumbsHolder.height<=thumbMask.height)){
return
}
//check to see if we have an enterframe event running, if not add it
if (! this.willTrigger(Event.ENTER_FRAME)) {
this.addEventListener(Event.ENTER_FRAME,entFrameScroll);
}
}
//--------------------------------------
// ENTERFRAME HANDLER
//--------------------------------------
private function entFrameScroll(event:Event):void{
//we have content to scroll, so lets scroll it!
panelDirection=="horizontal" ? scrollThumbsX(0) : scrollThumbsY(0)
}
//--------------------------------------
// SCROLLING IN THE X DIRECTION
//--------------------------------------
private function scrollThumbsX(nPos:Number = 0):void {
//store mouse pos as vars
mX = mouseX;
mY = mouseY;
//adjust mousePos inline with panelSnappingPoint
if(mX > maskWidth-panelSnap) mX = maskWidth
if(mX < panelSnap) mX = 0
//set value if scrolling from a source other than mouse
if (nPos != 0) {
mPos = hitRect.width*nPos;
}else if (useMouseScroll && hitRect.contains(mX,mY)) {
if (mX < 0) mX = 0;
mPos = mX;
}
targPos = -(mPos/(hitRect.width/(thumbsHolder.width - hitRect.width)));
thumbsHolder.x += Number(((targPos-thumbsHolder.x)) * scrollSpeed);
//dampening & kill event handler when we are belowing 1px movement increments
var n:Number = thumbsHolder.x- targPos;
if (n < 0) n = -n;
//turn on blurring, if its being used, if its being used and only if we have a big enough movement in the panel
if(blurScroll && mPos >= 0 && n > 1){
thumbsHolder.filters=[new BlurFilter((n * blurAmount)*.5,0,blurQual)];
}
//dispatch the CONTENT_SLIDING event
dispatchEvent(new NpScrollingPanelEvent(NpScrollingPanelEvent.SCROLLING,true, false, undefined, panelScrollPos));
if (n < 1) {
if (!useMouseScroll ||!hitRect.contains(mX,mY)) {
this.removeEventListener(Event.ENTER_FRAME, entFrameScroll);
if(blurScroll){
thumbsHolder.filters=[];
}
}
}
}
//--------------------------------------
// SCROLLING IN THE Y DIRECTION
//--------------------------------------
private function scrollThumbsY(nPos:Number = 0):void {
//store mouse pos as vars
mX = mouseX;
mY = mouseY;
//adjust mousePos inline with panelSnappingPoint
if(mY > maskHeight-panelSnap) mY = maskHeight
if(mY < panelSnap) mY = 0
//set value if scrolling from a source other than mouse
if (nPos!=0) {
mPos =hitRect.height*nPos;
}else if (useMouseScroll && hitRect.contains(mX,mY)) {
if (mY < 0) mY = 0;
mPos = mY;
}
targPos = -(mPos/(hitRect.height/(thumbsHolder.height-hitRect.height)));
thumbsHolder.y+=Number(((targPos-thumbsHolder.y))*scrollSpeed);
//dampening & kill event handler when we are belowing 1px movement increments
var n:Number = thumbsHolder.y- targPos;
if (n < 0) n = -n;
//turn on blurring, if its being used and only if we have a big enough movement in the panel
if(blurScroll && mPos >= 0 && n > 1){
thumbsHolder.filters=[new BlurFilter(0,(n * blurAmount)*.5,blurQual)];
}
//dispatch the CONTENT_SLIDING event
dispatchEvent(new NpScrollingPanelEvent(NpScrollingPanelEvent.SCROLLING,true, false, undefined, panelScrollPos));
if (n < 1) {
if (!useMouseScroll ||!hitRect.contains(mX,mY)) {
this.removeEventListener(Event.ENTER_FRAME, entFrameScroll);
if(blurScroll){
thumbsHolder.filters=[];
}
}
}
}
//--------------------------------------
// HANDLE A REMOVED FROM STAGE EVENT
//--------------------------------------
//clean up the class when removed from stage
private function handleRemovedFromStage(event:Event):void {
try {
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler)
removeEventListener(Event.REMOVED_FROM_STAGE, handleRemovedFromStage)
if(useStageDim){
stage.removeEventListener(Event.RESIZE, resizeHandler);
}
//call public removeAllContent Method
removeAllContent()
} catch (event:Error) {
trace("There was an error when attempting to delete all NpScrollingPanel content: "+Error);
}
}
}
}