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:
- Create a sample application and add controls
- Add event handlers
- Build and debug the application
- Rebuild in the release mode before publishing
Prerequisites:
- Visual Studio 2010 Professional, Premium, or Ultimate. If you do not have any of the releases, you can download any of the following trial versions as per your preference: Professional, Premium, or Ultimate.
- Windows Phone Developer Tools RTW
- Visual Basic
for Windows Phone Developer Tools – RTW
Note: You can install the newer version- Windows Phone Developer Tools 7.1 Beta instead of the above mentioned two tools as it will take comparatively less time. However, this sample was created using the previous version.
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
- Create a new project and browse to the “Silverlight for Windows Phone” node.
- Select the “Windows Phone Application” template.
- Enter a name for the application.
- Click OK. The MainPage.xaml page is displayed.
Add controls
- Click the MY APPLICATION text. In the Properties window, change the text property to “CONTROL TILT EFFECT”.
- Click the page name text. In the Properties window, change the text property to “select control”.
- 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>
- In the <phone> tag, add the following XAML code:
xmlns:local=”clr-namespace:ControlTiltEffect”
- 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:
- In Solution Explorer, right-click the application name, and then add an existing item. The Add Existing Item dialog box is displayed.
- 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:
- In Solution Explorer, right-click the application name, and then add a class. The Add New Item dialog box is displayed.
- Enter the name for the class as “TiltEffect.vb”, and then click Add. The TiltEffect.vb page is displayed.
- 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
- 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
- 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
- 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
- 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.
- To debug the application, set the deployment target of the application to “Windows Phone 7 Emulator”.
- Select Debug > Start Debugging. The emulator window is displayed.
- 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
- On the standard toolbar, change the configuration manager to Release.
- 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.
0 comments