Flex.org already has tons of tutorials and looks like a great resource for Flex development and the Flex community.

flex.org
I was first introduced to the ColorTransform class while reading the AS2 to AS3 migration documentation about setRGB(). I was immediately impressed with the features, stomach web but intimidated when I saw the constructor and all the offset, story color and alpha arguments. I just needed to change the color of something, nothing special, no gradients, no alpha, no space shuttle landings, just a simple hex color change.

So here is a simple color change utility that is a lot closer to what I am used to.

?View Code ACTIONSCRIPT
function paint(obj:Object,color:Number):void{
var ct:ColorTransform = new ColorTransform();
ct.color = color;
obj.transform.colorTransform = ct;
}



source here
I was first introduced to the ColorTransform class while reading the AS2 to AS3 migration documentation about setRGB(). I was immediately impressed with the features, stomach web but intimidated when I saw the constructor and all the offset, story color and alpha arguments. I just needed to change the color of something, nothing special, no gradients, no alpha, no space shuttle landings, just a simple hex color change.

So here is a simple color change utility that is a lot closer to what I am used to.

?View Code ACTIONSCRIPT
function paint(obj:Object,color:Number):void{
var ct:ColorTransform = new ColorTransform();
ct.color = color;
obj.transform.colorTransform = ct;
}



source here
Here is an AS2 version of the SuperLoader. It works just like the AS3 version found in the Custom HTML Templates post.

Quick Use:
1. Add loaderbar.swf and mainLoader.swf to your current project directory.

2. In the html file for your current project, pilule replace the src and movie parameters to mainLoader.

3. Then add [, website like this 'flashVars', stomach 'swfURL=FlashProjectToLoad.swf'] to the load script.

Example for AC_RunActiveContent:

AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '472',
'height', '280',
'src', 'mainLoader',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'mainLoader',
'bgcolor', '#000000',
'name', 'mainLoader',
'menu', 'true',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'mainLoader',
'salign', '',
'flashVars','swfURL=imgViewer.swf'
); //end AC code

Example for HTML Object/Embed:

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="472" height="280" id="mainLoader" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="mainLoader.swf?swfURL=imgViewer.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" />	<embed src="mainLoader.swf?swfURL=imgViewer.swf" quality="high" bgcolor="#ffffff" width="472" height="280" name="mainLoader" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

4. If your frame rate is different then 30, you will need to update the frame rate in the mainLoader.fla file.

5. If you are using this loader inside of your Flash movie, you may also need to comment out the line that sets _root to the loading file [mainMC._lockroot = true;].

Demo:

Source Here

UPDATE: 1.1

1. Added usage information, the class could be used as a simple loader monitor if needed.
2. Moved class path from com.hdi.util.HDLoader to com.hdi.as2.HDLoader.

See just the loader class below.

?View Code ACTIONSCRIPT
/**********************************************************
HDLoader is a simple loader monitor that can attach to your custom loading bar
version 1.1
date: 1-9-10
 
How To Use:
1. Have something that needs loading
 
2. Create a function to handle the loading monitor updates. Should look something like this.
function loaderUpdate(perc:Number){
// perc is the percent loaded in non decimal form. 0 - 100.
// you can make a loading bar move or scale like so
loaderBar._xscale = perc/100;
 
// you can display text of the loading status.
loaderText.text = "LOADING: " + perc + "%";
}
 
3. Create a funciton to handle when loading is complete
function loadComplete(){
// hiding the loader after loading is always a good thing.
loaderBar._visible = false;
 
// do what ever you want here, your crap is now loaded.
}
 
4. import HDLoader.
import com.hdi.as2.HDLoader;
 
5. Start the loader, placing the correct target references in the correct argument positions.
arg 1: the MovieClip doing the laoding.
arg 2: the loader update function created in step 2.
arg 3: the loader complete function created in step 3.
 
// we are assuming you have just started loading something (mc.loadMovie("someSWF.swf");
var loaderMon:HDLoader = new HDLoader(mc,loaderUpdate,loadComplete);
 
Author: Todd Williams
website: www.taterboy.com
website: hdinteractive.com
***********************************************************/
 
class com.hdi.as2.HDLoader{
var targMC:Object;
var monFunc:Function;
var finFunc:Function;
public function HDLoader(targ,mfunc,func){
init(targ,mfunc,func);
}
private function init(targ,mfunc,func){
var lbytes,tbytes,perc;
var frameParent:Object = targ._parent;
var cnt:Number = 3;
var frameObj:MovieClip = frameParent.createEmptyMovieClip("frameLdr",frameParent.getNextHighestDepth());
frameObj.onEnterFrame = function(){
lbytes = targ.getBytesLoaded();
tbytes = targ.getBytesTotal();
perc = Math.round((lbytes/tbytes)*100);
if (lbytes < tbytes) {
if(mfunc != null){
mfunc(perc);
}
}
else if(tbytes > 200){
if(cnt == 0){
if(func != undefined){
func();
}
delete frameObj.onEnterFrame;
}
cnt --;
if(mfunc != null){
mfunc(100);
}
}
}
}
}

I was first introduced to the ColorTransform class while reading the AS2 to AS3 migration documentation about setRGB(). I was immediately impressed with the features, stomach web but intimidated when I saw the constructor and all the offset, story color and alpha arguments. I just needed to change the color of something, nothing special, no gradients, no alpha, no space shuttle landings, just a simple hex color change.

So here is a simple color change utility that is a lot closer to what I am used to.

?View Code ACTIONSCRIPT
function paint(obj:Object,color:Number):void{
var ct:ColorTransform = new ColorTransform();
ct.color = color;
obj.transform.colorTransform = ct;
}



source here
Here is an AS2 version of the SuperLoader. It works just like the AS3 version found in the Custom HTML Templates post.

Quick Use:
1. Add loaderbar.swf and mainLoader.swf to your current project directory.

2. In the html file for your current project, pilule replace the src and movie parameters to mainLoader.

3. Then add [, website like this 'flashVars', stomach 'swfURL=FlashProjectToLoad.swf'] to the load script.

Example for AC_RunActiveContent:

AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '472',
'height', '280',
'src', 'mainLoader',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'mainLoader',
'bgcolor', '#000000',
'name', 'mainLoader',
'menu', 'true',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'mainLoader',
'salign', '',
'flashVars','swfURL=imgViewer.swf'
); //end AC code

Example for HTML Object/Embed:

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="472" height="280" id="mainLoader" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="mainLoader.swf?swfURL=imgViewer.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" />	<embed src="mainLoader.swf?swfURL=imgViewer.swf" quality="high" bgcolor="#ffffff" width="472" height="280" name="mainLoader" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

4. If your frame rate is different then 30, you will need to update the frame rate in the mainLoader.fla file.

5. If you are using this loader inside of your Flash movie, you may also need to comment out the line that sets _root to the loading file [mainMC._lockroot = true;].

Demo:

Source Here

UPDATE: 1.1

1. Added usage information, the class could be used as a simple loader monitor if needed.
2. Moved class path from com.hdi.util.HDLoader to com.hdi.as2.HDLoader.

See just the loader class below.

?View Code ACTIONSCRIPT
/**********************************************************
HDLoader is a simple loader monitor that can attach to your custom loading bar
version 1.1
date: 1-9-10
 
How To Use:
1. Have something that needs loading
 
2. Create a function to handle the loading monitor updates. Should look something like this.
function loaderUpdate(perc:Number){
// perc is the percent loaded in non decimal form. 0 - 100.
// you can make a loading bar move or scale like so
loaderBar._xscale = perc/100;
 
// you can display text of the loading status.
loaderText.text = "LOADING: " + perc + "%";
}
 
3. Create a funciton to handle when loading is complete
function loadComplete(){
// hiding the loader after loading is always a good thing.
loaderBar._visible = false;
 
// do what ever you want here, your crap is now loaded.
}
 
4. import HDLoader.
import com.hdi.as2.HDLoader;
 
5. Start the loader, placing the correct target references in the correct argument positions.
arg 1: the MovieClip doing the laoding.
arg 2: the loader update function created in step 2.
arg 3: the loader complete function created in step 3.
 
// we are assuming you have just started loading something (mc.loadMovie("someSWF.swf");
var loaderMon:HDLoader = new HDLoader(mc,loaderUpdate,loadComplete);
 
Author: Todd Williams
website: www.taterboy.com
website: hdinteractive.com
***********************************************************/
 
class com.hdi.as2.HDLoader{
var targMC:Object;
var monFunc:Function;
var finFunc:Function;
public function HDLoader(targ,mfunc,func){
init(targ,mfunc,func);
}
private function init(targ,mfunc,func){
var lbytes,tbytes,perc;
var frameParent:Object = targ._parent;
var cnt:Number = 3;
var frameObj:MovieClip = frameParent.createEmptyMovieClip("frameLdr",frameParent.getNextHighestDepth());
frameObj.onEnterFrame = function(){
lbytes = targ.getBytesLoaded();
tbytes = targ.getBytesTotal();
perc = Math.round((lbytes/tbytes)*100);
if (lbytes < tbytes) {
if(mfunc != null){
mfunc(perc);
}
}
else if(tbytes > 200){
if(cnt == 0){
if(func != undefined){
func();
}
delete frameObj.onEnterFrame;
}
cnt --;
if(mfunc != null){
mfunc(100);
}
}
}
}
}

Passing Flash variables to Javascript, online passing Javscript variables to Flash, price Calling Flash functions from Javascript.

There are a few conventions for getting Flash and Javascript to communicate like fscommand, getURL, LocalConnection, URL-encoded variables, FlashVars, SetVariable and TCallLabel to name a few.

Here is a little demo using Flash's External Interface and Javascript. It is more elegant then most of the procedures I have used in the past. Between External Interface and FlashVars, you should be able to fill most of your needs.

By the way, the syntax is almost exactly the same for AS2 and AS3.

Flash Usage:

?View Code ACTIONSCRIPT
//import flash.external.*; //for AS2
 
//1. calling javascript function from Flash.
ExternalInterface.call("sendData",tempStr);
// argument 1: javascript function, argument 2: data/variables to pass out.
 
//2. calling javascript function from Flash with recursion.
var returnValue:String = ExternalInterface.call("sendReturn",tempStr).toString();
 
//3. setting up a callback function for javascript
ExternalInterface.addCallback("callFlash",flashResponse);
// argument 1: function name called by javascript, argument 2: function on the Flash side.
// AS2 version looks like this : ExternalInterface.addCallback("callFlash",null,flashResponse);

Javascript Usage:

//1. javascript function as called from Flash.
function sendData(val){
alert(val);
document.flashForm.flashOutput.value = val;
}
 
//2. javascript function with recursion.
function sendReturn(val){
var tempData = "Hello from JS";
return tempData + ' :return';
}
 
//3. calling Flash function with javascript.
function sendToFlash(val){
flash.callFlash(val);
}



Source Here.
I was first introduced to the ColorTransform class while reading the AS2 to AS3 migration documentation about setRGB(). I was immediately impressed with the features, stomach web but intimidated when I saw the constructor and all the offset, story color and alpha arguments. I just needed to change the color of something, nothing special, no gradients, no alpha, no space shuttle landings, just a simple hex color change.

So here is a simple color change utility that is a lot closer to what I am used to.

?View Code ACTIONSCRIPT
function paint(obj:Object,color:Number):void{
var ct:ColorTransform = new ColorTransform();
ct.color = color;
obj.transform.colorTransform = ct;
}



source here
Here is an AS2 version of the SuperLoader. It works just like the AS3 version found in the Custom HTML Templates post.

Quick Use:
1. Add loaderbar.swf and mainLoader.swf to your current project directory.

2. In the html file for your current project, pilule replace the src and movie parameters to mainLoader.

3. Then add [, website like this 'flashVars', stomach 'swfURL=FlashProjectToLoad.swf'] to the load script.

Example for AC_RunActiveContent:

AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '472',
'height', '280',
'src', 'mainLoader',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'mainLoader',
'bgcolor', '#000000',
'name', 'mainLoader',
'menu', 'true',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'mainLoader',
'salign', '',
'flashVars','swfURL=imgViewer.swf'
); //end AC code

Example for HTML Object/Embed:

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="472" height="280" id="mainLoader" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="mainLoader.swf?swfURL=imgViewer.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" />	<embed src="mainLoader.swf?swfURL=imgViewer.swf" quality="high" bgcolor="#ffffff" width="472" height="280" name="mainLoader" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

4. If your frame rate is different then 30, you will need to update the frame rate in the mainLoader.fla file.

5. If you are using this loader inside of your Flash movie, you may also need to comment out the line that sets _root to the loading file [mainMC._lockroot = true;].

Demo:

Source Here

UPDATE: 1.1

1. Added usage information, the class could be used as a simple loader monitor if needed.
2. Moved class path from com.hdi.util.HDLoader to com.hdi.as2.HDLoader.

See just the loader class below.

?View Code ACTIONSCRIPT
/**********************************************************
HDLoader is a simple loader monitor that can attach to your custom loading bar
version 1.1
date: 1-9-10
 
How To Use:
1. Have something that needs loading
 
2. Create a function to handle the loading monitor updates. Should look something like this.
function loaderUpdate(perc:Number){
// perc is the percent loaded in non decimal form. 0 - 100.
// you can make a loading bar move or scale like so
loaderBar._xscale = perc/100;
 
// you can display text of the loading status.
loaderText.text = "LOADING: " + perc + "%";
}
 
3. Create a funciton to handle when loading is complete
function loadComplete(){
// hiding the loader after loading is always a good thing.
loaderBar._visible = false;
 
// do what ever you want here, your crap is now loaded.
}
 
4. import HDLoader.
import com.hdi.as2.HDLoader;
 
5. Start the loader, placing the correct target references in the correct argument positions.
arg 1: the MovieClip doing the laoding.
arg 2: the loader update function created in step 2.
arg 3: the loader complete function created in step 3.
 
// we are assuming you have just started loading something (mc.loadMovie("someSWF.swf");
var loaderMon:HDLoader = new HDLoader(mc,loaderUpdate,loadComplete);
 
Author: Todd Williams
website: www.taterboy.com
website: hdinteractive.com
***********************************************************/
 
class com.hdi.as2.HDLoader{
var targMC:Object;
var monFunc:Function;
var finFunc:Function;
public function HDLoader(targ,mfunc,func){
init(targ,mfunc,func);
}
private function init(targ,mfunc,func){
var lbytes,tbytes,perc;
var frameParent:Object = targ._parent;
var cnt:Number = 3;
var frameObj:MovieClip = frameParent.createEmptyMovieClip("frameLdr",frameParent.getNextHighestDepth());
frameObj.onEnterFrame = function(){
lbytes = targ.getBytesLoaded();
tbytes = targ.getBytesTotal();
perc = Math.round((lbytes/tbytes)*100);
if (lbytes < tbytes) {
if(mfunc != null){
mfunc(perc);
}
}
else if(tbytes > 200){
if(cnt == 0){
if(func != undefined){
func();
}
delete frameObj.onEnterFrame;
}
cnt --;
if(mfunc != null){
mfunc(100);
}
}
}
}
}

Passing Flash variables to Javascript, online passing Javscript variables to Flash, price Calling Flash functions from Javascript.

There are a few conventions for getting Flash and Javascript to communicate like fscommand, getURL, LocalConnection, URL-encoded variables, FlashVars, SetVariable and TCallLabel to name a few.

Here is a little demo using Flash's External Interface and Javascript. It is more elegant then most of the procedures I have used in the past. Between External Interface and FlashVars, you should be able to fill most of your needs.

By the way, the syntax is almost exactly the same for AS2 and AS3.

Flash Usage:

?View Code ACTIONSCRIPT
//import flash.external.*; //for AS2
 
//1. calling javascript function from Flash.
ExternalInterface.call("sendData",tempStr);
// argument 1: javascript function, argument 2: data/variables to pass out.
 
//2. calling javascript function from Flash with recursion.
var returnValue:String = ExternalInterface.call("sendReturn",tempStr).toString();
 
//3. setting up a callback function for javascript
ExternalInterface.addCallback("callFlash",flashResponse);
// argument 1: function name called by javascript, argument 2: function on the Flash side.
// AS2 version looks like this : ExternalInterface.addCallback("callFlash",null,flashResponse);

Javascript Usage:

//1. javascript function as called from Flash.
function sendData(val){
alert(val);
document.flashForm.flashOutput.value = val;
}
 
//2. javascript function with recursion.
function sendReturn(val){
var tempData = "Hello from JS";
return tempData + ' :return';
}
 
//3. calling Flash function with javascript.
function sendToFlash(val){
flash.callFlash(val);
}



Source Here.
One of my favorite statements is try..catch..finally.

When building web applications, this we as developers need to plan for the unexpected. We know the web does not always behave at the same level of consistency for all users. This does not take into account client systems which can compound minor glitches.

There are also times that you need to compile code that is reliant on external variables. If all the conditions are not returned in a valid format AS3, being very strict, will throw an error and not complete the remaining code sequences as intended.

Though the try..catch.. statement has been around since AS1/Flash Player 7, it's value was not as profound and often overlooked as AS2 scripts would just error out quietly anyway. This was bad because bad habits were easily developed and can cause some struggles when working in the much more structured AS3 environment.

Try..catch.. is great when working with database calls, loading external media and developing an enhanced error system. The moral of this post could be "learning to take control of errors before they take control of you".

?View Code ACTIONSCRIPT
try{
randomBall(numT.text);
}
catch(e){
trace("caught error: " + e);
errT.text = "That is not a valid object name.";
}
 
// even if error occurs above or in randomBall(), the rest of the
//method still executes.
trace("end of function");

The really cool thing about try..catch.. is that it not only catches errors in the immediate script that it wraps, but from every class that is called from within the block. A word of warning, try...catch... will not protect your "for" loops from causing the "script causing Flash Player to run slowly" Error. You still need to evaluate your variables and exit number values before execution.

Below is a sample app (like Lotto) with a terrible system of user interaction, but it should demo the point.

Type in the Object name (Ball1, Ball2, Ball3, etc.) in the input area, then click Enter. The numbers on the ball are random. Try to see how many clicks it takes to get all the numbers to match. The try..catch... statement comes into play when/if a user inputs the object name incorrectly.

Demo:

source here
I was first introduced to the ColorTransform class while reading the AS2 to AS3 migration documentation about setRGB(). I was immediately impressed with the features, stomach web but intimidated when I saw the constructor and all the offset, story color and alpha arguments. I just needed to change the color of something, nothing special, no gradients, no alpha, no space shuttle landings, just a simple hex color change.

So here is a simple color change utility that is a lot closer to what I am used to.

?View Code ACTIONSCRIPT
function paint(obj:Object,color:Number):void{
var ct:ColorTransform = new ColorTransform();
ct.color = color;
obj.transform.colorTransform = ct;
}



source here
Here is an AS2 version of the SuperLoader. It works just like the AS3 version found in the Custom HTML Templates post.

Quick Use:
1. Add loaderbar.swf and mainLoader.swf to your current project directory.

2. In the html file for your current project, pilule replace the src and movie parameters to mainLoader.

3. Then add [, website like this 'flashVars', stomach 'swfURL=FlashProjectToLoad.swf'] to the load script.

Example for AC_RunActiveContent:

AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '472',
'height', '280',
'src', 'mainLoader',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'mainLoader',
'bgcolor', '#000000',
'name', 'mainLoader',
'menu', 'true',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'mainLoader',
'salign', '',
'flashVars','swfURL=imgViewer.swf'
); //end AC code

Example for HTML Object/Embed:

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="472" height="280" id="mainLoader" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="mainLoader.swf?swfURL=imgViewer.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" />	<embed src="mainLoader.swf?swfURL=imgViewer.swf" quality="high" bgcolor="#ffffff" width="472" height="280" name="mainLoader" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

4. If your frame rate is different then 30, you will need to update the frame rate in the mainLoader.fla file.

5. If you are using this loader inside of your Flash movie, you may also need to comment out the line that sets _root to the loading file [mainMC._lockroot = true;].

Demo:

Source Here

UPDATE: 1.1

1. Added usage information, the class could be used as a simple loader monitor if needed.
2. Moved class path from com.hdi.util.HDLoader to com.hdi.as2.HDLoader.

See just the loader class below.

?View Code ACTIONSCRIPT
/**********************************************************
HDLoader is a simple loader monitor that can attach to your custom loading bar
version 1.1
date: 1-9-10
 
How To Use:
1. Have something that needs loading
 
2. Create a function to handle the loading monitor updates. Should look something like this.
function loaderUpdate(perc:Number){
// perc is the percent loaded in non decimal form. 0 - 100.
// you can make a loading bar move or scale like so
loaderBar._xscale = perc/100;
 
// you can display text of the loading status.
loaderText.text = "LOADING: " + perc + "%";
}
 
3. Create a funciton to handle when loading is complete
function loadComplete(){
// hiding the loader after loading is always a good thing.
loaderBar._visible = false;
 
// do what ever you want here, your crap is now loaded.
}
 
4. import HDLoader.
import com.hdi.as2.HDLoader;
 
5. Start the loader, placing the correct target references in the correct argument positions.
arg 1: the MovieClip doing the laoding.
arg 2: the loader update function created in step 2.
arg 3: the loader complete function created in step 3.
 
// we are assuming you have just started loading something (mc.loadMovie("someSWF.swf");
var loaderMon:HDLoader = new HDLoader(mc,loaderUpdate,loadComplete);
 
Author: Todd Williams
website: www.taterboy.com
website: hdinteractive.com
***********************************************************/
 
class com.hdi.as2.HDLoader{
var targMC:Object;
var monFunc:Function;
var finFunc:Function;
public function HDLoader(targ,mfunc,func){
init(targ,mfunc,func);
}
private function init(targ,mfunc,func){
var lbytes,tbytes,perc;
var frameParent:Object = targ._parent;
var cnt:Number = 3;
var frameObj:MovieClip = frameParent.createEmptyMovieClip("frameLdr",frameParent.getNextHighestDepth());
frameObj.onEnterFrame = function(){
lbytes = targ.getBytesLoaded();
tbytes = targ.getBytesTotal();
perc = Math.round((lbytes/tbytes)*100);
if (lbytes < tbytes) {
if(mfunc != null){
mfunc(perc);
}
}
else if(tbytes > 200){
if(cnt == 0){
if(func != undefined){
func();
}
delete frameObj.onEnterFrame;
}
cnt --;
if(mfunc != null){
mfunc(100);
}
}
}
}
}

Passing Flash variables to Javascript, online passing Javscript variables to Flash, price Calling Flash functions from Javascript.

There are a few conventions for getting Flash and Javascript to communicate like fscommand, getURL, LocalConnection, URL-encoded variables, FlashVars, SetVariable and TCallLabel to name a few.

Here is a little demo using Flash's External Interface and Javascript. It is more elegant then most of the procedures I have used in the past. Between External Interface and FlashVars, you should be able to fill most of your needs.

By the way, the syntax is almost exactly the same for AS2 and AS3.

Flash Usage:

?View Code ACTIONSCRIPT
//import flash.external.*; //for AS2
 
//1. calling javascript function from Flash.
ExternalInterface.call("sendData",tempStr);
// argument 1: javascript function, argument 2: data/variables to pass out.
 
//2. calling javascript function from Flash with recursion.
var returnValue:String = ExternalInterface.call("sendReturn",tempStr).toString();
 
//3. setting up a callback function for javascript
ExternalInterface.addCallback("callFlash",flashResponse);
// argument 1: function name called by javascript, argument 2: function on the Flash side.
// AS2 version looks like this : ExternalInterface.addCallback("callFlash",null,flashResponse);

Javascript Usage:

//1. javascript function as called from Flash.
function sendData(val){
alert(val);
document.flashForm.flashOutput.value = val;
}
 
