Flex Sliding Drawer Mask and Move Effect

By admin on 02/05/2010

I'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:

[SWF]/wp-content/uploads/StylingTest1.swf, 335, 180[/SWF]

However, this is the sort of behaviour that was giving me grief:

[SWF]/wp-content/uploads/StylingTestGlitchy.swf, 335, 180[/SWF]

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:

  1. In order to rotate a button, you need to embed the font.
  2. 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
  3. A mask needs to have cacheAsBitmap=true
  4. 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:


    

    	backgroundColor="#ffffff"

layout="vertical"

creationComplete="cc()"

>


/* 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;

}



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";

}

}

]]>


Hopefully this can save someone else the headaches I had.

Props to @andytrice for the cacheAsBitmap tip in his insideria article on masking.