17 August 2013

Extension methods to animate scaling and opacity on Windows Phone

This is the first part of a tree-part series handling animating scaling and opacity. If you kind of wonder how the hell something that simple can require three blog posts – bear with me, it will all become clear in the end.

For a game that – at the moment of this writing – I have just submitted to the Windows Phone Store I have developed a number of extension methods to animate a number of properties of a GUI element. You have already seen extension methods to animate an object over the screen via waypoints –that’s also part of the package that will be added to my wp7nl library on CodePlex, just as the extension methods that below that animate scaling and opacity. They are actually pretty simple, and are built on top of the  translation extension methods I already wrote earlier for animations. If have temporarily added them to a “StoryboardExtensions3” class – in wp7nl all the methods will sit snugly together in “StoryboardExtensions”

First, the class with the scaling methods:

using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Wp7nl.Utilities
{
  /// <summary>
  /// Extension methods to add animations to a storyboard
  /// </summary>
  public static class StoryboardExtensions3
  {
    public static void AddScalingAnimation(this Storyboard storyboard,
                                           FrameworkElement fe, double fromX, double toX, 
                                           double fromY, double toY, Duration duration)
    {
      storyboard.AddScalingAnimation(fe, fromX, toX, fromY, toY, duration, null);
    }

    public static void AddScalingAnimation(this Storyboard storyboard,
                                           FrameworkElement fe, double fromX, double toX, 
                                           double fromY, double toY, Duration duration,
                                           IEasingFunction easingFunction)
    {
      storyboard.AddAnimation(fe.RenderTransform,
                  storyboard.CreateDoubleAnimation(duration, fromX, toX, easingFunction),
                     CompositeTransform.ScaleXProperty);
      storyboard.AddAnimation(fe.RenderTransform,
                  storyboard.CreateDoubleAnimation(duration, fromY, toY, easingFunction),
                     CompositeTransform.ScaleYProperty);
    }
  }
}

if you have read the earlier article, there is not much special in there. The heavy lifting has already been done earlier, by making the CreateDoubleAnimation and AddAnimation extension methods. You can use the AddScaling methods to scale an object over Y from 1 to 0 (notice X stays the same), which will effectively let it disappear by folding the object upwards to a horizontal line, by using this code:

myGuiElement.RenderTransform = new CompositeTransform();
var s = new Storyboard();
s.AddScalingAnimation(myGuiElement, 1, 1, 1, 0, TimeSpan.FromMilliseconds(500));
s.Begin();
or letting it mirror itself over the X-axis by changing the 4th line to
s.AddScalingAnimation(myGuiElement, 1, -1, 1, 1, TimeSpan.FromMilliseconds(500));

I made a very similar set of methods for Opacity:

public static void AddOpacityAnimation(this Storyboard storyboard,
                                       UIElement fe, double from, double to, 
                                       Duration duration)
{
  AddOpacityAnimation(storyboard, fe, from, to, duration, null);
}

public static void AddOpacityAnimation(this Storyboard storyboard,
          UIElement fe, double from, double to, Duration duration,
          IEasingFunction easingFunction)
{
  storyboard.AddAnimation(fe,
         storyboard.CreateDoubleAnimation(duration, from, to, easingFunction),
         UIElement.OpacityProperty);
}

Opacity runs from 1 (totally visible) to 0 (totally transparent) so with this code:

var s = new Storyboard();
s.AddOpacityAnimation(myGuiElement, 1, 0, TimeSpan.FromMilliseconds(500));
s.Begin();

”myGuiElement” will fade out in half a second. And even more fun is combining the code to:

myGuiElement.RenderTransform = new CompositeTransform();
var s = new Storyboard();
s.AddScalingAnimation(myGuiElement, 1, 1, 1, 0, TimeSpan.FromMilliseconds(500));
s.AddOpacityAnimation(myGuiElement, 1, 0, TimeSpan.FromMilliseconds(500)); s.Begin();

foldingNow the element will fold up and fade out simultaneously. And that’s exactly what happens is this little demo app that contains all the source code. And it shows you how to do the opposite as well – fold the window out again.

I can hear you think now: “So why on earth would you want to do this from code? Animations can be made can be made in Blend, and if you are such a Blend fan, why do you make me do it from code now, huh?”. I am an probably always will be a Blend fan – very much so, as will become clear soon – but the problem with this kind of animations is that they are not reusable. Storyboards tend to become attached to the element they have been created for – they refer by name to it. So I am trying to find a way to make a few common animations reusable. Read the next posts, and it will become clear. In the mean time, enjoy this demo application that demonstrates how to use the stuff.

 

On more for the road: if you add following line of at the top of both the Button_Click and Button_Click1 in the demo app:

FoldingPanel.RenderTransformOrigin = new Point(0.5, 0.5);

the panel won’t fold up to the top, but it will kind of collapse on its horizontal middle. This way, you set the origin of the animation. By setting it to 0.5, 0.5 you set it in the center point of the window. If you would set it to 1,1 the panel will fold up to its bottom.

And finally – although developed for Windows Phone 8, this this will work in Windows Phone 7 as well. And most likely for Windows 8, which will get some attention from me when this game is finally done. I think ;-)

No comments: