Exploring the Microsoft Client Continuum

Masking & Clipping

Masking in Flash is one of those power features that lets you create effects that otherwise wouldn't be possible. When you combine a mask with dynamic MovieClips, the results can be really interesting.

Here is a Flash effect* produced with some clever masking:

To create this effect, we created an empty MovieClip named dots and placed it on the bottom layer of our main stage. Next, we added some text on the layer above it and converted this text layer to a mask layer to affect the dots beneath it. We then created and exported for ActionScript another movieClip named dot that has our shape animations growing and tinting the ellipse shape over its timeline like so:

Since each dot will play as soon as it is created, we need to stretch out the time it takes to add each diagonal strip of dots by using an onEnterFrame() loop on our main stage. The code looks something like this:

The positioning algorithm in the addDots() function is actually a nested loop if we think of the onEnterFrame() and xIndex incrementor as our outer loop. This onEnterFrame handler will fire sequentially 47 times, each time looping through its inner yIndex loop. The yIndex loop calculates a diagonal line of up to 7 dots and adds them to our masked dots movieClip if their location falls within the proper boundaries (Line 20). We also added an onMouseDown() handler to let the user repeat the animation (Line 5 through Line 12).

Part 1 - Using Clips in Silverlight

The direct relation to this type of layer Mask in Silverlight would be a Clipping region. So let's create a new Silverlight project and rebuild this effect in Blend using Paths and Clips. Afterward, we will look at another powerful masking technique Silverlight provides, OpacityMasks.

To recreate the above effect using Clipping, create a new Silverlight project and web hosting solution and modify Page.xaml as we've been doing every lesson ( Set the dimensions, add a Loaded event handler, and change LayoutRoot to a Canvas).

Inside LayoutRoot, you want to add empty Canvas tag named dots.

It is much easier to add the Clipping path in Blend, so right click on Page.xaml and select Open in Expression Blend...

You could import a text design from Illustrator and convert it to a XAML path, but we will use the default TextBlock in Blend to type in our message and then convert the text to a Clipping Path like so:

Notice that I also selected my dots canvas so that the Clipping Path would know which element to act upon.

Saving Page.xaml in Blend and reopening in Visual Studio gives us a very long Clip definition inside our dots Canvas that starts off something like this:

We will add the Loaded event handler in the code behind file once we recreate the dot movieClip we used in our Flash example with our own Silverlight User Control named dot.xaml.

Once you have created dot.xaml as a new User Control in your Silverlight project and do the usual tweaks (remove background, width and height values while converting LayoutRoot to a Canvas), add an Ellipse object inside LayoutRoot that looks like this:

Animating the size and color of the ellipse using a Storyboard is much easier in Blend, so go there and duplicate the shape animations we created in our Flash project:

I'm starting ellipse at a very small render scale and over the next 7 seconds, I'm growing it to a larger scale and tweening its Fill colors. If we look at dot.xaml to see the script for all these animations, it would look something like this:

The code behind file dot.xaml.cs has our X and Y public properties for easier positioning, a variable called milliseconds that we'll use to customize how long each dot should wait before firing the grow Storyboard we created above, and the fire() function that will set the BeginTime for grow before starting it. The finished dot.xaml.cs looks like this:

Since the Storyboard in dot.xaml gives us a way to programmatically delay the BeginTime, the initialization and positioning logic we need to add in Page.xaml is a bit more straightforward. The finished Page.xaml code behind file looks like this:

The MouseLeftButtonDown event handler allows the user to repeat the animation by clicking on the stage. All the real work is being handled by the addDot() function that starts on Line 29. The positioning logic is the same as we coded in Flash, only now the nested for loops are more obvious. We programmatically set the milliseconds parameter to delay the grow Storyboard in each progressive diagonal row of thumbs in Line 42 and call the fire() method (Line 44) once that is set and the thumb object has been added to our screen.

Here is the Silverlight result:

Part 2 - Silverlight Opacity Masks

Besides clipping paths on elements, Silverlight has another powerful type of masking called OpacityMasks that can be applied to various visual elements. Some of these more advanced features do not have a direct Flash correlation.

OpacityMasks can be defined not only with solid Shapes of color, but also transparency Gradients that control the degree of Opacity; a very nice addition to masking. But personally, my favorite feature of OpacityMasks is the ability to use an 24bit PNG image as the OpacityMask and be able to control the degree of opacity at the pixel level. Let's examine another Silverlight project that gives us an example of how this works.

Before starting the project, I manipulated a photo in Photoshop to create a stylized Black & White headshot against a transparent background. I then created a second version of the headshot but only with those regions I wanted to also overlay with a color gradient. My two finished .PNG files look like this:

I then created a new Silverlight Project and Hosting solution for these two images. bwBase.png will serve as the background image and colorMask.png will be applied to a Canvas with a gradient fill. After the usual tweaks and the addition of these elements, Page.xaml looks like this:

Running the project right now will let us see what the OpacityMask is actually doing to the gradient background of the colorBase (Line 10) canvas it is affecting:

However, the subtlety of this stacked approach is best highlighted if we also add some dynamic elements to colorBase while also shifting the Scale of the gradient while the mouse moves.

So as we did in Lesson 02, I will create a User Control that I can draw with a MouseMove event that plays out its Storyboard and removes itself. I'll call this User Control glow.xaml and it looks like this:

It was obviously easier to draw the Ellipse and create the grow Storyboard in Expression Blend, so that's what I did. Notice we have also done the usual changes we make to the User Control and LayoutRoot as well.

The code behind file glow.xaml.cs should also look familiar by now:

We define X and Y to make positioning easier, fire the grow Storyboard as soon as the User Control is Loaded, and then remove the User Control once grow is Completed.

The positioning logic we add to Page.xaml.cs to draw the glow objects on MouseMove should also look familiar by now:

And here is the finished Silverlight result:

Creative masking in Silverlight can be combined with programmatic visuals and XAML Storyboards to create some very engaging experiences. In this lesson, we only scratched the surface of what Silverlight Clipping and OpacityMasks can do. But the power and adaptability of these techniques definitely deserve further attention.

In our next lesson, we will continue our exploration of Silverlight by looking at Scale and Rotation techniques.

Additional Resources

*I first saw this effect in the book New Masters of Flash in the chapter by Jayson Singe for Neon Sky. His technique required placing MovieClips by hand along several dozen keyframes to create the effect. After some tinkering, I figured doing it all in a positioning algorithm would make things easier. I've used variations of this algorithm with students ever since.

Have a question or comment on this article? Have a suggestion for new content?
Send your feedback.
Microsoft Communities