AS2: StageManager

View Example
View Documentation
Download Class & Example Files

Creates an instance of the StageManager that aligns clips according to their selected alignment mode. Also dispatches an event, onStageResize, that allows for futher manipulation of clips to the stage sizing.

Actionscript:
  1. import mx.transitions.easing.*;
  2. import mx.transitions.Tween;
  3. import mx.events.EventDispatcher;
  4.  
  5. /**
  6. * Creates an instance of the StageManager that aligns clips according to their selected alignment mode.  Also dispatches an event, onStageResize, that allows for futher manipulation of clips to the stage sizing.
  7. *
  8. * @usage
  9. * <code>
  10. * <pre>
  11. import mx.transitions.easing.*;
  12. import com.reintroducing.utils.StageManager;
  13. var listener:Object = new Object();
  14. var sm:StageManager = new StageManager("easing", .5, Regular.easeOut);
  15. sm.addClip(test1_mc, "TL", 10, 10);
  16. sm.addClip(test2_mc, "TC");
  17. sm.addClip(test3_mc, "TR");
  18. sm.addClip(test4_mc, "ML");
  19. sm.addClip(test5_mc, "MC");
  20. sm.addClip(test6_mc, "MR");
  21. sm.addClip(test7_mc, "BL");
  22. sm.addClip(test8_mc, "BC");
  23. sm.addClip(test9_mc, "BR", -30, -50);
  24. trace("LENGTH OF CLIPS: " + sm.clips.length);
  25. sm.addEventListener("onStageResize", listener);
  26. listener.onStageResize = function():Void
  27. {
  28.     trace("STAGE WIDTH: " + Stage.width + " & STAGE HEIGHT: " + Stage.height);
  29. };
  30. sm.init();
  31. * </pre>
  32. * </code>
  33. *
  34. * @author Matt Przybylski [http://www.reintroducing.com]
  35. * @version 1.2
  36. */
  37.  
  38. class com.reintroducing.utils.StageManager
  39. {
  40.     /*
  41.      * ====================================================================================================
  42.      * PRIVATE VARIABLES
  43.      * ====================================================================================================
  44.      */
  45.     
  46.     private var dispatchEvent:Function;
  47.    
  48.     private var _clips:Array;
  49.     private var _resizeStyle:String;
  50.     private var _easeTime:Number;
  51.     private var _easeFunc:Function;
  52.     private var _tweenX:Tween;
  53.     private var _tweenY:Tween;
  54.     
  55.     /*
  56.      * ====================================================================================================
  57.      * PUBLIC VARIABLES
  58.      * ====================================================================================================
  59.      */
  60.    
  61.     public static var DEFAULT_NAME:String = "com.reintroducing.utils.StageManager";
  62.    
  63.     public var addEventListener:Function;
  64.     public var removeEventListener:Function;
  65.    
  66.     public var onStageResize:Function;
  67.    
  68.     /*
  69.      * ====================================================================================================
  70.      * CONSTRUCTOR
  71.      * ====================================================================================================
  72.      */
  73.    
  74.     /**
  75.      * Creates a new instance of the StageManager class.
  76.      *
  77.      * @usage <pre><code>var sm:StageManager = new StageManager($resizeStyle, $easeTime, $easeFunc);</code></pre>
  78.      *
  79.      * @param $resizeStyle A string value that represents how to move the clips into position ("easing" or "instant")
  80.      * @param $easeTime If the $resizeStyle is set to "easing", time (in seconds) it takes to ease clips into position
  81.      * @param $easeFunc If the $resizeStyle is set to "easing", the easing function used to ease clips into position
  82.      */
  83.    
  84.     public function StageManager($resizeStyle:String, $easeTime:Number, $easeFunc:Function)
  85.     {
  86.         EventDispatcher.initialize(this);
  87.        
  88.         Stage.scaleMode     = "noScale";
  89.         Stage.align         = "TL";
  90.         Stage.addListener(this);
  91.        
  92.         this._clips         = new Array();
  93.         this._resizeStyle   = $resizeStyle;
  94.         this._easeTime   = $easeTime;
  95.         this._easeFunc   = $easeFunc;
  96.     }
  97.    
  98.     /*
  99.      * ====================================================================================================
  100.      * PRIVATE METHODS
  101.      * ====================================================================================================
  102.      */
  103.    
  104.     private function onResize():Void
  105.     {
  106.         if (this._resizeStyle == "instant")
  107.         {
  108.             this.doInstantResize();
  109.         }
  110.         else if (this._resizeStyle == "easing")
  111.         {
  112.             this.doEasingResize();
  113.         }
  114.        
  115.         dispatchEvent({type: "onStageResize"});
  116.     }
  117.    
  118.     // Resizes the clips using no easing but instant movement.
  119.     private function doInstantResize():Void
  120.     {
  121.         var numClips:Number = this._clips.length;
  122.        
  123.         for (var i:Number = 0; i <numClips; i++)
  124.         {
  125.             var clip:MovieClip = this._clips[i].clip;
  126.             var clipX:Number = this._clips[i].x;
  127.             var clipY:Number = this._clips[i].y;
  128.            
  129.             switch (this._clips[i].mode)
  130.             {
  131.                 case "TL":
  132.                     clip._x = (0 + clipX);
  133.                     clip._y = (0 + clipY);
  134.                    
  135.                     break;
  136.                
  137.                 case "TC":
  138.                     clip._x = (((Stage.width / 2) - (clip._width / 2)) + clipX);
  139.                     clip._y = (0 + clipY);
  140.                    
  141.                     break;
  142.                 case "TR":
  143.                     clip._x = ((Stage.width - clip._width) + clipX);
  144.                     clip._y = (0 + clipY);
  145.                    
  146.                     break;
  147.                 case "ML":
  148.                     clip._x = (0 + clipX);
  149.                     clip._y = (((Stage.height / 2) - (clip._height / 2)) + clipY);
  150.                    
  151.                     break;
  152.                 case "MC":
  153.                     clip._x = (((Stage.width / 2) - (clip._width / 2)) + clipX);
  154.                     clip._y = (((Stage.height / 2) - (clip._height / 2)) + clipY);
  155.                    
  156.                     break;
  157.                 case "MR":
  158.                     clip._x = ((Stage.width - clip._width) + clipX);
  159.                     clip._y = (((Stage.height / 2) - (clip._height / 2)) + clipY);
  160.                    
  161.                     break;
  162.                 case "BL":
  163.                     clip._x = (0 + clipX);
  164.                     clip._y = ((Stage.height - clip._height) + clipY);
  165.                    
  166.                     break;
  167.                 case "BC":
  168.                     clip._x = (((Stage.width / 2) - (clip._width / 2)) + clipX);
  169.                     clip._y = ((Stage.height - clip._height) + clipY);
  170.                    
  171.                     break;
  172.                 case "BR":
  173.                     clip._x = ((Stage.width - clip._width) + clipX);
  174.                     clip._y = ((Stage.height - clip._height) + clipY);
  175.                    
  176.                     break;
  177.             }
  178.         }
  179.     }
  180.    
  181.     // Resizes the clips using an easing equation.
  182.     private function doEasingResize():Void
  183.     {
  184.         var numClips:Number = this._clips.length;
  185.        
  186.         for (var i:Number = 0; i <numClips; i++)
  187.         {
  188.             var clip:MovieClip = this._clips[i].clip;
  189.             var clipX:Number = this._clips[i].x;
  190.             var clipY:Number = this._clips[i].y;
  191.             var x:Number;
  192.             var y:Number;
  193.            
  194.             switch (this._clips[i].mode)
  195.             {
  196.                 case "TL":
  197.                     x = (0 + clipX);
  198.                     y = (0 + clipY);
  199.                    
  200.                     break;
  201.                
  202.                 case "TC":
  203.                     x = (((Stage.width / 2) - (clip._width / 2)) + clipX);
  204.                     y = (0 + clipY);
  205.                    
  206.                     break;
  207.                 case "TR":
  208.                     x = ((Stage.width - clip._width) + clipX);
  209.                     y = (0 + clipY);
  210.                    
  211.                     break;
  212.                 case "ML":
  213.                     x = (0 + clipX);
  214.                     y = (((Stage.height / 2) - (clip._height / 2)) + clipY);
  215.                    
  216.                     break;
  217.                 case "MC":
  218.                     x = (((Stage.width / 2) - (clip._width / 2)) + clipX);
  219.                     y = (((Stage.height / 2) - (clip._height / 2)) + clipY);
  220.                    
  221.                     break;
  222.                 case "MR":
  223.                     x = ((Stage.width - clip._width) + clipX);
  224.                     y = (((Stage.height / 2) - (clip._height / 2)) + clipY);
  225.                    
  226.                     break;
  227.                 case "BL":
  228.                     x = (0 + clipX);
  229.                     y = ((Stage.height - clip._height) + clipY);
  230.                    
  231.                     break;
  232.                 case "BC":
  233.                     x = (((Stage.width / 2) - (clip._width / 2)) + clipX);
  234.                     y = ((Stage.height - clip._height) + clipY);
  235.                    
  236.                     break;
  237.                 case "BR":
  238.                     x = ((Stage.width - clip._width) + clipX);
  239.                     y = ((Stage.height - clip._height) + clipY);
  240.                    
  241.                     break;
  242.             }
  243.            
  244.             this._tweenX = new Tween(clip, "_x", this._easeFunc, clip._x, x, this._easeTime, true);
  245.             this._tweenY = new Tween(clip, "_y", this._easeFunc, clip._y, y, this._easeTime, true);
  246.         }
  247.     }
  248.    
  249.     /*
  250.      * ====================================================================================================
  251.      * PUBLIC METHODS
  252.      * ====================================================================================================
  253.      */
  254.    
  255.     /**
  256.      * Initializes the StageManager and helps avoid the FireFox bug (won't manage the stage on initial load).
  257.      *
  258.      * @usage <pre><code>sm.init();</code></pre>
  259.      *
  260.      * @return Nothing
  261.      */
  262.    
  263.     public function init():Void
  264.     {
  265.         this.onResize();
  266.     }
  267.    
  268.     /**
  269.      * Adds a clip to the clips array so that is is tracked when resizing. $offsetX and $offsetY are optional and can be left blank to use no offsets.
  270.      *
  271.      * <p>
  272.      * The $alignMode parameter can be any of the following string values:
  273.      * <ul>
  274.      * <li>"TL": top left</li>
  275.      * <li>"TC": top center</li>
  276.      * <li>"TR": top right</li>
  277.      * <li>"ML": middle left</li>
  278.      * <li>"MC": middle center</li>
  279.      * <li>"MR": middle right</li>
  280.      * <li>"BL": bottom left</li>
  281.      * <li>"BC": bottom center</li>
  282.      * <li>"BR": bottom right</li>
  283.      * </ul>
  284.      * </p>
  285.      *
  286.      * @usage <pre><code>sm.addClip(test2_mc, "TL", 10, 30);</code></pre>
  287.      *
  288.      * @param $clip The movie clip that is to be added to the clips array.
  289.      * @param $alignMode A string value that represents the mode to align the movie clip to.
  290.      * @param $offsetX An optional number that represents the value to offset the clip on its x axis from its align spot (negative offsets left).
  291.      * @param $offsetY An optional number that represents the value to offset the clip on its y axis from its align spot (negative offsets up).
  292.      *
  293.      * @return Nothing
  294.      */
  295.    
  296.     public function addClip($clip:MovieClip, $alignMode:String, $offsetX:Number, $offsetY:Number):Void
  297.     {
  298.         var xOffset:Number = ($offsetX == undefined) ? 0 : $offsetX;
  299.         var yOffset:Number = ($offsetY == undefined) ? 0 : $offsetY;
  300.        
  301.         this._clips.push({clip: $clip, mode: $alignMode, x: xOffset, y: yOffset});
  302.     }
  303.    
  304.     /**
  305.      * Removes a clip from the clips array so it is no longer tracked by the resizing.
  306.      *
  307.      * @usage <pre><code>sm.removeClip(test_mc);</code></pre>
  308.      *
  309.      * @param $clip The movie clip that is to be removed from the clips array.
  310.      *
  311.      * @return Nothing
  312.      */
  313.    
  314.     public function removeClip($clip:MovieClip):Void
  315.     {
  316.         var numClips:Number = this._clips.length;
  317.        
  318.         for (var i:Number = 0; i <numClips; i++)
  319.         {
  320.             var clip:MovieClip = this._clips[i].clip;
  321.            
  322.             if (clip == $clip)
  323.             {
  324.                 this._clips.splice(i, 1);
  325.             }
  326.         }
  327.     }
  328.    
  329.     /*
  330.      * ====================================================================================================
  331.      * EVENT HANDLERS
  332.      * ====================================================================================================
  333.      */
  334.    
  335.    
  336.    
  337.     /*
  338.      * ====================================================================================================
  339.      * GETTERS & SETTERS
  340.      * ====================================================================================================
  341.      */
  342.    
  343.     /**
  344.      * Returns the current clips array.
  345.      *
  346.      * @usage <pre><code>trace(sm.clips);</code></pre>
  347.      */
  348.    
  349.     public function get clips():Array
  350.     {
  351.         return this._clips;
  352.     }
  353.    
  354.     /*
  355.      * ====================================================================================================
  356.      * HELPERS
  357.      * ====================================================================================================
  358.      */
  359.    
  360.     public function toString():String
  361.     {
  362.         return "com.reintroducing.utils.StageManager";
  363.     }
  364.    
  365.     /*
  366.      * ====================================================================================================
  367.      * END CLASS
  368.      * ====================================================================================================
  369.      */
  370. }

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

