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
Following in action
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>
Stay tuned for the next articles from this series coming up next week