//2. javascript function with recursion.
function sendReturn(val){
var tempData = "Hello from JS";
return tempData + ' :return';
}
 
//3. calling Flash function with javascript.
function sendToFlash(val){
flash.callFlash(val);
}



Source Here.
One of my favorite statements is try..catch..finally.

When building web applications, this we as developers need to plan for the unexpected. We know the web does not always behave at the same level of consistency for all users. This does not take into account client systems which can compound minor glitches.

There are also times that you need to compile code that is reliant on external variables. If all the conditions are not returned in a valid format AS3, being very strict, will throw an error and not complete the remaining code sequences as intended.

Though the try..catch.. statement has been around since AS1/Flash Player 7, it's value was not as profound and often overlooked as AS2 scripts would just error out quietly anyway. This was bad because bad habits were easily developed and can cause some struggles when working in the much more structured AS3 environment.

Try..catch.. is great when working with database calls, loading external media and developing an enhanced error system. The moral of this post could be "learning to take control of errors before they take control of you".

?View Code ACTIONSCRIPT
try{
randomBall(numT.text);
}
catch(e){
trace("caught error: " + e);
errT.text = "That is not a valid object name.";
}
 
// even if error occurs above or in randomBall(), the rest of the
//method still executes.
trace("end of function");

The really cool thing about try..catch.. is that it not only catches errors in the immediate script that it wraps, but from every class that is called from within the block. A word of warning, try...catch... will not protect your "for" loops from causing the "script causing Flash Player to run slowly" Error. You still need to evaluate your variables and exit number values before execution.

Below is a sample app (like Lotto) with a terrible system of user interaction, but it should demo the point.

Type in the Object name (Ball1, Ball2, Ball3, etc.) in the input area, then click Enter. The numbers on the ball are random. Try to see how many clicks it takes to get all the numbers to match. The try..catch... statement comes into play when/if a user inputs the object name incorrectly.

Demo:

source here
In normal uses PHP and other server/scripting languages are able to store variables for later usage. Due to the fact that the these pages are not actually living in a browser, adiposity remoting is one of the exceptions where variables do not live between calls. We have to plan out our Flash to PHP conversations as if PHP has very short term memory and include all the needed data to complete every transaction. For instance, page if you have to store information in a database using a userID, even though you have just recieved that userID from php, your next php call will have to include the userID because PHP just can not remember.

Here is a demo of using PHP session variables to temporarily store and read data. Even though normal variables vanish, session information is live and well.

This demo was built a while ago in AS2, but all the session code only effects the PHP side so the results should work with AS3 as well. There are some nice AS3 AMFPHP remoting tutorials already on the web. Here are a few of the many possible links: GotoAndLearn, Caleb.org

Starting php sessions are really simple.

//place this at the top of the page
session_start();
 
//use this syntax to add data to a session variable.
$_SESSION[$name] = $value;
 
//pulling data is just as straight forward.
return $_SESSION[$name];

To use the demo, type an interesting string into one of the input boxes then press "TELL". To recall the string from the session variable, press "ASK". You will see status information appear in the output areas.
Demo.

source here
I was first introduced to the ColorTransform class while reading the AS2 to AS3 migration documentation about setRGB(). I was immediately impressed with the features, stomach web but intimidated when I saw the constructor and all the offset, story color and alpha arguments. I just needed to change the color of something, nothing special, no gradients, no alpha, no space shuttle landings, just a simple hex color change.

So here is a simple color change utility that is a lot closer to what I am used to.

?View Code ACTIONSCRIPT
function paint(obj:Object,color:Number):void{
var ct:ColorTransform = new ColorTransform();
ct.color = color;
obj.transform.colorTransform = ct;
}



source here
Here is an AS2 version of the SuperLoader. It works just like the AS3 version found in the Custom HTML Templates post.

Quick Use:
1. Add loaderbar.swf and mainLoader.swf to your current project directory.

2. In the html file for your current project, pilule replace the src and movie parameters to mainLoader.

3. Then add [, website like this 'flashVars', stomach 'swfURL=FlashProjectToLoad.swf'] to the load script.

Example for AC_RunActiveContent:

AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '472',
'height', '280',
'src', 'mainLoader',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'mainLoader',
'bgcolor', '#000000',
'name', 'mainLoader',
'menu', 'true',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'mainLoader',
'salign', '',
'flashVars','swfURL=imgViewer.swf'
); //end AC code

Example for HTML Object/Embed:

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="472" height="280" id="mainLoader" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="mainLoader.swf?swfURL=imgViewer.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" />	<embed src="mainLoader.swf?swfURL=imgViewer.swf" quality="high" bgcolor="#ffffff" width="472" height="280" name="mainLoader" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

4. If your frame rate is different then 30, you will need to update the frame rate in the mainLoader.fla file.

5. If you are using this loader inside of your Flash movie, you may also need to comment out the line that sets _root to the loading file [mainMC._lockroot = true;].

Demo:

Source Here

UPDATE: 1.1

1. Added usage information, the class could be used as a simple loader monitor if needed.
2. Moved class path from com.hdi.util.HDLoader to com.hdi.as2.HDLoader.

See just the loader class below.

?View Code ACTIONSCRIPT
/**********************************************************
HDLoader is a simple loader monitor that can attach to your custom loading bar
version 1.1
date: 1-9-10
 
How To Use:
1. Have something that needs loading
 
2. Create a function to handle the loading monitor updates. Should look something like this.
function loaderUpdate(perc:Number){
// perc is the percent loaded in non decimal form. 0 - 100.
// you can make a loading bar move or scale like so
loaderBar._xscale = perc/100;
 
// you can display text of the loading status.
loaderText.text = "LOADING: " + perc + "%";
}
 
3. Create a funciton to handle when loading is complete
function loadComplete(){
// hiding the loader after loading is always a good thing.
loaderBar._visible = false;
 
// do what ever you want here, your crap is now loaded.
}
 
4. import HDLoader.
import com.hdi.as2.HDLoader;
 
5. Start the loader, placing the correct target references in the correct argument positions.
arg 1: the MovieClip doing the laoding.
arg 2: the loader update function created in step 2.
arg 3: the loader complete function created in step 3.
 
// we are assuming you have just started loading something (mc.loadMovie("someSWF.swf");
var loaderMon:HDLoader = new HDLoader(mc,loaderUpdate,loadComplete);
 
Author: Todd Williams
website: www.taterboy.com
website: hdinteractive.com
***********************************************************/
 
class com.hdi.as2.HDLoader{
var targMC:Object;
var monFunc:Function;
var finFunc:Function;
public function HDLoader(targ,mfunc,func){
init(targ,mfunc,func);
}
private function init(targ,mfunc,func){
var lbytes,tbytes,perc;
var frameParent:Object = targ._parent;
var cnt:Number = 3;
var frameObj:MovieClip = frameParent.createEmptyMovieClip("frameLdr",frameParent.getNextHighestDepth());
frameObj.onEnterFrame = function(){
lbytes = targ.getBytesLoaded();
tbytes = targ.getBytesTotal();
perc = Math.round((lbytes/tbytes)*100);
if (lbytes < tbytes) {
if(mfunc != null){
mfunc(perc);
}
}
else if(tbytes > 200){
if(cnt == 0){
if(func != undefined){
func();
}
delete frameObj.onEnterFrame;
}
cnt --;
if(mfunc != null){
mfunc(100);
}
}
}
}
}

Passing Flash variables to Javascript, online passing Javscript variables to Flash, price Calling Flash functions from Javascript.

There are a few conventions for getting Flash and Javascript to communicate like fscommand, getURL, LocalConnection, URL-encoded variables, FlashVars, SetVariable and TCallLabel to name a few.

Here is a little demo using Flash's External Interface and Javascript. It is more elegant then most of the procedures I have used in the past. Between External Interface and FlashVars, you should be able to fill most of your needs.

By the way, the syntax is almost exactly the same for AS2 and AS3.

Flash Usage:

?View Code ACTIONSCRIPT
//import flash.external.*; //for AS2
 
//1. calling javascript function from Flash.
ExternalInterface.call("sendData",tempStr);
// argument 1: javascript function, argument 2: data/variables to pass out.
 
//2. calling javascript function from Flash with recursion.
var returnValue:String = ExternalInterface.call("sendReturn",tempStr).toString();
 
//3. setting up a callback function for javascript
ExternalInterface.addCallback("callFlash",flashResponse);
// argument 1: function name called by javascript, argument 2: function on the Flash side.
// AS2 version looks like this : ExternalInterface.addCallback("callFlash",null,flashResponse);

Javascript Usage:

//1. javascript function as called from Flash.
function sendData(val){
alert(val);
document.flashForm.flashOutput.value = val;
}
 
//2. javascript function with recursion.
function sendReturn(val){
var tempData = "Hello from JS";
return tempData + ' :return';
}
 
//3. calling Flash function with javascript.
function sendToFlash(val){
flash.callFlash(val);
}



Source Here.
One of my favorite statements is try..catch..finally.

When building web applications, this we as developers need to plan for the unexpected. We know the web does not always behave at the same level of consistency for all users. This does not take into account client systems which can compound minor glitches.

There are also times that you need to compile code that is reliant on external variables. If all the conditions are not returned in a valid format AS3, being very strict, will throw an error and not complete the remaining code sequences as intended.

Though the try..catch.. statement has been around since AS1/Flash Player 7, it's value was not as profound and often overlooked as AS2 scripts would just error out quietly anyway. This was bad because bad habits were easily developed and can cause some struggles when working in the much more structured AS3 environment.

Try..catch.. is great when working with database calls, loading external media and developing an enhanced error system. The moral of this post could be "learning to take control of errors before they take control of you".

?View Code ACTIONSCRIPT
try{
randomBall(numT.text);
}
catch(e){
trace("caught error: " + e);
errT.text = "That is not a valid object name.";
}
 
// even if error occurs above or in randomBall(), the rest of the
//method still executes.
trace("end of function");

The really cool thing about try..catch.. is that it not only catches errors in the immediate script that it wraps, but from every class that is called from within the block. A word of warning, try...catch... will not protect your "for" loops from causing the "script causing Flash Player to run slowly" Error. You still need to evaluate your variables and exit number values before execution.

Below is a sample app (like Lotto) with a terrible system of user interaction, but it should demo the point.

Type in the Object name (Ball1, Ball2, Ball3, etc.) in the input area, then click Enter. The numbers on the ball are random. Try to see how many clicks it takes to get all the numbers to match. The try..catch... statement comes into play when/if a user inputs the object name incorrectly.

Demo:

source here
In normal uses PHP and other server/scripting languages are able to store variables for later usage. Due to the fact that the these pages are not actually living in a browser, adiposity remoting is one of the exceptions where variables do not live between calls. We have to plan out our Flash to PHP conversations as if PHP has very short term memory and include all the needed data to complete every transaction. For instance, page if you have to store information in a database using a userID, even though you have just recieved that userID from php, your next php call will have to include the userID because PHP just can not remember.

Here is a demo of using PHP session variables to temporarily store and read data. Even though normal variables vanish, session information is live and well.

This demo was built a while ago in AS2, but all the session code only effects the PHP side so the results should work with AS3 as well. There are some nice AS3 AMFPHP remoting tutorials already on the web. Here are a few of the many possible links: GotoAndLearn, Caleb.org

Starting php sessions are really simple.

//place this at the top of the page
session_start();
 
//use this syntax to add data to a session variable.
$_SESSION[$name] = $value;
 
//pulling data is just as straight forward.
return $_SESSION[$name];

To use the demo, type an interesting string into one of the input boxes then press "TELL". To recall the string from the session variable, press "ASK". You will see status information appear in the output areas.
Demo.

source here
I know there are some really nice scroll components similar to this on the web, viagra 100mg but I think this still has merit. It seems like every job comes with a different scroll bar design, information pills the buttons and scroll bar can be any shape, size or configuration. While most Flash scroll bar components are easily skinned, this is kind of the opposite of skinning. You create the artwork, convert each item to a MovieClip, then apply the class. The code wraps the artwork instead of the artwork skinning the code.

This class started around 3 years ago and has been modified for many different projects and continued to evolve into what we have today. It is not perfect, but it can handle most jobs needing custom scroll bars.

Demo:

Some of the features include:
Auto On/Off - you may need a scrolling clip that could change in size as dynamic content is displayed or entered. When the scroll bar is not needed, it will turn itself off and back on when it is needed. Or you can manually turn it on and with your code.

Easing - Control the amount of ease or delay of the scrolling object.

Scroll Bar Resizing - To simulate the function of desktop applications, the scroll bar will automatically scale depending on the amount of scroll, This feature can be turned on or off.

Auto Resize - Say you have a project that needs multiple scroll bars. One 150 px tall, the other 500 px tall. With this class you can build one set of artwork and the class will automatically adjust the bottom button, scroll background, scrollbar scroll area to fit the needed size. Based on Mask size.

Down Button Flip - This will not change the world, but if you have an Up Button that is exactly like the bottom button just flipped vertically. The class will compensate for this, saving a few minutes of development time and a few kilobytes.

Scroll Background Hiding and resizing - Many scroll bars have a background track, you may want it visible when the scroll bars are disabled as a visual place holder. This feature can be turned on or off.

Works without a scroll bar or without up and down buttons.

Button Type Behaviors - Even though the buttons and scrollbars are made with movieClips, sample code and calls are provided to give them button type effects on rollOver, rollOut, press and release.

Usage may seem a little complex at first, but if you like designing and using custom scroll bars and buttons, it is totally worth it.

1. Create all your scroll objects, they should be converted to MovieClips.
(upButton, DownButton, ScrollBar, and ScrollBkg)

2. Place the up and down buttons, scroll bar, and scroll background into a new movieClip.
(ScrollObject)

3. Align the top button and scrollbar to it's starting position.

4. Create the MovieClip to be scrolled, can include a TextField, graphics or both.
(ScrollMovieClip)

5. Create a mask and convert it to a MovieClip and mask the viewable area of the "ScrollMovieClip".
(MaskMC)

5. Apply the class, this is the most complex part.

var scrollVert:HDScrollMC = HDScrollMC(ScrollObject, ScrollMovieClip, MaskMC, UpButton, DownButton, ScrollBar, ScrollBarResize, ScrollBkg, ScrollBkgHide, DownButtonFlip, ResizeScrollObjects, AutoOn, Ease);

This is where you assign all the MovieClips and enable any of the features. Other than the 7 MovieClips that the class points to, the other 6 arguments are features to enable or disable.

ScrollBarResize: Boolean (true/false)
ScrollBkgHide: Boolean (true/false)
DownButtonFlip: Boolean (true/false)
ResizeScrollObjects: Boolean (true/false)
AutoOn: Boolean (true/false)
Ease: Number (0-100) *(5 - 20) for best effect.

Once enabled, it can manage itself or you can manage it manually with a method like so:
scrollVert.ScrollStatus(true); or scrollVert.ScrollStatus(false);

When you are done with everything, you can strip all the code out by calling scrollVert.killScrollBar();

You can check the status of the scrollbar at anytime using
scrollVert.scrollStat; returns true or false.

