Animating a built-in button

Exclusive offer: get 50% off this eBook here
Instant Silverlight 5 Animation [Instant]

Instant Silverlight 5 Animation [Instant] — Save 50%

Enrich your web page or Silverlight business application with Silverlight animations book and ebook.

£7.99    £4.00
by Nick Polyak | March 2013 | Enterprise Articles Microsoft

This article by Nick Polyak, author of Instant Silverlight 5 Animation , will describe the process involved in animating a built-in button.

A Silverlight button has the following mouse-driven states:

  • Normal

  • MouseOver

  • Pressed

(For more resources related to this topic, see here.)

Note that there might be more states to a fully functioning button, for example, there is also a Disabled state, but whether a button is disabled or not usually does not depend on mouse movements or positions, it does not have to be animated, and we do not describe it here. Our purpose in this section is not to create a fully functioning button, but rather to demonstrate some generic concepts for re-styling a control and providing custom animations for it.

Let's create a Silverlight project containing a single page with the button in its center. The following is the resulting XAML code of the main page:

<UserControl x:Class="AnimatingButtonStates.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="LayoutRoot" Background="White"> <Button Width="100" Height="25" Background="LightGray" Content="Press Me" /> </Grid> </UserControl>

We want to re-style this button completely, modifying it shape, border, colors, and creating custom animations for the transition between states.

Now, we'll create a very simple custom template for the button by changing the button code to the following code:

<!-- Here we provide custom button template --> <Button> <Button.Template> <ControlTemplate TargetType="Button"> <Grid x:Name="TopLevelButtonGrid"> <!--Button Border--> <Border x:Name="ButtonBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> <!-- button content is placed here--> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </ControlTemplate> </Button.Template> <Button>

If we run the code, as it is, we shall be able to see the button and its Press Me content, but the button will not react visually to mouse over or press events. That is because once we replace the button's template we will have to provide our own solution to the visual changes for different button states.

Now, let's discuss how we want the button to look in the different states and how we want it to handle the transitions between states.

When the mouse is over the button, we want a blue border to appear. The animation to achieve this can be fast or even instantaneous.

When the button is pressed, we want it to scale down significantly and we want the button to scale up and down several times, each time with lower amplitude before achieving a steady pressed state.

Note that the control template developers and designers usually try to avoid changing colors within animations (they are considered to be more complex and less intuitive); instead, they try to achieve color-changing effects by changing opacities of several template parts. So to change the border to blue on mouse over, let's create another border element MouseOverBorder with blue BorderBrush, and non-zero BorderThickness within the control template. At normal state, its opacity property will be 0, and it will be completely transparent. When the state of the button changes to MouseOver, the opacity of this border will change to 1.

After we add the MouseOverBorder element together with the visual state manager functionality, the resulting template code will look as follows:

<Button> <Button.Template> <ControlTemplate TargetType="Button"> <Grid x:Name="TopLevelButtonGrid"> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualStateGroup.Transitions> <!-- duration for the MouseOver animation is set here to 0.2 seconds --> <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.2" /> </VisualStateGroup.Transitions> <VisualState x:Name="Normal" /> <VisualState x:Name="MouseOver"> <VisualState.Storyboard> <Storyboard> <!--animation performed when the button gets into "MouseOver" State--> <DoubleAnimation Storyboard. TargetName="MouseOverBorder" Storyboard.TargetProperty="Opacity" To="1" /> </Storyboard> </VisualState.Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <!--Button Border--> <Border x:Name="ButtonBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> <!--MouseOverBorder has opacity 0 normally. Only when the mouse moves over the button, the opacity is changed to 1--> <Border x:Name="MouseOverBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="5" BorderBrush="Blue" BorderThickness="2" Opacity="0"> </Border> <!-- button content is placed here--> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </ControlTemplate> </Button.Template> </Button>

Now, if we start the application, we'll see that the border of the button becomes blue, if the mouse pointer is placed over it, and returns to its usual color when the mouse pointer is moved away from the button, as shown in the following screenshot:

The next step is to animate the pressed state.

To achieve this, we add a ScaleTransform object to the top-level grid of the button's template:

<ControlTemplate TargetType="Button"> <Grid x:Name="TopLevelButtonGrid" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransform> <!-- scale transform is used to shrink the button when it is pressed --> <ScaleTransform x:Name="OnPressedScaleTransform" ScaleX="1" ScaleY="1" /> </Grid.RenderTransform> ...

The purpose of the ScaleTransform object is to shrink the button once it is pressed. Originally, its ScaleX and ScaleY parameters are set to 1, while the animation that starts when the button is pressed changes them to 0.5.

This animation is defined within VisualState defined as Pressed:

