FrameBased vs TimeBased Animation in Windows Phone 7


Introduction

Here we will be creating an animation of spinning text in a Windows Phone, either frame-based or time-based. To do this in Windows Phone we will use a CompositionTarget.Rendering event. You can pace this animation either by the rate that the video hardware refreshes the display, or by clock time. Because each refresh of the video display is called a frame, these two methods of pacing animation are referred to as frame-based and time-based. In this article the content area of the XAML file has two TextBlock elements with RotateTransform objects set to their RenderTransform properties, and a Button that handles its OnClick event. The code-behind file saves the current time in a field and then attaches a handler for the CompositionTarget.Rendering event. This event handler is then called in synchronization with the video frame rate.

The rotation angle for the first TextBlock is increased by 0.2 d. every frame. I calculated this by knowing that the phone display is refreshed at 30 frames per second. Multiply 30 frames per second by 60 seconds per minute by 0.2 d and you get 360 d.The rotation angle for the second TextBlock is calculated based on the elapsed time. The TimeSpan structure has a convenient TotalMinutes property and this is multiplied by 360 for the total number of degrees to rotate the text.

Step 1 : Open Visual Studio.
  • Select new -> project
  • Select your preferred language
  • Select the silverlight for Windows Phone application
  • Name the project
  • Now name of project is "WindowsPhoneAnimation"

clock1.gif

phone1.gif

Step  2 :  Open the Toolbox of the Windows Phone application.

  • Drag & Drop two TextBlock controls onto the design view.
  • Drag & Drop a button control onto the design view.

phone2.gif

Step 3 : Set some formatting on the TextBlock and Button properties in  XAML code.

Code

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <Grid.RowDefinitions>
   <RowDefinition Height="*" />
   <RowDefinition Height="*" />
   <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
<
TextBlock Grid.Row="0"
Text="Frame-Based"
FontSize="{StaticResource PhoneFontSizeLarge}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5 0.5">
<
TextBlock.RenderTransform>
<
RotateTransform x:Name="rotate1"></RotateTransform>
</
TextBlock.RenderTransform>
</
TextBlock>
<
TextBlock Grid.Row="1"
Text="Time-Based"
FontSize="{StaticResource PhoneFontSizeLarge}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5 0.5">
<
TextBlock.RenderTransform>
<
RotateTransform x:Name="rotate2" />
</
TextBlock.RenderTransform>
</
TextBlock>
 <Button Grid.Row="2"
Content="Hang for 5 seconds"
HorizontalAlignment="Center"
Click="OnButtonClick" />
</
Grid>

Step 4 : The final presentation of the design view is given below:

Code

<phone:PhoneApplicationPage
    x:Class="WindowsPhoneAnimation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
 
    <!--LayoutRoot is the root grid where all page content is placed-->

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!--TitlePanel contains the name of the application and page title-->

   <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
    <TextBlock x:Name="PageTitle" Text="Animation" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
   </StackPanel>
 
        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0"
Text="Frame-Based"
FontSize="{StaticResource PhoneFontSizeLarge}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5 0.5">
<
TextBlock.RenderTransform>
<
RotateTransform x:Name="rotate1"></RotateTransform>
    </TextBlock.RenderTransform>
            </TextBlock>
            <TextBlock Grid.Row="1"
Text="Time-Based"
FontSize="{StaticResource PhoneFontSizeLarge}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5 0.5">
<
TextBlock.RenderTransform>
<
RotateTransform x:Name="rotate2" />
</
TextBlock.RenderTransform>
            </TextBlock>
<
Button Grid.Row="2"
Content="Hang for 5 seconds"
HorizontalAlignment="Center"
Click="OnButtonClick" />
        </Grid>
    </Grid>
</
phone:PhoneApplicationPage>

phone3.gif

Step 5 : The code of the MainPage.xaml.cs file is:

Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Threading;
 
namespace WindowsPhoneAnimation

{
    public partial class MainPage : PhoneApplicationPage
    {
        DateTime startTime;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            startTime = DateTime.Now;
            CompositionTarget.Rendering += OnCompositionTargetRendering;
        }
        void OnCompositionTargetRendering(object sender, EventArgs args)
        {
            // Frame-based
            rotate1.Angle = (rotate1.Angle + 0.2) % 360;
            // Time-based
            TimeSpan elapsedTime = DateTime.Now - startTime;
            rotate2.Angle = (elapsedTime.TotalMinutes * 360) % 360;
        }
        void OnButtonClick(object sender, RoutedEventArgs args)
        {
            Thread.Sleep(5000);
        }
    }
}

Output

phone4.gif

Just click on the button; both text will spin for 5 seconds.

phone5.gif

Resources


Similar Articles