Contact Me


Recent Posts


Categories


Archives


Tags

3d actionscript Actionscript 2 Actionscript 3 api APIs as2 as3 brand caching carousel channel code compress contest contract CSS Flash flv fp10 free freelance gadget gadgets gdata google JavaScript jquery mvc papervision papervision3d PHP player playlist puremvc pv3d search tube tutorial twitter video widget XML you youtube

Recent Comments

  • Ahmed: Well not designed, I merely consulted, gave my ideas, helped them with ux and code and deployment too!...
  • Zain Hasan: Oh wow, I am crazy about Olympism and today I came too knw that “best of us” is designed by...
  • Ahmed: Anything I can do to help, I need to update this plugin, need to implement oembed too
  • Phil: Currently not in use on the live site (given) but will be soon as it all works in development while renovating...
  • Ahmed: Yeah, I’ll come to writing stuff up one day! Sorry for the lack of docs, it takes time and I know I...

Links


Help end world hunger

Scale Any DisplayObject with My ‘ScaleObject’ Class

Update (another): I’m no longer updating the code on here, instead it’s all on my Github account.

Update: there was a slight issue with the “height()” overrride, thanks to the comments I’ve updated the code with the fix.

Most designers and developers will be familiar with Actionscript 3’s “scale9Grid“. Now when you can use “scale9Grid”, it’s awesome, but there are times when you can’t use it or it doesn’t work:

  • You can’t use it on Bitmaps or non-vector objects
  • If the object has children, they won’t have the grid enforced on them
  • And more…


Here’s a nice run down of when it works and when it doesn’t work: http://www.ovidiudiac.ro/blog/2009/05/scale9grid-work-and-fail/

So what do you do if your object has children or is a bitmap? Simple, use my class that I painstakingly wrote this morning!

I’m currently working on a project where I’ve created some assets in the Flash IDE, exported them as classes via a SWC and am using them in the Actionscript 3 code. One of the assets contains multiple children, rather than a straight vector object, meaning that it can’t have a “scale9Grid” thrust upon it.

So I got thinking about it and decided the best way was to do this:

  1. Convert the object to bitmap data
  2. Slice the object up into a 9 piece grid
  3. Align those grid pieces accordingly
  4. Override the “height” and “width” functions that would expand the centre grid items leaving the outside ones to scale

Simples! So I got on creating the class. One of the biggest problems was getting over the way Actionscript 3’s BitmapData “draw()” function misleads you. You see it says that you can pass a “clipRect” parameter as a “Rectangle()” which leads one to the assumption that it will clip the bitmap data according the rectangle you pass. Wrong, how very wrong. What it does, instead, is leave empty space where it’s been clipped. Not fun.

After much Googling, I came across this post: http://pixelwelders.com/blog/actionscript-3/2008/as3-bitmapdata-foibles/ which explained a little hack around this failed method. I’ve taken his code and just re-factored it so it fits within my code base, here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.firestartermedia.lib.as3.utils
{
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    public class BitmapUtil
    {
        public static function grab(source:DisplayObject, rect:Rectangle, smoothing:Boolean=true):BitmapData
        {
            var draw:BitmapData = new BitmapData( source.width, source.height, true, 0 );
            var copy:BitmapData = new BitmapData( rect.width, rect.height, true, 0 );
           
            draw.draw( source, null, null, null, null, smoothing );
            copy.copyPixels( draw, rect, new Point( 0, 0 ) );
           
            draw.dispose();
           
            return copy;
        }
    }
}

