Visual Basic Windows Phone 7 Series #5. How to create a control tilt effect application for Windows Phone 7

Avatar

In our last post, I explained how to implement a model-view-viewmodel pattern in a Windows Phone application. In this blog post, I want to share a sample that will help you to create a control tilt effect application for Windows Phone 7. This application will have a feature to add additional feedback for control interaction. It provides a “tilt”-like effect when a control is clicked or selected.

I will now demonstrate how easy it is to create a control tilt effect application for Windows Phone 7, using Visual Basic for Windows Phone Developer Tools. The control tilt effect application can be created in 4 simple steps as follows:

  1. Create a sample application and add controls
  2. Add event handlers
  3. Build and debug the application
  4. Rebuild in the release mode before publishing

Prerequisites:

            To create the control tilt effect application, let’s follow the 4 simple steps mentioned earlier:

            Step 1 – Create a sample application and add controls

            Create a sample application

            1. Create a new project and browse to the “Silverlight for Windows Phone” node.
            2. Select the “Windows Phone Application” template.
            3. Enter a name for the application.
            4. Click OK. The MainPage.xaml page is displayed.

            Add controls

            1. Click the MY APPLICATION text. In the Properties window, change the text property to “CONTROL TILT EFFECT”.
            2. Click the page name text. In the Properties window, change the text property to “select control”.
            3. In the Grid <tag>, add the following XAML code:

              <Button Width=”186″ Height=”185″ Content=”Button” HorizontalAlignment=”Left” VerticalAlignment=”Top” Margin=”9,20,0,0″ />

              <Button Content=”Button (Suppressed)” Height=”150″ HorizontalAlignment=”Left” Margin=”37,0,0,161″ VerticalAlignment=”Bottom” Width=”380″ local:TiltEffect.SuppressTilt=”True”/>

              <CheckBox Content=”CheckBox” Height=”72″ HorizontalAlignment=”Left” Margin=”235,25,0,0″ Name=”checkBox1″ VerticalAlignment=”Top” />

              <RadioButton Content=”RadioButton” Height=”72″ HorizontalAlignment=”Left” Margin=”235,103,0,0″ Name=”radioButton1″ VerticalAlignment=”Top” />

              <HyperlinkButton Content=”HyperlinkButton” Height=”30″ HorizontalAlignment=”Left” Margin=”25,211,0,0″ Name=”hyperlinkButton1″ VerticalAlignment=”Top” Width=”409″ />

              <ListBox Height=”110″ HorizontalAlignment=”Left” Margin=”6,472,0,0″ Name=”listBox1″ VerticalAlignment=”Top” Width=”460″ ItemsSource=”{Binding}” >

                       <ListBoxItem Content=”First ListBoxItem” ></ListBoxItem>

                       <ListBoxItem Content=”Second ListBoxItem” ></ListBoxItem>

                       <ListBoxItem Content=”Third ListBoxItem” ></ListBoxItem>

                       <ListBoxItem Content=”Fourth ListBoxItem” ></ListBoxItem>

              </ListBox>

            4. In the <phone> tag, add the following XAML code:

              xmlns:local=”clr-namespace:ControlTiltEffect”

            5.  To enable the IsTiltEnabled property, add the following XAML code in the <phone> tag:

              local:TiltEffect.IsTiltEnabled=”True”

            Add event handlers

            Adding event handlers is one of the important tasks. These event handlers are required to control the tilt effect in the container and the object.

            Note: To add the event handlers, you can download the full source code of the application from here, and import the TiltEffect.vb file from the downloaded sample application. To import the file, do the following:

            1. In Solution Explorer, right-click the application name, and then add an existing item. The Add Existing Item dialog box is displayed.
            2. Browse to the folder containing the TiltEffect.vb file, and click Add.

            To create the TiltEffect.vb file and add the event handlers manually, do the following:

            1. In Solution Explorer, right-click the application name, and then add a class. The Add New Item dialog box is displayed.
            2. Enter the name for the class as “TiltEffect.vb”, and then click Add. The TiltEffect.vb page is displayed.
            3. Replace the code with the following code:

              #If WINDOWS_PHONE Then

              Imports Microsoft.Phone.Controls

              #End If

               

               

              ”’ <summary>

              ”’ This code provides attached properties for adding a ’tilt’ effect to all controls within a container.

              ”’ </summary>

              Public Class TiltEffect

                  Inherits DependencyObject

               

              End Class

               

              ”’ <summary>

              ”’ Couple of simple helpers for walking the visual tree

              ”’ </summary>

              Friend Module TreeHelpers

                  ”’ <summary>

                  ”’ Gets the ancestors of the element, up to the root

                  ”’ </summary>

                  ”’ <param name=”node”>The element to start from</param>

                  ”’ <returns>An enumerator of the ancestors</returns>

                  <System.Runtime.CompilerServices.Extension()>

                  Public Function GetVisualAncestors(ByVal node As FrameworkElement) As IEnumerable(Of FrameworkElement)

                      Dim returnResult = New List(Of FrameworkElement)()

                      Dim parent = node.GetVisualParent()

                      Do While parent IsNot Nothing

                          returnResult.Add(parent)

               

                          parent = parent.GetVisualParent()

                      Loop

                      Return returnResult

                  End Function

               

                  ”’ <summary>

                  ”’ Gets the visual parent of the element

                  ”’ </summary>

                  ”’ <param name=”node”>The element to check</param>

                  ”’ <returns>The visual parent</returns>

                  <System.Runtime.CompilerServices.Extension()>

                  Public Function GetVisualParent(ByVal node As FrameworkElement) As FrameworkElement

                      Return TryCast(VisualTreeHelper.GetParent(node), FrameworkElement)

                  End Function

              End Module

            4. In the TiltEffect class, add the following code:

              #Region “Constructor and Static Constructor”

                  ”’ <summary>

                  ”’ This is not a constructable class, but it cannot be static because it derives from DependencyObject.

                  ”’ </summary>

                  Private Sub New()

                  End Sub

               

                  ”’ <summary>

                  ”’ Initialize the static properties

                  ”’ </summary>

                  Shared Sub New()

                      ‘ The tiltable items list.

                      TiltableItems = New List(Of Type) From {GetType(ButtonBase), GetType(ListBoxItem)}

                      UseLogarithmicEase = False

                  End Sub

              #End Region

               

              #Region “Fields and simple properties”

               

                  ‘ These constants are the same as the built-in effects

                  ”’ <summary>

                  ”’ Maximum amount of tilt, in radians

                  ”’ </summary>

                  Private Const MaxAngle = 0.3

               

                  ”’ <summary>

                  ”’ Maximum amount of depression, in pixels

                  ”’ </summary>

                  Private Const MaxDepression = 25.0

               

                  ”’ <summary>

                  ”’ Delay between releasing an element and the tilt release animation playing

                  ”’ </summary>

                  Private Shared ReadOnly TiltReturnAnimationDelay As TimeSpan =

                      TimeSpan.FromMilliseconds(200)

               

                  ”’ <summary>

                  ”’ Duration of tilt release animation

                  ”’ </summary>

                  Private Shared ReadOnly TiltReturnAnimationDuration As TimeSpan =

                      TimeSpan.FromMilliseconds(100)

               

                  ”’ <summary>

                  ”’ The control that is currently being tilted

                  ”’ </summary>

                  Private Shared currentTiltElement As FrameworkElement

               

                  ”’ <summary>

                  ”’ The single instance of a storyboard used for all tilts

                  ”’ </summary>

                  Private Shared tiltReturnStoryboard As Storyboard

               

                  ”’ <summary>

                  ”’ The single instance of an X rotation used for all tilts

                  ”’ </summary>

                  Private Shared tiltReturnXAnimation As DoubleAnimation

               

                  ”’ <summary>

                  ”’ The single instance of a Y rotation used for all tilts

                  ”’ </summary>

                  Private Shared tiltReturnYAnimation As DoubleAnimation

               

                  ”’ <summary>

                  ”’ The single instance of a Z depression used for all tilts

                  ”’ </summary>

                  Private Shared tiltReturnZAnimation As DoubleAnimation

               

                  ”’ <summary>

                  ”’ The center of the tilt element

                  ”’ </summary>

                  Private Shared currentTiltElementCenter As Point

               

                  ”’ <summary>

                  ”’ Whether the animation just completed was for a ‘pause’ or not

                  ”’ </summary>

                  Private Shared wasPauseAnimation As Boolean = False

               

                  ”’ <summary>

                  ”’ Whether to use a slightly more accurate (but slightly slower) tilt animation easing function

                  ”’ </summary>

                  Public Shared Property UseLogarithmicEase() As Boolean

               

                  ”’ <summary>

                  ”’ Default list of items that are tiltable

                  ”’ </summary>

                  Private Shared _tiltableItems As List(Of Type)

                  Public Shared Property TiltableItems() As List(Of Type)

                      Get

                          Return _tiltableItems

                      End Get

                      Private Set(ByVal value As List(Of Type))

                          _tiltableItems = value

                      End Set

                  End Property

               

              #End Region

            5. To add the event handlers and dependency properties, add the following code after the code given in Step 4:

              #Region “Dependency properties”

               

                  ”’ <summary>

                  ”’ Whether the tilt effect is enabled on a container (and all its children)

                  ”’ </summary>

                  Public Shared ReadOnly IsTiltEnabledProperty As DependencyProperty =

                      DependencyProperty.RegisterAttached(“IsTiltEnabled”,

                                                          GetType(Boolean),

                                                          GetType(TiltEffect),

                                                          New PropertyMetadata(AddressOf OnIsTiltEnabledChanged))

               

                  ”’ <summary>

                  ”’ Gets the IsTiltEnabled dependency property from an object

                  ”’ </summary>

                  ”’ <param name=”source”>The object to get the property from</param>

                  ”’ <returns>The property’s value</returns>

                  Public Shared Function GetIsTiltEnabled(ByVal source As DependencyObject) As Boolean

                      Return CBool(source.GetValue(IsTiltEnabledProperty))

                  End Function

               

                  ”’ <summary>

                  ”’ Sets the IsTiltEnabled dependency property on an object

                  ”’ </summary>

                  ”’ <param name=”source”>The object to set the property on</param>

                  ”’ <param name=”value”>The value to set</param>

                  Public Shared Sub SetIsTiltEnabled(ByVal source As DependencyObject, ByVal value As Boolean)

                      source.SetValue(IsTiltEnabledProperty, value)

                  End Sub

               

                  ”’ <summary>

                  ”’ Suppresses the tilt effect on a single control that would otherwise be tilted

                  ”’ </summary>

                  Public Shared ReadOnly SuppressTiltProperty As DependencyProperty =

                      DependencyProperty.RegisterAttached(“SuppressTilt”,

                                                          GetType(Boolean),

                                                          GetType(TiltEffect),

                                                          Nothing)

               

                  ”’ <summary>

                  ”’ Gets the SuppressTilt dependency property from an object

                  ”’ </summary>

                  ”’ <param name=”source”>The object to get the property from</param>

                  ”’ <returns>The property’s value</returns>

                  Public Shared Function GetSuppressTilt(ByVal source As DependencyObject) As Boolean

                      Return CBool(source.GetValue(SuppressTiltProperty))

                  End Function

               

                  ”’ <summary>

                  ”’ Sets the SuppressTilt dependency property from an object

                  ”’ </summary>

                  ”’ <param name=”source”>The object to get the property from</param>

                  Public Shared Sub SetSuppressTilt(ByVal source As DependencyObject,

                                                    ByVal value As Boolean)

                      source.SetValue(SuppressTiltProperty, value)

                  End Sub

               

                  ”’ <summary>

                  ”’ Property change handler for the IsTiltEnabled dependency property

                  ”’ </summary>

                  ”’ <param name=”target”>The element that the property is atteched to</param>

                  ”’ <param name=”args”>Event args</param>

                  ”’ <remarks>

                  ”’ Adds or removes event handlers from the element that has been (un)registered for tilting

                  ”’ </remarks>

                  Private Shared Sub OnIsTiltEnabledChanged(ByVal target As DependencyObject,

                                                            ByVal args As DependencyPropertyChangedEventArgs)

                      If TypeOf target Is FrameworkElement Then

                          ‘ Add / remove the event handler if necessary

                          If CBool(args.NewValue) = True Then

                              AddHandler TryCast(target, FrameworkElement).ManipulationStarted,

                                  AddressOf TiltEffect_ManipulationStarted

                          Else

                              RemoveHandler TryCast(target, FrameworkElement).ManipulationStarted,

                                  AddressOf TiltEffect_ManipulationStarted

                          End If

                      End If

                  End Sub

               

              #End Region

               

               

              #Region “Top-level manipulation event handlers”

               

                  ”’ <summary>

                  ”’ Event handler for ManipulationStarted

                  ”’ </summary>

                  ”’ <param name=”sender”>sender of the event – this will be the tilt container (eg, entire page)</param>

                  ”’ <param name=”e”>event args</param>

                  Private Shared Sub TiltEffect_ManipulationStarted(ByVal sender As Object,

                                                                    ByVal e As ManipulationStartedEventArgs)

                      TryStartTiltEffect(TryCast(sender, FrameworkElement), e)

                  End Sub

               

                  ”’ <summary>

                  ”’ Event handler for ManipulationDelta

                  ”’ </summary>

                  ”’ <param name=”sender”>sender of the event – this will be the tilting object (eg a button)</param>

                  ”’ <param name=”e”>event args</param>

                  Private Shared Sub TiltEffect_ManipulationDelta(ByVal sender As Object,

                                                                  ByVal e As ManipulationDeltaEventArgs)

                      ContinueTiltEffect(TryCast(sender, FrameworkElement), e)

                  End Sub

               

                  ”’ <summary>

                  ”’ Event handler for ManipulationCompleted

                  ”’ </summary>

                  ”’ <param name=”sender”>sender of the event – this will be the tilting object (eg a button)</param>

                  ”’ <param name=”e”>event args</param>

                  Private Shared Sub TiltEffect_ManipulationCompleted(ByVal sender As Object,

                                                                      ByVal e As ManipulationCompletedEventArgs)

                      EndTiltEffect(currentTiltElement)

                  End Sub

              #End Region

               

              #Region “Core tilt logic”

              #End Region

               

               

              #Region “Custom easing function”

               

                  ”’ <summary>

                  ”’ Provides an easing function for the tilt return

                  ”’ </summary>

                  Private Class LogarithmicEase

                      Inherits EasingFunctionBase

                      ”’ <summary>

                      ”’ Computes the easing function

                      ”’ </summary>

                      ”’ <param name=”normalizedTime”>The time</param>

                      ”’ <returns>The eased value</returns>

                      Protected Overrides Function EaseInCore(ByVal normalizedTime As Double) As Double

                          Return Math.Log(normalizedTime + 1) / 0.693147181 ‘ ln(t + 1) / ln(2)

                      End Function

                  End Class

               

              #End Region

            6.  To define the logic for the tilt effect, add the following code in the Core tilt logic region given in Step 5:

                  ”’ <summary>

                  ”’ Checks if the manipulation should cause a tilt, and if so starts the tilt effect

                  ”’ </summary>

                  ”’ <param name=”source”>The source of the manipulation (the tilt container, eg entire page)</param>

                  ”’ <param name=”e”>The args from the ManipulationStarted event</param>

                  Private Shared Sub TryStartTiltEffect(ByVal source As FrameworkElement, ByVal e As ManipulationStartedEventArgs)

                      For Each ancestor In (TryCast(e.OriginalSource, FrameworkElement)).GetVisualAncestors()

                          For Each t As Type In TiltableItems

                              If t.IsAssignableFrom(ancestor.GetType()) Then

                                  If CBool(ancestor.GetValue(SuppressTiltProperty)) <> True Then

                                      ‘ Use first child of the control, so that you can add transforms and not

                                      ‘ impact any transforms on the control itself

                                      Dim element = TryCast(VisualTreeHelper.GetChild(ancestor, 0), FrameworkElement)

                                      Dim container = TryCast(e.ManipulationContainer, FrameworkElement)

               

                                      If element Is Nothing OrElse container Is Nothing Then

                                          Return

                                      End If

               

                                      ‘ Touch point relative to the element being tilted

                                      Dim tiltTouchPoint = container.TransformToVisual(element).Transform(e.ManipulationOrigin)

               

                                      ‘ Center of the element being tilted

                                      Dim elementCenter As New Point(element.ActualWidth / 2,

                                                                     element.ActualHeight / 2)

               

                                      ‘ Camera adjustment

                                      Dim centerToCenterDelta = GetCenterToCenterDelta(element, source)

               

                                      BeginTiltEffect(element, tiltTouchPoint, elementCenter, centerToCenterDelta)

                                      Return

                                  End If

                              End If

                          Next t

                      Next ancestor

                  End Sub

               

                  ”’ <summary>

                  ”’ Computes the delta between the centre of an element and its container

                  ”’ </summary>

                  ”’ <param name=”element”>The element to compare</param>

                  ”’ <param name=”container”>The element to compare against</param>

                  ”’ <returns>A point that represents the delta between the two centers</returns>

                  Private Shared Function GetCenterToCenterDelta(ByVal element As FrameworkElement,

                                                                 ByVal container As FrameworkElement) As Point

                      Dim elementCenter As New Point(element.ActualWidth / 2, element.ActualHeight / 2)

                      Dim containerCenter As Point

               

              #If WINDOWS_PHONE Then

                          ‘ Need to special-case the frame to handle different orientations

                          If TypeOf container Is PhoneApplicationFrame Then

                              Dim frame  = TryCast(container, PhoneApplicationFrame)

               

                              ‘ Switch width and height in landscape mode

                              If (frame.Orientation And PageOrientation.Landscape) = PageOrientation.Landscape Then

               

                                  containerCenter = New Point(container.ActualHeight / 2, container.ActualWidth / 2)

                              Else

                                  containerCenter = New Point(container.ActualWidth / 2, container.ActualHeight / 2)

                              End If

                          Else

                              containerCenter = New Point(container.ActualWidth / 2, container.ActualHeight / 2)

                          End If

              #Else

               

                      containerCenter = New Point(container.ActualWidth / 2, container.ActualHeight / 2)

               

              #End If

               

                      Dim transformedElementCenter = element.TransformToVisual(container).Transform(elementCenter)

                      Dim result As New Point(containerCenter.X – transformedElementCenter.X,

                                              containerCenter.Y – transformedElementCenter.Y)

                      Return result

                  End Function

               

                  ”’ <summary>

                  ”’ Begins the tilt effect by preparing the control and doing the initial animation

                  ”’ </summary>

                  ”’ <param name=”element”>The element to tilt </param>

                  ”’ <param name=”touchPoint”>The touch point, in element coordinates</param>

                  ”’ <param name=”centerPoint”>The center point of the element in element coordinates</param>

                  ”’ <param name=”centerDelta”>The delta between the <paramref name=”element”/>‘s center and

                  ”’ the container’s center</param>

                  Private Shared Sub BeginTiltEffect(ByVal element As FrameworkElement,

                                                     ByVal touchPoint As Point,

                                                     ByVal centerPoint As Point,

                                                     ByVal centerDelta As Point)

                      If tiltReturnStoryboard IsNot Nothing Then

                          StopTiltReturnStoryboardAndCleanup()

                      End If

               

                      If PrepareControlForTilt(element, centerDelta) = False Then

                          Return

                      End If

               

                      currentTiltElement = element

                      currentTiltElementCenter = centerPoint

                      PrepareTiltReturnStoryboard(element)

               

                      ApplyTiltEffect(currentTiltElement, touchPoint, currentTiltElementCenter)

                  End Sub

               

                  ”’ <summary>

                  ”’ Prepares a control to be tilted by setting up a plane projection and some event handlers

                  ”’ </summary>

                  ”’ <param name=”element”>The control that is to be tilted</param>

                  ”’ <param name=”centerDelta”>Delta between the element’s center and the tilt container’s</param>

                  ”’ <returns>true if successful; false otherwise</returns>

                  ”’ <remarks>

                  ”’ This method is conservative; it will fail any attempt to tilt a control that already

                  ”’ has a projection on it

                  ”’ </remarks>

                  Private Shared Function PrepareControlForTilt(ByVal element As FrameworkElement,

                                                                ByVal centerDelta As Point) As Boolean

                      ‘ Prevents interference with any existing transforms

                      If element.Projection IsNot Nothing OrElse

                          (element.RenderTransform IsNot Nothing AndAlso

                           element.RenderTransform.GetType() IsNot GetType(MatrixTransform)) Then

                          Return False

                      End If

               

                      Dim transform As New TranslateTransform()

                      transform.X = centerDelta.X

                      transform.Y = centerDelta.Y

                      element.RenderTransform = transform

               

                      Dim projection As New PlaneProjection()

                      projection.GlobalOffsetX = -1 * centerDelta.X

                      projection.GlobalOffsetY = -1 * centerDelta.Y

                      element.Projection = projection

               

                      AddHandler element.ManipulationDelta, AddressOf TiltEffect_ManipulationDelta

                      AddHandler element.ManipulationCompleted, AddressOf TiltEffect_ManipulationCompleted

               

                      Return True

                  End Function

               

                  ”’ <summary>

                  ”’ Removes modifications made by PrepareControlForTilt

                  ”’ </summary>

                  ”’ <param name=”element”>THe control to be un-prepared</param>

                  ”’ <remarks>

                  ”’ This method is basic; it does not do anything to detect if the control being un-prepared

                  ”’ was previously prepared

                  ”’ </remarks>

                  Private Shared Sub RevertPrepareControlForTilt(ByVal element As FrameworkElement)

                      RemoveHandler element.ManipulationDelta, AddressOf TiltEffect_ManipulationDelta

                      RemoveHandler element.ManipulationCompleted, AddressOf TiltEffect_ManipulationCompleted

                      element.Projection = Nothing

                      element.RenderTransform = Nothing

                  End Sub

               

                  ”’ <summary>

                  ”’ Creates the tilt return storyboard (if not already created) and targets it to the projection

                  ”’ </summary>

                  Private Shared Sub PrepareTiltReturnStoryboard(ByVal element As FrameworkElement)

                      If tiltReturnStoryboard Is Nothing Then

                          tiltReturnStoryboard = New Storyboard()

                          AddHandler tiltReturnStoryboard.Completed, AddressOf TiltReturnStoryboard_Completed

               

                          tiltReturnXAnimation = New DoubleAnimation()

                          Storyboard.SetTargetProperty(tiltReturnXAnimation,

                                                       New PropertyPath(PlaneProjection.RotationXProperty))

                          tiltReturnXAnimation.BeginTime = TiltReturnAnimationDelay

                          tiltReturnXAnimation.To = 0

                          tiltReturnXAnimation.Duration = TiltReturnAnimationDuration

               

                          tiltReturnYAnimation = New DoubleAnimation()

                          Storyboard.SetTargetProperty(tiltReturnYAnimation,

                                                       New PropertyPath(PlaneProjection.RotationYProperty))

                          tiltReturnYAnimation.BeginTime = TiltReturnAnimationDelay

                          tiltReturnYAnimation.To = 0

                          tiltReturnYAnimation.Duration = TiltReturnAnimationDuration

               

                          tiltReturnZAnimation = New DoubleAnimation()

                          Storyboard.SetTargetProperty(tiltReturnZAnimation,

                                                       New PropertyPath(PlaneProjection.GlobalOffsetZProperty))

                          tiltReturnZAnimation.BeginTime = TiltReturnAnimationDelay

                          tiltReturnZAnimation.To = 0

                          tiltReturnZAnimation.Duration = TiltReturnAnimationDuration

               

                          If UseLogarithmicEase Then

                              tiltReturnXAnimation.EasingFunction = New LogarithmicEase()

                              tiltReturnYAnimation.EasingFunction = New LogarithmicEase()

                              tiltReturnZAnimation.EasingFunction = New LogarithmicEase()

                          End If

               

                          tiltReturnStoryboard.Children.Add(tiltReturnXAnimation)

                          tiltReturnStoryboard.Children.Add(tiltReturnYAnimation)

                          tiltReturnStoryboard.Children.Add(tiltReturnZAnimation)

                      End If

               

                      Storyboard.SetTarget(tiltReturnXAnimation, element.Projection)

                      Storyboard.SetTarget(tiltReturnYAnimation, element.Projection)

                      Storyboard.SetTarget(tiltReturnZAnimation, element.Projection)

                  End Sub

               

                  ”’ <summary>

                  ”’ Continues a tilt effect that is currently applied to an element, presumably because

                  ”’ the user moved their finger

                  ”’ </summary>

                  ”’ <param name=”element”>The element being tilted</param>

                  ”’ <param name=”e”>The manipulation event args</param>

                  Private Shared Sub ContinueTiltEffect(ByVal element As FrameworkElement,

                                                        ByVal e As ManipulationDeltaEventArgs)

                      Dim container As FrameworkElement = TryCast(e.ManipulationContainer, FrameworkElement)

                      If container Is Nothing OrElse element Is Nothing Then

                          Return

                      End If

               

                      Dim tiltTouchPoint As Point = container.TransformToVisual(element).Transform(e.ManipulationOrigin)

               

                      ‘ If touch moved outside bounds of element, then pause the tilt (but don’t cancel it)

                      If New Rect(0,

                                  0,

                                  currentTiltElement.ActualWidth,

                                  currentTiltElement.ActualHeight).Contains(tiltTouchPoint) <> True Then

               

                          PauseTiltEffect()

                          Return

                      End If

               

                      ‘ Apply the updated tilt effect

                      ApplyTiltEffect(currentTiltElement, e.ManipulationOrigin, currentTiltElementCenter)

                  End Sub 

                  ”’ <summary>

                  ”’ Ends the tilt effect by playing the animation 

                  ”’ </summary>

                  ”’ <param name=”element”>The element being tilted</param>

                  Private Shared Sub EndTiltEffect(ByVal element As FrameworkElement)

                      If element IsNot Nothing Then

                          RemoveHandler element.ManipulationCompleted, AddressOf TiltEffect_ManipulationCompleted

                          RemoveHandler element.ManipulationDelta, AddressOf TiltEffect_ManipulationDelta

                      End If

               

                      If tiltReturnStoryboard IsNot Nothing Then

                          wasPauseAnimation = False

                          If tiltReturnStoryboard.GetCurrentState() <> ClockState.Active Then

                              tiltReturnStoryboard.Begin()

                          End If

                      Else

                          StopTiltReturnStoryboardAndCleanup()

                      End If

                  End Sub

               

                  ”’ <summary>

                  ”’ Handler for the storyboard complete event

                  ”’ </summary>

                  ”’ <param name=”sender”>sender of the event</param>

                  ”’ <param name=”e”>event args</param>

                  Private Shared Sub TiltReturnStoryboard_Completed(ByVal sender As Object, ByVal e As EventArgs)

                      If wasPauseAnimation Then

                          ResetTiltEffect(currentTiltElement)

                      Else

                          StopTiltReturnStoryboardAndCleanup()

                      End If

                  End Sub

               

                  ”’ <summary>

                  ”’ Resets the tilt effect on the control, making it appear ‘normal’ again

                  ”’ </summary>

                  ”’ <param name=”element”>The element to reset the tilt on</param>

                  ”’ <remarks>

                  ”’ This method doesn’t turn off the tilt effect or cancel any current

                  ”’ manipulation; it just temporarily cancels the effect

                  ”’ </remarks>

                  Private Shared Sub ResetTiltEffect(ByVal element As FrameworkElement)

                      Dim projection As PlaneProjection = TryCast(element.Projection, PlaneProjection)

                      projection.RotationY = 0

                      projection.RotationX = 0

                      projection.GlobalOffsetZ = 0

                  End Sub

               

                  ”’ <summary>

                  ”’ Stops the tilt effect and release resources applied to the currently-tilted control

                  ”’ </summary>

                  Private Shared Sub StopTiltReturnStoryboardAndCleanup()

                      If tiltReturnStoryboard IsNot Nothing Then

                          tiltReturnStoryboard.Stop()

                      End If

                      RevertPrepareControlForTilt(currentTiltElement)

                  End Sub

               

                  ”’ <summary>

                  ”’ Pauses the tilt effect so that the control returns to the ‘at rest’ position, but doesn’t

                  ”’ stop the tilt effect (handlers are still attached, etc.)

                  ”’ </summary>

                  Private Shared Sub PauseTiltEffect()

                      If (tiltReturnStoryboard IsNot Nothing) AndAlso (Not wasPauseAnimation) Then

                          tiltReturnStoryboard.Stop()

                          wasPauseAnimation = True

                          tiltReturnStoryboard.Begin()

                      End If

                  End Sub

               

                  ”’ <summary>

                  ”’ Resets the storyboard to not running

                  ”’ </summary>

                  Private Shared Sub ResetTiltReturnStoryboard()

                      tiltReturnStoryboard.Stop()

                      wasPauseAnimation = False

                  End Sub

               

                  ”’ <summary>

                  ”’ Applies the tilt effect to the control

                  ”’ </summary>

                  ”’ <param name=”element”>the control to tilt</param>

                  ”’ <param name=”touchPoint”>The touch point, in the container’s coordinates</param>

                  ”’ <param name=”centerPoint”>The center point of the container</param>

                  Private Shared Sub ApplyTiltEffect(ByVal element As FrameworkElement,

                                                     ByVal touchPoint As Point,

                                                     ByVal centerPoint As Point)

                      ‘ Stop any active animation

                      ResetTiltReturnStoryboard()

               

                      ‘ Get relative point of the touch in percentage of container size

                      Dim normalizedPoint As New Point(Math.Min(Math.Max(touchPoint.X / (centerPoint.X * 2), 0), 1),

                                                       Math.Min(Math.Max(touchPoint.Y / (centerPoint.Y * 2), 0), 1))

                      ‘ Shell values

                      Dim xMagnitude = Math.Abs(normalizedPoint.X – 0.5)

                      Dim yMagnitude = Math.Abs(normalizedPoint.Y – 0.5)

                      Dim xDirection = –Math.Sign(normalizedPoint.X – 0.5)

                      Dim yDirection = Math.Sign(normalizedPoint.Y – 0.5)

                      Dim angleMagnitude = xMagnitude + yMagnitude

                      Dim xAngleContribution = If(xMagnitude + yMagnitude > 0,

                                                  xMagnitude / (xMagnitude + yMagnitude),

                                                  0)

               

                      Dim angle = angleMagnitude * MaxAngle * 180 / Math.PI

                      Dim depression = (1 – angleMagnitude) * MaxDepression

                      ‘ RotationX and RotationY are the angles of rotations about the x- or y-*axis*;

                      ‘ to achieve a rotation in the x- or y-*direction*, we need to swap the two.

                      ‘ That is, a rotation to the left about the y-axis is a rotation to the left in the x-direction,

                      ‘ and a rotation up about the x-axis is a rotation up in the y-direction.

                      Dim projection As PlaneProjection = TryCast(element.Projection, PlaneProjection)

                      projection.RotationY = angle * xAngleContribution * xDirection

                      projection.RotationX = angle * (1 – xAngleContribution) * yDirection

                      projection.GlobalOffsetZ = -depression

                  End Sub

               

               

               

             Voila! Now your control tilt effect application for Windows Phone 7 is ready! You just need to build and debug the application.

            Step 3 – Build and debug the application

            1. To build the application, select Build > Build Application. The project should build without any errors. If there are errors, check the earlier steps, correct the errors, and then build the application again.
            2. To debug the application, set the deployment target of the application to “Windows Phone 7 Emulator”.
            3. Select Debug > Start Debugging. The emulator window is displayed.
            4. To test the tilt effect, click any of the controls.

            Note: To stop debugging the application, select Debug > Stop Debugging.

            Step 4 – Rebuild in the release mode for publishing

            1. On the standard toolbar, change the configuration manager to Release.
            2. To rebuild the application, select Build > Rebuild. The XAP file of the application is generated, which is the package you will have to submit to the marketplace in order to publish the application. You can also locate this XAP file in the BinRelease folder.

            Finally, to submit your application to the market place, you can refer to upload your application walkthrough.

            Summary

            That’s it! You have now successfully created the control tilt effect application for Windows Phone 7, that too in just 4 simple steps!

            You can find the full source code for the Visual Basic Control Tilt Effect application here.

            Avatar

            Follow    

            No Comments.