Charles Petzold

A Circular Gradient Brush for Silverlight

June 5, 2010
Roscoe, N.Y.

Yesterday I received an email asking if I knew how to create a circular gradient brush in Silverlight. Such a brush begins with one color and circles around to another color. It might possibly be animated like so:

Get Microsoft Silverlight

Unless I missed some recent enhancements to Silverlight, you really can't do this by deriving from Brush (even in WPF). Instead, you need to create an element or control colored the way you want. I immediately thought of my blog entry Graphical Paths with Gradient Colors, but that's WPF and a similar technique would be rather messier in Silverlight.

I also considered a custom shader or WriteableBitmap but both would require specifying the gradient on a pixel-by-pixel basis.

Late last night it occurred to me that I could fake it — and by "fake it" I mean create something visually persuasive that might not be mathematically correct — using just four Rectangle elements colored with Silverlight's normal LinearGradientBrush coupled with projection transforms, and clipping. I was thnking about it as I drifted off to sleep last night and I confess I may have dreamed about it. (The programmer's occupational hazard.)

It turned out to be quite simple. Let's begin with a 2×2 Grid. Put a Rectangle in the top and another in the bottom both spanning two columns:

Put two more Rectangle elements in the left and right spanning two rows:

All four Rectangle elements are filled with a LinearGradientBrush with the same two colors but different Offset values, StartPoint, and EndPoint.

Now apply taper transforms to all four Rectangle elements so they meet in the center. Confronting the mathematics of taper transforms might seem daunting but fortunately I've done a lot of preliminary work in my blog entry Taper Transforms with Matrix3DProjection: An Analytical Approach and provided an easy-to-use class. Here are the taper transforms applied:

Now I'm sure you see where this is going. All that's left is to define a Clip path based on a pair of EllipseGeometry objects:

The class CircularGradientBrushControl derives from UserControl and defines Color1, Color2, Thickness, and Angle properties. Here's the source code