Home >
One thing that has always fascinated me with Flex/Flash is the power of native graphics APIs built into the Flash player. This is one feature where I have not seen an equal in any other RIA technology, based on ease of use and capability. These graphics APIs allow you to do everything from drawing a line from point A to point B, manipulate images, draw shapes, change image properties, etc... They enable a majority of the functionality in the Flex that makes it both extremely powerful, and unique. These graphics APIs enable dynamic charting, skinning, programmatic drawing, among countless other features, but for now I want to focus on one technique that seems strangely under-used in Flex: Graphics Masks.
Masks can be used for a variety of purposes. As an example, you can take a standard bar chart, and make it look something like this...
Most developers who have made the transition from Flash into Flex already know what I am talking about. Most developers that I have seen transition from the Java world into Flex do not.
Essentially, a mask is a "hole" (or shape) where the graphics of the masked object are visible. Any DisplayObject can be used as a mask on another display Object. The actual graphics of the masked object will only be displayed in the non-transparent part of the graphics mask.
Masks can be used to achieve some very dynamic interfaces and powerful graphics and visualizations. Some examples of which you will find later on in this post.
A mask can be hard to explain, so let's take a look at an example... If we start with this source image:
... apply this mask:
... this is what the result will look like:
As I mentioned before, any DisplayObject can be a mask of any other DisplayObject. This includes default Flex components, images, or custom drawing with the drawing API.
Now, lets look at how you do this...
My first example is using a mx:Canvas to create a mask over an image. You can see that the visible area of the canvas is the area of the image that is actually visible within the application, which includes the rounded corners of the image.
<mx:Image source="assets/chicago.jpg" x="518" y="10" mask="{maskCanvas}">
<mx:filters>
<filters:DropShadowFilter />
</mx:filters>
</mx:Image>
<mx:Canvas x="596" y="61" width="344" height="274" backgroundColor="#ff0000" id="maskCanvas" cornerRadius="15" borderStyle="solid"/>
Notice that the only thing you have to do to mask one object with another is to set the "mask" property.
This is a very simple example, but keep in mind masks can get much more complicated. When a mask object moves on the screen, so does the visible portion of the mask image. When using Image masks, you can actually use the transparency of images (png and gif) to determine the area that mask will show. Notice that the code is actually very simple:
<mx:Image source="assets/chicago.jpg" x="518" y="10" mask="{ maskImage }">
<mx:filters>
<filters:DropShadowFilter />
</mx:filters>
</mx:Image>
<mx:Image source="assets/imageMask.png" x="518" y="10" id="maskImage" cacheAsBitmap="true" /^gt;
There is one distinct, and very important difference in this case. You must set the value of the cacheAsBitmap parameter on the mask object to "true" for this to work properly.
Things get even more interesting when you start using png images that support semi-transparency as masks on your images. The code to do so is almost identical to that above, however you need to make sure that you set cacheAsBitmap='true' on both the mask and the object that is being masked. A simple semi-transparent gradient mask looks something like this.
when applied to an image, it will yield a result like this:
You can also use any DisplayObject as a mask on another object. So far, I have mostly focused on using images to mask other images, but what happens if you use an actionscript-rendered objects to mask an object? ... You get interesting results.
Here's an example showing a mask that changes over time. First, take a look at the screenshot:
Here's how it is applied; Notice that cacheAsBitmap must be set to true for both teh mask, and the masked object.
<mx:Image source="assets/chicago.jpg" x="518" y="10" mask="{ maskImage }" cacheAsBitmap="true">
<mx:filters>
<filters:DropShadowFilter />
</mx:filters>
</mx:Image>
<components:AnimatedMask id="maskImage" x="518" y="10" width="500" height="375" cacheAsBitmap="true" />
And here is the source of the mask object itself:
public class AnimatedMask extends Container
{
private var count : Number = 0;
public function AnimatedMask()
{
super();
this.addEventListener( Event.ENTER_FRAME, onEnterFrame )
}
private function onEnterFrame( event : Event ) : void
{
if ( this.visible )
{
count++;
var g:Graphics = this.graphics;
if ( count % 250 == 0 ) g.clear();
g.lineStyle( 3, 0, .5 );
g.moveTo( Math.random() * width, Math.random() * height )
g.lineTo( Math.random() * width, Math.random() * height )
}
}
}
The mask actually changes with every enterFrame event. This is a pretty basic example, but these concepts can go a long way. Now, lets look at some real-world scenarios how these techniques can be applied in your applications.
My first example is for creating dynamically color-coded complex objects. This could apply to almost anything, but for now, lets focus on a gear. Let's say that you have a gear in your application that represents part of a workflow process. You want that gear to change color based on data coming into you application. You can easily achieve this kind of effect without having to programmaticly draw every part of that shape. You can just use a mask that is the shape of a gear, and apply it to a Canvas object that has the background color changed at runtime. The results can be very dramatic. Here's an example:
And the code to achieve this is very simple as well:
<mx:Canvas x="10" y="10" width="200" height="200" id="colorCanvas" backgroundColor="#ff0000" mask="{ maskImage }" cacheAsBitmap="true">
<mx:filters>
<filters:DropShadowFilter />
</mx:filters>
</mx:Canvas>
<mx:Image source="assets/gearMask.png" x="10" y="10" id="maskImage" cacheAsBitmap="true" />
To change the color of the rendered gear image, all you need to do is change the color of the canvas that is being masked. This can be done very simply by changing the backgroundColor style property:
colorCanvas.setStyle( "backgroundColor", Math.random() * 0xFFFFFF );
As I said before, any DisplayObject can be used as a mask on any other DisplayObject. Here are a few examples showing you Flex charts that are applied as masks on images. you can create some really wild interfaces with these techniques.
You can view all of these examples in action at:
http://www.cynergysystems.com/blogs/blogs/andrew.trice/masks/masks.html
All of the source for this application is publicly available at:
http://www.cynergysystems.com/blogs/blogs/andrew.trice/masks/srcview/index.html
You can also check out a cool example using video on my Cynergy blog at:
http://www.cynergysystems.com/blogs/page/andrewtrice?entry=fun_with_masks















