Stage Resizing



The Flash movie at left allows you to specify a number of columns and rows for a grid, then generates a new browser window containing a .swf with the specified grid. This .swf redraws itself dynamically based on the size and shape of the browser window.

Download a variation on the .swf file here.

The Stage object was an addition to your Actionscript arsenal with the release Flash MX. One terrific use for the Stage object is to dynamically set the size and position of objects in your Flash movie based on the size of the stage. Since we can do this at runtime, we can dynamically alter the layout of our movies in response to the user resizing the browser window. In this tutorial, I'm going to show you how to utilize the Stage object to make your movies responsive to the user's actions. We'll make two movies - one that repositions movieclips and another that dynamically redraws itself, both in response to user actions.


  1. The first movie we will make will reposition four boxes based on the size and shape of the window. Open this file to see it in action. You can download the sourcefile here. To make you own, first create a new file named "resize.fla".
  2. Our movie requires only one asset. Make a 50x50px box using the rectangle tool. Convert this into a movieclip (F8) with its registration point in its center. Name this symbol "corner".
  3. Drop four instances of "corner" (including the one you originally drew) on your stage, anywhere you'd like. Name the instances "tl", "tr", "bl" and "br" (top left, top right, bottom left and bottom right). That's it for graphic set-up. Now to the code!
  4. With the first and only frame selected, open your Actionscript editor and type the following lines:


  5. Stage.scaleMode = "noScale";
    Stage.align = "TL";

    Not too tough to start out, is it? (I'll let you in on a little secret - it's not too tough the entire way through!)

    The two lines of code above just set up our stage to act as we need it to in order for our resizing to work. scaleMode and align are two properties of the Stage object in much the same way as _xscale and _alpha are properties of the MovieClip object. scaleMode tells our stage that it shouldn't scale at all once published -- this will lock its dimensions. Next, we set the align to "TL" or top left so that our Flash movie is aligned at the top left of our window. Once these properties are set, we can get accurate readings for the width and height of the stage.

  6. Add two more lines under the two you wrote above:


  7. w = tl._width/2;
    h = tl._height/2;

    This should be nothing new. We store half of the width and height of our corners in two separate variables (in case you wanted something other than a perfect square). We will need these to position our corners with the knowledge that their registration points are in the center of the box graphic.

  8. Can you believe we're nearly done? Add the following lines to the code:


  9. Stage.addListener(this);

    OK, so what are we doing here? To understand what's going on, and how it will work, you need to understand what a listener is. You see, most objects in Flash have built in methods (or handlers) that run when certain events are fired. For instance, when a button is pressed, it automatically runs its onPress handler. When it is then released, it runs its onRelease handler. You could say that the button is enabled to "hear" the pressing and releasing event whenever it is fired. The same is true for movieclips as they "hear" when a frame is entered and so run their onEnterFrame handler. Well, when the stage is resized, another event is fired -- let's call it "resize". Problem is, there are no objects that are enabled to "hear" this event. But! All is not lost! We can add listeners to the Stage object so that they can "hear" when the resize event is fired. This is what we do in the above line of code - we enable the main timeline (this) to "hear" the Stage's events. Now all we need is to set up a handler to run when the resize event is fired. Next step!

  10. End of the line! Add the following lines to the code in the Actionscript editor to finish up:



  11. this.onResize = function() {
      tl._x = bl._x = w;
      tl._y = tr._y = h;
      tr._x = br._x = Stage.width - w;
      bl._y = br._y = Stage.height - h;
    };

    That's it! Whenever the stage is resized, the main timeline will run its onResize handler (this should always be named onResize, by the way). It then repositions the four corners based on the Stage.width and Stage.height - two additional properties of the Stage object.

  12. To see this work, publish your .swf with an HTML file with the following settings in the File>Publish Settings window. Then open the HTML file in a browser and see the dynamic repositioning in action.




