2

As you well know in as3 we have a getBounds() method which returns the exact dimension and coordinates of the movieclip in the DisplayObject container we want. Fact is that these data are calculated based on the graphics in their state in the MC at the frame it is while getBounds() is called.

What I want is the REAL bounds rectangle, that is the larger rectangle that the WHOLE animated movieclip will take in its container.
I thought of two ways:
1 - a flash built-in method that I don't know
2 - going through every frame always getting the bounds and finally returning the biggest (but what if it's a long animation? should I wait for it to play completely before I can get what I want?)

I hope I've been clear. If you need examples, let me know!

Andrea Silvestri
  • 1,082
  • 4
  • 14
  • 41

2 Answers2

4

You can iterate through each frame without having to wait for the animation to play:

Let's say your clip is called bob:

var lifetimeBounds:Rectangle = new Rectangle();
bob.gotoAndStop(1);
for(var i:int=1;i<=bob.totalFrames;i++){
    lifetimeBounds.width = Math.max(lifetimeBounds.width, bob.width);
    lifetimeBounds.height = Math.max(lifetimeBounds.height, bob.height);
    lifetimeBounds.x = Math.min(lifetimeBounds.x, bob.x);
    lifetimeBounds.y = Math.min(lifetimeBounds.y, bob.y);
    bob.nextFrame();
}

bob.gotoAndStop(1); //reset bob back to the beginning

It's more CPU taxing (so I'd recommend not using it if the above works for your situation), but you could also use getBounds() in the example above and compare the returned rectangle against the lifetimeBounds rectangle:

var tempRect:Rectangle;
var lifetimeBounds:Rectangle = new Rectangle();
bob.gotoAndStop(1);
for(var i:int=1;i<=bob.totalFrames;i++){
    tmpRect = bob.getBounds(this);
    lifetimeBounds.width = Math.max(lifetimeBounds.width, tempRect.width);
    lifetimeBounds.height = Math.max(lifetimeBounds.height, tempRect.height);
    lifetimeBounds.x = Math.min(lifetimeBounds.x, tempRect.x);
    lifetimeBounds.y = Math.min(lifetimeBounds.y, tempRect.y);
    bob.nextFrame();
}
someOne
  • 1,975
  • 2
  • 14
  • 20
BadFeelingAboutThis
  • 14,445
  • 2
  • 33
  • 40
  • 1
    You could use `getBounds()` in the loop too, but it's more expensive and I wouldn't use it if width/height are sufficient – BadFeelingAboutThis Dec 06 '12 at 18:31
  • Though I like the FOR idea I don't think this is gonna work. What if the bounds of a frame is Rectangle(100, 300, 200, 900) and the one after is Rectangle(0,0, 1000, 600)? With your method I would take the second rectangle for it's the biggest but as a bounds rect won't work because it won't include the previous one. For each getBounds I would look for the lowest min_x, lowest min_y, highest max_x and highest max_y. This would give all the info to draw a rectangle which would include all the animation. Hope I've been clear. – Andrea Silvestri Dec 07 '12 at 17:16
  • This is just an example of the syntax you'd use. You can tweak the math however you'd like to meet your situations. You could easily change MaxH/MaxW to a rectangle object. You didn't specify what you need this data for so I provided the most efficient sample code. – BadFeelingAboutThis Dec 07 '12 at 17:38
  • I updated the answer to use a rectangle instead, and an exmaple that uses `getBounds()` – BadFeelingAboutThis Dec 07 '12 at 17:46
  • this is what I wanted: http://pastebin.com/6SuFfC2d and here is the example working and fast: https://dl.dropbox.com/u/4064417/getRealBounds.fla – Andrea Silvestri Dec 07 '12 at 17:48
  • Some efficiency tips: You don't need to cast mc as MovieClip because that's already it's type. 2. use a rectangle like in my example above instead of creating minx/y max_x/y vars. While naturally you're sample is fast (it's the only thing your program does so it has all the cpu overhead it needs), it's always a best practice to do things as efficiently as possible so you don't have go back later as much. – BadFeelingAboutThis Dec 07 '12 at 18:08
  • Thanks for the advice, I will do like you say. (I cast instance names in the IDE just to have the autocomplete of the code. I usually write on FlashDeveloper where I don't have to do this) – Andrea Silvestri Dec 08 '12 at 00:33
1

I had this issue when converting animations to bitmapData frames, as I wanted all the resulting frames to be a uniform size and match the largest frame dimensions.

I basically had to loop through the animation 1 frame at a time and compare the bounding box to the current largest dimensions. I too thought it was a less than an ideal solution, but it worked.

So #2 is your best bet, as there is no flash built in method that provides what you seek.

prototypical
  • 6,731
  • 3
  • 24
  • 34
  • I see. Is it possible to go through every frame at CPU speed and not by the frame rate? If the animation is 10 seconds I can't wait that much time before I get the information. – Andrea Silvestri Dec 06 '12 at 15:59
  • 1
    @AndreaSilvestri Sure. You can use a timer, which can advance much faster. – inhan Dec 06 '12 at 16:03
  • I vaguely remember this, but even though that makes complete sense... I believe there was a caveat to that. Can't remember if I had a workaround, but basically I think the issue is that the gotoAndPlay() only updates the clip on enterframe. So if you put it on a timer... it still wasn't ever accurate except when a new frame was entered. If you get what I mean. :) Let me know if that works for you, that's just my recollection. – prototypical Dec 06 '12 at 17:53
  • I made just a quick test with setInterval (every 1ms) and nextFrame() and it seemed to get the right bounds, though for a 10 sec animation it takes something like 3 or more seconds to calculate =\ – Andrea Silvestri Dec 07 '12 at 17:09