Thursday, March 19, 2009

The new features in Silverlight 3 – 3D Projections

Lots of interesting new stuff in the beta of Silverlight 3 – the 2D plane into 3D projection property that has been added to the UIElement class is obviously going to provide lots of opportunity to enhance control templates with mouse over and selected states in VSM. It is pretty easy to knock up a poor-man’s carousel type effect with a few buttons and a template with PlaneProjection transitions:

QuickCarousel 

<ControlTemplate TargetType="Button">
        <Grid x:Name="grid">
            <
Grid.Projection>
                <
PlaneProjection CenterOfRotationY="1" />
            </
Grid.Projection>
            <
vsm:VisualStateManager.VisualStateGroups>
                <
vsm:VisualStateGroup x:Name="CommonStates">
                    <
vsm:VisualStateGroup.Transitions>
                        <
vsm:VisualTransition GeneratedDuration="00:00:00.2000000" To="MouseOver"/>
                        <
vsm:VisualTransition From="MouseOver" GeneratedDuration="00:00:00.5000000"/>
                    </
vsm:VisualStateGroup.Transitions>
                    <
vsm:VisualState x:Name="Normal">
                        <
Storyboard>
                            <
DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="grid" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationX)">
                                <
EasingDoubleKeyFrame KeyTime="00:00:00" Value="-85"/>
                            </
DoubleAnimationUsingKeyFrames>
                        </
Storyboard>
                    </
vsm:VisualState>
                    <
vsm:VisualState x:Name="MouseOver">
                        <
Storyboard>

etc...
</ControlTemplate>

<
Grid x:Name="LayoutRoot" Background="White" Width="400">
<
Grid.Resources>
</
Grid.Resources>
    <
Grid.RowDefinitions>
        <
RowDefinition />
        <
RowDefinition />
    </
Grid.RowDefinitions>
    <
Grid.ColumnDefinitions>
        <
ColumnDefinition />
        <
ColumnDefinition />
        <
ColumnDefinition />
        <
ColumnDefinition />
        <
ColumnDefinition />
    </
Grid.ColumnDefinitions>
    <
Button x:Name="Button1" Content="Fred" Grid.Column="0" Style="{StaticResource FlipButton}" />
    <
Button x:Name="Button2" Content="Barney" Grid.Column="1" Style="{StaticResource FlipButton}" />
    <
Button x:Name="Button3" Content="Wilma" Grid.Column="2" Style="{StaticResource FlipButton}" />
    <
Button x:Name="Button4" Content="Betty" Grid.Column="3" Style="{StaticResource FlipButton}" />
    <
Button x:Name="Button5" Content="Pebbles" Grid.Column="4" Style="{StaticResource FlipButton}" />
</
Grid>

The key thing is to target the UIElement’s Projection.ProjectionPlane property and to animate its RotationX, RotationY and RotationZ properties to transform the 2D plane of the element in the X, Y & Z dimensions. Setting the CentreOfRotationX, CentreOfRotationY & CentreOfRotationZ properties determines when the movement ‘hinges’ and the rotations are in degrees from the normal, untransformed state (i.e. 0 degrees).

Five minutes obviously doesn’t make for a control – but interesting to play with the effect and I expect to see it crop up in many a control and Silverlight app in the future.