Facebook Application Development
Andrew,
Excellent post! Thanks for the great tips and examples. It really does show how easy it is to make things look like you put a lot of time and design into them.
Cheers,
ewH
Very interesting post! (Coming from someone which never -really- programmed in any flash'esque tool).
Great post! Thanks for sharing with us..great codes and examples
Thanks... will defenetly give it a try.
Great tutorial. Your examples helped me make some animated masks from flash swfs.
That is really nice example.... so could you plz help in finding out???? how to find whether mask is used in project or not!!!! is there is any way to get mask layer name and its object present in that time line
Wow! You really opened my eyes to a wonderful use of just about every DisplayObject I can think of. What's ironic is that I used to use all of these tricks when I first started using Flash but they faded into my subconscious in the years of coding.
Great tutorial. I was getiing frustrated as the mask function seemed very straightforward but if you forget to assign the masking object a color then nothing happens.
Maybe you can help me out with something that might be useful to other people aswell.
Say you have an image 100x300 and you apply a blur to it and then mask the left 100x100 part of the image. What happens (I think) is that the image is masked to the 100x100 rect first and then a blur is applied because I get the overflowing of the blur effect over the edges. I want the mask to really clip to the 100x100 area.
How?
Kind regards,
Alexandro
Is possible to use an AS3 Graphic (a circle, or square) drawed by AS3 code, and set as mask over image?
I pretend to make this effect similar:
http://www.flashframing.com/?prod=486
Select any photo to edit it. Select a circle and see the hole printed over shape and image.
How I do this effect using mask and dynamic graphics (my "hole" maybe can be circle, square, star) ????
(Obs: I use Flex3)
Thanks.
great examples...thanks for sharing
Thanks so much.
Thanks for these great examples.
I have a strange issue with Animated Mask. In my case it only works with solid shapes created inside a begin/endFill block. If I use lineStyle and simple lines or circles only as in your example, then the mask doesn't get applied.
Are there any hints for masking with simple lines other than setting cacheAsBitmap = true?
Thanks for these great examples.
I have a strange issue with Animated Mask. In my case it only works with solid shapes created inside a begin/endFill block. If I use lineStyle and simple lines or circles only as in your example, then the mask doesn't get applied.
Are there any hints for masking with simple lines other than setting cacheAsBitmap = true?
Found the solution to my problem above: The image on which the mask is to be applied needs to reside in a (Flash) Sprite. I had it in a Canvas, in which case masking strokes and alphas are ignored.
Stefan
PS: Sorry for the double post above
I read this when you first wrote it and I was just starting Flex. Recently I wrote a component to generate a BitmapAsset from any DisplayObject. When it was finally hammered out and I wanted to use it as a mask it didn't work :/ You're note about cacheAsBitmap was a gem ... I looked over my problem for hours and don't think I would have figured that out and lost the usefulness of something I spent a couple days writing.
Thx!!!!!
Excellent Tutorial
Thank you for your tutorial, but I am having troubles with compiling your source. Do i have to add any libraries ? Forgive me I am just one day old when it comes to flex.
Do you know why masking using an image works only when applying a filter to the masked image?
Is there a way for it to work without applying a filter?
Thanks a lot
Please any body tell how can i apply mask to only text border not to the entire text .
I have a requirement that,
Ex:
MASK TEXT is the text, here i have to apply a pattern like
stitching around the text border not for the text.
Please if any knows about this send me some sample.
thanks
naresh