?View Code ACTIONSCRIPT
import mx.utils.Delegate;
class com.hdi.as2.HDScrollMC{
/*
HDScrollMC oringinally created 11/2005 by Todd Williams and HD Interactive.
©2005 - 2010 HD Interactive & Taterboy, Inc.
version: 2.4
Date: 7-26-10
 
Compatibility:  Action Script 2, Flash Player 7 and higher.
Purpose:
To Build a scrollbar class that is truly portable and can be applied to custom artwork
of any size and shape. This class wraps the graphics instead of graphics wrapping the code.
This gives the designer complete 	control over look and feel. One of the major features
needed was to have one set of scroll objects to be 	used in multiple instances and allow
them to automatically conform to different scrolling needs. One set of scroll objects can
control a scroll window that is 200 pixels tall or 600 pixels tall on the same stage at the
same time.
 
HDScrollMC handles Vertical Scrolling Only, for horizontal scrolling use HDScrollHorizontal.
 
Features:
1. Automatically arranges scroll objects so that one set scrollbar objects can be used in multiple
instances with different sized scrolling windows.
2. Resizing scroll bar similar to OS and desktop application scroll bar behavior.
3. Customizable Easing options for enhanced feel and response.
4. Code Wraps to custom artwork instead of skinning a preexisting component.
5. Auto on and off. The scroll bar is smart enough to know when it is needed or not.
6. Code provided to build button type behavior into MovieClip buttons and scrollbar.
7. Have multiple scrolling objects visible and functioning on the same stage at a time.
 
 
Preparation:
To prepare graphic objects for use with HDScrollMC, you will need to create 7 MovieClips.
MC 1. The MovieClip to be scrolled:
For scrolling text, create a TextField inside of a MovieClip, fill it with text manually,
or use dynamic text and the TextField.autoSize = true;
 
MC 2. Mask for MC 1 display area: This must be a MovieClip so that class can determine the size of the
masked area.
 
MC 3. Container for Scroll Objects: To make it possible to have multiple scrolling objects on the
stage at the same time, it is best to have at least the scrollbar and scroll button objects in a
container, the mask and MC to be scrolled can also be in this container if desired.
 
MC 4 & 5.  Scroll buttons UP and Down. These buttons are not required if a scrollbar only design is
needed. Scroll buttons can be MovieClips or buttons. Code for rollover and press events will be
sent to each MovieClip. If you want to use a MovieClip, disperse your button states on frames as you
would a button and add a stop action to the first frame. Also the down button and be a vertically
flipped instance if the top button if the design allows for this.
 
The scroll button MovieClips receive the following method calls from the class.
btnEvent(1); roll on
btnEvent(0); roll out
btnEvent(2); mouse down
btnEvent(1); mouse up
 
Use the sample method below for MovieClips with button type behavior.
**Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
Long-hand Sample:
function btnEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
 
MC 6. Scroll Bar: Must be a MovieClip and like the buttons, code will be sent for rollover and press events.
A scrollbar is not required if a button only design is required. The scroll bar has a resize feature
with two modes. The scroll bar will resize based on the amount of scroll and the size of the scroll
area, similar to OS scroll bars.
 
Mode 1: (recommended) The scrollbar MovieClip resizes the whole Scroll Bar MovieClip. Some graphic distortion or stretching may occur.
You can set the scale9Grid to this MovieClip prior to enabling this class.
 
Mode 2: Three individual MovieClips within the Scroll Bar are used to represent the top, middle
and bottom of the scroll bar, the middle will be stretched the top and bottom MovieClips will retain
their graphic integrity. To use this option divide the Scrollbar into three horizontal slices. Create
MovieClip instances named scrollbBarTop, scrollBarBot, and scrollBarMid.
(this was implimented before scale9Grid capibilities (Flash Player 7))
 
The scrollbar receives the following method calls from the class.
barEvent(1); roll on
barEvent(0); roll out
barEvent(2); mouse down
barEvent(1); mouse up
 
Use the method below for MovieClips with button type Behavior.
**Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
Long-hand Sample:
function barEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
 
MC 7. Scroll background, Must be a MovieClip,  will span the entire size of the scroll area
if the class is set to resize the objects. This MovieClip can be used to have a decorative
track for the scroll area and can be set to vanish or remain when the scrollbar is disabled
or enabled. This object is not required.
 
Usage:
Place the class folder in the working directory next to the fla you are using;
add import com.hdi.as2.HDScrollMC; to the actions panel before the code below.
 
var vertScroll:HDScrollMC = new HDScrollMC(ScrollObject, ScrollMovieClip, MaskMC, UpButton,
DownButton, ScrollBar, ScrollBarResize, ScrollBkg, ScrollBkgHide, DownButtonFlip ResizeScrollObjects,
AutoOn, Ease);
 
**should be all one line.
 
I know there are a lot of arguments, and the descriptions/Usage are as follows:
1. ScrollObject - (required) target of scroll object container, MC 3 from the preparation list.
2. ScrollMovieClip - (required) target of MovieClip to be scrolled, MC 1 from preparation list.
3. MaskMC - (required) target to Mask for the scrolling MovieClip, MC 2 from preparation list.
4. UpButton - target or null, to Up Button MovieClip or Button. MC 4 & 5 from preparation list.
5. DownButton - target  or null, to Down Button MovieClip or Button. MC 4 & 5 from preparation list.
6. ScrollBar - target or null, to Scroll Bar MovieClip. MC 6 from preparation list.
7. ScrollBarResize - Boolean: true or false, To enable scroll bar resizing depending on scroll amount.
8. ScrollBkg - target or null, to resize scroll background graphic.
9. ScrollBkgHide - Boolean: true or false, default behavior is to hide scroll background and scroll objects
when scrollbar is disabled;
10. DownButtonFlip - Boolean: true or false, If the down button is an instance of the up button that is
vertically flipped.
11. ResizeScrollObjects - Boolean: true or false, when scroll bar loads, it calculates the size of the mask,
buttons, scrollbars and distributes them to the appropriate height and coordinates. This allows
different instances of a set of scroll objects to be used with different sized scrolling Objects.
12. AutoOn - Boolean: true or false, Turns control of turning the scroll bar objects on and off to the class.
If the scrolling MovieClip changes in size the class will automatically enable or disable the
scroll objects.
13. Ease - Number, changes the scrolling MovieClip's response to scroll events. set to 0 for no delay.
 
 
Other methods and properties:
You can use these properties and methods for external control and monitoring.
 
scrollStatus:  property (Boolean) - tells if scrolling is enabled or disabled.
setScrollStatus: Function (Boolean)- manually enables/disables scrolling - use with AutoOn set to false.
killScrollBar: Function - permanently disables the scrollbar and removes all listeners and events.
setScrollPos: Function (Number) manually sets the scroll position of the scrolling clip and uptdates the scrollbar position.
 
Tips:
1. For best performance, zero out  x and y coordinates to whole numbers on all MovieClips.
Also try to build artwork with artwork rounded to the nearest whole pixel. This stops a lot
of the little glitches 	that can appear when a user interacts with the scrolling objects.
 
2. If you do not want your scroll objects to flash on then off on load, set the scroll Object
Container's (MC 3) 	alpha property to 0. The class will automatically set it to 100 when enabled.
 
3. By default the class uses the scroll background  and/or the up button to align and distribute
the rest of the objects. You should align the top button and the top of the scroll background.
The top of the scrollbar should be aligned to the button of the top button. These coordinates
are used as starting points for all of 	the scroll objects and will used as return positions
when the scroll bar is reset.
 
*/
private var scrollObj:Object; //scroll MovieClip containing up button, down button, scrollbar, background.
private var tClip:Object; //MovieClip that holds the text clip.
private var tMask:Object; //Mask for the Text MovieClip, must be a MovieClip.
private var dwnBtn:Object; //Down button, should be movieClip or button.
private var upBtn:Object; //Down button, should be movieClip or button.
private var scrollBar:Object; //MovieClip to do the scrolling.
private var barAutoSize:Boolean; //Resizes the scroll bar to the scroll amount.
private var scrollBkg:Object; //Background behind scrollButtons and scrollBar.
private var scrollBkgHide:Boolean; //When scroll objects are not on, ScrollBkg is can be visible or not.
private var flipDwnButton:Boolean; // If you have flipped the upBtn to make the dwnBtn. Used for autoResize.
private var resizeObj:Boolean; // Resizes scroll objects to match the mask size and location.
private var autoOn:Boolean; //Let's the scroll object control if the scrollBar is on or off, depending on the size of the text box.
private var easeIn:Number; // Amount of delay for scrolling text to ease into possition.
private var scrollYPos:Number;
public var scrollStatus:Boolean; //Scrollbar is On or Off.
private var startParams:Boolean;
private var inc:Number;
private var resetAllSizes:Function;
function HDScrollMC(targObj,tclip,tmask,upbtn,dwnbtn,sbar,barsize,sbkg,sbkgHide,flip,reSize,auto,ease){
scrollObj = targObj;
tClip = tclip;
tMask = tmask;
upBtn = upbtn;
dwnBtn = dwnbtn;
scrollBar = sbar;
barAutoSize = barsize;
scrollBkg = sbkg;
scrollBkgHide = sbkgHide;
flipDwnButton = flip;
resizeObj = reSize;
autoOn = auto;
easeIn = ease;
scrollYPos = tClip._y;
if(tMask._height >= tClip._height){
scrollStatus = false;
if(scrollBkgHide && scrollBkg){
scrollBkg._visible = false;
}
 
}
else{
scrollStatus = true;
}
var testConfig:Boolean = true;
if(scrollObj == null || scrollObj == undefined){
trace("ERROR: ScrollObject (arg 0) needs to be a valid MovieClip ");
testConfig = false;
}
if(tMask == null || tMask == undefined){
trace("ERROR: MaskMC (arg 2) needs to be a valid MovieClip - please mask the scrolling object with a named instance of a MovieClip");
testConfig = false;
}
if(easeIn == NaN || easeIn == undefined){
trace("ERROR: Ease (arg 12) needs to be a Number - 0 for no ease, 1 and higher to add ease/delay to the scrolling object");
testConfig = false;
}
if((scrollBar == null || scrollBar == undefined) && (upBtn == null || upBtn == undefined) && (dwnBtn == null || dwnBtn == undefined)){
trace("ERROR: Very funny, you need at least 1 control object (scrollBar, upBtn or dwnBtn) assigned to initiate scrolling");
testConfig = false;
}
if(testConfig){
init();
}
}
public function setScrollStatus(val){
scrollStatus = val;
scrollObj.stat = val;
scrollObj.tmask = tMask;
scrollObj.yPos = scrollObj.starty;
tClip._y = scrollObj.starty;
scrollBar._y = scrollObj.bary;
setSizes();
if(val){
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
scrollBkg._visible = true;
}
else{
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
if(scrollBkgHide){
scrollBkg._visible = false;
}
}
}
public function setScrollPos(val){
setSizes();
var tempY:Number = val;
if(tempY > scrollObj.starty){
tempY = scrollObj.starty;
}
else if(tempY < scrollObj.starty - scrollObj.scrolldist){
tempY = scrollObj.starty - scrollObj.scrolldist;
}
 
scrollObj.yPos = tempY
tClip._y = tempY;
scrollBar._y = (((scrollObj.starty - scrollObj.yPos) / scrollObj.scrolldist) * scrollObj.barslack) + scrollObj.topy;
}
public function killScrollBar(){
tClip._y = scrollObj.starty;
scrollBar._y = scrollObj.bary;
scrollObj.yPos = scrollObj.starty;
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
delete scrollObj.onEnterFrame;
delete scrollBar.onMouseUp;
delete scrollBar.onMouseDown;
delete scrollBar.onMouseMove;
delete upBtn.onMouseUp;
delete upBtn.onMouseDown;
delete dwnBtn.onMouseUp;
delete dwnBtn.onMouseDown;
delete upBtn.onRollOut;
delete upBtn.onRollOver;
delete dwnBtn.onRollOut;
delete dwnBtn.onRollOver;
delete scrollBar.onRollOut;
delete scrollBar.onRollOver;
clearInterval(inc);
Mouse.removeListener(scrollObj.myWheel);
}
private function setSizes(){
scrollObj.maskh = tMask._height;
if(tClip._y < scrollObj.starty - (tClip._height - scrollObj.maskh)){
if(tClip._height <= scrollObj.maskh){
scrollObj.yPos = scrollObj.starty;
}
else{
scrollObj.yPos = scrollObj.starty - (tClip._height - scrollObj.maskh);
}
}
else if(tClip._y > scrollObj.starty){
scrollObj.yPos = scrollObj.starty;
}
 
tClip._y = scrollObj.yPos;
 
if(barAutoSize == true){
//setup dynamic scrollbar height.
var sbHeight:Number;
if(tClip._height > scrollObj.maskh){
sbHeight = Math.floor((scrollObj.maskh / Math.ceil(tClip._height)) * scrollObj.bardist);
}
else{
//sbHeight =
}
if(sbHeight < 20){
sbHeight = 20;
}
if(scrollBar.scrollbBarTop._name == undefined){
 
scrollBar._height = sbHeight;
}
else{
scrollBar.sheight = sbHeight
scrollBar.scrollBarMid._height = scrollBar.sheight - (scrollBar.scrollbBarTop._height + scrollBar.scrollbBarTop._height);
scrollBar.scrollbBarTop._y = scrollBar.scrollBarMid._height + scrollBar.scrollBarMid._y;
}
 
}
scrollObj.bht = Math.ceil(scrollBar._height);
scrollObj.barslack = (scrollObj.boty - scrollObj.topy) - scrollObj.bht;
scrollObj.scrolldist = Math.ceil(Math.ceil(tClip._height) - (scrollObj.maskh));// + 10;
scrollObj.scrollspeed = scrollObj.scrolldist / 8;
scrollObj.yspeed = tMask._height/10;//16;
scrollObj.upscroll = 0;
scrollObj.dwnscroll = 0;
scrollBar._y = (((scrollObj.starty - scrollObj.yPos) / scrollObj.scrolldist) * scrollObj.barslack) + scrollObj.topy;
}
private function setCoors(){
tMask._height = Math.ceil(tMask._height);
scrollObj.maskh = tMask._height;
if(resizeObj){
flipDwnButton == true? dwnBtn._y = Math.round(tMask._height): dwnBtn._y = Math.round((tMask._height) - dwnBtn._height);
//flipDwnButton == true? dwnBtn._y = Math.round(tMask._height + tMask._y): dwnBtn._y = Math.round((tMask._height + tMask._y) - dwnBtn._height);
 
if(scrollBkg != null){
upBtn != null ? scrollBkg._height = scrollObj.maskh: scrollBkg._height = scrollObj.maskh;
}
 
}
upBtn._y = Math.floor(upBtn._y);
scrollObj.tht = Math.ceil(tClip._height);
if(!startParams){
scrollObj.starty = tClip._y;
startParams = true;
}
//scrollObj.starty = tClip._y;
scrollObj.barx = scrollBar._x;
scrollObj.bary = scrollBar._y;
if(upBtn != null){
scrollObj.topy = Math.round(upBtn._y + upBtn._height);
flipDwnButton == true? scrollObj.boty = Math.round(dwnBtn._y - dwnBtn._height): scrollObj.boty = Math.round(dwnBtn._y);
}
else{
scrollObj.topy = Math.round(scrollBar._y);
scrollObj.boty = Math.round(scrollBar._y + tMask._height);
}
scrollObj.bardist = (scrollObj.boty - scrollObj.topy);
setSizes();
}
 
private function init(){
setCoors();
if(scrollStatus == false){
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
}
else{
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
}
scrollObj._alpha = 100;
scrollObj.objectRef = this;
scrollBar.objectRef = this;
upBtn.objectRef = this;
dwnBtn.objectRef = this;
var scrollParent:Object = scrollObj;
 
scrollObj.stat = scrollStatus;
scrollObj.yPos = scrollYPos;
 
var ref:Object = this;
scrollObj.myWheel = new Object();
scrollObj.myWheel.onMouseWheel = function(delta){
trace(delta);
 
if(ref.scrollObj.stat && ref.scrollObj.tmask.hitTest(_root._xmouse, _root._ymouse)){
if(delta > 0){
if(ref.scrollObj.yPos < ref.scrollObj.starty - ref.scrollObj.yspeed){
ref.scrollObj.yPos += Math.round(ref.scrollObj.yspeed);
ref.scrollBar._y = (((ref.scrollObj.starty - ref.scrollObj.yPos) / ref.scrollObj.scrolldist) * ref.scrollObj.barslack) + ref.scrollObj.topy;
}
else{
ref.scrollObj.yPos = ref.scrollObj.starty;
ref.scrollBar._y = ref.scrollObj.topy;
}
}
else if(delta < 0){
if(ref.scrollObj.yPos > ref.scrollObj.starty - (ref.scrollObj.scrolldist - ref.scrollObj.yspeed)){
ref.scrollObj.yPos -= Math.round(ref.scrollObj.yspeed);
ref.scrollBar._y = (((ref.scrollObj.starty - ref.scrollObj.yPos) / ref.scrollObj.scrolldist) * ref.scrollObj.barslack) + ref.scrollObj.topy;
}
else{
ref.scrollObj.yPos = ref.scrollObj.starty - ref.scrollObj.scrolldist;
ref.scrollBar._y = ref.scrollObj.boty - ref.scrollObj.bht;
}
}
}
}
Mouse.addListener(scrollObj.myWheel);
 
if(resizeObj){
resetAllSizes = setCoors;//setSizes;
}
 
scrollBar.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(2);
scrollParent.scrollchk = true;
this.startDrag(false,scrollParent.barx,scrollParent.topy,scrollParent.barx,scrollParent.boty - scrollParent.bht);
this.onMouseMove = function(){
if(scrollParent.scrollchk == true){
scrollParent.yPos = scrollParent.starty - (scrollParent.scrolldist * ((this._y - scrollParent.topy)  / scrollParent.barslack));
}
 
}
}
}
else{
}
}
scrollBar.onMouseUp = function(){
scrollParent.scrollchk = false;
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(1);
}
this.stopDrag();
}
scrollBar.onRollOut = function(){
this.barEvent(0);
}
scrollBar.onRollOver = function(){
this.barEvent(1);
}
upBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.upscroll = 1;
}
}
}
upBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.upscroll = 0;
}
upBtn.onRollOut = function(){
this.btnEvent(0);
}
upBtn.onRollOver = function(){
this.btnEvent(1);
}
dwnBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.dwnscroll = 1;
}
}
}
dwnBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.dwnscroll = 0;
}
dwnBtn.onRollOut = function(){
this.btnEvent(0);
}
dwnBtn.onRollOver = function(){
this.btnEvent(1);
}
 
inc = setInterval(Delegate.create(this, frameLoop),10);
}
 
private function frameLoop(){
if(scrollObj.upscroll == 1){
if(scrollObj.yPos < scrollObj.starty - scrollObj.yspeed){
scrollObj.yPos += Math.round(scrollObj.yspeed);
scrollBar._y = (((scrollObj.starty - scrollObj.yPos) / scrollObj.scrolldist) * scrollObj.barslack) + scrollObj.topy;
}
else{
scrollObj.yPos = scrollObj.starty;
scrollBar._y = scrollObj.topy;
}
}
if(scrollObj.dwnscroll == 1){
if(scrollObj.yPos > scrollObj.starty - (scrollObj.scrolldist - scrollObj.yspeed)){
scrollObj.yPos -= Math.round(scrollObj.yspeed);
scrollBar._y = (((scrollObj.starty - scrollObj.yPos) / scrollObj.scrolldist) * scrollObj.barslack) + scrollObj.topy;
}
else{
scrollObj.yPos = scrollObj.starty - scrollObj.scrolldist;
scrollBar._y = scrollObj.boty - scrollObj.bht;
}
}
 
if(scrollStatus){
var dirStat:Number = 0;
scrollObj.dwnscroll == 1 ? dirStat = -1:null;
scrollObj.upscroll == 1 ? dirStat = 1:null;
easeMainClip(tClip,scrollObj.yPos,easeIn,dirStat);
if(autoOn){
if(tClip._height <= tMask._height){
setScrollStatus(false);
}
var checkScrollDist:Number = Math.ceil(Math.ceil(tClip._height) - (scrollObj.maskh));// + 10;
if(scrollObj.scrolldist < checkScrollDist || (scrollObj.maskh != tMask._height)){
//reset size - ;
if(resetAllSizes && tMask._height != scrollObj.maskh){
resetAllSizes();
}
setSizes();
}
else if (scrollObj.scrolldist > checkScrollDist){
//reset size + ;
if(resetAllSizes && tMask._height != scrollObj.maskh){
resetAllSizes();
}
setSizes();
}
}
 
}
else{
if(autoOn){
if(tClip._height > tMask._height){
setScrollStatus(true);
}
resetAllSizes();
}
}
updateAfterEvent();
}
private function easeMainClip(obj,val,ease,dir){
if(ease > 0){
if(dir == 0){
if(Math.floor(obj._y) > val + 1){
dir = -1;
}
else if(Math.ceil(obj._y) < val - 1){
dir = 1;
}
}
if(dir == -1){
obj._y -= (obj._y - val)/ease;
}
else if(dir == 1){
obj._y += (val - obj._y)/ease;
}
else{
obj._y = val;
}
}
else{
obj._y = val;
}
}
 
}

Source Here

***** Some of the applications of this class may be better suited for HDSlide, a newer AS2 class to make things slide horizontally or vertically, without scroll bars using mouse movement.

Major Update and rewrite (2.0), Please download again to update your files

1. Multiple instances now work
2. Scrollbar background will be invisible if the text is not the correct size.
3. Added in code for resizing the text MC and mask to be more browser like. Not fully tested but does not seem to break other features.
4. Added code for scroll wheel support, but is it commented out. I have not tested it yet with multiple instances.

Horizontal version (2.2) is is available here.
Horizontal Scroll Source

UPDATE: 2.1

Source can be updated, using the links above.
added - clearInterval(inc); to the killScrollBar method.

UPDATE: 2.2

Source can be updated, using the links above.
1. Minor bug fixes adding reliability.
2. Scrollbars adjust if content is resized when autoOn and ResizeScrollObjects are set to true, like browser window functionality.
3. Horizontal scroll bar has been fully tested to work with vertical scroll bar on the same ScrollMovieClip. (browser type functionality)
4. Some of the documentation and usage in the class files has been clarified.
5. Both class files are included in each download above (horizontal and vertical).

UPDATE: 2.3

1. MouseWheel is now enabled by default. Thanks Pawe for pointing out the ref reference. MouseWheel support in AS2 still only works on Windows, not my fault, that is a dispute with Flash Player and Apple.
2. Added setScrollPos(Number) function to manually set the scroll position of the scrolling clip and uptdate the scrollbar position. In my testing calling this right after a textField autoSize call did not work until the next frame. Giving the scrolling clip a chance to redraw. Just pass in a number of where you want the scrolling clip to go. If the number is out of range, it will automatically correct itself.
3. Moved the class path from com.hdi.util.HDScrollMC to com.hdi.as2.HDScrollMC. All previous and future asctionScript 2 classes with organized this way.

UPDATE: 2.4

1. Fixed an issue when overriding scrollMC postition after changing the size of the scrollMC.

Thanks for the input and testing.

The Tampa Flash, physician stuff Flex and AIR Developers Group has launched their website with their first meeting scheduled for October 7th, check 2008 at 7:00 PM. They have some cool things planned and some great sponsors. The meeting will be held at the Art Institutes of Tampa and refreshments provided by the International Culinary Schools.

Greg Wilson, from Adobe, will be the presenter for the inaugural event and we can expect frequent visits from Adobe representatives in the future. Find out more at www.tffadg.com and RSVP if you are in the area.
The Tampa Flash, physician stuff Flex and AIR Developers Group has launched their website with their first meeting scheduled for October 7th, check 2008 at 7:00 PM. They have some cool things planned and some great sponsors. The meeting will be held at the Art Institutes of Tampa and refreshments provided by the International Culinary Schools.

Greg Wilson, from Adobe, will be the presenter for the inaugural event and we can expect frequent visits from Adobe representatives in the future. Find out more at www.tffadg.com and RSVP if you are in the area.
This is a two in one post, hospital the first half will demonstrate how to build a small but powerful animation engine. The second half is a demo and source for an expanded version of the same animation engine.

The goals for our engine are:
1. Light Weight - We do not want to apply an onEnterFrame event handler on every MovieClip. Each instance of an onEnterFrame event increases processor usage, page so we will use one onEnterFrame event to process all animation.

2. Robust - Issues can arise with you try daisy chain onEnterFrame events, garbage collection and rendering sequences can cause the chain to break. So we need a powerful management system.

3. Flexible - Some projects we only need to animate _alpha, others will need to tween _x, _y, _rotation, _xScale or a combination of them all. With a little extra code we can make this animation engine process most MovieClip Properties.

When I program something new, I make a list of all the features I need for the app. Below are the notes for this engine, now we can add the variables and methods to support each feature.

?View Code ACTIONSCRIPT
// data, array and object management.
 
// data handler, add data to array
 
// remove data from array
 
// enter frame event
 
// process animation and make tweens happen

The Array:
First is data, we will use an array to hold all the data for each animation while the engine runs. Keeping all the data in a central location means less issues caused by garbage collection and objects being added to and removed from the stage.

Arrays are super powerful, you may be familiar with an array that looks like this:

?View Code ACTIONSCRIPT
var tempArr:Array = new Array("red","blue","green","yellow");
trace(tempArr[0]); // "red"
 
//or
 
var tempArr:Array = [];
tempArr[0] = "red";
tempArr[1] = "blue";
tempArr[2] = "green";
tempArr[3] = "yellow";
trace(tempArr[1]); // "blue"

This engine will require much more information that is tightly organized. For this we will add a data object to each element of the array. A data object can look similar to an array, that is because they can be indexed like an array.

?View Code ACTIONSCRIPT
var tempObj:Object = new Object();
tempObj[0] = "hello";
trace(tempObj[0]); // "hello"

Property type variables can also be set on a data object.

?View Code ACTIONSCRIPT
tempObj.mess = "world";
 
trace(tempObj[0] + " " + tempObj.mess); // "hello world"

By combining a data object and an array we can keep a ton of data that is easily retrieved while the engine runs. First we need to declare our array. This is a short hand version of setting a new array.

?View Code ACTIONSCRIPT
// data, array and object management.
 
var animationArr:Array  = [];

Adding Data To The Array:
That was too easy, but don't worry, it will get a little more complicated in a minute. Now we need to add data to our array, so this section will cover a method to do just that. The function will need to receive the following information as arguments then add the data to the array.

1. obj:Object - This will reference the object (MovieClip) to be animated. Object can also reference TextFields and Buttons.

2. prop:String - the property ("_x") of the object we want to animate. To animate multiple properties for the same object, we need to call this method one time for each property. It may seem like extra work, but gives the engine greater flexibility.

3. val:Number - the value we desire the object property to be when the animation has finished.

4. ease:Number - The amount of ease to apply to the object property as it changes over time. Easing can require complicated equations, but we will keep things as simple as possible. If a positive number, the tween will have no ease and process the property changes over the amount of frames specified linearly. If a negative number, we will use that value in a simple easing equation that will cause an ease effect by incrementing the property value less and less as it gets closer to it's destination value.

5. end:Function - To allow daisy chaining, we will be able to call a function when each animation has ended.

This method will execute the following:
A. Send data to the removeTween method to make sure we are not duplicating an animation of any property animations, that would be bad. We will pass the object and the property string, so the removeTween method can validate and remove the correct element if it exists.

B. Find the tween increment amount (jump) to adjust the object property each frame.

C. Enter the new data as an object into the array using push. To do this we will use the curly brackets { } to designate an object. similar to how square brackets [ ] designate an array. Inside the curly brackets we will assign each variable (variable name, colon (:), variable value). A comma separates each element in the object list, similar to an array.

?View Code ACTIONSCRIPT
// data handler, add data to array
function insertTween(obj:Object, prop:String, val:Number, ease:Number, end:Function){
//A. manage duplicates in the array
removeTween(obj, prop);
 
//B. figure out the tween increment for the frames specified.
// target value minus the current value, as a positive number, divided by the number of frames.
var dif:Number = Math.abs(obj[prop] - val) / ease;
 
//C. add data to the animation array
animationArr.push({ aniObj: obj, propStr: prop, propValue: val, jump: dif, aniEase: ease, endFunction: end });
 
}

Remove Element or Duplicates:
We need to make sure that that the same object property is not trying to be animated twice. Say you have an animation connected to a button that slides something up, then when the button is clicked again, it slides back down. If the button is pressed before the object tween is complete we need to end the first animation, then we need to start the tween back down starting at it's current location.

This method will loop through the animationArr and look for any duplicates, if one is found, then it is removed. We will also use this method when a tween is complete to remove the animation from the array.

We need two arguments to validate a tween match, the object and the property to be animated. There may be two instances of the object in the array as long as they are for different properties.

1. obj:Object - Object to be animated

2. prop:String - The property of the object to be animated.

As we loop through the array, we will compare the obj in the argument to the aniObject of each element. If we get a match on the Object and the property, then the element will be removed using Array.splice(), then we will stop the loop. As long as duplicates are always checked before data is entered into the array, there should never be an instance of more than one element matching.

?View Code ACTIONSCRIPT
// remove data from array
function removeTween(obj:Object, prop:String){
for(var p:String in animationArr ){
if(animationArr[p].obj == targObj && animationArr[p].prop == prop){
animationArr.splice(Number(p),1);
break;
}
}
}

To keep things running fast, we only want to use one onEnterFrame event to run everything. You may also add other method calls to this event listener to power other features in your application.

We will use another for loop to pass the object from each array element to the animation handler method. That is where all the real magic happens.

?View Code ACTIONSCRIPT
// enter frame event
this.onEnterFrame = function(){
for(var p:String in animationArr){
animationHandler(animationArr[p]);
}
}

Finally making things move, this method will receive a data object and increment the object properties to be tweened.
1. obj:Object - This is the data object from addTween method, it has references to the visible objects to be animated as well as the property and easing information.

A. Set the current property value to "tempVal"

B. Find out if the value is increasing or decreasing.

C. If the value is increasing, we need addition.

D. Let's talk about easing, if the ease value is above 0, we are going to use the animation increment (jump) we made in the addTween method. This is super easy but makes for boring animation. If the value of ease is less then 0, we will use a simple easing equation. ((t - c )/ e) 1. We get the difference of the current value and the target value (t-c). 2. Then divide that value by ease amount. We are only using the negative value to differentiate if we want an ease or linear animation, so we need to convert the ease value to a positive number using Math.abs(ease). Every time the object property value moves closer to target value the difference is divided by much smaller numbers. This causes the tween to move slower as the target value is reached creating a very accentuated ease effect.

The only catch is if you have a function call set to go off at the end of this animation, the ease ,if set too high, can cause the animation to take an extra second to finish before the function is called.

E. Check to see if the destination has been reached or over shot, if so, set the value manually to the target value, remove the tween and fire off the function call if present.

F. Now do the same thing as above, but use subtraction this time.

?View Code ACTIONSCRIPT
// process animation
function animationHandler(obj){
 
//A. get current value of object property.
var tempVal:Number = obj.aniObj[obj.propStr];
 
//B. check if value should go up or down.
var dir:Boolean;
tempVal < obj.propValue ? dir = true: dir = false;
 
//C. if value needs to increase we add.
if(dir){
 
//D. check for an ease value, if linear, increase using jump amount, else use the ease equation.
obj.aniEase > 0 ? tempVal += obj.jump:  tempVal += (obj.propValue - tempVal) / Math.abs(obj.aniEase);
 
//E. if destination has been reached, remove tween from array and call function.
if(Math.round(tempVal) >= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
//call end function if present
if(obj.endFunction != null){
obj.endFunction();
}
}
// apply the tempVal to the object property. By setting the value in this way,
// we are able to tween any property using the same code
// Example: (boxMC["_x"] = 200; will set the _x property of a MovieClip instance
// called "boxMC" to 200.
obj.aniObj[obj.propStr] = tempVal;
}
else{ // same as above except using subtraction.
obj.aniEase > 0 ? tempVal -= obj.jump: tempVal -= (tempVal - obj.propValue) / Math.abs(obj.aniEase);
if(Math.round(tempVal) <= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
if(obj.endFunction != null){
obj.endFunction();
}
}
obj.aniObj[obj.propStr] = tempVal;
}
}