10 Comments

1. I think its a bad idead to include the whole positioning part in that script.. it should just return the values, then u can do with it what u want..

2. Why have the whole switch on Stage.align twice?

1. What values would it be returning? The whole point of the script is for it to manage the positioning of the clips so you don't have to write code to do it. If you just wanted values, all you'd have to do is set up the stage listener yourself and then react to that how you normally do without using a manager class to do so.

2. I dont think you're looking at the class closely enough. The reason there are two switch statements is because one is for normal resizing and the other is for resizing when you want it to resize with an ease. There are two separate methods to handle each type of resizing that you specify.

1. First of all i'd the class up in two. Have one returning the x y pos for any object/mc trying to align to any width/height. And another class one doing the actaully moving of objects.

getAlignedPos(myMc,"MT")
that would return an object {x:450,y:0}

var xyValues:Object = getAlignedPos(myMc,"MT")
myMc._x = xyValues.x
myMc._y = xyValues.y

2. First one kinda answers this one.. if you cannot see that ure using the exact same calcualtions nad just use them differently, then there's no use to argue about it =)

I hope you expect some constructive critisism, now when you posting ure stuff, and commenting is on 😛

ups.. first sentance.. i meant to write:

1. First of all i'd the class up in two.

1. First of all i'd >> SPLIT << the class up in two.

