Clipping Path Transformations Don't Work in Silverlight?

January 18, 2008
No Comments.

Url: http://wilderminds.blob.core.windows.net/downloads/spotlightproble…

Near the end of the Silverlight Tour class yesterday, one of the students (Rik Robinson of R2Musings.com fame) asked about how a clipping mask could be moved around a page.  He wanted to do something like a spotlight over an image. The problem was mostly exacerbated by the fact that the Ellipse tool in Expression Blend 2 created a PathGeometry (in the form of a Path.Data syntax) like so:

  <Image x:Name="theImage" Width="472" Height="472" 
         Canvas.Top="8" Source="4033636_thumbnail.jpg" 
         Stretch="Fill" Canvas.Left="63.489" 
         Clip="M250.011,177.5 ..."/>

As a background, the Geometry class supports a Transform which should allow us to move it with a TranslateTransform.  The PathGeometry syntax in the Clip is smaller than using a EllipseGeometry so I can understand why Blend does it that way.  I wanted to see this work starting with the XAML so I had Blend translate this to the verbose syntax (by adding it to a WPF app where size isn’t as important as it uses baml for serialization, but that’s another story).  With the new verbose syntax in hand I added the TranslateTransform:

<Image x:Name="theImage" Width="472" Height="472" 
       Canvas.Top="8" Source="Background.jpg" 
       Stretch="Fill" Canvas.Left="19.489">
  <Image.Clip>
    <PathGeometry>
      <PathFigure IsClosed="True" StartPoint="301.011,148.5">
        <BezierSegment Point1="301.011,197.10105798511" 
                       Point2="260.268912234602,236.5" 
                       Point3="210.011,236.5" /> 
                       <!-- Removed: IsSmoothJoin="True"-->
        <BezierSegment Point1="159.753087765398,236.5" 
                       Point2="119.011,197.10105798511" 
                       Point3="119.011,148.5" /> 
                       <!-- Removed: IsSmoothJoin="True"-->
        <BezierSegment Point1="119.011,99.8989420148902" 
                       Point2="159.753087765398,60.5" 
                       Point3="210.011,60.5" /> 
                       <!-- Removed: IsSmoothJoin="True"-->
        <BezierSegment Point1="260.268912234602,60.5" 
                       Point2="301.011,99.8989420148902" 
                       Point3="301.011,148.5" /> 
                       <!-- Removed: IsSmoothJoin="True"-->
      </PathFigure>
      <PathGeometry.Transform>
        <TranslateTransform X="0" Y="0" 
                            x:Name="spotlightMover" />
      </PathGeometry.Transform>
    </PathGeometry>
  </Image.Clip>
</Image>

Note that I had to remvoe the “IsSmoothJoin” from the Segments as that’s not valid Silverlight XAML, but otherwise it was the same.  This should allow us to move the X or Y of the spotlightMover in code right?  Unfortuantely changing the TranslateTransform has no effect.  I tested the code to make sure that the Transform existed and that the X value was changing…nope it was changing, but the Clip wasn’t moving.

Last attempt, I copied all this same code into a WPF app to see if maybe the Transform didn’t work the way I expected…nope it worked perfectly there.  Hrmph!

I finally relented and used an EllipseGeometry in the Clip and tried a TranslateTransform there to see if the problem was related to the PathGeometry…nope same behavior.  To help Rik get an answer, I showed him a solution using the EllipseGeometry’s CenterPoint property to assign new Points to move it around the page.  Not satisfying but workable.

I’ve attached the example of the problem in WPF and Silverlight to show it works in WPF but not in Silverlight.  (Note the example using the CenterPoint isn’t in there but its easy to implement…maybe even Rik will post his example on his blog…hint, hint).