Now that all the stuff is done, we can initiate the engine with one line of code.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 10, null);

To animate more properties of an object we need to add a call for each property to be animated. The following example will animate the _x, _y, and _alpha properties of a MovieClip instance called "boxMC" over 15 frames. You can change the ease values to create more interesting animations.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 15, null);
insertTween(boxMC, "_y", 300, 15, null);
insertTween(boxMC, "_alpha", 0, 15, null);

The New Animation Class:
This was originally built in 2002, but it was too complicated to use with most projects. It has been revised a few times over the years into the latest, simpler incarnation. There are more powerful solutions out there like Tweener, but I think this is simple and light enough for most of my needs.

Features:
1. Tweens all common properties for MovieClip like: _x, _y, _width, _height, _xScale, _yScale, _rotation and _alpha.

2. Easing is not perfect code-wise, but looks and works pretty nice. Includes a Tweens class with Super Ease, ease in and ease out.

3. Simple to use.

4. Multiple instances of this class can run at the same time, not that you should need to, but it is possible.

5. This class uses an interval instead of onEnterFrame form more consistent animation across projects that are set to different frame rates. Based on 24 fps.

This version adds an argument for speed. With expanded ease functionality we needed an extra argument.

Class Usage:
The following sample will animate the _x property of a MovieClip instance named "boxMC" over twenty frames with a ease value of 80.

?View Code ACTIONSCRIPT
// import and register the Animation class.
import com.hdi.as2.Animation;
var ae:Animation = new Animation();
 
// sample call to Animation class to initiate a tween.
ae.setTrans(boxMC,350,"_x",20,80,null);
//Arguments:
//ae.setTrans(objMC:Object, propValue:Number, property:String, speed:Number, ease:Number, endFunction:Function);

In the demo below you can change the property, value, speed and ease values of each tween by updating the input fields and pressing the tween button. Ease values between 0 - 100 and -1 and -100 produce similar tweens to the standard Flash tween. Ease Values between greater than 100 and less than -100 will produce a super tween and the speed value will be ignored. Super Ease values between 103 - 120 and -103 - -120 produce the best results.

Demo

Download Source

The Tampa Flash, physician stuff Flex and AIR Developers Group has launched their website with their first meeting scheduled for October 7th, check 2008 at 7:00 PM. They have some cool things planned and some great sponsors. The meeting will be held at the Art Institutes of Tampa and refreshments provided by the International Culinary Schools.

Greg Wilson, from Adobe, will be the presenter for the inaugural event and we can expect frequent visits from Adobe representatives in the future. Find out more at www.tffadg.com and RSVP if you are in the area.
This is a two in one post, hospital the first half will demonstrate how to build a small but powerful animation engine. The second half is a demo and source for an expanded version of the same animation engine.

The goals for our engine are:
1. Light Weight - We do not want to apply an onEnterFrame event handler on every MovieClip. Each instance of an onEnterFrame event increases processor usage, page so we will use one onEnterFrame event to process all animation.

2. Robust - Issues can arise with you try daisy chain onEnterFrame events, garbage collection and rendering sequences can cause the chain to break. So we need a powerful management system.

3. Flexible - Some projects we only need to animate _alpha, others will need to tween _x, _y, _rotation, _xScale or a combination of them all. With a little extra code we can make this animation engine process most MovieClip Properties.

When I program something new, I make a list of all the features I need for the app. Below are the notes for this engine, now we can add the variables and methods to support each feature.

?View Code ACTIONSCRIPT
// data, array and object management.
 
// data handler, add data to array
 
// remove data from array
 
// enter frame event
 
// process animation and make tweens happen

The Array:
First is data, we will use an array to hold all the data for each animation while the engine runs. Keeping all the data in a central location means less issues caused by garbage collection and objects being added to and removed from the stage.

Arrays are super powerful, you may be familiar with an array that looks like this:

?View Code ACTIONSCRIPT
var tempArr:Array = new Array("red","blue","green","yellow");
trace(tempArr[0]); // "red"
 
//or
 
var tempArr:Array = [];
tempArr[0] = "red";
tempArr[1] = "blue";
tempArr[2] = "green";
tempArr[3] = "yellow";
trace(tempArr[1]); // "blue"

This engine will require much more information that is tightly organized. For this we will add a data object to each element of the array. A data object can look similar to an array, that is because they can be indexed like an array.

?View Code ACTIONSCRIPT
var tempObj:Object = new Object();
tempObj[0] = "hello";
trace(tempObj[0]); // "hello"

Property type variables can also be set on a data object.

?View Code ACTIONSCRIPT
tempObj.mess = "world";
 
trace(tempObj[0] + " " + tempObj.mess); // "hello world"

By combining a data object and an array we can keep a ton of data that is easily retrieved while the engine runs. First we need to declare our array. This is a short hand version of setting a new array.

?View Code ACTIONSCRIPT
// data, array and object management.
 
var animationArr:Array  = [];

Adding Data To The Array:
That was too easy, but don't worry, it will get a little more complicated in a minute. Now we need to add data to our array, so this section will cover a method to do just that. The function will need to receive the following information as arguments then add the data to the array.

1. obj:Object - This will reference the object (MovieClip) to be animated. Object can also reference TextFields and Buttons.

2. prop:String - the property ("_x") of the object we want to animate. To animate multiple properties for the same object, we need to call this method one time for each property. It may seem like extra work, but gives the engine greater flexibility.

3. val:Number - the value we desire the object property to be when the animation has finished.

4. ease:Number - The amount of ease to apply to the object property as it changes over time. Easing can require complicated equations, but we will keep things as simple as possible. If a positive number, the tween will have no ease and process the property changes over the amount of frames specified linearly. If a negative number, we will use that value in a simple easing equation that will cause an ease effect by incrementing the property value less and less as it gets closer to it's destination value.

5. end:Function - To allow daisy chaining, we will be able to call a function when each animation has ended.

This method will execute the following:
A. Send data to the removeTween method to make sure we are not duplicating an animation of any property animations, that would be bad. We will pass the object and the property string, so the removeTween method can validate and remove the correct element if it exists.

B. Find the tween increment amount (jump) to adjust the object property each frame.

C. Enter the new data as an object into the array using push. To do this we will use the curly brackets { } to designate an object. similar to how square brackets [ ] designate an array. Inside the curly brackets we will assign each variable (variable name, colon (:), variable value). A comma separates each element in the object list, similar to an array.

?View Code ACTIONSCRIPT
// data handler, add data to array
function insertTween(obj:Object, prop:String, val:Number, ease:Number, end:Function){
//A. manage duplicates in the array
removeTween(obj, prop);
 
//B. figure out the tween increment for the frames specified.
// target value minus the current value, as a positive number, divided by the number of frames.
var dif:Number = Math.abs(obj[prop] - val) / ease;
 
//C. add data to the animation array
animationArr.push({ aniObj: obj, propStr: prop, propValue: val, jump: dif, aniEase: ease, endFunction: end });
 
}

Remove Element or Duplicates:
We need to make sure that that the same object property is not trying to be animated twice. Say you have an animation connected to a button that slides something up, then when the button is clicked again, it slides back down. If the button is pressed before the object tween is complete we need to end the first animation, then we need to start the tween back down starting at it's current location.

This method will loop through the animationArr and look for any duplicates, if one is found, then it is removed. We will also use this method when a tween is complete to remove the animation from the array.

We need two arguments to validate a tween match, the object and the property to be animated. There may be two instances of the object in the array as long as they are for different properties.

1. obj:Object - Object to be animated

2. prop:String - The property of the object to be animated.

As we loop through the array, we will compare the obj in the argument to the aniObject of each element. If we get a match on the Object and the property, then the element will be removed using Array.splice(), then we will stop the loop. As long as duplicates are always checked before data is entered into the array, there should never be an instance of more than one element matching.

?View Code ACTIONSCRIPT
// remove data from array
function removeTween(obj:Object, prop:String){
for(var p:String in animationArr ){
if(animationArr[p].obj == targObj && animationArr[p].prop == prop){
animationArr.splice(Number(p),1);
break;
}
}
}

To keep things running fast, we only want to use one onEnterFrame event to run everything. You may also add other method calls to this event listener to power other features in your application.

We will use another for loop to pass the object from each array element to the animation handler method. That is where all the real magic happens.

?View Code ACTIONSCRIPT
// enter frame event
this.onEnterFrame = function(){
for(var p:String in animationArr){
animationHandler(animationArr[p]);
}
}

Finally making things move, this method will receive a data object and increment the object properties to be tweened.
1. obj:Object - This is the data object from addTween method, it has references to the visible objects to be animated as well as the property and easing information.

A. Set the current property value to "tempVal"

B. Find out if the value is increasing or decreasing.

C. If the value is increasing, we need addition.

D. Let's talk about easing, if the ease value is above 0, we are going to use the animation increment (jump) we made in the addTween method. This is super easy but makes for boring animation. If the value of ease is less then 0, we will use a simple easing equation. ((t - c )/ e) 1. We get the difference of the current value and the target value (t-c). 2. Then divide that value by ease amount. We are only using the negative value to differentiate if we want an ease or linear animation, so we need to convert the ease value to a positive number using Math.abs(ease). Every time the object property value moves closer to target value the difference is divided by much smaller numbers. This causes the tween to move slower as the target value is reached creating a very accentuated ease effect.

The only catch is if you have a function call set to go off at the end of this animation, the ease ,if set too high, can cause the animation to take an extra second to finish before the function is called.

E. Check to see if the destination has been reached or over shot, if so, set the value manually to the target value, remove the tween and fire off the function call if present.

F. Now do the same thing as above, but use subtraction this time.

?View Code ACTIONSCRIPT
// process animation
function animationHandler(obj){
 
//A. get current value of object property.
var tempVal:Number = obj.aniObj[obj.propStr];
 
//B. check if value should go up or down.
var dir:Boolean;
tempVal < obj.propValue ? dir = true: dir = false;
 
//C. if value needs to increase we add.
if(dir){
 
//D. check for an ease value, if linear, increase using jump amount, else use the ease equation.
obj.aniEase > 0 ? tempVal += obj.jump:  tempVal += (obj.propValue - tempVal) / Math.abs(obj.aniEase);
 
//E. if destination has been reached, remove tween from array and call function.
if(Math.round(tempVal) >= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
//call end function if present
if(obj.endFunction != null){
obj.endFunction();
}
}
// apply the tempVal to the object property. By setting the value in this way,
// we are able to tween any property using the same code
// Example: (boxMC["_x"] = 200; will set the _x property of a MovieClip instance
// called "boxMC" to 200.
obj.aniObj[obj.propStr] = tempVal;
}
else{ // same as above except using subtraction.
obj.aniEase > 0 ? tempVal -= obj.jump: tempVal -= (tempVal - obj.propValue) / Math.abs(obj.aniEase);
if(Math.round(tempVal) <= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
if(obj.endFunction != null){
obj.endFunction();
}
}
obj.aniObj[obj.propStr] = tempVal;
}
}

Now that all the stuff is done, we can initiate the engine with one line of code.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 10, null);

To animate more properties of an object we need to add a call for each property to be animated. The following example will animate the _x, _y, and _alpha properties of a MovieClip instance called "boxMC" over 15 frames. You can change the ease values to create more interesting animations.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 15, null);
insertTween(boxMC, "_y", 300, 15, null);
insertTween(boxMC, "_alpha", 0, 15, null);

The New Animation Class:
This was originally built in 2002, but it was too complicated to use with most projects. It has been revised a few times over the years into the latest, simpler incarnation. There are more powerful solutions out there like Tweener, but I think this is simple and light enough for most of my needs.

Features:
1. Tweens all common properties for MovieClip like: _x, _y, _width, _height, _xScale, _yScale, _rotation and _alpha.

2. Easing is not perfect code-wise, but looks and works pretty nice. Includes a Tweens class with Super Ease, ease in and ease out.

3. Simple to use.

4. Multiple instances of this class can run at the same time, not that you should need to, but it is possible.

5. This class uses an interval instead of onEnterFrame form more consistent animation across projects that are set to different frame rates. Based on 24 fps.

This version adds an argument for speed. With expanded ease functionality we needed an extra argument.

Class Usage:
The following sample will animate the _x property of a MovieClip instance named "boxMC" over twenty frames with a ease value of 80.

?View Code ACTIONSCRIPT
// import and register the Animation class.
import com.hdi.as2.Animation;
var ae:Animation = new Animation();
 
// sample call to Animation class to initiate a tween.
ae.setTrans(boxMC,350,"_x",20,80,null);
//Arguments:
//ae.setTrans(objMC:Object, propValue:Number, property:String, speed:Number, ease:Number, endFunction:Function);

In the demo below you can change the property, value, speed and ease values of each tween by updating the input fields and pressing the tween button. Ease values between 0 - 100 and -1 and -100 produce similar tweens to the standard Flash tween. Ease Values between greater than 100 and less than -100 will produce a super tween and the speed value will be ignored. Super Ease values between 103 - 120 and -103 - -120 produce the best results.

Demo

Download Source

Was anyone else thrown for a loop as much as I was about Flash CS4s animation system? I knew the basics and played around with the new animation tools before, viagra approved but then I had my first real animation job with it. Wow! that really sucked.

It is hard to say if the new tools are better then before, that all depends on your needs. If you want to do a quick animation, then stick with the classic tweens. If you want higher quality animation with some real fine tuning then the new tools are for you. I have to admit, if I had written this post just one day earlier, my option of the new animation tools would have been completely 180° opposite. Now I think they are great, so if you are frustrated now, read on and take a deep breath.

Forgetting How to Animate:
My first hurdle was to forget how I animated in the past. Instead of placing a keyframe on the timeline everywhere you want the x, y or z property to change in value, you keyframe the two extremes of your your animation. Everything in-between and easing is handled by custom tween curves.

In this demo we will do a bouncing ball, but this one will animate and bounce off all four sides of the stage. Previously we would place our ball on the stage where we want the ball to hit the sides, maybe add a motion guide for some nice arks to simulate gravity, then tweak the tweens between each keyframe until we have something that looks believable. Now a single tween last the entire length of our animation, so adding those extra keyframes on the timeline will mess up your tween.

Extremes:
We just start with two keyframes, one at each extreme of where we want the ball to travel.
Then with the ball selected, open the motion editor. Here we see our x and y curves, well they are just strait lines. If you apply a tween you will just get a change in the motion dynamics between the two keyframes. Instead scroll down to the Eases row, this is where all the real animation happens now. Click on the plus icon and select custom from the bottom of the list. Do this twice. I hate that we are not able to name our custom tweens, maybe next release, anyway, create one for the x axis and one for the y axis.

By default each curve starts at 0% on the left and goes to 100% on the right. On the right side of the curve, change the value to 0%. Now slide back up to the x and y tween drop downs and select the custom tween you wan to apply to each property. I chose "1-custom" for x and "2-custom" for y. Now slide back down and lets get to work.

If you test out the animation now, nothing will happen, not even the diagonal movement we had before.

Custom Curves:
On each custom curve place four keyframes. Now with the individual keyframes selected, slide the values of each tween until you get the desired placement of the ball on each axis. Now we can mess with the curves to effect the dynamics of how the ball bounces from one side to the next. We can even create nice arc effects to really pull off a convincing animation.

We only need to do this for the x, y and z properties. The other properties like scale, color and filters allow you to apply curves directly in their tween rows. The three "statual" properties do not allow any curves to be applied directly, all you can do is apply an existing tween from the tweens section of the Motion Editor. If you try to keyframe your x and y properties on the timeline and apply a tween, you will notice the tween is applied across all frames and you will not get the desired result. The movement will work, but the easing will not.

I finished off the animation with some blur and a shadow animation. I just copied the ball tween, added an advanced color setting, broadened the x and y extremes and tweaked the blur.

Tip:
Though you cannot save tween curves, (they do this in photoshop, so hopefully on next release) you can copy curves from one object's Motion Editor to another. Once you have an animation in the can, you can save it as a motion preset. This is really powerful, it even saves the blank keyframe I place at the end of my tweans for tidiness.

Other Pros to the Motion Editor:
You can stretch or condense the animation by dragging the last frame and all the keyframes adjust proportionally. You also can change instance properties like the instance type MovieClip to Graphic, instance name and loop properties once then it applies across the whole tween.

There may be a better way of doing this but if you want to continue an animation and start where the previous tween ended. It may be best to start a new tween instead of stretching things out and adjusting your tween curves inside the Motion Editor to make room. The best way I have figured out how to do this is to grab the tween on the timeline, hold down option (Mac) or alt (PC) as you drag it to an empty spot on the timeline, which will make a copy. Convert the tween to Frame by Frame Animation. Now you can remove all the frames but the last one which is right where the previous tween left off. It would be nice it this was available as a one step command too.

In the sample below, I keyframed the x and y extremes, though I wanted the animation to start a little to the right of extreme left. I understand the tweens start and 0 (extreme left) and end at 100 (extreme right), but these are not really just tweens anymore, are they? To make this work without making two animations, I set frame 1 to the desired x coordinate and the alpha on the previous frame to 0. I then copied the tween, using the method above, and pulled out the second frame to place over the first frame on the timeline.

The new tweening tools are very powerful and will help us produce better quality animations, I am glad they still have the option of a classic tween as I still use that from time to time for really simple stuff (it is just faster) along with shape tweens. I do not look at this as a replacement of the tools I am used to using, but a new really powerful option when animating. You do have to plan ahead a little and it will take a extra time setting up custom tween and tweaking things to look right. We had to do a lot of animation slight-of-hand tricks to get things to look right before, so you have to admit this is cool. Just remember with great power comes great responsibility (Ben Parker).

Download Source
The Tampa Flash, physician stuff Flex and AIR Developers Group has launched their website with their first meeting scheduled for October 7th, check 2008 at 7:00 PM. They have some cool things planned and some great sponsors. The meeting will be held at the Art Institutes of Tampa and refreshments provided by the International Culinary Schools.

Greg Wilson, from Adobe, will be the presenter for the inaugural event and we can expect frequent visits from Adobe representatives in the future. Find out more at www.tffadg.com and RSVP if you are in the area.
This is a two in one post, hospital the first half will demonstrate how to build a small but powerful animation engine. The second half is a demo and source for an expanded version of the same animation engine.

The goals for our engine are:
1. Light Weight - We do not want to apply an onEnterFrame event handler on every MovieClip. Each instance of an onEnterFrame event increases processor usage, page so we will use one onEnterFrame event to process all animation.

2. Robust - Issues can arise with you try daisy chain onEnterFrame events, garbage collection and rendering sequences can cause the chain to break. So we need a powerful management system.

3. Flexible - Some projects we only need to animate _alpha, others will need to tween _x, _y, _rotation, _xScale or a combination of them all. With a little extra code we can make this animation engine process most MovieClip Properties.

When I program something new, I make a list of all the features I need for the app. Below are the notes for this engine, now we can add the variables and methods to support each feature.

?View Code ACTIONSCRIPT
// data, array and object management.
 
// data handler, add data to array
 
// remove data from array
 
// enter frame event
 
// process animation and make tweens happen

The Array:
First is data, we will use an array to hold all the data for each animation while the engine runs. Keeping all the data in a central location means less issues caused by garbage collection and objects being added to and removed from the stage.

Arrays are super powerful, you may be familiar with an array that looks like this:

?View Code ACTIONSCRIPT
var tempArr:Array = new Array("red","blue","green","yellow");
trace(tempArr[0]); // "red"
 
//or
 
var tempArr:Array = [];
tempArr[0] = "red";
tempArr[1] = "blue";
tempArr[2] = "green";
tempArr[3] = "yellow";
trace(tempArr[1]); // "blue"

This engine will require much more information that is tightly organized. For this we will add a data object to each element of the array. A data object can look similar to an array, that is because they can be indexed like an array.

?View Code ACTIONSCRIPT
var tempObj:Object = new Object();
tempObj[0] = "hello";
trace(tempObj[0]); // "hello"

Property type variables can also be set on a data object.

?View Code ACTIONSCRIPT
tempObj.mess = "world";
 
trace(tempObj[0] + " " + tempObj.mess); // "hello world"

By combining a data object and an array we can keep a ton of data that is easily retrieved while the engine runs. First we need to declare our array. This is a short hand version of setting a new array.

?View Code ACTIONSCRIPT
// data, array and object management.
 
var animationArr:Array  = [];

Adding Data To The Array:
That was too easy, but don't worry, it will get a little more complicated in a minute. Now we need to add data to our array, so this section will cover a method to do just that. The function will need to receive the following information as arguments then add the data to the array.

1. obj:Object - This will reference the object (MovieClip) to be animated. Object can also reference TextFields and Buttons.

2. prop:String - the property ("_x") of the object we want to animate. To animate multiple properties for the same object, we need to call this method one time for each property. It may seem like extra work, but gives the engine greater flexibility.

3. val:Number - the value we desire the object property to be when the animation has finished.

4. ease:Number - The amount of ease to apply to the object property as it changes over time. Easing can require complicated equations, but we will keep things as simple as possible. If a positive number, the tween will have no ease and process the property changes over the amount of frames specified linearly. If a negative number, we will use that value in a simple easing equation that will cause an ease effect by incrementing the property value less and less as it gets closer to it's destination value.

5. end:Function - To allow daisy chaining, we will be able to call a function when each animation has ended.

This method will execute the following:
A. Send data to the removeTween method to make sure we are not duplicating an animation of any property animations, that would be bad. We will pass the object and the property string, so the removeTween method can validate and remove the correct element if it exists.

B. Find the tween increment amount (jump) to adjust the object property each frame.

C. Enter the new data as an object into the array using push. To do this we will use the curly brackets { } to designate an object. similar to how square brackets [ ] designate an array. Inside the curly brackets we will assign each variable (variable name, colon (:), variable value). A comma separates each element in the object list, similar to an array.

?View Code ACTIONSCRIPT
// data handler, add data to array
function insertTween(obj:Object, prop:String, val:Number, ease:Number, end:Function){
//A. manage duplicates in the array
removeTween(obj, prop);
 
//B. figure out the tween increment for the frames specified.
// target value minus the current value, as a positive number, divided by the number of frames.
var dif:Number = Math.abs(obj[prop] - val) / ease;
 
//C. add data to the animation array
animationArr.push({ aniObj: obj, propStr: prop, propValue: val, jump: dif, aniEase: ease, endFunction: end });
 
}

Remove Element or Duplicates:
We need to make sure that that the same object property is not trying to be animated twice. Say you have an animation connected to a button that slides something up, then when the button is clicked again, it slides back down. If the button is pressed before the object tween is complete we need to end the first animation, then we need to start the tween back down starting at it's current location.

This method will loop through the animationArr and look for any duplicates, if one is found, then it is removed. We will also use this method when a tween is complete to remove the animation from the array.

We need two arguments to validate a tween match, the object and the property to be animated. There may be two instances of the object in the array as long as they are for different properties.

1. obj:Object - Object to be animated

2. prop:String - The property of the object to be animated.

As we loop through the array, we will compare the obj in the argument to the aniObject of each element. If we get a match on the Object and the property, then the element will be removed using Array.splice(), then we will stop the loop. As long as duplicates are always checked before data is entered into the array, there should never be an instance of more than one element matching.

?View Code ACTIONSCRIPT
// remove data from array
function removeTween(obj:Object, prop:String){
for(var p:String in animationArr ){
if(animationArr[p].obj == targObj && animationArr[p].prop == prop){
animationArr.splice(Number(p),1);
break;
}
}
}

To keep things running fast, we only want to use one onEnterFrame event to run everything. You may also add other method calls to this event listener to power other features in your application.

We will use another for loop to pass the object from each array element to the animation handler method. That is where all the real magic happens.

