Charles Petzold



Displaying Text at Angles

November 12, 2009
New York, N.Y.

I'm not sure if this TV trend is for real, or whether I'm just noticing it more, but I think there's been an increase in the past year or so of text displayed with perspective effects — not necessarily 3D text had has depth and body, but regular flat 2D text that appears to occupy a 3D space. One example is the titles on Fringe that seem to be attached to the sides of buildings, but I've also seen text in TV commercials where the words seem to meet at angles.

That's the effect I was after in this Silverlight 3 program, but of course I wanted to animate it as well:


TextAtAngles.html

Here's the source code. Making the text seem to taper off into the distance requires a non-affine transform, and for that I used the Matrix3DProjection class. (Because the transforms I used are fairly simple, I suspect that PlaneProjection could have been used instead, but I find that "easy" class more complex than the first-principles approach of the other.) The Matrix3DProjection class has a property of type Matrix3D that allows non-affine transforms.

I have found it convenient to use a little algorithm I developed that derives a Matrix3D object based on a Rect structure describing the location and size of a graphical object, and four Point objects that indicate the locations to which you want each of the four corners of that rectangle transformed. I originally discussed the mathematics in connection with WPF in the blog entry Non-Affine Transforms in 2D? and then showed how it could be used in Silverlight in Using the Matrix3DProjection Class in Silverlight 3 and other blog entries, and described a different approach to deriving the transforms in Taper Transforms with Matrix3DProjection: An Analytical Approach

For this program, I wanted a little animation, and I wanted to use the Silverlight animation classes to do it. Silverlight doesn't have a Matrix3DAnimation class so I created a class that derives from ContentControl named PerspectiveControl that defines a dependency property named BaseRectangle and four more dependency properties of type Point named UpperLeft, UpperRight, BottomLeft, and BottomRight. The class itself derives a Matrix3D based on this information, and then uses it to set its own Projection property. Because Silverlight does have a PointAnimation, these four properties can be the targets of animations.

The three pieces of text are defined in the MainPage.xaml file like so:

<src:PerspectiveControl Name="txt1">
    <TextBlock Text="Silverlight " />
</src:PerspectiveControl>

<src:PerspectiveControl Name="txt2">
    <TextBlock Text="does" />
</src:PerspectiveControl>

<src:PerspectiveControl Name="txt3">
    <TextBlock Text=" perspective" />
</src:PerspectiveControl>

Without any transforms, these three pieces of text are aligned at the upper-left corner of their container, one on top of the other. The MainPage.xaml.cs file determines the actual dimensions of each of these objects and uses that to set the BaseRectangle property of the PerspectiveControl. This information also allows deriving Point objects for each of the four corners of each of the text strings to display the text stacked horizontally, one after the other. These points are stored in an array named ptBase. Then it's just a matter of determining where the corners should go for different perspective effects, and setting up the animations.