(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Visuals staring at the mouse cursor

(137 votes)
Miroslav Miroslavov
>
Miroslav Miroslavov
Joined Nov 24, 2009
Articles:   8
Comments:   6
More Articles
5 comments   /   posted on Apr 22, 2010
Tags:   animations , mousemove , attachedbehaviors , completit , miroslav-miroslavov
Categories:   White Papers , General

This article is compatible with the latest version of Silverlight.

This is part 1 of the series "Silverlight in Action".

Here we’re sharing our experience from the amazing CompletIT web site.

Let's suppose we want our visual objects to "watch" and "follow with eyes" the mouse cursor while it moves around. The idea is simply to define our visuals to be somehow on a different Z coordinate than the actual screen is. This way while moving the cursor around, the visual objects will look and follow the mouse. We'll use a simple PlaneProjection to achieve this.

This is very important part of the actual “look and feel” of the web site. The main menu items are following the mouse while moving the cursor around.

See how it looks

FollowMouse

Following in action

Get Microsoft Silverlight

Implementation

The idea is to create an attached behavior for a panel, so all its children will stare at the mouse. We need two attached properties of the behaviour:
  • IsChildrenFollowingMouse - just to enable the behavior for that panel.
  • ItemsZ - the Z coordinate of the Items. This means how far the items are from the screen.

We need to handle the MouseMove event, so we can rotate our visuals in such a way, that they will look like are following the mouse.

Here is the actual magic
 private static void panel_MouseMove(object sender, MouseEventArgs e) 
 { 
     var panel = sender as Panel; 
     if (panel != null) 
     { 
        var point = e.GetPosition(panel); 
         var z = GetItemsZ(panel); 
         foreach (FrameworkElement item in panel.Children) 
         { 
             var center = item.TransformToVisual(panel).Transform(new Point(item.ActualWidth / 2, item.ActualHeight / 2)); 
   
             //Vector from current point to 3D center of the item. 
             double len = Math.Sqrt(Math.Pow(center.X - point.X, 2) + Math.Pow(center.Y - point.Y, 2) + z * z); 
   
             double cosOy = (center.Y - point.Y) / len; 
   
             double cosOx = (center.X - point.X) / len; 
   
             PlaneProjection projection; 
             EnsureProjection(item, out projection); 
   
             projection.RotationX = Math.Acos(cosOy) * (180 / Math.PI) - 90; 
             projection.RotationY = 90 - Math.Acos(cosOx) * (180 / Math.PI); 
         } 
     } 
 } 

What we actually do is just a simple math. We calculate the angles between the line (from the cursor to the center of the item) and the Ox and Oy axes of the item’s surface (the item's actually with different z-coordinate from the screen). Having the angles, we can calculate the needed RotationX and RotationY properties. You can see the drawing over the screenshot for reference.

So let's see how we use the newly created Attached properties, to force our panel's children to track the mouse.

How to use the behavior
 <Grid x:Name="LayoutRoot"> 
     <Grid.Resources> 
         <Style TargetType="StackPanel" 
                x:Key="st"> 
            <Setter Property="FollowingMouse:FollowingService.IsChildrenFollowingMouse" 
                    Value="True" /> 
             <Setter Property="FollowingMouse:FollowingService.ItemsZ" 
                     Value="200" /> 
         </Style> 
     </Grid.Resources> 
     <StackPanel Orientation="Horizontal" Style="{StaticResource st}"> 
         <StackPanel.Resources> 
             <Style TargetType="ContentControl" 
                    x:Key="faceControl"> 
                 <Setter Property="Height" 
                         Value="75" /> 
                 <Setter Property="Width" 
                         Value="75" /> 
                 <Setter Property="Margin" 
                         Value="10" /> 
                 <Setter Property="Template"> 
                     <Setter.Value> 
                         <ControlTemplate> 
                             <Grid> 
                                 <Ellipse Fill="{TemplateBinding Background}" /> 
                                 <Ellipse Height="10" 
                                          Width="10" 
                                          Fill="Blue" 
                                          Margin="20 20 0 0" 
                                          HorizontalAlignment="Left" 
                                          VerticalAlignment="Top" /> 
                                 <Ellipse Height="10" 
                                          Fill="Blue" 
                                          Width="10" 
                                          Margin="0 20 20 0" 
                                          HorizontalAlignment="Right" 
                                          VerticalAlignment="Top" /> 
                                 <Path Data="M0,0 A 10, 10 0 0 0 25, 0" 
                                       Stroke="#FFFA0D0D" 
                                       HorizontalAlignment="Center" 
                                       VerticalAlignment="Bottom" 
                                       Margin="0 0 0 10" 
                                       StrokeThickness="2" /> 
                             </Grid> 
                         </ControlTemplate> 
                     </Setter.Value> 
                 </Setter> 
             </Style> 
         </StackPanel.Resources> 
   
         <ContentControl Style="{StaticResource faceControl}" 
                         Background="Yellow" /> 
         <ContentControl Style="{StaticResource faceControl}" 
                         Background="Silver" /> 
         <ContentControl Style="{StaticResource faceControl}" 
                         Background="Cyan" /> 
         <ContentControl Style="{StaticResource faceControl}" 
                         Background="Green" /> 
         <ContentControl Style="{StaticResource faceControl}" 
                         Background="Brown" /> 
     </StackPanel> 
 </Grid> 

Download the code.

Stay tuned for the next articles from this series coming up next week


Subscribe

Comments

  • -_-

    RE: Visuals staring at the mouse cursor


    posted by Fallon on Apr 22, 2010 20:37
    Simple but sweet... thanks.
  • -_-

    RE: Visuals staring at the mouse cursor


    posted by Aaron on Apr 23, 2010 15:29
    Brilliant.  You guys rock for sharing this!
  • miromiroslavov

    RE: Visuals staring at the mouse cursor


    posted by miromiroslavov on Apr 23, 2010 19:08

    Thank you! :)

    More "showcase" articles are on the road.

  • forgetu

    Re: Visuals staring at the mouse cursor


    posted by forgetu on Aug 18, 2011 09:20

    Thanks.

  • nikhildixit87

    Re: Visuals staring at the mouse cursor


    posted by nikhildixit87 on Sep 09, 2011 14:55

    Great work..

Add Comment

Login to comment:
  *      *       

From this series