?View Code ACTIONSCRIPT
// enter frame event
this.onEnterFrame = function(){
for(var p:String in animationArr){
animationHandler(animationArr[p]);
}
}

Finally making things move, this method will receive a data object and increment the object properties to be tweened.
1. obj:Object - This is the data object from addTween method, it has references to the visible objects to be animated as well as the property and easing information.

A. Set the current property value to "tempVal"

B. Find out if the value is increasing or decreasing.

C. If the value is increasing, we need addition.

D. Let's talk about easing, if the ease value is above 0, we are going to use the animation increment (jump) we made in the addTween method. This is super easy but makes for boring animation. If the value of ease is less then 0, we will use a simple easing equation. ((t - c )/ e) 1. We get the difference of the current value and the target value (t-c). 2. Then divide that value by ease amount. We are only using the negative value to differentiate if we want an ease or linear animation, so we need to convert the ease value to a positive number using Math.abs(ease). Every time the object property value moves closer to target value the difference is divided by much smaller numbers. This causes the tween to move slower as the target value is reached creating a very accentuated ease effect.

The only catch is if you have a function call set to go off at the end of this animation, the ease ,if set too high, can cause the animation to take an extra second to finish before the function is called.

E. Check to see if the destination has been reached or over shot, if so, set the value manually to the target value, remove the tween and fire off the function call if present.

F. Now do the same thing as above, but use subtraction this time.

?View Code ACTIONSCRIPT
// process animation
function animationHandler(obj){
 
//A. get current value of object property.
var tempVal:Number = obj.aniObj[obj.propStr];
 
//B. check if value should go up or down.
var dir:Boolean;
tempVal < obj.propValue ? dir = true: dir = false;
 
//C. if value needs to increase we add.
if(dir){
 
//D. check for an ease value, if linear, increase using jump amount, else use the ease equation.
obj.aniEase > 0 ? tempVal += obj.jump:  tempVal += (obj.propValue - tempVal) / Math.abs(obj.aniEase);
 
//E. if destination has been reached, remove tween from array and call function.
if(Math.round(tempVal) >= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
//call end function if present
if(obj.endFunction != null){
obj.endFunction();
}
}
// apply the tempVal to the object property. By setting the value in this way,
// we are able to tween any property using the same code
// Example: (boxMC["_x"] = 200; will set the _x property of a MovieClip instance
// called "boxMC" to 200.
obj.aniObj[obj.propStr] = tempVal;
}
else{ // same as above except using subtraction.
obj.aniEase > 0 ? tempVal -= obj.jump: tempVal -= (tempVal - obj.propValue) / Math.abs(obj.aniEase);
if(Math.round(tempVal) <= obj.propValue){
tempVal = obj.propValue;
 
//remove tween
removeTween(obj.aniObj, obj.propStr);
 
if(obj.endFunction != null){
obj.endFunction();
}
}
obj.aniObj[obj.propStr] = tempVal;
}
}

Now that all the stuff is done, we can initiate the engine with one line of code.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 10, null);

To animate more properties of an object we need to add a call for each property to be animated. The following example will animate the _x, _y, and _alpha properties of a MovieClip instance called "boxMC" over 15 frames. You can change the ease values to create more interesting animations.

?View Code ACTIONSCRIPT
insertTween(boxMC, "_x", 360, 15, null);
insertTween(boxMC, "_y", 300, 15, null);
insertTween(boxMC, "_alpha", 0, 15, null);

The New Animation Class:
This was originally built in 2002, but it was too complicated to use with most projects. It has been revised a few times over the years into the latest, simpler incarnation. There are more powerful solutions out there like Tweener, but I think this is simple and light enough for most of my needs.

Features:
1. Tweens all common properties for MovieClip like: _x, _y, _width, _height, _xScale, _yScale, _rotation and _alpha.

2. Easing is not perfect code-wise, but looks and works pretty nice. Includes a Tweens class with Super Ease, ease in and ease out.

3. Simple to use.

4. Multiple instances of this class can run at the same time, not that you should need to, but it is possible.

5. This class uses an interval instead of onEnterFrame form more consistent animation across projects that are set to different frame rates. Based on 24 fps.

This version adds an argument for speed. With expanded ease functionality we needed an extra argument.

Class Usage:
The following sample will animate the _x property of a MovieClip instance named "boxMC" over twenty frames with a ease value of 80.

?View Code ACTIONSCRIPT
// import and register the Animation class.
import com.hdi.as2.Animation;
var ae:Animation = new Animation();
 
// sample call to Animation class to initiate a tween.
ae.setTrans(boxMC,350,"_x",20,80,null);
//Arguments:
//ae.setTrans(objMC:Object, propValue:Number, property:String, speed:Number, ease:Number, endFunction:Function);

In the demo below you can change the property, value, speed and ease values of each tween by updating the input fields and pressing the tween button. Ease values between 0 - 100 and -1 and -100 produce similar tweens to the standard Flash tween. Ease Values between greater than 100 and less than -100 will produce a super tween and the speed value will be ignored. Super Ease values between 103 - 120 and -103 - -120 produce the best results.

Demo

Download Source

Was anyone else thrown for a loop as much as I was about Flash CS4s animation system? I knew the basics and played around with the new animation tools before, viagra approved but then I had my first real animation job with it. Wow! that really sucked.

It is hard to say if the new tools are better then before, that all depends on your needs. If you want to do a quick animation, then stick with the classic tweens. If you want higher quality animation with some real fine tuning then the new tools are for you. I have to admit, if I had written this post just one day earlier, my option of the new animation tools would have been completely 180° opposite. Now I think they are great, so if you are frustrated now, read on and take a deep breath.

Forgetting How to Animate:
My first hurdle was to forget how I animated in the past. Instead of placing a keyframe on the timeline everywhere you want the x, y or z property to change in value, you keyframe the two extremes of your your animation. Everything in-between and easing is handled by custom tween curves.

In this demo we will do a bouncing ball, but this one will animate and bounce off all four sides of the stage. Previously we would place our ball on the stage where we want the ball to hit the sides, maybe add a motion guide for some nice arks to simulate gravity, then tweak the tweens between each keyframe until we have something that looks believable. Now a single tween last the entire length of our animation, so adding those extra keyframes on the timeline will mess up your tween.

Extremes:
We just start with two keyframes, one at each extreme of where we want the ball to travel.
Then with the ball selected, open the motion editor. Here we see our x and y curves, well they are just strait lines. If you apply a tween you will just get a change in the motion dynamics between the two keyframes. Instead scroll down to the Eases row, this is where all the real animation happens now. Click on the plus icon and select custom from the bottom of the list. Do this twice. I hate that we are not able to name our custom tweens, maybe next release, anyway, create one for the x axis and one for the y axis.

By default each curve starts at 0% on the left and goes to 100% on the right. On the right side of the curve, change the value to 0%. Now slide back up to the x and y tween drop downs and select the custom tween you wan to apply to each property. I chose "1-custom" for x and "2-custom" for y. Now slide back down and lets get to work.

If you test out the animation now, nothing will happen, not even the diagonal movement we had before.

Custom Curves:
On each custom curve place four keyframes. Now with the individual keyframes selected, slide the values of each tween until you get the desired placement of the ball on each axis. Now we can mess with the curves to effect the dynamics of how the ball bounces from one side to the next. We can even create nice arc effects to really pull off a convincing animation.

We only need to do this for the x, y and z properties. The other properties like scale, color and filters allow you to apply curves directly in their tween rows. The three "statual" properties do not allow any curves to be applied directly, all you can do is apply an existing tween from the tweens section of the Motion Editor. If you try to keyframe your x and y properties on the timeline and apply a tween, you will notice the tween is applied across all frames and you will not get the desired result. The movement will work, but the easing will not.

I finished off the animation with some blur and a shadow animation. I just copied the ball tween, added an advanced color setting, broadened the x and y extremes and tweaked the blur.

Tip:
Though you cannot save tween curves, (they do this in photoshop, so hopefully on next release) you can copy curves from one object's Motion Editor to another. Once you have an animation in the can, you can save it as a motion preset. This is really powerful, it even saves the blank keyframe I place at the end of my tweans for tidiness.

Other Pros to the Motion Editor:
You can stretch or condense the animation by dragging the last frame and all the keyframes adjust proportionally. You also can change instance properties like the instance type MovieClip to Graphic, instance name and loop properties once then it applies across the whole tween.

There may be a better way of doing this but if you want to continue an animation and start where the previous tween ended. It may be best to start a new tween instead of stretching things out and adjusting your tween curves inside the Motion Editor to make room. The best way I have figured out how to do this is to grab the tween on the timeline, hold down option (Mac) or alt (PC) as you drag it to an empty spot on the timeline, which will make a copy. Convert the tween to Frame by Frame Animation. Now you can remove all the frames but the last one which is right where the previous tween left off. It would be nice it this was available as a one step command too.

In the sample below, I keyframed the x and y extremes, though I wanted the animation to start a little to the right of extreme left. I understand the tweens start and 0 (extreme left) and end at 100 (extreme right), but these are not really just tweens anymore, are they? To make this work without making two animations, I set frame 1 to the desired x coordinate and the alpha on the previous frame to 0. I then copied the tween, using the method above, and pulled out the second frame to place over the first frame on the timeline.

The new tweening tools are very powerful and will help us produce better quality animations, I am glad they still have the option of a classic tween as I still use that from time to time for really simple stuff (it is just faster) along with shape tweens. I do not look at this as a replacement of the tools I am used to using, but a new really powerful option when animating. You do have to plan ahead a little and it will take a extra time setting up custom tween and tweaking things to look right. We had to do a lot of animation slight-of-hand tricks to get things to look right before, so you have to admit this is cool. Just remember with great power comes great responsibility (Ben Parker).

Download Source

Sketches & Guides

This series will cover the basics of illustrating with Adobe Illustrator from start to finish, ed geared more toward novice Illustrator users with a few intermediate tips along the way. Some of the principles discussed are applicable to most illustration programs and illustration in general.

This collection of posts will be based on a philosophy of illustrating Quick, buy Clean and Correct. Discussing time saving tips, preparing your artwork so that it can be easily used by others for web and print, and how to achieve consistent results based on your style. Everyone who reads this post has their own unique illustration style. I am in no way trying to convert people to my personal style, but hope that what is shown here can be incorporated to refine that style and produce beautiful graphics in a more efficient way.

Starting with Sketches:
It is becoming more and more common for artists to sketch directly into the computer using a drawing tablet. Others, like myself, roll old-school with a pencil and paper. Then, using a scanner or digital camera to get the rough ideas into the computer. Sketches may seem like an extra step or waste of time, especially when creating simple graphics, but sketches can really help to give your vector work some flare. When working from native shapes or precise curse, there is a danger of vector work becoming rigid and/or boring. I have fallen into the same trap, thinking I could save some time on a simple graphic. After an hour of messing around and it still not looking right, a few seconds on a sketch is all it took to get things back on track.

Using guides and grids:
We will start this post illustrating a 3/4 view of a building so we will need to produce some guides to help keep things in proper perspective. As you can see my sketch is a little off so these guides will help correct some wayward lines.

Alignment and perspective can be tricky and we can waste a lot of time moving things around, looking at it, then adjusting again to get things looking correct. This method of 2 point perspective, most of us learned in early art or drafting classes. We had large art tables with rulers and t-squares to produce a horizon line and all the perspective lines for each plane. Illustrator is great with it's very large workspace around the art-board to accommodate these horizon lines and vanishing points.

A few reasons we may neglect this step are: We remember that some of those perspective drawings didn't really look that exciting, unless you had a smaller desk and your angles were so sharp they could put an eye out. With the amount of time it takes to layout all the lines and match everything up, it is much faster to guess. Also, holding strict to the grid can put pull all the life out of our sketch.

The pros:
1. Hopefully we are sketching something a little more exciting than the barracks styled houses from grade school.

2. The time it takes to make guides, most of the time, does not compare to the time we could spend adjusting lines over and over till they look right. We risk progressing in the illustration until new details reveal that some of the perspective is still a little off, when it is much more time consuming to adjust everything.

3. A guide is just a guide, not the illustration, we use it to save time by finding the correct lines quickly. It does not need to overpower our ability to illustrate.

This last point leads into the style dilemma. Say you are the anti-perspective illustrator, all your objects are thick at the top and thin at the bottom or visa-versa, or curved like something made from cooked pasta. A few guide lines may help find your curves even faster. No one ever said your grid had to be made of straight lines. They can be curvy, bent, skewed into all kinds of meshes. just something to think about.

Knowing where perspective is not only helps you build a solid foundation for more realistic illustration, it can also show you where you can break the rules for more stylized illustrations. I think the biggest problem with not using guides is that some illustrations come of half stylized and half in perspective making everything look off. You should pick your style and commit to it. If you are stylized then be stylized, kick those lines and angles out there, you do not want anything looking close to straight or close to proper perspective. If you are shooting for realism, then your work should be governed by the laws that govern real objects.

Grouping and pre-grouping:
Guides and grids should be grouped and locked on a separate layer.
It is a pain to work with grids that are not grouped together, at least on a separate layer they are easily locked away and hidden when not needed. Sometimes we build a grid then realize later we needed to group it. It is hard to select all the lines if there are other objects on the art-board as well.

If you are building a grid by duplicating a copy/move using command + D or copy/moving manually, you can try pre-grouping. You can pre-group your guide lines, textures, star fields, sparkles, bubbles, by taking two objects and grouping them, then using your copy/move method on one of the objects (Select the object and while dragging, hold down the Command + Option on the Mac or Control + Alt on the PC). All the new copies will be made within the larger group.

Using Align and Disperse:
We may not need a full grid or perspective guides for some illustration. Some may only need a center line or to center an object. Using a few temporary rectangles and paths can help to find the center of an object without moving the original object from it's position.

To find proper sizing and position of objects in perspective only takes a few paths and the free transform tool. It is very easy to illustrate flat especially things like keyboard keys or windows for our building. Align and disperse everything while it is still flat, then using the Free Transform tool we can apply the grid to our plane.

Guides for Sketching:
Guides do not only apply to artwork coming into the computer. A quick way to keep sketches in perspective without T-Squares and Angles is to print out your perspective grid and place it under your tracing paper or under sketching paper on a light box. You can prepare any kind of guide (text, curves, wireframes) quickly in the computer and print them out for use with your sketches.

Now that we have our guides in place we are ready to add all the construction elements that make up our building. Next - Illustrating In Illustrator 101 Part 2 of 5: Construction

source here

Here is the twin brother of the Easy Scrollbar MovieClip Class that works with TextFields. It does not require the masking and is perfect for Input TextFields. It has all the features of the MovieClip version except for easing. TextFields scroll one line at a time which is not very smooth.

Some of the features include:
Auto On/Off - you may need a scrolling clip that could change in size as dynamic content is displayed or entered. When the scroll bar is not needed, symptoms capsule it will turn itself off and back on when it is needed. Or you can manually turn it on and with your code.

Scroll Bar Resizing - To simulate the function of desktop applications, the scroll bar will automatically scale depending on the amount of scroll, This feature can be turned on or off.

Auto Resize - Say you have a project that needs multiple scroll bars. One 150 px tall, the other 500 px tall. With this class you can build one set of artwork and the class will automatically adjust the bottom button, scroll background, scrollbar scroll area to fit the needed size.

Down Button Flip - This will not change the world, but if you have an Up Button that is exactly like the bottom button just flipped vertically. The class will compensate for this, saving a few minutes of development time and a few kilobytes.

Scroll Background Hiding and resizing - Many scroll bars have a background track, you may want it visible when the scroll bars are disabled as a visual place holder. This feature can be turned on or off.

Works without a scroll bar or without up and down buttons.

Button Type Effects - Even though the buttons and scrollbars are made with movieClips, sample code and calls are provided to give them button type effects on rollOver, rollOut, press and release.

Usage may seem a little complex at first, but if you like designing and using custom scroll bars and buttons, it is totally worth it.

1. Create all your scroll objects, they should be converted to MovieClips.
(upButton, DownButton, ScrollBar, and ScrollBkg)

2. Place the up and down buttons, scroll bar, and scroll background into a new movieClip.
(ScrollObject)

3. Align the top button and scrollbar to it's starting position.

4. Apply the class, this is the most complex part.

var scrollSet:HDScrollText = HDScrollText(ScrollObject,ScrollMovieClip,UpButton,DownButton,ScrollBar,ScrollBarResize,ScrollBkg, ScrollBkgHide,DownButtonFlip,ResizeScrollObjects,AutoOn);

This is where you assign all the MovieClips and enable any of the features. Other than the 6 MovieClips that the class points to, the other 5 arguments are features to enable or disable.

ScrollBarResize: Boolean
ScrollBkgHide: Boolean
DownButtonFlip: Boolean
ResizeScrollObjects: Boolean
AutoOn: Boolean

Once it is enabled, it can manage itself or you can manage it manually with a method like so:
scrollSet.ScrollStatus(true); or scrollSet.ScrollStatus(false);

When you are done with everything, you can strip all the code out by calling scrollSet.killScrollBar();