So by using this static function in the class, I can create a proper grid of any display object, and here’s the class that does it all:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.firestartermedia.lib.as3.display.tools
{
    import com.firestartermedia.lib.as3.utils.BitmapUtil;
   
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.geom.Rectangle;

    public class ScaleObject extends Sprite
    {
        private var bitmapTL:Sprite;
        private var bitmapTC:Sprite;
        private var bitmapTR:Sprite;
        private var bitmapML:Sprite;
        private var bitmapMC:Sprite;
        private var bitmapMR:Sprite;
        private var bitmapBL:Sprite;
        private var bitmapBC:Sprite;
        private var bitmapBR:Sprite;
        private var master:DisplayObject;
        private var scaleGrid:Rectangle;
       
        public function ScaleObject(master:DisplayObject, scaleGrid:Rectangle)
        {
            this.master = master;
            this.scaleGrid = scaleGrid;
           
            init();
        }
       
        private function init():void
        {
            var tlX:Number = 0;
            var tlY:Number = 0;
            var tlWidth:Number = scaleGrid.x;
            var tlHeight:Number = scaleGrid.y;
            var tcX:Number = tlWidth;
            var tcY:Number = tlY;
            var tcWidth:Number = scaleGrid.width;
            var tcHeight:Number = tlHeight;
            var trX:Number = tlWidth + tcWidth;
            var trY:Number = tlY;
            var trWidth:Number = master.width - trX;
            var trHeight:Number = tlHeight;
           
            var mlX:Number = 0;
            var mlY:Number = tlHeight;
            var mlWidth:Number = tlWidth;
            var mlHeight:Number = scaleGrid.height;
            var mcX:Number = tlWidth;
            var mcY:Number = mlY;
            var mcWidth:Number = tcWidth;
            var mcHeight:Number = mlHeight;
            var mrX:Number = trX;
            var mrY:Number = mlY;
            var mrWidth:Number = trWidth;
            var mrHeight:Number = mlHeight;
           
            var blX:Number = 0;
            var blY:Number = tlHeight + mlHeight;
            var blWidth:Number = tlWidth;
            var blHeight:Number = master.height - blY;
            var bcX:Number = tlWidth;
            var bcY:Number = blY;
            var bcWidth:Number = tcWidth;
            var bcHeight:Number = blHeight;
            var brX:Number = trX;
            var brY:Number = blY;
            var brWidth:Number = trWidth;
            var brHeight:Number = blHeight;
           
            bitmapTL = slice( tlX, tlY, tlWidth, tlHeight );
            bitmapTC = slice( tcX, tcY, tcWidth, tcHeight );
            bitmapTR = slice( trX, trY, trWidth, trHeight );
            bitmapML = slice( mlX, mlY, mlWidth, mlHeight );
            bitmapMC = slice( mcX, mcY, mcWidth, mcHeight );
            bitmapMR = slice( mrX, mrY, mrWidth, mrHeight );
            bitmapBL = slice( blX, blY, blWidth, blHeight );
            bitmapBC = slice( bcX, bcY, bcWidth, bcHeight );
            bitmapBR = slice( brX, brY, brWidth, brHeight );
        }
       
        private function slice(x:Number, y:Number, width:Number, height:Number):Sprite
        {
            var rect:Rectangle = new Rectangle( x, y, width, height );
            var sliceData:BitmapData = BitmapUtil.grab( master, rect );
            var slice:Sprite;
           
            slice = new Sprite();
           
            slice.graphics.beginBitmapFill( sliceData );
            slice.graphics.drawRect( 0, 0, width, height );
            slice.graphics.endFill();
            slice.x = x;
            slice.y = y;
           
            addChild( slice );
           
            return slice;
        }
       
        override public function set width(value:Number):void
        {
            var targetWidth:Number = value - bitmapTL.width - bitmapTR.width;
            var targetX:Number = value - bitmapTL.width;
           
            bitmapTC.width = targetWidth;
            bitmapMC.width = targetWidth;
            bitmapBC.width = targetWidth;
           
            bitmapTR.x = targetX;
            bitmapMR.x = targetX;
            bitmapBR.x = targetX;
        }
       
        override public function set height(value:Number):void
        {
            var targetHeight:Number = value - bitmapTL.height - bitmapBL.height;
            var targetY:Number = value - bitmapBL.height;
           
            bitmapML.height = targetHeight;
            bitmapMC.height = targetHeight;
            bitmapMR.height = targetHeight;
           
            bitmapBL.y = targetY;
            bitmapBC.y = targetY;
            bitmapBR.y = targetY;
        }
    }
}

The basic usage is like so:

1
2
3
var sprite:Sprite = new ScaleObject( displayObject, new Rectangle( 5, 2, 78, 6 ) );

sprite.width = 300;

And here’s a little example:


11 Responses to “Scale Any DisplayObject with My ‘ScaleObject’ Class”

Leave a Reply

Your comment:

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Fork me on GitHub