Flex Sliding Drawer Mask and Move Effect
Published on May 2nd, 2010 by DannyT. Filed under FlexI’ve just been trying to create a simple Sliding Drawer effect in Flex 3 and came across a load of weird and wonderful glitches that made something which should take 20 minutes leave me banging my head against the table for a couple of hours.
Here’s the end result:
However, this is the sort of behaviour that was giving me grief:
Nice eh? The components disappear randomly, the mask doesn’t stay still, the label isn’t viewable on the rotated button and it’s generally a bit of a pig.
Here’s the few things I learned to eliminate this glitchy behavior:
- In order to rotate a button, you need to embed the font.
- When you rotate a button the width property actually reports the height of the rotated button (which makes sense but is a bit odd at first), this also confuses any containers the button is in
- A mask needs to have cacheAsBitmap=true
- Sprite seems to be the best class to use for masks but you’ll need to add it to rawChildren when adding it to the displaylist as it isn’t a DisplayObject
Most of this is demonstrated in the source for the above:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#ffffff" layout="vertical" creationComplete="cc()" > <mx:Style> /* need to embed font to allow rotated buttons */ @font-face { src: local("Arial"); fontFamily: ArialEmbedded; fontWeight: normal; } @font-face { src: local("Arial"); fontFamily: ArialEmbedded; fontWeight: bold; } Button { font-family: ArialEmbedded; } </mx:Style> <mx:Script> <![CDATA[ private function cc(): void { // create mask var drawerMask : Sprite = new Sprite(); drawerMask.graphics.beginFill(0xffffff); drawerMask.graphics.drawRect(0, 0, drawer.width + 20, 300); drawerMask.graphics.endFill(); drawerMask.x = tabs.x; // eliminate glitchiness drawerMask.cacheAsBitmap = true; this.rawChildren.addChild(drawerMask); // assign mask this.drawer.mask = drawerMask; } private function slide() : void { if(openBtn.label == "Open") { drawerPusher.width = drawer.width + 20; openBtn.label = "Close"; } else { drawerPusher.width = 0 openBtn.label = "Open"; } } ]]> </mx:Script> <mx:HBox width="100%" horizontalScrollPolicy="off" verticalScrollPolicy="off"> <mx:Spacer id="drawerPusher" width="0" /> <mx:VBox id="drawer" moveEffect="Move" backgroundColor="#cccccc"> <mx:Label text="I'm in a drawer" /> <mx:Button label="Button1" /> <mx:Button label="Button2" /> <mx:Button label="Button3" /> </mx:VBox> <mx:Spacer id="tabSpacer" width="8" /> <mx:HBox id="tabs" rotation="90" moveEffect="Move"> <mx:Button id="openBtn" label="Open" click="slide()" /> </mx:HBox> </mx:HBox> </mx:Application>
Hopefully this can save someone else the headaches I had.
Props to @andytrice for the cacheAsBitmap tip in his insideria article on masking.

Bill
May 2nd, 2010 at 5:54 pm
I did something similar with a masked sliding drawer here: http://www.billdwhite.com/wordpress/?p=44
It uses degrafa, but the concept is the same. Hope that helps.