AS3 scrollRect vs height & getBounds()

 Oct, 22 - 2008   14 comments   Uncategorized

The new scrollRect property in AS3 DisplayObjects is pretty cool. If you haven’t run into it yet, it’s a fairly simple way to set a rectangular window on a larger piece of content without the hassle of drawing a rectangle and using a mask and inverse positioning the content… For the most common masking operations it comes in really handy.

And then reality sets in. You want to check the height of your content so you can set up boundary conditions for the scrolling behavior. But! When you get the height property, it’s been modified to reflect the fact that the content is now masked. You don’t get the “native” height anymore. What’s even worse, this update to the property doesn’t take effect until the next frame (following a change to scrollRect — and you’ll need another frame if you’re doing this the first frame the asset is on the stage — YMMV), so you’ve got to add (and remove) a temporary enterframe event listener … it’s a total mess. Thinking about using getBounds instead? Save yourself the trip. It works (as in “doesn’t work”) the same way.

Now suppose you suck it up and decide to deal with waiting a frame after your content fires onResize. You can handle a little add/remove listener juggling. No biggie. Alas, you’ve got no way to get access to your original height once a scrollRect has been set. You could temporarily remove the scrollRect, but that change won’t take effect until the next frame. Gah!

So, I went digging through the docs to find an alternative. The only thing that looked even remotely promising was the transform property. I went through my code and replaced references to content.height with content.transform.pixelBounds.height and I was in business. As far as I can tell, this property responds appropriately to scale, rotation, etc while omitting any scaleRect clipping. However, if you were to grab content.parent.transform.pixelBounds.height, it would take the clipping into account.

Hopes this helps someone else out there…

— UPDATE —

You know what’s awesome? If the DisplayObject isn’t on the stage, pixelBounds values are the “native” x, y, width, and height you’d expect looking at the Flash IDE property inspector. Times 5. Don’t look at me like that. Try it. You’ll get values five times bigger than you ought to. Maybe it’s something to do with twips

The whole idea of this exercise was to find a way to grab the height of a DisplayObject without a bunch of if/else hassle. But if you’ve got to sniff for a stage object, you might as well sniff for the scrollRect object itself — and the value you read won’t be subject to the frame delay. That’s only a problem when reading it via the height property. Hope that clears up any confusion.


Related articles

 Comments 14 comments

  • Odem says:

    Thank you very much! It’s very helpfull to me!

    ReplyReply
  • Geoffrey Hom says:

    Wow, that helped me, too. Thank you!

    ReplyReply
  • Kramer auto Pingback[…] Karoshi Ethos " AS3 scrollRect vs height & getBounds() SAVE Just figured this out for myself too – scrollRect has a one-frame delay before you can read back its effect on widht/height or getBounds. tomc […]

  • Thanks!
    I spent 3 months trying to figure out why content.height would output the correct values… content.transform.pixelBounds.height is the solution!!

    ReplyReply
  • Joe Wheeler says:

    Sorry, I’ve found a bug. The pixelBounds value changes if the parent, or any of the display containers surrounding the clipped DisplayObject are transformed in any way what so ever. So, if you scale the parent clip to 10% your pixelBounds will be 10% of the correct value. Probably the easiest work-around is to temporarily remove the DisplayObject from the display list and divide the pixelBounds values by five. What a palava.

    ReplyReply
  • […] Jon Williams posted an interesting idea, using transform.pixelBounds. Which actually gets most of the way to a solution, but it all goes horribly wrong when the any of the parent objects are scaled and/or rotated. It also finds weird values when the object is off the display list (always x5 the actual value). […]

  • Hardik Dubal says:

    Thank you… content.transform.pixelBounds.height worked for me while trying to make a scroll bar.

    ReplyReply
  • Joe Wheeler says:

    Here’s a fix: accurately get the width and height of scrollRect content. It takes a bit of mucking about with matrixes, but I works consistently, whether  or not the DisplayObject is on the display list; doesn’t require adding/removing from the display list and is unaffected by parent transforms.

    Hope this helps someone.
    J

    ReplyReply
  • […] You may remember my article on scrollRect and getBounds(). […]

  • azurDePuch says:

    nice try, but it didn’t work for me

    take a look at this

    http://www.moock.org/blog/archives/000292.html

    ReplyReply
  • Aaron Beall says:

    Moock’s example is to draw to an arbitrarily large bitmapdata and use getColorBoundsRect. There are a number of problems with that approach (as well as all other examples I could find), but it led me to discover the one workaround that seems to account for everything:
    BitmapData.draw() forces an object to be redrawn immediately. It works around all the wonky deferring of changing scrollRect, and it works with parent trees, getBounds, and all other scenarios I could find.
    It’s kind of frustrating there isn’t a built in solution, if BitmapData.draw can tell what needs to be redrawn and redraw it immediately, why isn’t there a way for us? Anyway, in the end my redraw method is simply:
    package {
    import flash.display.DisplayObject;
    import flash.display.BitmapData;

    public function redrawNow(displayObject:DisplayObject):void {
    var bitmapData:BitmapData = new BitmapData(1, 1);
    bitmapData.draw(displayObject);
    bitmapData.dispose();
    }
    }
    So now for instance I can:
    var oldRect:Rectangle = obj.scrollRect;
    obj.scrollRect = null;
    redrawNow(obj);
    var bounds:Rectangle = obj.getBounds(this);
    obj.scrollRect = oldRect;
    redrawNow(obj);

    ReplyReply
  • […] http://karoshiethos.com/2008/10/22/as3-scrollrect-vs-height-getbounds/ Advertisement GA_googleAddAttr("AdOpt", "1"); GA_googleAddAttr("Origin", "other"); GA_googleAddAttr("theme_bg", "ffffff"); GA_googleAddAttr("theme_border", "dddddd"); GA_googleAddAttr("theme_text", "444444"); GA_googleAddAttr("theme_link", "ac6c13"); GA_googleAddAttr("theme_url", "6ab32e"); GA_googleAddAttr("LangId", "1"); GA_googleAddAttr("Autotag", "books"); GA_googleAddAttr("Autotag", "entertainment"); GA_googleAddAttr("Autotag", "technology"); GA_googleFillSlot("wpcom_below_post"); Like this:LikeBe the first to like this post. […]

  • almo says:

    One way to fix the problem with the “scrollRect one-frame delay before you can read width/height” is to use scrollRect.width or scrollRect.height instead of width/height. Those values are available right away.

    ReplyReply
  • Colorao says:

    THANKS !!!
    Really save my project !!!

    ReplyReply

  • Leave a Reply

    Your email address will not be published. Fields with * are mandatory.