<VisualStateGroup> ... <VisualState x:Name="Pressed"> <VisualState.Storyboard> <Storyboard> <!-- animation performed when the button gets into "Pressed" State will scale down the button by a factor of 0.5 in both dimensions --> <DoubleAnimation Storyboard.TargetProperty="ScaleX" Storyboard.TargetName="TheScaleTransform" To="0.5" /> <DoubleAnimation Storyboard.TargetProperty="ScaleY" Storyboard.TargetName="TheScaleTransform" To="0.5" /> </Storyboard> </VisualState.Storyboard> </VisualState> ... </VisualStateGroup>

VisualState defines the animation storyboard to be triggered once the button switches to the Pressed state.

We can also add VisualStateTransition to the VisualStateGroup element's Transition property:

<VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualStateGroup.Transitions> ... <VisualTransition To="Pressed" GeneratedDuration="0:0:0.5"> <VisualTransition.GeneratedEasingFunction> <!-- elastic ease will provide a few attenuating bounces before the pressed button reaches a steady state --> <ElasticEase /> </VisualTransition.GeneratedEasingFunction> </VisualTransition> </VisualStateGroup.Transitions> ... </VisuateStateGroup> </VisualStateManager.VisualStateGroups>

VisualTransition elements allow us to modify the animation behavior depending on what the original and final states of the transition are. It has properties such as From and To for the purpose of specifying the original and final states. In our case, we set only its To property to Pressed, which means that it applies to transit from any state to the Pressed state. VisualTransition sets the duration of the animation to 0.5 second and adds the ElasticEase easing function to it, which results in the button size bouncing effect.

Once we started talking about easing functions, we can explain in detail how they work, and give examples of other easing functions.

Easing functions provide a way to modify Silverlight (and WPF) animations. A good article describing easing functions can be found at http://tinyurl.com/arbitrarypathanimations. The easing formula presented in this article is:

v = (V2 – V1)/T * f(t/T) + V1

Here v is the resulting animation value, t is the time parameter, T is the time period in question (either time between two frames in an animation with frames or time between the To and From values in the case of a simple animation), V2 and V1 are the animation values at the end and beginning of the animation correspondingly at the absence of easing, and f is the easing function. In the previous formula, we assumed a linear animation (not a spline one).

There are a bunch of built-in easing functions that come together with the Silverlight framework, for example, BackEase, BounceEase, CircleEase, and so on. For a comprehensive list of built-in easing functions, please check the following website: http://tinyurl.com/silverlighteasing.. Most easing functions have parameters described on this website. As an exercise you can change the easing function in the previous VisualTransition XAML code, modify its parameters, and observe the changes in button animation.

Summary

Here we have just learned how to animate a built-in button using Silverlight.

Resources for Article :


Further resources on this subject:


Instant Silverlight 5 Animation [Instant] Enrich your web page or Silverlight business application with Silverlight animations book and ebook.
Published: January 2013
eBook Price: £7.99
See more
Select your format and quantity:

About the Author :


Nick Polyak

Nick Polyak is a technology enthusiast who enjoys building software and learning new technologies. For the past six years, Nick worked primarily on Silverlight/WPF projects, and prior to that he worked with C++ and Java. Nick is looking forward to harnessing the new capabilities coming with HTML5 and modern JavaScript libraries.

Nick got his Ph.D. from Rensselaer Polytechnic Institute in 1998. He did his research in Wavelet based image processing and published a number of papers on the subject.

More recently Nick published several articles on codeproject.com some of which (a Prism tutorial and an article on MVVM) became quite popular.

Nick is the owner of the AWebPros.com consulting company.

Books From Packt


Windows Phone 7 Silverlight Cookbook
Windows Phone 7 Silverlight Cookbook

Android 3.0 Animations: Beginner’s Guide
Android 3.0 Animations: Beginner’s Guide

3D Game Development with Microsoft Silverlight 3: Beginner's Guide
3D Game Development with Microsoft Silverlight 3: Beginner's Guide

Silverlight 4 User Interface Cookbook
NSilverlight 4 User Interface Cookbook

Microsoft Silverlight 5 and Windows Azure Enterprise Integration
Microsoft Silverlight 5 and Windows Azure Enterprise Integration

Microsoft Silverlight 5: Building Rich Enterprise Dashboards
Microsoft Silverlight 5: Building Rich Enterprise Dashboards

MVVM Survival Guide for Enterprise Architectures in Silverlight and WPF
MVVM Survival Guide for Enterprise Architectures in Silverlight and WPF

Mastering LOB Development for Silverlight 5: A Case Study in Action
Mastering LOB Development for Silverlight 5: A Case Study in Action


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software