?View Code ACTIONSCRIPT
import mx.utils.Delegate;
class com.hdi.util.HDScrollText{
/*
HDScrollText oringinally created 11/2005 by Todd Williams and HD Interactive.
©2005 - 2010 HD Interactive & Taterboy, Inc.
version: 2.1
date: 1-9-10
 
Compatibility:  Action Script 2, Flash Player 7 and higher.
Purpose:
To Build a scrollbar class that is truly portable and can be applied to custom artwork
of any size and shape. This class wraps the graphics instead of graphics wrapping the code.
This gives the designer complete control over look and feel. One of the major features
needed was to have one set of scroll objects to be 	used in multiple instances and allow
them to automatically conform to different scrolling needs. One set of scroll objects can
control a scroll window that is 200 pixels tall or 600 pixels tall on the same stage at the
same time.
 
Features:
1. Automatically arranges scroll objects so that one set scrollbar objects can be used in multiple
instances with different sized scrolling windows.
2. Resizing scroll bar similar to OS and desktop application scroll bar behavior.
3. Code Wraps to custom artwork instead of skinning a preexisting component.
4. Auto on and off. The scroll bar is smart enough to know when it is needed or not.
5. Code provided to build button type effects into MovieClip buttons and scrollbar.
6. Have multiple scrolling objects visible and functioning on the same stage at a time.
 
 
Preparation:
To prepare graphic objects for use with HDScrollMC, you will need to create 7 MovieClips.
MC 1. The MovieClip to be scrolled:
For scrolling text, create a TextField inside of a MovieClip, fill it with text manually,
or use dynamic text and the TextField.autoSize = true;
 
MC 2. Container for Scroll Objects: To make it possible to have multiple scrolling objects on the
stage at the same time, it is best to have at least the scrollbar and scroll button objects in a
container, the mask and MC to be scrolled can also be in this container if desired.
 
MC 3 & 4.  Scroll buttons UP and Down. These buttons are not required if a scrollbar only design is
needed. Scroll buttons can be movieClips or buttons. Code for rollover and press events will be 		sent to each button. If you want to use a MovieClip, disperse your button states on frames as you 		would a button and add a stop action to the first frame. Also the down button and be a vertically 		flipped instance if the top button if the artwork allows for this.
 
The scroll buttons receive the following method calls from the class, use the method below for
MovieClips with button type effects.
btnEvent(1); roll on
btnEvent(0); roll out
btnEvent(2); mouse down
btnEvent(1); mouse up
Sample:
function btnEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
MC 5. Scroll Bar: Must be a MovieClip and like the buttons, code will be sent for rollover and press events.
A scrollbar is not required if a button only design is required. For the scroll bar has a resize feature
with two modes. The scroll bar will resize bases on the amount of scroll and the size of the scroll
area, similar to OS scroll bars. Mode 1 is the scrollbar MovieClip resizes the whole MovieClip. Some
graphic distortion or stretching may occur. You can set the scale9Grid to this MovieClip prior to
enabling this class. Mode 2 uses three MovieClips within the Scroll Bar to represent the top, middle
and bottom of the scroll bar, the middle will stretched will the top and bottom MovieClips will retain
their graphic integrity. To use this option divide the Scrollbar into three horizontal slices. Create
MovieClip instances named scrollbBarTop, scrollBarBot, and scrollBarMid.
 
The scrollbar receives the following method calls from the class, use the method below for
MovieClips with button type effects.
 
barEvent(1); roll on
barEvent(0); roll out
barEvent(2); mouse down
barEvent(1); mouse up
Sample:
function barEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
MC 6. Scroll background, Must be a MovieClip,  will span the entire size of the scroll area
if the class is set to resize the objects. This MovieClip can be used to have a decorative
track for the scroll area and can be set to vanish or remain when the scrollbar is enabled
or disabled. This object is not required.
 
Usage:
Place the class folder in the working directory next to the fla you are using;
add import com.hdi.as2.HDScrollText; to the actions panel before the code below.
 
HDScrollText(ScrollObject,TextField,UpButton,DownButton,ScrollBar,
ScrollBarResize,ScrollBkg,ScrollBkgHide,DownButtonFlip,ResizeScrollObjects,AutoOn);
 
I know there are a lot of arguments, and the descriptions/Usage are as follows:
ScrollObject - (required) target of scroll object container, MC 3 from the preparation list.
ScrollMovieClip - (required) target of MovieClip to be scrolled, MC 1 from preparation list.
UpButton - target or null, to Up Button MovieClip or Button. MC 4 & 5 from preparation list.
DownButton - target  or null, to Down Button MovieClip or Button. MC 4 & 5 from preparation list.
ScrollBar - target or null, to Scroll Bar MovieClip. MC 6 from preparation list.
ScrollBarResize - Boolean: true or false, To enable scroll bar resizing depending on scroll amount.
ScrollBkg - target or null, to scroll background graphic.
ScrollBkgHide - Boolean: true or false, default behavior is to hide scroll background and scroll objects;
DownButtonFlip - Boolean: true or false, If the down button is an instance of the up button that is
vertically flipped.
ResizeScrollObjects - Boolean: true or false, when scroll bar loads, it calculates the size of the mask,
buttons, scrollbars and distributes them to the appropriate height and coordinates. This allows
different instances of a set of scroll objects to be used with different sized scrolling Objects.
AutoOn - Boolean: true or false, Turns control of turning the scroll bar objects on and off to the class.
If the scrolling MovieClip changes in size the class will automatically enable or disable the
scroll objects.
 
 
Other methods and properties:
 
scrollStatus:  property (Boolean) - tells if scrolling is enabled or disabled.
setScrollStatus: Function - manually enables/disables scrolling.
killScrollBar: Function - permanently disables the scrollbar and removes all listeners and events.
 
Tips:
1. For best performance, zero out  x and y coordinates to whole numbers on all MovieClips.
Also try to build artwork with artwork rounded to the nearest whole pixel. This stops a lot
of the little glitches 	that can appear when a user interacts with the scrolling objects.
 
2. If you do not want you scroll objects to flash on then off on load, set the scroll Object
Container's (MC 3) 	alpha property to 0. The class will automatically set it to 100 when enabled.
 
3. By default the class uses the scroll background  and/or the up button to align and distribute
the rest of the 	objects. You should align the top button and the top of the scroll background.
The top of the scrollbar 	should be aligned to the button of the top button. These coordinates
are used as starting points for all of 	the scroll objects and will return them to these
positions when the scroll bar is reset.
 
*/
private var scrollObj:Object; //scroll MovieClip containing up button, down button, scrollbar, background.
private var tClip:Object; //TextField to be scrolled.
private var tMask:Object; //Mask for the Text MovieClip, must be a MovieClip.
private var dwnBtn:Object; //Down button, should be movieClip or button.
private var upBtn:Object; //Down button, should be movieClip or button.
private var scrollBar:Object; //MovieClip to do the scrolling.
private var barAutoSize:Boolean; //Resizes the scroll bar to the scroll amount.
private var scrollBkg:Object; //Background behind scrollButtons and scrollBar.
private var scrollBkgHide:Boolean; //When scroll objects are not on, ScrollBkg is can be visible or not.
private var flipDwnButton:Boolean; // If you have flipped the upBtn to make the dwnBtn. Used for autoResize.
private var resizeObj:Boolean; // Resizes scroll objects to match the mask size and location.
private var autoOn:Boolean; //Let's the scroll object control if the scrollBar is on or off, depending on the size of the text box.
private var easeIn:Number; // Amount of delay for scrolling text to ease into possition.
private var scrollYPos:Number;
public var scrollStatus:Boolean; //Scrollbar is On or Off.
private var inc:Number;
private var resetAllSizes:Function;
function HDScrollText(targObj,tclip,upbtn,dwnbtn,sbar,barsize,sbkg,sbkgHide,flip,reSize,auto){
scrollObj = targObj;
tClip = tclip;
tMask = tclip;
upBtn = upbtn;
dwnBtn = dwnbtn;
scrollBar = sbar;
barAutoSize = barsize;
scrollBkg = sbkg;
scrollBkgHide = sbkgHide;
flipDwnButton = flip;
resizeObj = reSize;
autoOn = auto;
easeIn = 0;
 
scrollYPos = tClip.scroll;
if(tClip.maxscroll < 2){
scrollStatus = false;
if(scrollBkgHide && scrollBkg){
scrollBkg._visible = false;
}
}
else{
scrollStatus = true;
}
 
var testConfig:Boolean = true;
if(scrollObj == null || scrollObj == undefined){
trace("ERROR: ScrollObject (arg 0) needs to be a valid MovieClip ");
testConfig = false;
}
if(tMask == null || tMask == undefined){
trace("ERROR: MaskMC (arg 2) needs to be a valid MovieClip - please mask the scrolling object with a named instance of a MovieClip");
testConfig = false;
}
if((scrollBar == null || scrollBar == undefined) && (upBtn == null || upBtn == undefined) && (dwnBtn == null || dwnBtn == undefined)){
trace("ERROR: Very funny, you need at least 1 control object (scrollBar, upBtn or dwnBtn) assigned to initiate scrolling");
testConfig = false;
}
if(testConfig){
init();
}
}
public function setScrollStatus(val,overRide){
scrollStatus = val;
scrollObj.stat = val;
scrollObj.yPos = scrollObj.starty;
tClip.scroll = scrollObj.starty;
scrollBar._y = scrollObj.bary;
setSizes();
if(val){
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
scrollBkg._visible = true;
}
else{
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
if(scrollBkgHide){
scrollBkg._visible = false;
}
}
}
public function killScrollBar(){
tClip.scroll = scrollObj.starty;
scrollBar._y = scrollObj.bary;
scrollObj.yPos = scrollObj.starty;
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
delete scrollObj.onEnterFrame;
delete scrollBar.onMouseUp;
delete scrollBar.onMouseDown;
delete scrollBar.onMouseMove;
delete upBtn.onMouseUp;
delete upBtn.onMouseDown;
delete dwnBtn.onMouseUp;
delete dwnBtn.onMouseDown;
delete upBtn.onRollOut;
delete upBtn.onRollOver;
delete dwnBtn.onRollOut;
delete dwnBtn.onRollOver;
delete scrollBar.onRollOut;
delete scrollBar.onRollOver;
//Mouse.removeListener(scrollObj.myWheel);
}
private function setSizes(){
if(tClip.scroll < scrollObj.starty){
if(tClip.scroll <= tClip.maxscroll){
scrollObj.yPos = scrollObj.starty;
}
else{
scrollObj.yPos = tClip.maxscroll;
}
}
else if(tClip.scroll > scrollObj.starty){
scrollObj.yPos = scrollObj.starty;
}
 
tClip.scroll = scrollObj.yPos;
 
if(barAutoSize == true){
//setup dynamic scrollbar height.
var sbHeight:Number;
if(tClip._height > scrollObj.maskh){
sbHeight = Math.floor((tClip._height / tClip.textHeight) * scrollObj.bardist);
}
else{
//sbHeight =
}
if(sbHeight < 20){
sbHeight = 20;
}
if(scrollBar.scrollbBarTop._name == undefined){
 
scrollBar._height = sbHeight;
}
else{
scrollBar.sheight = sbHeight
scrollBar.scrollBarMid._height = scrollBar.sheight - (scrollBar.scrollbBarTop._height + scrollBar.scrollbBarTop._height);
scrollBar.scrollbBarTop._y = scrollBar.scrollBarMid._height + scrollBar.scrollBarMid._y;
}
 
}
 
scrollObj.bht = Math.ceil(scrollBar._height);
scrollObj.barslack = (scrollObj.boty - scrollObj.topy) - scrollObj.bht;
scrollObj.scrolldist = tClip.maxscroll;
scrollObj.scrollspeed = 1;
scrollObj.yspeed = tMask._height/10;//16;
scrollObj.upscroll = 0;
scrollObj.dwnscroll = 0;
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
private function setCoors(){
tMask._height = Math.ceil(tMask._height);
scrollObj.maskh = tMask._height;
if(resizeObj){
flipDwnButton == true? dwnBtn._y = Math.round(tMask._height): dwnBtn._y = Math.round((tMask._height) - dwnBtn._height);
//flipDwnButton == true? dwnBtn._y = Math.round(tMask._height + tMask._y): dwnBtn._y = Math.round((tMask._height + tMask._y) - dwnBtn._height);
 
if(scrollBkg != null){
upBtn != null ? scrollBkg._height = scrollObj.maskh: scrollBkg._height = scrollObj.maskh;
}
 
}
upBtn._y = Math.floor(upBtn._y);
scrollObj.tht = Math.ceil(tClip._height);
scrollObj.starty = tClip.scroll;
scrollObj.barx = scrollBar._x;
scrollObj.bary = scrollBar._y;
if(upBtn != null){
scrollObj.topy = Math.round(upBtn._y + upBtn._height);
flipDwnButton == true? scrollObj.boty = Math.round(dwnBtn._y - dwnBtn._height): scrollObj.boty = Math.round(dwnBtn._y);
}
else{
scrollObj.topy = Math.round(scrollBar._y);
scrollObj.boty = Math.round(scrollBar._y + tMask._height);
}
scrollObj.bardist = (scrollObj.boty - scrollObj.topy);
setSizes();
}
 
private function init(){
setCoors();
if(scrollStatus == false){
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
}
else{
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
}
scrollObj._alpha = 100;
scrollObj.objectRef = this;
scrollBar.objectRef = this;
upBtn.objectRef = this;
dwnBtn.objectRef = this;
var scrollParent:Object = scrollObj;
var scrollTextField:Object = tClip;
 
scrollObj.stat = scrollStatus;
scrollObj.yPos = scrollYPos;
 
if(resizeObj){
resetAllSizes = setCoors;//setSizes;
}
 
scrollBar.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(2);
scrollParent.scrollchk = true;
this.startDrag(false,scrollParent.barx,scrollParent.topy,scrollParent.barx,scrollParent.boty - scrollParent.bht);
this.onMouseMove = function(){
if(scrollParent.scrollchk == true){
scrollParent.yPos = Math.round(scrollTextField.maxscroll * ((this._y - scrollParent.topy)  /scrollParent.barslack));
}
 
}
}
}
else{
}
}
scrollBar.onMouseUp = function(){
scrollParent.scrollchk = false;
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(1);
}
this.stopDrag();
}
scrollBar.onRollOut = function(){
this.barEvent(0);
}
scrollBar.onRollOver = function(){
this.barEvent(1);
}
upBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.upscroll = 1;
}
}
}
upBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.upscroll = 0;
}
upBtn.onRollOut = function(){
this.btnEvent(0);
}
upBtn.onRollOver = function(){
this.btnEvent(1);
}
dwnBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.dwnscroll = 1;
}
}
}
dwnBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.dwnscroll = 0;
}
dwnBtn.onRollOut = function(){
this.btnEvent(0);
}
dwnBtn.onRollOver = function(){
this.btnEvent(1);
}
 
inc = setInterval(Delegate.create(this, frameLoop),10);
}
 
private function frameLoop(){
if(scrollObj.upscroll == 1){
if(tClip.scroll > 1){
scrollObj.yPos -= 1;
}
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
if(scrollObj.dwnscroll == 1){
if(tClip.scroll < tClip.maxscroll){
scrollObj.yPos += 1;
}
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
 
if(scrollStatus){
var dirStat:Number = 0;
scrollObj.dwnscroll == 1 ? dirStat = -1:null;
scrollObj.upscroll == 1 ? dirStat = 1:null;
if(tClip.scroll != scrollObj.yPos){
easeMainClip(tClip,scrollObj.yPos,easeIn,dirStat);
}
if(autoOn){
if(tClip.maxscroll < 2){
setScrollStatus(false);
}
var checkScrollDist:Number = tClip.maxscroll;
if(scrollObj.scrolldist != checkScrollDist){
//reset size - ;
setSizes();
}
}
 
}
else{
if(autoOn){
if(tClip.maxscroll > 1){
setScrollStatus(true);
}
}
}
updateAfterEvent();
}
private function easeMainClip(obj,val,ease,dir){
if(ease > 0){
if(dir == 0){
if(Math.ceil(obj.scroll) > val){
dir = -1;
}
else if(Math.ceil(obj.scroll) < val){
dir = 1;
}
}
if(dir == -1){
obj.scroll -= Math.ceil((obj.scroll - val)/ease);
}
else if(dir == 1){
obj.scroll += Math.ceil((val - obj._y)/ease);
}
else{
obj.scroll = val;
}
}
else{
obj.scroll = val;
}
}
 
}

Demo:
OK, so my wife has been taking out all the halloween clothes and decorations this weekend. Maybe a little of that is rubbing off on me.

Source Here

Update:

The class has been updated to version (2.0), please re-download to keep current. This class and updates are based on the HDScrollMC class. http://www.taterboy.com/blog/2008/09/easy-flash-custom-scrollbar-class-as2/

Update: 2.1

Moved the class path from com.hdi.util.HDScrollText to com.hdi.as2.HDScrollText. All previous actionScript 2 classes are getting moved to com.hdi.as2.

Here is the twin brother of the Easy Scrollbar MovieClip Class that works with TextFields. It does not require the masking and is perfect for Input TextFields. It has all the features of the MovieClip version except for easing. TextFields scroll one line at a time which is not very smooth.

Some of the features include:
Auto On/Off - you may need a scrolling clip that could change in size as dynamic content is displayed or entered. When the scroll bar is not needed, symptoms capsule it will turn itself off and back on when it is needed. Or you can manually turn it on and with your code.

Scroll Bar Resizing - To simulate the function of desktop applications, the scroll bar will automatically scale depending on the amount of scroll, This feature can be turned on or off.

Auto Resize - Say you have a project that needs multiple scroll bars. One 150 px tall, the other 500 px tall. With this class you can build one set of artwork and the class will automatically adjust the bottom button, scroll background, scrollbar scroll area to fit the needed size.

Down Button Flip - This will not change the world, but if you have an Up Button that is exactly like the bottom button just flipped vertically. The class will compensate for this, saving a few minutes of development time and a few kilobytes.

Scroll Background Hiding and resizing - Many scroll bars have a background track, you may want it visible when the scroll bars are disabled as a visual place holder. This feature can be turned on or off.

Works without a scroll bar or without up and down buttons.

Button Type Effects - Even though the buttons and scrollbars are made with movieClips, sample code and calls are provided to give them button type effects on rollOver, rollOut, press and release.

Usage may seem a little complex at first, but if you like designing and using custom scroll bars and buttons, it is totally worth it.

1. Create all your scroll objects, they should be converted to MovieClips.
(upButton, DownButton, ScrollBar, and ScrollBkg)

2. Place the up and down buttons, scroll bar, and scroll background into a new movieClip.
(ScrollObject)

3. Align the top button and scrollbar to it's starting position.

4. Apply the class, this is the most complex part.

var scrollSet:HDScrollText = HDScrollText(ScrollObject,ScrollMovieClip,UpButton,DownButton,ScrollBar,ScrollBarResize,ScrollBkg, ScrollBkgHide,DownButtonFlip,ResizeScrollObjects,AutoOn);

This is where you assign all the MovieClips and enable any of the features. Other than the 6 MovieClips that the class points to, the other 5 arguments are features to enable or disable.

ScrollBarResize: Boolean
ScrollBkgHide: Boolean
DownButtonFlip: Boolean
ResizeScrollObjects: Boolean
AutoOn: Boolean

Once it is enabled, it can manage itself or you can manage it manually with a method like so:
scrollSet.ScrollStatus(true); or scrollSet.ScrollStatus(false);

When you are done with everything, you can strip all the code out by calling scrollSet.killScrollBar();

?View Code ACTIONSCRIPT
import mx.utils.Delegate;
class com.hdi.util.HDScrollText{
/*
HDScrollText oringinally created 11/2005 by Todd Williams and HD Interactive.
©2005 - 2010 HD Interactive & Taterboy, Inc.
version: 2.1
date: 1-9-10
 
Compatibility:  Action Script 2, Flash Player 7 and higher.
Purpose:
To Build a scrollbar class that is truly portable and can be applied to custom artwork
of any size and shape. This class wraps the graphics instead of graphics wrapping the code.
This gives the designer complete control over look and feel. One of the major features
needed was to have one set of scroll objects to be 	used in multiple instances and allow
them to automatically conform to different scrolling needs. One set of scroll objects can
control a scroll window that is 200 pixels tall or 600 pixels tall on the same stage at the
same time.
 
Features:
1. Automatically arranges scroll objects so that one set scrollbar objects can be used in multiple
instances with different sized scrolling windows.
2. Resizing scroll bar similar to OS and desktop application scroll bar behavior.
3. Code Wraps to custom artwork instead of skinning a preexisting component.
4. Auto on and off. The scroll bar is smart enough to know when it is needed or not.
5. Code provided to build button type effects into MovieClip buttons and scrollbar.
6. Have multiple scrolling objects visible and functioning on the same stage at a time.
 
 
Preparation:
To prepare graphic objects for use with HDScrollMC, you will need to create 7 MovieClips.
MC 1. The MovieClip to be scrolled:
For scrolling text, create a TextField inside of a MovieClip, fill it with text manually,
or use dynamic text and the TextField.autoSize = true;
 
MC 2. Container for Scroll Objects: To make it possible to have multiple scrolling objects on the
stage at the same time, it is best to have at least the scrollbar and scroll button objects in a
container, the mask and MC to be scrolled can also be in this container if desired.
 
MC 3 & 4.  Scroll buttons UP and Down. These buttons are not required if a scrollbar only design is
needed. Scroll buttons can be movieClips or buttons. Code for rollover and press events will be 		sent to each button. If you want to use a MovieClip, disperse your button states on frames as you 		would a button and add a stop action to the first frame. Also the down button and be a vertically 		flipped instance if the top button if the artwork allows for this.
 
The scroll buttons receive the following method calls from the class, use the method below for
MovieClips with button type effects.
btnEvent(1); roll on
btnEvent(0); roll out
btnEvent(2); mouse down
btnEvent(1); mouse up
Sample:
function btnEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
MC 5. Scroll Bar: Must be a MovieClip and like the buttons, code will be sent for rollover and press events.
A scrollbar is not required if a button only design is required. For the scroll bar has a resize feature
with two modes. The scroll bar will resize bases on the amount of scroll and the size of the scroll
area, similar to OS scroll bars. Mode 1 is the scrollbar MovieClip resizes the whole MovieClip. Some
graphic distortion or stretching may occur. You can set the scale9Grid to this MovieClip prior to
enabling this class. Mode 2 uses three MovieClips within the Scroll Bar to represent the top, middle
and bottom of the scroll bar, the middle will stretched will the top and bottom MovieClips will retain
their graphic integrity. To use this option divide the Scrollbar into three horizontal slices. Create
MovieClip instances named scrollbBarTop, scrollBarBot, and scrollBarMid.
 
The scrollbar receives the following method calls from the class, use the method below for
MovieClips with button type effects.
 
barEvent(1); roll on
barEvent(0); roll out
barEvent(2); mouse down
barEvent(1); mouse up
Sample:
function barEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
MC 6. Scroll background, Must be a MovieClip,  will span the entire size of the scroll area
if the class is set to resize the objects. This MovieClip can be used to have a decorative
track for the scroll area and can be set to vanish or remain when the scrollbar is enabled
or disabled. This object is not required.
 
Usage:
Place the class folder in the working directory next to the fla you are using;
add import com.hdi.as2.HDScrollText; to the actions panel before the code below.
 
HDScrollText(ScrollObject,TextField,UpButton,DownButton,ScrollBar,
ScrollBarResize,ScrollBkg,ScrollBkgHide,DownButtonFlip,ResizeScrollObjects,AutoOn);
 
I know there are a lot of arguments, and the descriptions/Usage are as follows:
ScrollObject - (required) target of scroll object container, MC 3 from the preparation list.
ScrollMovieClip - (required) target of MovieClip to be scrolled, MC 1 from preparation list.
UpButton - target or null, to Up Button MovieClip or Button. MC 4 & 5 from preparation list.
DownButton - target  or null, to Down Button MovieClip or Button. MC 4 & 5 from preparation list.
ScrollBar - target or null, to Scroll Bar MovieClip. MC 6 from preparation list.
ScrollBarResize - Boolean: true or false, To enable scroll bar resizing depending on scroll amount.
ScrollBkg - target or null, to scroll background graphic.
ScrollBkgHide - Boolean: true or false, default behavior is to hide scroll background and scroll objects;
DownButtonFlip - Boolean: true or false, If the down button is an instance of the up button that is
vertically flipped.
ResizeScrollObjects - Boolean: true or false, when scroll bar loads, it calculates the size of the mask,
buttons, scrollbars and distributes them to the appropriate height and coordinates. This allows
different instances of a set of scroll objects to be used with different sized scrolling Objects.
AutoOn - Boolean: true or false, Turns control of turning the scroll bar objects on and off to the class.
If the scrolling MovieClip changes in size the class will automatically enable or disable the
scroll objects.
 
 
Other methods and properties:
 
scrollStatus:  property (Boolean) - tells if scrolling is enabled or disabled.
setScrollStatus: Function - manually enables/disables scrolling.
killScrollBar: Function - permanently disables the scrollbar and removes all listeners and events.
 
Tips:
1. For best performance, zero out  x and y coordinates to whole numbers on all MovieClips.
Also try to build artwork with artwork rounded to the nearest whole pixel. This stops a lot
of the little glitches 	that can appear when a user interacts with the scrolling objects.
 
2. If you do not want you scroll objects to flash on then off on load, set the scroll Object
Container's (MC 3) 	alpha property to 0. The class will automatically set it to 100 when enabled.
 
3. By default the class uses the scroll background  and/or the up button to align and distribute
the rest of the 	objects. You should align the top button and the top of the scroll background.
The top of the scrollbar 	should be aligned to the button of the top button. These coordinates
are used as starting points for all of 	the scroll objects and will return them to these
positions when the scroll bar is reset.
 
*/
private var scrollObj:Object; //scroll MovieClip containing up button, down button, scrollbar, background.
private var tClip:Object; //TextField to be scrolled.
private var tMask:Object; //Mask for the Text MovieClip, must be a MovieClip.
private var dwnBtn:Object; //Down button, should be movieClip or button.
private var upBtn:Object; //Down button, should be movieClip or button.
private var scrollBar:Object; //MovieClip to do the scrolling.
private var barAutoSize:Boolean; //Resizes the scroll bar to the scroll amount.
private var scrollBkg:Object; //Background behind scrollButtons and scrollBar.
private var scrollBkgHide:Boolean; //When scroll objects are not on, ScrollBkg is can be visible or not.
private var flipDwnButton:Boolean; // If you have flipped the upBtn to make the dwnBtn. Used for autoResize.
private var resizeObj:Boolean; // Resizes scroll objects to match the mask size and location.
private var autoOn:Boolean; //Let's the scroll object control if the scrollBar is on or off, depending on the size of the text box.
private var easeIn:Number; // Amount of delay for scrolling text to ease into possition.
private var scrollYPos:Number;
public var scrollStatus:Boolean; //Scrollbar is On or Off.
private var inc:Number;
private var resetAllSizes:Function;
function HDScrollText(targObj,tclip,upbtn,dwnbtn,sbar,barsize,sbkg,sbkgHide,flip,reSize,auto){
scrollObj = targObj;
tClip = tclip;
tMask = tclip;
upBtn = upbtn;
dwnBtn = dwnbtn;
scrollBar = sbar;
barAutoSize = barsize;
scrollBkg = sbkg;
scrollBkgHide = sbkgHide;
flipDwnButton = flip;
resizeObj = reSize;
autoOn = auto;
easeIn = 0;
 
scrollYPos = tClip.scroll;
if(tClip.maxscroll < 2){
scrollStatus = false;
if(scrollBkgHide && scrollBkg){
scrollBkg._visible = false;
}
}
else{
scrollStatus = true;
}
 
var testConfig:Boolean = true;
if(scrollObj == null || scrollObj == undefined){
trace("ERROR: ScrollObject (arg 0) needs to be a valid MovieClip ");
testConfig = false;
}
if(tMask == null || tMask == undefined){
trace("ERROR: MaskMC (arg 2) needs to be a valid MovieClip - please mask the scrolling object with a named instance of a MovieClip");
testConfig = false;
}
if((scrollBar == null || scrollBar == undefined) && (upBtn == null || upBtn == undefined) && (dwnBtn == null || dwnBtn == undefined)){
trace("ERROR: Very funny, you need at least 1 control object (scrollBar, upBtn or dwnBtn) assigned to initiate scrolling");
testConfig = false;
}
if(testConfig){
init();
}
}
public function setScrollStatus(val,overRide){
scrollStatus = val;
scrollObj.stat = val;
scrollObj.yPos = scrollObj.starty;
tClip.scroll = scrollObj.starty;
scrollBar._y = scrollObj.bary;
setSizes();
if(val){
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
scrollBkg._visible = true;
}
else{
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
if(scrollBkgHide){
scrollBkg._visible = false;
}
}
}
public function killScrollBar(){
tClip.scroll = scrollObj.starty;
scrollBar._y = scrollObj.bary;
scrollObj.yPos = scrollObj.starty;
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
delete scrollObj.onEnterFrame;
delete scrollBar.onMouseUp;
delete scrollBar.onMouseDown;
delete scrollBar.onMouseMove;
delete upBtn.onMouseUp;
delete upBtn.onMouseDown;
delete dwnBtn.onMouseUp;
delete dwnBtn.onMouseDown;
delete upBtn.onRollOut;
delete upBtn.onRollOver;
delete dwnBtn.onRollOut;
delete dwnBtn.onRollOver;
delete scrollBar.onRollOut;
delete scrollBar.onRollOver;
//Mouse.removeListener(scrollObj.myWheel);
}
private function setSizes(){
if(tClip.scroll < scrollObj.starty){
if(tClip.scroll <= tClip.maxscroll){
scrollObj.yPos = scrollObj.starty;
}
else{
scrollObj.yPos = tClip.maxscroll;
}
}
else if(tClip.scroll > scrollObj.starty){
scrollObj.yPos = scrollObj.starty;
}
 
tClip.scroll = scrollObj.yPos;
 
if(barAutoSize == true){
//setup dynamic scrollbar height.
var sbHeight:Number;
if(tClip._height > scrollObj.maskh){
sbHeight = Math.floor((tClip._height / tClip.textHeight) * scrollObj.bardist);
}
else{
//sbHeight =
}
if(sbHeight < 20){
sbHeight = 20;
}
if(scrollBar.scrollbBarTop._name == undefined){
 
scrollBar._height = sbHeight;
}
else{
scrollBar.sheight = sbHeight
scrollBar.scrollBarMid._height = scrollBar.sheight - (scrollBar.scrollbBarTop._height + scrollBar.scrollbBarTop._height);
scrollBar.scrollbBarTop._y = scrollBar.scrollBarMid._height + scrollBar.scrollBarMid._y;
}
 
}
 
scrollObj.bht = Math.ceil(scrollBar._height);
scrollObj.barslack = (scrollObj.boty - scrollObj.topy) - scrollObj.bht;
scrollObj.scrolldist = tClip.maxscroll;
scrollObj.scrollspeed = 1;
scrollObj.yspeed = tMask._height/10;//16;
scrollObj.upscroll = 0;
scrollObj.dwnscroll = 0;
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
private function setCoors(){
tMask._height = Math.ceil(tMask._height);
scrollObj.maskh = tMask._height;
if(resizeObj){
flipDwnButton == true? dwnBtn._y = Math.round(tMask._height): dwnBtn._y = Math.round((tMask._height) - dwnBtn._height);
//flipDwnButton == true? dwnBtn._y = Math.round(tMask._height + tMask._y): dwnBtn._y = Math.round((tMask._height + tMask._y) - dwnBtn._height);
 
if(scrollBkg != null){
upBtn != null ? scrollBkg._height = scrollObj.maskh: scrollBkg._height = scrollObj.maskh;
}
 
}
upBtn._y = Math.floor(upBtn._y);
scrollObj.tht = Math.ceil(tClip._height);
scrollObj.starty = tClip.scroll;
scrollObj.barx = scrollBar._x;
scrollObj.bary = scrollBar._y;
if(upBtn != null){
scrollObj.topy = Math.round(upBtn._y + upBtn._height);
flipDwnButton == true? scrollObj.boty = Math.round(dwnBtn._y - dwnBtn._height): scrollObj.boty = Math.round(dwnBtn._y);
}
else{
scrollObj.topy = Math.round(scrollBar._y);
scrollObj.boty = Math.round(scrollBar._y + tMask._height);
}
scrollObj.bardist = (scrollObj.boty - scrollObj.topy);
setSizes();
}
 
private function init(){
setCoors();
if(scrollStatus == false){
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
}
else{
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
}
scrollObj._alpha = 100;
scrollObj.objectRef = this;
scrollBar.objectRef = this;
upBtn.objectRef = this;
dwnBtn.objectRef = this;
var scrollParent:Object = scrollObj;
var scrollTextField:Object = tClip;
 
scrollObj.stat = scrollStatus;
scrollObj.yPos = scrollYPos;
 
if(resizeObj){
resetAllSizes = setCoors;//setSizes;
}
 
scrollBar.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(2);
scrollParent.scrollchk = true;
this.startDrag(false,scrollParent.barx,scrollParent.topy,scrollParent.barx,scrollParent.boty - scrollParent.bht);
this.onMouseMove = function(){
if(scrollParent.scrollchk == true){
scrollParent.yPos = Math.round(scrollTextField.maxscroll * ((this._y - scrollParent.topy)  /scrollParent.barslack));
}
 
}
}
}
else{
}
}
scrollBar.onMouseUp = function(){
scrollParent.scrollchk = false;
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(1);
}
this.stopDrag();
}
scrollBar.onRollOut = function(){
this.barEvent(0);
}
scrollBar.onRollOver = function(){
this.barEvent(1);
}
upBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.upscroll = 1;
}
}
}
upBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.upscroll = 0;
}
upBtn.onRollOut = function(){
this.btnEvent(0);
}
upBtn.onRollOver = function(){
this.btnEvent(1);
}
dwnBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.dwnscroll = 1;
}
}
}
dwnBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.dwnscroll = 0;
}
dwnBtn.onRollOut = function(){
this.btnEvent(0);
}
dwnBtn.onRollOver = function(){
this.btnEvent(1);
}
 