That's a quick sample of how to put together a movie that will reposition its internal elements based on the stage size. Let's take it a step further and create a gridded movie that redraws based on the stage size and shape. The example above illustrates this. You can download a modified sourcefile here.

  1. Create a new Flash file named "resizableWindows.fla". This file will need nothing in its library nor nothing on its stage. It's all code, baby!
  2. Select the first and only frame in the movie, open your Actionscript editor, and start the code rolling:


  3. Stage.scaleMode = "noScale";
    Stage.align = "TL";
    Stage.addListener(this);

    Nothing new here, let's keep it moving ("Nothing to see, people!").

  4. We're now going to add some variables to the top of our code that will set the look of our movie:


  5. columns = [0, .15, .25, .95, 1];
    rows = [0, .25, .5, 1];
     
    borderThickness = 3;
    borderColor = 0x3F3754;
    fillColor = 0xC1A1FF;

    The first two variables control the number of rows and columns in our grid, and the size of each one. To make it easier later on (though it might seem unintuitive here), the numbers in the columns and rows arrays specify the start and ending percentages (out of 1) of each column or row. So the first column goes from 0-15%, the second goes from 15-25%, etc. The thickness and color variables set the colors of our grid.

  6. This next bit of code is just a function to draw a rectangle using the drawing API. Add it next.


  7. drawBox = function(pt, w, h) {
      with (this) {
      moveTo(pt.x, pt.y);
      lineTo(pt.x + w, pt.y);
      lineTo(pt.x + w, pt.y + h);
      lineTo(pt.x, pt.y + h);
      lineTo(pt.x, pt.y);
      }
    }

    We will send the drawBox() function three parameters: the point of the top left corner of a rectangle and the width and height of the rectangle. Using these, we use the drawing API commands moveTo() and lineTo() to draw the rectangle. We will call this function for each section of our grid.

  8. Almost there! We have previously enabled the main timeline (this) to "hear" Stage events, so now we need to write a function for onResize that will redraw our grid whenever the stage size and shape are changed. Let's start it like this (you can place this at the end of all of our previous code):


  9. this.onResize = function() {
      var w = Stage.width;
      var h = Stage.height;
      with (this) {
      clear();
      lineStyle(borderThickness, borderColor, 100);
      }
    }

    This doesn't do anything as of yet, but will serve as the bookends of our onResize. All we do so far is store the current stage height and width in variables and clear all graphics in our main timeline. After clearing the stage, we need to reset our lineStyle based on our variables above (when you clear a movieclip, its lineStyle is automatically reset).

  10. Last bit of code, but it's a doozy! We will now loop through each row and column and draw a rectangle of the appropriate size. Since a grid is two dimensions, we will use nested for loops to run through both rows AND columns. Add the lines in bold:


  11. this.onResize = function() {
      var w = Stage.width;
      var h = Stage.height;
      with (this) {
      clear();
      lineStyle(borderThickness, borderColor, 100);
      for (var i = 0; i < rows.length-1; i++) {
      for (var j = 0; j < columns.length-1; j++) {
      var x = columns[j] * w;
      var y = rows[i] * h;
      var bW = w * (columns[j+1] - columns[j]);
      var bH = h * (rows[i+1] - rows[i]);
      beginFill(fillColor, 100);
      drawBox({x:x, y:y}, bW, bH);
      endFill();
      }
      }
      }
    }

    Breaking this down, the first for loop runs through each row, then the second runs through each column in that row. The top left corner for the particular section of the grid is then calculated and stored in the x and y variables. Next, the width and the height of the grid section is calcluated and stored in variables as well. Once all of this information is determined, we draw a solid rectangle for that section.

  12. Once again, to see this in action publish an HTML page and a .swf file, then open it inside a browser. Alter the values we set at the top of the code to change the look. Try adding or removing columns and rows as well as changing their sizes. Resize the browser window to see the stage redraw itself. Nice!

That's all it takes! Using the Stage object to check on the size and shape of Flash window, you can now create more responsive interfaces that react to user actions. One way I have utilized this at 27Bobs is to set the maximum and minimum sizes for my Website. Although the user can scale the browser up and down, I have limited the scaling of the Flash movie embedded in the window so that things never get too small (illegible) or too large (too processor-intensive). That's one use, but there are many more. Now that you know how to code it, go and find those other uses! Explore and enjoy!