ffs.. how uncool =D

Jakob,
Constructive criticism is always welcome and suggestions that would make the classes better are great for everyone. However, in this instance, I do not agree on what you are saying. There is no need to split the class up into two classes. I'm not really going to argue on this point though because there is more than one way to skin a cat and thats the way i chose. If you don't see this as a viable solution for your uses, simply create your own class(es) to do this and you don't have to use this one. I posted it because it works great for me and I figured others would see a benefit from it as well.

As for the second point, it could probably be condensed into one method that at the end has a conditional statement based on the type of movement you want to handle, but i wrote it into two separate methods just in case there was something i needed to change about these movements in the future. again, feel free to make the change in the class for your own use. i may eventually change it myself and repost it as well so thanks for the suggestion.

Fine with me =), just commenting..

I care alot about how resourcive scripts can/should be.. and i care alot about file size, as i use AS2 for webbanners.
...and i already have what i'm talking about, not as a class but a generic function that i use for any positioning.

Great work as usual Matt - thanks for your additions to the community. Though I work primarily in AS3 (use some of your classes there) this is working great for a coworker who is currently using as2.

Thanks again! Kudos!

Glad it is helping you guys out, Scotty. Thanks for the kind words.

Why doesn't this work with components?

Even components insie and MC!

It loads OK to start, but on resize the component is a long way from the right side when i use TR

Leave a comment

(required)

(required)