inc = setInterval(Delegate.create(this, frameLoop),10);
}
 
private function frameLoop(){
if(scrollObj.upscroll == 1){
if(tClip.scroll > 1){
scrollObj.yPos -= 1;
}
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
if(scrollObj.dwnscroll == 1){
if(tClip.scroll < tClip.maxscroll){
scrollObj.yPos += 1;
}
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
 
if(scrollStatus){
var dirStat:Number = 0;
scrollObj.dwnscroll == 1 ? dirStat = -1:null;
scrollObj.upscroll == 1 ? dirStat = 1:null;
if(tClip.scroll != scrollObj.yPos){
easeMainClip(tClip,scrollObj.yPos,easeIn,dirStat);
}
if(autoOn){
if(tClip.maxscroll < 2){
setScrollStatus(false);
}
var checkScrollDist:Number = tClip.maxscroll;
if(scrollObj.scrolldist != checkScrollDist){
//reset size - ;
setSizes();
}
}
 
}
else{
if(autoOn){
if(tClip.maxscroll > 1){
setScrollStatus(true);
}
}
}
updateAfterEvent();
}
private function easeMainClip(obj,val,ease,dir){
if(ease > 0){
if(dir == 0){
if(Math.ceil(obj.scroll) > val){
dir = -1;
}
else if(Math.ceil(obj.scroll) < val){
dir = 1;
}
}
if(dir == -1){
obj.scroll -= Math.ceil((obj.scroll - val)/ease);
}
else if(dir == 1){
obj.scroll += Math.ceil((val - obj._y)/ease);
}
else{
obj.scroll = val;
}
}
else{
obj.scroll = val;
}
}
 
}

Demo:
OK, so my wife has been taking out all the halloween clothes and decorations this weekend. Maybe a little of that is rubbing off on me.

Source Here

Update:

The class has been updated to version (2.0), please re-download to keep current. This class and updates are based on the HDScrollMC class. http://www.taterboy.com/blog/2008/09/easy-flash-custom-scrollbar-class-as2/

Update: 2.1

Moved the class path from com.hdi.util.HDScrollText to com.hdi.as2.HDScrollText. All previous actionScript 2 classes are getting moved to com.hdi.as2.

Targeting Loaded swfs and Streaming

As we move into the Object Oriented mindset, unhealthy communication between a host and loaded swf can be a little controversial. Though using bubbling events is great for easy plug and play type communication, diagnosis establishing a direct connection to pass information can be more efficient.

As a comparison, to load an swf into an AS2 project, all you have to do is tell a MovieClip to load an swf and then that MovieClip will take on all the attributes of the loading swf. To access the loaded timeline you use, MovieClip.gotoAndPlay(2);

In AS3 all loaded swfs are loaded into a loader object that is added to a container. To access the timeline of a loaded swf you would use an instance of the Loader Object's content.

?View Code ACTIONSCRIPT
var loadedSwf:Object = Loader.loaderInfo.content;
//or
var loadedSwf:Object = Loader.contentLoaderInfo.content;
 
//then:
loadedSwf.gotoAndPlay(2);

Here are a few things to keep in mind when communicating with loaded swfs with AS3.

1. Use an object as a content instance if you need to access your loaded swf.

?View Code ACTIONSCRIPT
var newSwfContent:Object;
var ldr:Loader = new Loader();
var urlReq:URLRequest("content.swf");
ldr.load(urlReq);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, finHandler);
 
function finHandler(ev:Event):void{
newSwfContent = ev.target.content;
newSwfContent.gotoAndPlay(2);
}

2. For the sake of organization it may be useful to reference multiple instances of loaded content in a single object. Like loading a bunch of images, it may be easiest to do something like this.

?View Code ACTIONSCRIPT
var imageHolder:Oject = new Object();
....
function finHandler(ev:Event):void{
imageHolder[imageHolder.length] = ev.target.content;
}

There are many ways to set this up to have quick access to your content using the powerful Object Class.

3. Another way to target a loaded swf is to have the loaded swf request information from the host. One way to accomplish this is using dispatch event.

?View Code ACTIONSCRIPT
//Loading SWF:
this.loaderInfo.addEventListener(Event.COMPLETE,completeHandler);
function completeHandler(ev:Event):void{
dispatchEvent(new Event("LOADING_COMPLETE",true));
}
 
//Host File:
addEventListener("LOADING_COMPLETE",eventHandler);
function eventHandler(ev:Event):void{
trace("loaded: " + ev.target.currentFrame);
}

4. In AS2 you could access the timeline of a loading swf almost instantly. It was more of a streaming environment allowing the access of code or objects on the first few frames while the rest of the swf continued to load. You can access the timeline before a complete load with AS3, but in all my testing I have not been able to get access (without error) before about 80% of the swf is loaded. Using That just does not help out as much as access at 10% with AS2.

Event.INIT is triggered before the swf is completely loaded still allowing access to variables and objects, but you can not assign the target's content to an object before the load is complete. Any attempt to access the loaded swfs timeline before Event.INIT results in the following error:
"The loading object is not sufficiently loaded to provide this information."

The following demo shows a host file with complete access to the timeline of the loaded SWF.

Source Here

Here is the twin brother of the Easy Scrollbar MovieClip Class that works with TextFields. It does not require the masking and is perfect for Input TextFields. It has all the features of the MovieClip version except for easing. TextFields scroll one line at a time which is not very smooth.

Some of the features include:
Auto On/Off - you may need a scrolling clip that could change in size as dynamic content is displayed or entered. When the scroll bar is not needed, symptoms capsule it will turn itself off and back on when it is needed. Or you can manually turn it on and with your code.

Scroll Bar Resizing - To simulate the function of desktop applications, the scroll bar will automatically scale depending on the amount of scroll, This feature can be turned on or off.

Auto Resize - Say you have a project that needs multiple scroll bars. One 150 px tall, the other 500 px tall. With this class you can build one set of artwork and the class will automatically adjust the bottom button, scroll background, scrollbar scroll area to fit the needed size.

Down Button Flip - This will not change the world, but if you have an Up Button that is exactly like the bottom button just flipped vertically. The class will compensate for this, saving a few minutes of development time and a few kilobytes.

Scroll Background Hiding and resizing - Many scroll bars have a background track, you may want it visible when the scroll bars are disabled as a visual place holder. This feature can be turned on or off.

Works without a scroll bar or without up and down buttons.

Button Type Effects - Even though the buttons and scrollbars are made with movieClips, sample code and calls are provided to give them button type effects on rollOver, rollOut, press and release.

Usage may seem a little complex at first, but if you like designing and using custom scroll bars and buttons, it is totally worth it.

1. Create all your scroll objects, they should be converted to MovieClips.
(upButton, DownButton, ScrollBar, and ScrollBkg)

2. Place the up and down buttons, scroll bar, and scroll background into a new movieClip.
(ScrollObject)

3. Align the top button and scrollbar to it's starting position.

4. Apply the class, this is the most complex part.

var scrollSet:HDScrollText = HDScrollText(ScrollObject,ScrollMovieClip,UpButton,DownButton,ScrollBar,ScrollBarResize,ScrollBkg, ScrollBkgHide,DownButtonFlip,ResizeScrollObjects,AutoOn);

This is where you assign all the MovieClips and enable any of the features. Other than the 6 MovieClips that the class points to, the other 5 arguments are features to enable or disable.

ScrollBarResize: Boolean
ScrollBkgHide: Boolean
DownButtonFlip: Boolean
ResizeScrollObjects: Boolean
AutoOn: Boolean

Once it is enabled, it can manage itself or you can manage it manually with a method like so:
scrollSet.ScrollStatus(true); or scrollSet.ScrollStatus(false);

When you are done with everything, you can strip all the code out by calling scrollSet.killScrollBar();

?View Code ACTIONSCRIPT
import mx.utils.Delegate;
class com.hdi.util.HDScrollText{
/*
HDScrollText oringinally created 11/2005 by Todd Williams and HD Interactive.
©2005 - 2010 HD Interactive & Taterboy, Inc.
version: 2.1
date: 1-9-10
 
Compatibility:  Action Script 2, Flash Player 7 and higher.
Purpose:
To Build a scrollbar class that is truly portable and can be applied to custom artwork
of any size and shape. This class wraps the graphics instead of graphics wrapping the code.
This gives the designer complete control over look and feel. One of the major features
needed was to have one set of scroll objects to be 	used in multiple instances and allow
them to automatically conform to different scrolling needs. One set of scroll objects can
control a scroll window that is 200 pixels tall or 600 pixels tall on the same stage at the
same time.
 
Features:
1. Automatically arranges scroll objects so that one set scrollbar objects can be used in multiple
instances with different sized scrolling windows.
2. Resizing scroll bar similar to OS and desktop application scroll bar behavior.
3. Code Wraps to custom artwork instead of skinning a preexisting component.
4. Auto on and off. The scroll bar is smart enough to know when it is needed or not.
5. Code provided to build button type effects into MovieClip buttons and scrollbar.
6. Have multiple scrolling objects visible and functioning on the same stage at a time.
 
 
Preparation:
To prepare graphic objects for use with HDScrollMC, you will need to create 7 MovieClips.
MC 1. The MovieClip to be scrolled:
For scrolling text, create a TextField inside of a MovieClip, fill it with text manually,
or use dynamic text and the TextField.autoSize = true;
 
MC 2. Container for Scroll Objects: To make it possible to have multiple scrolling objects on the
stage at the same time, it is best to have at least the scrollbar and scroll button objects in a
container, the mask and MC to be scrolled can also be in this container if desired.
 
MC 3 & 4.  Scroll buttons UP and Down. These buttons are not required if a scrollbar only design is
needed. Scroll buttons can be movieClips or buttons. Code for rollover and press events will be 		sent to each button. If you want to use a MovieClip, disperse your button states on frames as you 		would a button and add a stop action to the first frame. Also the down button and be a vertically 		flipped instance if the top button if the artwork allows for this.
 
The scroll buttons receive the following method calls from the class, use the method below for
MovieClips with button type effects.
btnEvent(1); roll on
btnEvent(0); roll out
btnEvent(2); mouse down
btnEvent(1); mouse up
Sample:
function btnEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
MC 5. Scroll Bar: Must be a MovieClip and like the buttons, code will be sent for rollover and press events.
A scrollbar is not required if a button only design is required. For the scroll bar has a resize feature
with two modes. The scroll bar will resize bases on the amount of scroll and the size of the scroll
area, similar to OS scroll bars. Mode 1 is the scrollbar MovieClip resizes the whole MovieClip. Some
graphic distortion or stretching may occur. You can set the scale9Grid to this MovieClip prior to
enabling this class. Mode 2 uses three MovieClips within the Scroll Bar to represent the top, middle
and bottom of the scroll bar, the middle will stretched will the top and bottom MovieClips will retain
their graphic integrity. To use this option divide the Scrollbar into three horizontal slices. Create
MovieClip instances named scrollbBarTop, scrollBarBot, and scrollBarMid.
 
The scrollbar receives the following method calls from the class, use the method below for
MovieClips with button type effects.
 
barEvent(1); roll on
barEvent(0); roll out
barEvent(2); mouse down
barEvent(1); mouse up
Sample:
function barEvent(val){
if(val == 1){
//roll on / release
}
else if(val == 2){
//press
}
else{
//roll out
}
}
Super Simple Sample:
function btnEvent(val){
gotoAndStop(val+1);
}
 
MC 6. Scroll background, Must be a MovieClip,  will span the entire size of the scroll area
if the class is set to resize the objects. This MovieClip can be used to have a decorative
track for the scroll area and can be set to vanish or remain when the scrollbar is enabled
or disabled. This object is not required.
 
Usage:
Place the class folder in the working directory next to the fla you are using;
add import com.hdi.as2.HDScrollText; to the actions panel before the code below.
 
HDScrollText(ScrollObject,TextField,UpButton,DownButton,ScrollBar,
ScrollBarResize,ScrollBkg,ScrollBkgHide,DownButtonFlip,ResizeScrollObjects,AutoOn);
 
I know there are a lot of arguments, and the descriptions/Usage are as follows:
ScrollObject - (required) target of scroll object container, MC 3 from the preparation list.
ScrollMovieClip - (required) target of MovieClip to be scrolled, MC 1 from preparation list.
UpButton - target or null, to Up Button MovieClip or Button. MC 4 & 5 from preparation list.
DownButton - target  or null, to Down Button MovieClip or Button. MC 4 & 5 from preparation list.
ScrollBar - target or null, to Scroll Bar MovieClip. MC 6 from preparation list.
ScrollBarResize - Boolean: true or false, To enable scroll bar resizing depending on scroll amount.
ScrollBkg - target or null, to scroll background graphic.
ScrollBkgHide - Boolean: true or false, default behavior is to hide scroll background and scroll objects;
DownButtonFlip - Boolean: true or false, If the down button is an instance of the up button that is
vertically flipped.
ResizeScrollObjects - Boolean: true or false, when scroll bar loads, it calculates the size of the mask,
buttons, scrollbars and distributes them to the appropriate height and coordinates. This allows
different instances of a set of scroll objects to be used with different sized scrolling Objects.
AutoOn - Boolean: true or false, Turns control of turning the scroll bar objects on and off to the class.
If the scrolling MovieClip changes in size the class will automatically enable or disable the
scroll objects.
 
 
Other methods and properties:
 
scrollStatus:  property (Boolean) - tells if scrolling is enabled or disabled.
setScrollStatus: Function - manually enables/disables scrolling.
killScrollBar: Function - permanently disables the scrollbar and removes all listeners and events.
 
Tips:
1. For best performance, zero out  x and y coordinates to whole numbers on all MovieClips.
Also try to build artwork with artwork rounded to the nearest whole pixel. This stops a lot
of the little glitches 	that can appear when a user interacts with the scrolling objects.
 
2. If you do not want you scroll objects to flash on then off on load, set the scroll Object
Container's (MC 3) 	alpha property to 0. The class will automatically set it to 100 when enabled.
 
3. By default the class uses the scroll background  and/or the up button to align and distribute
the rest of the 	objects. You should align the top button and the top of the scroll background.
The top of the scrollbar 	should be aligned to the button of the top button. These coordinates
are used as starting points for all of 	the scroll objects and will return them to these
positions when the scroll bar is reset.
 
*/
private var scrollObj:Object; //scroll MovieClip containing up button, down button, scrollbar, background.
private var tClip:Object; //TextField to be scrolled.
private var tMask:Object; //Mask for the Text MovieClip, must be a MovieClip.
private var dwnBtn:Object; //Down button, should be movieClip or button.
private var upBtn:Object; //Down button, should be movieClip or button.
private var scrollBar:Object; //MovieClip to do the scrolling.
private var barAutoSize:Boolean; //Resizes the scroll bar to the scroll amount.
private var scrollBkg:Object; //Background behind scrollButtons and scrollBar.
private var scrollBkgHide:Boolean; //When scroll objects are not on, ScrollBkg is can be visible or not.
private var flipDwnButton:Boolean; // If you have flipped the upBtn to make the dwnBtn. Used for autoResize.
private var resizeObj:Boolean; // Resizes scroll objects to match the mask size and location.
private var autoOn:Boolean; //Let's the scroll object control if the scrollBar is on or off, depending on the size of the text box.
private var easeIn:Number; // Amount of delay for scrolling text to ease into possition.
private var scrollYPos:Number;
public var scrollStatus:Boolean; //Scrollbar is On or Off.
private var inc:Number;
private var resetAllSizes:Function;
function HDScrollText(targObj,tclip,upbtn,dwnbtn,sbar,barsize,sbkg,sbkgHide,flip,reSize,auto){
scrollObj = targObj;
tClip = tclip;
tMask = tclip;
upBtn = upbtn;
dwnBtn = dwnbtn;
scrollBar = sbar;
barAutoSize = barsize;
scrollBkg = sbkg;
scrollBkgHide = sbkgHide;
flipDwnButton = flip;
resizeObj = reSize;
autoOn = auto;
easeIn = 0;
 
scrollYPos = tClip.scroll;
if(tClip.maxscroll < 2){
scrollStatus = false;
if(scrollBkgHide && scrollBkg){
scrollBkg._visible = false;
}
}
else{
scrollStatus = true;
}
 
var testConfig:Boolean = true;
if(scrollObj == null || scrollObj == undefined){
trace("ERROR: ScrollObject (arg 0) needs to be a valid MovieClip ");
testConfig = false;
}
if(tMask == null || tMask == undefined){
trace("ERROR: MaskMC (arg 2) needs to be a valid MovieClip - please mask the scrolling object with a named instance of a MovieClip");
testConfig = false;
}
if((scrollBar == null || scrollBar == undefined) && (upBtn == null || upBtn == undefined) && (dwnBtn == null || dwnBtn == undefined)){
trace("ERROR: Very funny, you need at least 1 control object (scrollBar, upBtn or dwnBtn) assigned to initiate scrolling");
testConfig = false;
}
if(testConfig){
init();
}
}
public function setScrollStatus(val,overRide){
scrollStatus = val;
scrollObj.stat = val;
scrollObj.yPos = scrollObj.starty;
tClip.scroll = scrollObj.starty;
scrollBar._y = scrollObj.bary;
setSizes();
if(val){
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
scrollBkg._visible = true;
}
else{
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
if(scrollBkgHide){
scrollBkg._visible = false;
}
}
}
public function killScrollBar(){
tClip.scroll = scrollObj.starty;
scrollBar._y = scrollObj.bary;
scrollObj.yPos = scrollObj.starty;
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
delete scrollObj.onEnterFrame;
delete scrollBar.onMouseUp;
delete scrollBar.onMouseDown;
delete scrollBar.onMouseMove;
delete upBtn.onMouseUp;
delete upBtn.onMouseDown;
delete dwnBtn.onMouseUp;
delete dwnBtn.onMouseDown;
delete upBtn.onRollOut;
delete upBtn.onRollOver;
delete dwnBtn.onRollOut;
delete dwnBtn.onRollOver;
delete scrollBar.onRollOut;
delete scrollBar.onRollOver;
//Mouse.removeListener(scrollObj.myWheel);
}
private function setSizes(){
if(tClip.scroll < scrollObj.starty){
if(tClip.scroll <= tClip.maxscroll){
scrollObj.yPos = scrollObj.starty;
}
else{
scrollObj.yPos = tClip.maxscroll;
}
}
else if(tClip.scroll > scrollObj.starty){
scrollObj.yPos = scrollObj.starty;
}
 
tClip.scroll = scrollObj.yPos;
 
if(barAutoSize == true){
//setup dynamic scrollbar height.
var sbHeight:Number;
if(tClip._height > scrollObj.maskh){
sbHeight = Math.floor((tClip._height / tClip.textHeight) * scrollObj.bardist);
}
else{
//sbHeight =
}
if(sbHeight < 20){
sbHeight = 20;
}
if(scrollBar.scrollbBarTop._name == undefined){
 
scrollBar._height = sbHeight;
}
else{
scrollBar.sheight = sbHeight
scrollBar.scrollBarMid._height = scrollBar.sheight - (scrollBar.scrollbBarTop._height + scrollBar.scrollbBarTop._height);
scrollBar.scrollbBarTop._y = scrollBar.scrollBarMid._height + scrollBar.scrollBarMid._y;
}
 
}
 
scrollObj.bht = Math.ceil(scrollBar._height);
scrollObj.barslack = (scrollObj.boty - scrollObj.topy) - scrollObj.bht;
scrollObj.scrolldist = tClip.maxscroll;
scrollObj.scrollspeed = 1;
scrollObj.yspeed = tMask._height/10;//16;
scrollObj.upscroll = 0;
scrollObj.dwnscroll = 0;
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
private function setCoors(){
tMask._height = Math.ceil(tMask._height);
scrollObj.maskh = tMask._height;
if(resizeObj){
flipDwnButton == true? dwnBtn._y = Math.round(tMask._height): dwnBtn._y = Math.round((tMask._height) - dwnBtn._height);
//flipDwnButton == true? dwnBtn._y = Math.round(tMask._height + tMask._y): dwnBtn._y = Math.round((tMask._height + tMask._y) - dwnBtn._height);
 
if(scrollBkg != null){
upBtn != null ? scrollBkg._height = scrollObj.maskh: scrollBkg._height = scrollObj.maskh;
}
 
}
upBtn._y = Math.floor(upBtn._y);
scrollObj.tht = Math.ceil(tClip._height);
scrollObj.starty = tClip.scroll;
scrollObj.barx = scrollBar._x;
scrollObj.bary = scrollBar._y;
if(upBtn != null){
scrollObj.topy = Math.round(upBtn._y + upBtn._height);
flipDwnButton == true? scrollObj.boty = Math.round(dwnBtn._y - dwnBtn._height): scrollObj.boty = Math.round(dwnBtn._y);
}
else{
scrollObj.topy = Math.round(scrollBar._y);
scrollObj.boty = Math.round(scrollBar._y + tMask._height);
}
scrollObj.bardist = (scrollObj.boty - scrollObj.topy);
setSizes();
}
 
private function init(){
setCoors();
if(scrollStatus == false){
upBtn._visible = false;
dwnBtn._visible = false;
scrollBar._visible = false;
}
else{
upBtn._visible = true;
dwnBtn._visible = true;
scrollBar._visible = true;
}
scrollObj._alpha = 100;
scrollObj.objectRef = this;
scrollBar.objectRef = this;
upBtn.objectRef = this;
dwnBtn.objectRef = this;
var scrollParent:Object = scrollObj;
var scrollTextField:Object = tClip;
 
scrollObj.stat = scrollStatus;
scrollObj.yPos = scrollYPos;
 
if(resizeObj){
resetAllSizes = setCoors;//setSizes;
}
 
scrollBar.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(2);
scrollParent.scrollchk = true;
this.startDrag(false,scrollParent.barx,scrollParent.topy,scrollParent.barx,scrollParent.boty - scrollParent.bht);
this.onMouseMove = function(){
if(scrollParent.scrollchk == true){
scrollParent.yPos = Math.round(scrollTextField.maxscroll * ((this._y - scrollParent.topy)  /scrollParent.barslack));
}
 
}
}
}
else{
}
}
scrollBar.onMouseUp = function(){
scrollParent.scrollchk = false;
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.barEvent(1);
}
this.stopDrag();
}
scrollBar.onRollOut = function(){
this.barEvent(0);
}
scrollBar.onRollOver = function(){
this.barEvent(1);
}
upBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.upscroll = 1;
}
}
}
upBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.upscroll = 0;
}
upBtn.onRollOut = function(){
this.btnEvent(0);
}
upBtn.onRollOver = function(){
this.btnEvent(1);
}
dwnBtn.onMouseDown = function(){
if(this._visible == true){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(2);
scrollParent.dwnscroll = 1;
}
}
}
dwnBtn.onMouseUp = function(){
if(this.hitTest(_root._xmouse, _root._ymouse, false)){
this.btnEvent(1);
}
else{
this.btnEvent(0);
}
scrollParent.dwnscroll = 0;
}
dwnBtn.onRollOut = function(){
this.btnEvent(0);
}
dwnBtn.onRollOver = function(){
this.btnEvent(1);
}
 
