Last week one day, a very nice WPF/E reflected image started popping up all over the web.

Today, Michael Schwarz took that reflection on as a project and posted this animation. He discusses it and has the code on his blog.

I stared at that for quite a while trying to figure out why I didn't think of doing that when I realized it would sure be cool if the gear would roll across te screen.
The truth is that didn't take all that long to do. What took the time was I also wanted it to roll back the other way, and I had no prior experience with synchronizing the two pieces of animation.

The counter clockwise gear rotation was simply reversing the sense on the RotateTransforms that Michael had already done. I tested this by modifying the existing xaml.

I wrapped the existing forward rotating gear and reflection in a canvas and gave it the name "MichaelsAnimation". I then duplicated that section, reversed the RotateTransform, and changed all names to be an obvious reversal of the initial names used such as "MichaelsAnimationReverse".

While trying to synchronize the two pieces, I found could start them off the canvas, and drive them off the canvas on the other side and it was very smooth, and no jerking at the edges, but that didn't take any real effort on my part, so what I really wanted was to have them start and end just at the canvas edge. This gives a discontinuity at the edges that I'll attribute to 'bouncing' off the wall... at least that's my story.

The real magic for this is to use another canvas with a Storyboard that ran each of the other two animations. I need the rotating image in each direction of course, to give the impression of rolling, but I also need to wrap them in an outer animation that moves them across the canvas.

<Canvas.Triggers>
  <EventTrigger >
    <EventTrigger.Actions>
      <BeginStoryboard>
        <Storyboard x:Name="Fwd" 
          BeginTime="1" 
          Completed="javascript:forward_completed" >
          <DoubleAnimation 
            Storyboard.TargetProperty="(Canvas.Left)" 
            Storyboard.TargetName="MichaelsAnimation" 
            From="0" 
            To="600" 
            Duration="0:0:5" />
        </Storyboard>
      </BeginStoryboard>
      <BeginStoryboard>         <Storyboard x:Name="Rev"           BeginTime="1"           Completed="javascript:reverse_completed" >           <DoubleAnimation             Storyboard.TargetProperty="(Canvas.Left)"             Storyboard.TargetName="MichaelsAnimationReverse"             From="600"             To="0"             Duration="0:0:5" />         </Storyboard>       </BeginStoryboard>     </EventTrigger.Actions>   </EventTrigger> </Canvas.Triggers>


The outer canvas has a loaded= line that launches a javascript that sets the opacity on the reverse animation to 0, and starts the "Fwd" Storyboard.

The "Fwd" Storyboard has a Completed line that launches a javascript that sets the opacity on the forward animation to 0, the opacity on the reverse animation to 1, stops the forward animation, and starts the reverse.

The reverse animation has a similar function, so the whole thing simply repeats.

Once I found the code to help me with the synchronization, it was really quite easy!

Demo Page

I have the executable with full xaml exploded available here.

References

First an article by Karsten Januszewski discussing Animation handoff, and that article referenced one by Hans Hull that really had the information I was needing.