Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't these animations work when I'm using a storyboard?

I've created a simple subclass of StackPanel that I can move around on the screen using an animated TranslateTransform. It looks like this:

public class MovingStackPanel : StackPanel
{
    public void BeginMove(Point translatePosition)
    {
        RenderTransform = new TranslateTransform();
        Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400));
        DoubleAnimation x = new DoubleAnimation(translatePosition.X, d);
        DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d);
        /*
        Storyboard.SetTarget(x, RenderTransform);
        Storyboard.SetTargetProperty(x, new PropertyPath("X"));

        Storyboard.SetTarget(y, RenderTransform);
        Storyboard.SetTargetProperty(y, new PropertyPath("Y"));

        Storyboard sb = new Storyboard();
        sb.Children.Add(x);
        sb.Children.Add(y);
        sb.Completed += sb_Completed;
        sb.Begin();
        */
        RenderTransform.BeginAnimation(TranslateTransform.XProperty, x);
        RenderTransform.BeginAnimation(TranslateTransform.YProperty, y);
    }

    void sb_Completed(object sender, EventArgs e)
    {
        Console.WriteLine("Completed.");
    }
} 

And here is my problem: If I animate the X and Y properties directly, as the code above does, it works. But if I use the commented-out code above it, which is really the simplest creation of a Storyboard in code imaginable, nothing happens. The animation runs - at least, the Completed event gets raised - but nothing changes on the screen.

Clearly I'm doing something wrong, but I can't see what it is. Every example of creating storyboards in code I've seen looks just like this. There's obviously something about animations and storyboards that I don't know yet: what is it?

like image 573
Robert Rossney Avatar asked Feb 26 '10 00:02

Robert Rossney


People also ask

Can you animate without storyboard?

Animations can be applied without using the StoryBoard. BeginAnimation() method can be used to apply animations instead of StoryBoard. This method can be used when simple animations are applied to a property of a control. The following code snippet animates the width of the TextBlock using the 'BeginAnimation' method.

Why do animators use storyboards *?

Creating a storyboard allows animation studios to prepare a clear outline for developing the video, including information about the critical requirements. Storyboards are essential because they help studios define the parameters of the story within the required resources and time.

What is 3D storyboard?

A storyboard is a series of drawings that provide a basic outline of the final 3D animation. Much like a rough draft helps plan out a written piece, a storyboard helps plan out a completed film or TV production. The basic premise conveyed by the storyboard will then be refined throughout the life of the project.


2 Answers

As it turns out, you can't use property path syntax in this case, because the properties being animated aren't properties of a FrameworkElement. At least, that's how I interpret the remarkably bewildering exception that I get when I make the change that Anvaka suggested:

Cannot automatically create animation clone for frozen property values on     
'System.Windows.Media.TranslateTransform' objects. Only FrameworkElement and 
FrameworkContentElement (or derived) types are supported.

To animate those, it seems, I have to use a NameScope and use SetTargetName to name the TransformElement. Then, as long as I pass the FrameworkElement that I set the name scope on to the Begin method, the storyboard can find the object and the properties and animate them and it all works. The end result looks like this:

public void BeginMove(Point translatePosition)
{
    NameScope.SetNameScope(this, new NameScope());

    RenderTransform = new TranslateTransform();
    RegisterName("TranslateTransform", RenderTransform);

    Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400));
    DoubleAnimation x = new DoubleAnimation(translatePosition.X, d);
    DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d);

    Storyboard.SetTargetName(x, "TranslateTransform");
    Storyboard.SetTargetProperty(x, new PropertyPath(TranslateTransform.XProperty));

    Storyboard.SetTargetName(y, "TranslateTransform");
    Storyboard.SetTargetProperty(y, new PropertyPath(TranslateTransform.YProperty));

    Storyboard sb = new Storyboard();
    sb.Children.Add(x);
    sb.Children.Add(y);
    sb.Completed += sb_Completed;

    // you must pass this to the Begin method, otherwise the timeline won't be
    // able to find the named objects it's animating because it doesn't know
    // what name scope to look in

    sb.Begin(this);

}
like image 60
Robert Rossney Avatar answered Nov 16 '22 03:11

Robert Rossney


It's property path syntax. The following approach works:

public void BeginMove(Point translatePosition)
{
  RenderTransform = new TranslateTransform();
  Duration d = new Duration(new TimeSpan(0, 0, 0, 0, 400));
  DoubleAnimation x = new DoubleAnimation(translatePosition.X, d);
  DoubleAnimation y = new DoubleAnimation(translatePosition.Y, d);

  Storyboard.SetTarget(x, this);
  Storyboard.SetTargetProperty(x, 
              new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));

  Storyboard.SetTarget(y, this);
  Storyboard.SetTargetProperty(y, 
              new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

  Storyboard sb = new Storyboard();
  sb.Children.Add(x);
  sb.Children.Add(y);
  sb.Completed += sb_Completed;
  sb.Begin();

  //RenderTransform.BeginAnimation(TranslateTransform.XProperty, x);
  //RenderTransform.BeginAnimation(TranslateTransform.YProperty, y);
}
like image 37
Anvaka Avatar answered Nov 16 '22 02:11

Anvaka