AS3 Mask Example

I was tasked recently with adding a way to scroll clickable buttons inside of a fixed-height UI panel for a new release of StrataLogica. I haven’t dealt much with masking in AS3 so I thought I’d post a quick example of how masking works. The idea is that you’ve got an area for buttons ( content items/whatever ), and that sometimes this area of buttons exceeds the height of the area the content must fit into. So you need some way to scroll these buttons up and down.

The biggest, most irritating thing I ran into, and that you may run into when trying to figure out masking is: empty Sprites/MovieClips will always default to a height/width of ZERO. Keep this in mind and we’ll return to it towards the end of the post.

Lets look at a visual representation of what we’re trying to accomplish.

In the image, the container holding the buttons is 170px high but we only have 100px worth of area where we can display the button list. If we create a 100px high mask and apply it to the button container, it will hide everything that is not inside of those 100px. Then, simply adding some scroll up/down buttons, we can move the button container up or down (the mask does not move once set) and it looks like we’re scrolling our list of buttons.

Read on to see the code and example FLA/SWF/ZIP

package com.zf {
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import fl.controls.Button;
	
	public class MaskTest extends MovieClip {
		// MovieClip Container for our buttons
		private var buttonContainer:MovieClip;
		
		// MovieClip that will be masking our buttonContainer
		private var buttonMask:Sprite;
				
		// Number of buttons to have in the buttonContainer
		private var numButtons:int = 20;
		
		// Height of the mask
		private var maskHeight:int = 100;
		
		// Width of the mask
		private var maskWidth:int = 100;
		
		// Amount, in pixels, to scroll up/down
		private const SCROLL_AMOUNT:int = 20;
		
		public function MaskTest() {
			buttonContainer = new MovieClip();
			
			addChild( buttonContainer );
			
			addButtonsToContainer();
			
			buttonMask 		= new Sprite();
			// Very important to have "something" in the sprite
			// choice of color does not matter as it will be 
			// invisible anyways
			buttonMask.graphics.beginFill( 0x000000 );	
			buttonMask.graphics.drawRect( 0 , 0 , maskWidth , maskHeight );
			buttonMask.x = 0;
			buttonMask.y = 0;
			
			addChild( buttonMask );
			
			// Does the actual work of turning buttonMask INTO a mask
			buttonContainer.mask = buttonMask;
			
			// _scrollUp & _scrollDown are buttons already on stage in FLA
			_scrollUp.addEventListener( MouseEvent.MOUSE_DOWN , onScrollUpHandler );
			_scrollDown.addEventListener( MouseEvent.MOUSE_DOWN	, onScrollDownHandler );
		}
		
		private function addButtonsToContainer():void  {
			// How tall the buttons will be
			var btnHeight:int = 20;
			
			// Button Width
			var btnWidth:int = 100;
			
			// How many pixels between each button
			var btnGap:int = 5;
			
			// Y-Position inside buttonContainer
			var yPos:int = 0;
			
			for( var i:int = 0; i < numButtons; i++ )  {
				// Create new button and assign properties
				var btn:Button = new Button();
				btn.height 	= btnHeight;
				btn.width 	= btnWidth;
				btn.label 	= "Button " + ( i + 1 ).toString();
				btn.x 		= 0;
				btn.y 		= yPos;
				
				buttonContainer.addChild( btn );
				
				// Set up yPos for the next button
				yPos += btnHeight + btnGap;
			}
		}
		
		private function onScrollUpHandler( e:MouseEvent ):void  {
			buttonContainer.y -= SCROLL_AMOUNT;
		}

		private function onScrollDownHandler( e:MouseEvent ):void  {
			buttonContainer.y += SCROLL_AMOUNT;
		}
	}
}

The biggest, most irritating thing I ran into when trying to figure out masking is: empty Sprites/MovieClips will always default to a height/width of Zero. Meaning, when you take a fresh maskMC:MovieClip = new MovieClip(); then set maskMC.width to however wide you want your mask, and .height to however tall you want your mask, if that maskMC has no children and it’s graphics layer is clear, it will immediately default back to a width/height of zero.

The cool thing about the Mask, the Sprite/MovieClip you are using to act as the .mask of something else, is that it will become invisible when it is used as a Mask. This is why, in Line 37 and Line 38 we actually draw a big, black rectangle on our buttonMask MovieClip. It’s going to be invisible anyways, and the point of the Mask is to cover the area you want Visible. So we make a large rectangle the appropriate dimensions for our viewable area, in this case 100×100, and after adding the buttonMask to the stage, Line 45 turns buttonMask invisible, and makes only the parts that buttonMask covers over buttonContainer visible.

Download a ZIP containing the FLA/SWF/AS

FacebookTwitterGoogle+Share

Leave a Comment

Your email address will not be published.