inc = setInterval(Delegate.create(this, frameLoop),10);
}
 
private function frameLoop(){
if(scrollObj.upscroll == 1){
if(tClip.scroll > 1){
scrollObj.yPos -= 1;
}
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
if(scrollObj.dwnscroll == 1){
if(tClip.scroll < tClip.maxscroll){
scrollObj.yPos += 1;
}
scrollBar._y = (((tClip.scroll-1)/(tClip.maxscroll-1)) * (scrollObj.barslack)) + scrollObj.topy;
}
 
if(scrollStatus){
var dirStat:Number = 0;
scrollObj.dwnscroll == 1 ? dirStat = -1:null;
scrollObj.upscroll == 1 ? dirStat = 1:null;
if(tClip.scroll != scrollObj.yPos){
easeMainClip(tClip,scrollObj.yPos,easeIn,dirStat);
}
if(autoOn){
if(tClip.maxscroll < 2){
setScrollStatus(false);
}
var checkScrollDist:Number = tClip.maxscroll;
if(scrollObj.scrolldist != checkScrollDist){
//reset size - ;
setSizes();
}
}
 
}
else{
if(autoOn){
if(tClip.maxscroll > 1){
setScrollStatus(true);
}
}
}
updateAfterEvent();
}
private function easeMainClip(obj,val,ease,dir){
if(ease > 0){
if(dir == 0){
if(Math.ceil(obj.scroll) > val){
dir = -1;
}
else if(Math.ceil(obj.scroll) < val){
dir = 1;
}
}
if(dir == -1){
obj.scroll -= Math.ceil((obj.scroll - val)/ease);
}
else if(dir == 1){
obj.scroll += Math.ceil((val - obj._y)/ease);
}
else{
obj.scroll = val;
}
}
else{
obj.scroll = val;
}
}
 
}

Demo:
OK, so my wife has been taking out all the halloween clothes and decorations this weekend. Maybe a little of that is rubbing off on me.

Source Here

Update:

The class has been updated to version (2.0), please re-download to keep current. This class and updates are based on the HDScrollMC class. http://www.taterboy.com/blog/2008/09/easy-flash-custom-scrollbar-class-as2/

Update: 2.1

Moved the class path from com.hdi.util.HDScrollText to com.hdi.as2.HDScrollText. All previous actionScript 2 classes are getting moved to com.hdi.as2.

Targeting Loaded swfs and Streaming

As we move into the Object Oriented mindset, unhealthy communication between a host and loaded swf can be a little controversial. Though using bubbling events is great for easy plug and play type communication, diagnosis establishing a direct connection to pass information can be more efficient.

As a comparison, to load an swf into an AS2 project, all you have to do is tell a MovieClip to load an swf and then that MovieClip will take on all the attributes of the loading swf. To access the loaded timeline you use, MovieClip.gotoAndPlay(2);

In AS3 all loaded swfs are loaded into a loader object that is added to a container. To access the timeline of a loaded swf you would use an instance of the Loader Object's content.

?View Code ACTIONSCRIPT
var loadedSwf:Object = Loader.loaderInfo.content;
//or
var loadedSwf:Object = Loader.contentLoaderInfo.content;
 
//then:
loadedSwf.gotoAndPlay(2);

Here are a few things to keep in mind when communicating with loaded swfs with AS3.

1. Use an object as a content instance if you need to access your loaded swf.

?View Code ACTIONSCRIPT
var newSwfContent:Object;
var ldr:Loader = new Loader();
var urlReq:URLRequest("content.swf");
ldr.load(urlReq);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, finHandler);
 
function finHandler(ev:Event):void{
newSwfContent = ev.target.content;
newSwfContent.gotoAndPlay(2);
}

2. For the sake of organization it may be useful to reference multiple instances of loaded content in a single object. Like loading a bunch of images, it may be easiest to do something like this.

?View Code ACTIONSCRIPT
var imageHolder:Oject = new Object();
....
function finHandler(ev:Event):void{
imageHolder[imageHolder.length] = ev.target.content;
}

There are many ways to set this up to have quick access to your content using the powerful Object Class.

3. Another way to target a loaded swf is to have the loaded swf request information from the host. One way to accomplish this is using dispatch event.

?View Code ACTIONSCRIPT
//Loading SWF:
this.loaderInfo.addEventListener(Event.COMPLETE,completeHandler);
function completeHandler(ev:Event):void{
dispatchEvent(new Event("LOADING_COMPLETE",true));
}
 
//Host File:
addEventListener("LOADING_COMPLETE",eventHandler);
function eventHandler(ev:Event):void{
trace("loaded: " + ev.target.currentFrame);
}

4. In AS2 you could access the timeline of a loading swf almost instantly. It was more of a streaming environment allowing the access of code or objects on the first few frames while the rest of the swf continued to load. You can access the timeline before a complete load with AS3, but in all my testing I have not been able to get access (without error) before about 80% of the swf is loaded. Using That just does not help out as much as access at 10% with AS2.

Event.INIT is triggered before the swf is completely loaded still allowing access to variables and objects, but you can not assign the target's content to an object before the load is complete. Any attempt to access the loaded swfs timeline before Event.INIT results in the following error:
"The loading object is not sufficiently loaded to provide this information."

The following demo shows a host file with complete access to the timeline of the loaded SWF.

Source Here

I like to at least add a post once a week, dosage but this past friday I had an idea for a quick flash project. Like everything quick, doctor it never is. Finally here is the result of that idea.

WhackyVoting


It is a whack-a-mole styled game based on a scenario that voter turnout in the upcoming election is so great that the ballets could not be contained in the ballet boxes. They are over stuffed and popping out everywhere. Your job is to pick one of the major party candidates (John McCain or Barack Obama) and guard their votes. Being a good partisan citizen, you are only concerned about the votes for your candidate/party and have to let all the others go free. Ballets also contain images of vice presidental candidates as well as party logos, so you have to pay attention. The game adds up the scores for partisan votes and deducts points for crossing the isle (how dare you!). Each Candidate is given a score based on each players score. So the more people that play for one candidate, the higher their score. Current scores and stats are right on the home page.

The game is built with AS3 in Flash.

Enjoy
Sorry no source is available for this game yet.

Sketches & Guides

This series will cover the basics of illustrating with Adobe Illustrator from start to finish, help drug geared more toward novice Illustrator users with a few intermediate tips along the way. Some of the principles discussed are applicable to most illustration programs and illustration in general.

This collection of posts will be based on a philosophy of illustrating Quick, viagra 60mg Clean and Correct. Discussing time saving tips, preparing your artwork so that it can be easily used by others for web and print, and how to achieve consistent results based on your style. Everyone who reads this post has their own unique illustration style. I am in no way trying to convert people to my personal style, but hope that what is shown here can be incorporated to refine that style and produce beautiful graphics in a more efficient way.

Starting with Sketches:
It is becoming more and more common for artists to sketch directly into the computer using a drawing tablet. Others, like myself, roll old-school with a pencil and paper. Then, using a scanner or digital camera to get the rough ideas into the computer. Sketches may seem like an extra step or waste of time, especially when creating simple graphics, but sketches can really help to give your vector work some flare. When working from native shapes or precise curse, there is a danger of vector work becoming rigid and/or boring. I have fallen into the same trap, thinking I could save some time on a simple graphic. After an hour of messing around and it still not looking right, a few seconds on a sketch is all it took to get things back on track.

Using guides and grids:
We will start this post illustrating a 3/4 view of a building so we will need to produce some guides to help keep things in proper perspective. As you can see my sketch is a little off so these guides will help correct some wayward lines.

Alignment and perspective can be tricky and we can waste a lot of time moving things around, looking at it, then adjusting again to get things looking correct. This method of 2 point perspective, most of us learned in early art or drafting classes. We had large art tables with rulers and t-squares to produce a horizon line and all the perspective lines for each plane. Illustrator is great with it's very large workspace around the art-board to accommodate these horizon lines and vanishing points.

A few reasons we may neglect this step are: We remember that some of those perspective drawings didn't really look that exciting, unless you had a smaller desk and your angles were so sharp they could put an eye out. With the amount of time it takes to layout all the lines and match everything up, it is much faster to guess. Also, holding strict to the grid can put pull all the life out of our sketch.

The pros:
1. Hopefully we are sketching something a little more exciting than the barracks styled houses from grade school.

2. The time it takes to make guides, most of the time, does not compare to the time we could spend adjusting lines over and over till they look right. We risk progressing in the illustration until new details reveal that some of the perspective is still a little off, when it is much more time consuming to adjust everything.

3. A guide is just a guide, not the illustration, we use it to save time by finding the correct lines quickly. It does not need to overpower our ability to illustrate.

This last point leads into the style dilemma. Say you are the anti-perspective illustrator, all your objects are thick at the top and thin at the bottom or visa-versa, or curved like something made from cooked pasta. A few guide lines may help find your curves even faster. No one ever said your grid had to be made of straight lines. They can be curvy, bent, skewed into all kinds of meshes. just something to think about.

Knowing where perspective is not only helps you build a solid foundation for more realistic illustration, it can also show you where you can break the rules for more stylized illustrations. I think the biggest problem with not using guides is that some illustrations come of half stylized and half in perspective making everything look off. You should pick your style and commit to it. If you are stylized then be stylized, kick those lines and angles out there, you do not want anything looking close to straight or close to proper perspective. If you are shooting for realism, then your work should be governed by the laws that govern real objects.

Grouping and pre-grouping:
Guides and grids should be grouped and locked on a separate layer.
It is a pain to work with grids that are not grouped together, at least on a separate layer they are easily locked away and hidden when not needed. Sometimes we build a grid then realize later we needed to group it. It is hard to select all the lines if there are other objects on the art-board as well.

If you are building a grid by duplicating a copy/move using command + D or copy/moving manually, you can try pre-grouping. You can pre-group your guide lines, textures, star fields, sparkles, bubbles, by taking two objects and grouping them, then using your copy/move method on one of the objects (Select the object and while dragging, hold down the Command + Option on the Mac or Control + Alt on the PC). All the new copies will be made within the larger group.

Using Align and Disperse:
We may not need a full grid or perspective guides for some illustration. Some may only need a center line or to center an object. Using a few temporary rectangles and paths can help to find the center of an object without moving the original object from it's position.

To find proper sizing and position of objects in perspective only takes a few paths and the free transform tool. It is very easy to illustrate flat especially things like keyboard keys or windows for our building. Align and disperse everything while it is still flat, then using the Free Transform tool we can apply the grid to our plane.

Guides for Sketching:
Guides do not only apply to artwork coming into the computer. A quick way to keep sketches in perspective without T-Squares and Angles is to print out your perspective grid and place it under your tracing paper or under sketching paper on a light box. You can prepare any kind of guide (text, curves, wireframes) quickly in the computer and print them out for use with your sketches.

Now that we have our guides in place we are ready to add all the construction elements that make up our building. Next - Illustrating In Illustrator 101 Part 2 of 5: Construction

source here

Sketches & Guides

This series will cover the basics of illustrating with Adobe Illustrator from start to finish, help drug geared more toward novice Illustrator users with a few intermediate tips along the way. Some of the principles discussed are applicable to most illustration programs and illustration in general.

This collection of posts will be based on a philosophy of illustrating Quick, viagra 60mg Clean and Correct. Discussing time saving tips, preparing your artwork so that it can be easily used by others for web and print, and how to achieve consistent results based on your style. Everyone who reads this post has their own unique illustration style. I am in no way trying to convert people to my personal style, but hope that what is shown here can be incorporated to refine that style and produce beautiful graphics in a more efficient way.

Starting with Sketches:
It is becoming more and more common for artists to sketch directly into the computer using a drawing tablet. Others, like myself, roll old-school with a pencil and paper. Then, using a scanner or digital camera to get the rough ideas into the computer. Sketches may seem like an extra step or waste of time, especially when creating simple graphics, but sketches can really help to give your vector work some flare. When working from native shapes or precise curse, there is a danger of vector work becoming rigid and/or boring. I have fallen into the same trap, thinking I could save some time on a simple graphic. After an hour of messing around and it still not looking right, a few seconds on a sketch is all it took to get things back on track.

Using guides and grids:
We will start this post illustrating a 3/4 view of a building so we will need to produce some guides to help keep things in proper perspective. As you can see my sketch is a little off so these guides will help correct some wayward lines.

Alignment and perspective can be tricky and we can waste a lot of time moving things around, looking at it, then adjusting again to get things looking correct. This method of 2 point perspective, most of us learned in early art or drafting classes. We had large art tables with rulers and t-squares to produce a horizon line and all the perspective lines for each plane. Illustrator is great with it's very large workspace around the art-board to accommodate these horizon lines and vanishing points.

A few reasons we may neglect this step are: We remember that some of those perspective drawings didn't really look that exciting, unless you had a smaller desk and your angles were so sharp they could put an eye out. With the amount of time it takes to layout all the lines and match everything up, it is much faster to guess. Also, holding strict to the grid can put pull all the life out of our sketch.

The pros:
1. Hopefully we are sketching something a little more exciting than the barracks styled houses from grade school.

2. The time it takes to make guides, most of the time, does not compare to the time we could spend adjusting lines over and over till they look right. We risk progressing in the illustration until new details reveal that some of the perspective is still a little off, when it is much more time consuming to adjust everything.

3. A guide is just a guide, not the illustration, we use it to save time by finding the correct lines quickly. It does not need to overpower our ability to illustrate.

This last point leads into the style dilemma. Say you are the anti-perspective illustrator, all your objects are thick at the top and thin at the bottom or visa-versa, or curved like something made from cooked pasta. A few guide lines may help find your curves even faster. No one ever said your grid had to be made of straight lines. They can be curvy, bent, skewed into all kinds of meshes. just something to think about.

Knowing where perspective is not only helps you build a solid foundation for more realistic illustration, it can also show you where you can break the rules for more stylized illustrations. I think the biggest problem with not using guides is that some illustrations come of half stylized and half in perspective making everything look off. You should pick your style and commit to it. If you are stylized then be stylized, kick those lines and angles out there, you do not want anything looking close to straight or close to proper perspective. If you are shooting for realism, then your work should be governed by the laws that govern real objects.

Grouping and pre-grouping:
Guides and grids should be grouped and locked on a separate layer.
It is a pain to work with grids that are not grouped together, at least on a separate layer they are easily locked away and hidden when not needed. Sometimes we build a grid then realize later we needed to group it. It is hard to select all the lines if there are other objects on the art-board as well.

If you are building a grid by duplicating a copy/move using command + D or copy/moving manually, you can try pre-grouping. You can pre-group your guide lines, textures, star fields, sparkles, bubbles, by taking two objects and grouping them, then using your copy/move method on one of the objects (Select the object and while dragging, hold down the Command + Option on the Mac or Control + Alt on the PC). All the new copies will be made within the larger group.

Using Align and Disperse:
We may not need a full grid or perspective guides for some illustration. Some may only need a center line or to center an object. Using a few temporary rectangles and paths can help to find the center of an object without moving the original object from it's position.

To find proper sizing and position of objects in perspective only takes a few paths and the free transform tool. It is very easy to illustrate flat especially things like keyboard keys or windows for our building. Align and disperse everything while it is still flat, then using the Free Transform tool we can apply the grid to our plane.

Guides for Sketching:
Guides do not only apply to artwork coming into the computer. A quick way to keep sketches in perspective without T-Squares and Angles is to print out your perspective grid and place it under your tracing paper or under sketching paper on a light box. You can prepare any kind of guide (text, curves, wireframes) quickly in the computer and print them out for use with your sketches.

Now that we have our guides in place we are ready to add all the construction elements that make up our building. Next - Illustrating In Illustrator 101 Part 2 of 5: Construction

source here

Building a Fullscreen Kiosk Web Browser using Flex and AIR.

There are a number a fullscreen web browsers/plugins out there, sales but not all of them are free. We have used a couple different ones over the years for kiosks that need Web Browsing capability or to display an HTML based kiosk application. Next time I can just build one, all I need is a few lines of code and a touchscreen monitor.

I am impressed with AIR's webkit (HTML Component), it is light and loads pages pretty fast. Here is an example of building a serious utility with very few lines of code. The core fullscreen browser takes only 4 lines of code in Flex 3.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init();">
<mx:Script>
<![CDATA[
private function init():void{
//center window
nativeWindow.x = (Capabilities.screenResolutionX - nativeWindow.width) / 2;
nativeWindow.y = (Capabilities.screenResolutionY - nativeWindow.height) / 2;
 
//fullscreen
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
}
]]>
</mx:Script>
 
<mx:HTML id="browser" location="http://www.taterboy.com/blog/" width="100%" height="100%" />
</mx:WindowedApplication>

The version of the browser below incorporates more code for the following features.

Hidden Address bar that can be opened and closed using Command + u on a Mac or Ctrl + u on PC.
URLs are saved in a SharedObject so it only needs to be configured once. This allows the kiosk to restart and automatically load the home page.

There are many more features left (like onscreen keyboard, bookmarks, and a url filter) to be added but here is the code to date.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init();">
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
 
private var currURL:String;
private var so:SharedObject;
private var comKey:Boolean;
private var uKey:Boolean;
 
private function init():void{
//center window
nativeWindow.x = (Capabilities.screenResolutionX - nativeWindow.width) / 2;
nativeWindow.y = (Capabilities.screenResolutionY - nativeWindow.height) / 2;
 
//fullscreen
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyHandler);
stage.addEventListener(KeyboardEvent.KEY_UP,keyHandler);
 
//resizeBkg();
 
// pulling SharedObject to check for previous URL
so = SharedObject.getLocal("HDBrowser","/");
 
// If previous URL is valid, set browser location and close URL input bar.
if(so.data.url){
currURL = so.data.url;
browser.location = currURL;
navURL.visible = false;
}
}
private function resizeBkg():void{
 
}
 
//navigate browser to URL and save SharedObject
private function gotoURL():void{
currURL = urlTxt.text;
so.data.url = currURL;
browser.location = currURL;
navURL.visible = false;
}
 
// evavluate Command/Control, U, Enter keys: Open/Close URL input bar or call gotoURL().
private function keyHandler(ev:KeyboardEvent):void{
//trace(ev.keyCode);
var stat:Boolean;
if(ev.type == "keyUp"){
stat = false;
ev.keyCode == 15? comKey = uKey = stat:null;
ev.keyCode == 85? uKey = stat:null;
}
else{
stat = true;
ev.keyCode == 15? comKey = stat:null;
ev.keyCode == 85? uKey = stat:null;
}
 
if(comKey && uKey){
navURL.visible ? navURL.visible = false: navURL.visible = true;
}
if(ev.keyCode == 13 && navURL.visible){
gotoURL();
}
 
}
]]>
</mx:Script>
 
<mx:HTML id="browser" width="100%" height="100%" />
<mx:HBox id="navURL" width="100%" height="30" backgroundAlpha="1" backgroundColor="0x323232" paddingLeft="10" paddingTop="5">
<mx:TextInput id="urlTxt" width="95%" />
<mx:Button id="urlBtn" label="GO" click="gotoURL();"/>
</mx:HBox>
</mx:WindowedApplication>

To install and run the HDBrowser Hound AIR app use the installer badge below.

Technorati Tags: , , , , , , , , ,

5 Replies to “Free Fullscreen Kiosk Web Browser”

  1. Hi Tatterboy,

    thank you for providing this information, it ist of great help! I do have a question though. The Shortcut to display the URL bar does not work on Windows. On my Mac it functions fine. Is there a way to reset the URL in a different way? I tried to uninstall HDBrowserhound, but somehow the URL ist saved and I don’t get to access the URL input bar. Can I actually edit the SharedObject? And where is it? Your help is greatelt appreciated.

  2. The shared object is not plain text, but there are a couple .sol editors out there, I normally just delete the shared objects and the address bar will show up again. On the Mac the shared objects are located in the Users preferences folder, on the PC they are located in the Documents and Settings/User/Application Data folder. (I have not verified the location on the PC.) There will be a folder called “HDBrowser” with a couple more folders then the shared object file.

  3. Great, I found the .sol file and deleted it to get the URL bar back. Great work around! And here is my contribution for everybody out there. If you want the Browser to be a true full screen display, without that stupid statusbar at the bottom, add the following to the title of the WindowedApplication.

    showStatusBar=”false”

    So the complete title shoud read:

    Many Thanks!!!

  4. No update yet, but looking forward to messing with the new gesture classes for touch screens. It is on my list of things to do, but it may be a while. Sorry.

Leave a Reply