属性动画技术概述

本主题介绍用于对属性进行动画处理的不同方法:情节提要、本地动画、时钟和每帧动画。

先决条件

若要了解本主题,应熟悉 动画概述中所述的基本动画功能。

动画处理的不同方法

由于有多种属性动画化的场景,WPF 提供了多种属性动画化的方法。

对于每个方法,下表指示是否可以在样式、控件模板或数据模板中使用每个实例;是否可以在 XAML 中使用;以及该方法是否允许你以交互方式控制动画。 “Per-Instance”是指一种将动画或故事板直接应用于对象实例的技术,而不是应用于样式、控件模板或数据模板中。

动画技术 情境 支持 XAML 交互式可控制
情节提要动画 每个实例、StyleControlTemplateDataTemplate 是的 是的
本地动画 每个实例
时钟动画 每个实例 是的
每帧动画 每个实例

情节提要动画

在您想在 XAML 中定义和应用动画、在动画启动后互动地控制它们、创建复杂的动画树、或在StyleControlTemplateDataTemplate中进行动画时,请使用Storyboard。 要使对象由某个Storyboard进行动画处理,它必须是一个FrameworkElementFrameworkContentElement,或者必须用于设置FrameworkElementFrameworkContentElement。 有关更多详细信息,请参阅 情节提要概述

A Storyboard 是一种特殊类型的容器 Timeline ,它为它包含的动画提供目标信息。 若要使用 a Storyboard进行动画处理,请完成以下三个步骤。

  1. 声明一个 Storyboard 并声明一个或多个动画。

  2. TargetName TargetProperty使用附加属性指定每个动画的目标对象和属性。

  3. (仅限代码)为 FrameworkElementFrameworkContentElement 定义一个 NameScope。 注册动画对象的名称与FrameworkElementFrameworkContentElement一起。

  4. 开始 Storyboard

启动Storyboard后,对其动画属性应用动画并开始动画。 有两种方法可以开始Storyboard:可以使用Storyboard类提供的Begin方法,或者使用BeginStoryboard动作。 在 XAML 中进行动画处理的唯一方法是使用 BeginStoryboard 动作。 BeginStoryboard动作可以用于EventTriggerTrigger属性或DataTrigger中。

下表显示了支持每个 Storyboard 开始技术的不同位置:每个实例、样式、控件模板和数据模板。

故事板已经开始使用… 每个实例 风格 控件模板 数据模板 示例:
BeginStoryboardEventTrigger 是的 是的 是的 是的 使用故事板为属性添加动画效果
BeginStoryboard 和属性 Trigger 是的 是的 是的 当属性值更改时触发动画
BeginStoryboard 和 a DataTrigger 是的 是的 是的 如何:在数据更改时触发动画
Begin 方法 是的 使用故事板为属性添加动画效果

关于Storyboard对象的详细信息,请参阅情节提要概述

本地动画

本地动画提供了一种便捷的方法,可以对任何 Animatable 对象的依赖属性进行动画处理。 如果要将单个动画应用于属性,并且无需在动画启动时以交互方式控制动画,请使用本地动画。 本地动画不同于Storyboard动画,可以对未与FrameworkElementFrameworkContentElement关联的对象进行动画处理。 你也不必为这种类型的动画定义一个 NameScope

本地动画只能在代码中使用,不能在样式、控件模板或数据模板中定义。 启动本地动画后无法以交互方式控制。

若要使用本地动画进行动画处理,请完成以下步骤。

  1. 创建一个 AnimationTimeline 对象。

  2. 通过使用要进行动画处理的对象的BeginAnimation方法,将AnimationTimeline应用于您指定的属性。

下面的示例演示如何对 Button的宽度和背景色进行动画处理。

/*

   This sample demonstrates how to apply non-storyboard animations to a property.
   To animate in markup, you must use storyboards.

*/

using namespace System;
using namespace System::Windows;
using namespace System::Windows::Navigation;
using namespace System::Windows::Media;
using namespace System::Windows::Media::Animation;
using namespace System::Windows::Shapes;
using namespace System::Windows::Controls;


namespace Microsoft {
   namespace Samples {
      namespace Animation {
         namespace LocalAnimations {
            // Create the demonstration.
            public ref class LocalAnimationExample : Page {

            public: 
               LocalAnimationExample ()
               {
                  WindowTitle = "Local Animation Example";
                  StackPanel^ myStackPanel = gcnew StackPanel();
                  myStackPanel->Margin = Thickness(20);

                  // Create and set the Button.
                  Button^ aButton = gcnew Button();
                  aButton->Content = "A Button";

                  // Animate the Button's Width.
                  DoubleAnimation^ myDoubleAnimation = gcnew DoubleAnimation();
                  myDoubleAnimation->From = 75;
                  myDoubleAnimation->To = 300;
                  myDoubleAnimation->Duration = Duration(TimeSpan::FromSeconds(5));
                  myDoubleAnimation->AutoReverse = true;
                  myDoubleAnimation->RepeatBehavior = RepeatBehavior::Forever;

                  // Apply the animation to the button's Width property.
                  aButton->BeginAnimation(Button::WidthProperty, myDoubleAnimation);

                  // Create and animate a Brush to set the button's Background.
                  SolidColorBrush^ myBrush = gcnew SolidColorBrush();
                  myBrush->Color = Colors::Blue;

                  ColorAnimation^ myColorAnimation = gcnew ColorAnimation();
                  myColorAnimation->From = Colors::Blue;
                  myColorAnimation->To = Colors::Red;
                  myColorAnimation->Duration = Duration(TimeSpan::FromMilliseconds(7000));
                  myColorAnimation->AutoReverse = true;
                  myColorAnimation->RepeatBehavior = RepeatBehavior::Forever;

                  // Apply the animation to the brush's Color property.
                  myBrush->BeginAnimation(SolidColorBrush::ColorProperty, myColorAnimation);
                  aButton->Background = myBrush;

                  // Add the Button to the panel.
                  myStackPanel->Children->Add(aButton);
                  this->Content = myStackPanel;
               };
            };
         }
      }
   }
}
/*

   This sample demonstrates how to apply non-storyboard animations to a property.
   To animate in markup, you must use storyboards.

*/

using System;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace Microsoft.Samples.Animation.LocalAnimations
{

    // Create the demonstration.
    public class LocalAnimationExample : Page
    {

        public LocalAnimationExample()
        {

            WindowTitle = "Local Animation Example";
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            // Create and set the Button.
            Button aButton = new Button();
            aButton.Content = "A Button";

            // Animate the Button's Width.
            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 75;
            myDoubleAnimation.To = 300;
            myDoubleAnimation.Duration =  new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Apply the animation to the button's Width property.
            aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation);

            // Create and animate a Brush to set the button's Background.
            SolidColorBrush myBrush = new SolidColorBrush();
            myBrush.Color = Colors.Blue;

            ColorAnimation myColorAnimation = new ColorAnimation();
            myColorAnimation.From = Colors.Blue;
            myColorAnimation.To = Colors.Red;
            myColorAnimation.Duration =  new Duration(TimeSpan.FromMilliseconds(7000));
            myColorAnimation.AutoReverse = true;
            myColorAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Apply the animation to the brush's Color property.
            myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation);
            aButton.Background = myBrush;

            // Add the Button to the panel.
            myStackPanel.Children.Add(aButton);
            this.Content = myStackPanel;
        }
    }
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''This sample demonstrates how to apply non-storyboard animations to a property.
'''To animate in markup, you must use storyboards.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Imports System.Windows
Imports System.Windows.Navigation
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports System.Windows.Controls

Namespace Microsoft.Samples.Animation.LocalAnimations

    ' Create the demonstration.
    Public Class LocalAnimationExample
        Inherits Page

        Public Sub New()

            WindowTitle = "Animate Property Example"
            Dim myStackPanel As New StackPanel()
            myStackPanel.Margin = New Thickness(20)

            ' Create and set the Button.
            Dim aButton As New Button()
            aButton.Content = "A Button"

            ' Animate the Button's Width.
            Dim myDoubleAnimation As New DoubleAnimation()
            myDoubleAnimation.From = 75
            myDoubleAnimation.To = 300
            myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
            myDoubleAnimation.AutoReverse = True
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

            ' Apply the animation to the button's Width property.
            aButton.BeginAnimation(Button.WidthProperty, myDoubleAnimation)

            ' Create and animate a Brush to set the button's Background.
            Dim myBrush As New SolidColorBrush()
            myBrush.Color = Colors.Blue

            Dim myColorAnimation As New ColorAnimation()
            myColorAnimation.From = Colors.Blue
            myColorAnimation.To = Colors.Red
            myColorAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(7000))
            myColorAnimation.AutoReverse = True
            myColorAnimation.RepeatBehavior = RepeatBehavior.Forever

            ' Apply the animation to the brush's Color property.
            myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation)
            aButton.Background = myBrush

            ' Add the Button to the panel.
            myStackPanel.Children.Add(aButton)
            Me.Content = myStackPanel
        End Sub
    End Class
End Namespace

时钟动画

Clock对象允许您在不使用Storyboard来进行动画时,创建复杂的时间树或在动画开始后交互控制动画。 可以使用时钟对象对任何 Animatable 对象的依赖属性进行动画处理。

不能直接使用 Clock 对象对样式、控件模板或数据模板进行动画处理。 (动画和计时系统实际上确实使用Clock对象对样式、控件模板和数据模板进行动画处理,但它必须为您从一个Storyboard创建这些Clock对象。有关Storyboard对象与Clock对象之间的关系的详细信息,请参阅动画和计时系统概述。)

若要将单个 Clock 属性应用于属性,请完成以下步骤。

  1. 创建一个 AnimationTimeline 对象。

  2. 使用CreateClock方法AnimationTimeline来创建一个AnimationClock

  3. 使用要进行动画处理的对象的方法,把AnimationClock应用到您指定的属性上。

以下示例演示如何创建一个 AnimationClock 并将其应用于两个类似的属性。

/*
    This example shows how to create and apply
    an AnimationClock.
*/

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Microsoft.Samples.Animation.TimingBehaviors
{
    public class AnimationClockExample : Page
    {

        ScaleTransform myScaleTransform;

        public AnimationClockExample()
        {

            this.WindowTitle = "Opacity Animation Example";
            this.Background = Brushes.White;
            StackPanel myStackPanel = new StackPanel();
            myStackPanel.Margin = new Thickness(20);

            // Create a button that with a ScaleTransform.
            // The ScaleTransform will animate when the
            // button is clicked.
            Button myButton = new Button();
            myButton.Margin = new Thickness(50);
            myButton.HorizontalAlignment = HorizontalAlignment.Left;
            myButton.Content = "Click Me";
            myScaleTransform = new ScaleTransform(1,1);
            myButton.RenderTransform = myScaleTransform;

            // Associate an event handler with the
            // button's Click event.
            myButton.Click += new RoutedEventHandler(myButton_Clicked);

            myStackPanel.Children.Add(myButton);
            this.Content = myStackPanel;
        }

        // Create and apply and animation when the button is clicked.
        private void myButton_Clicked(object sender, RoutedEventArgs e)
        {

            // Create a DoubleAnimation to animate the
            // ScaleTransform.
            DoubleAnimation myAnimation =
                new DoubleAnimation(
                    1, // "From" value
                    5, // "To" value
                    new Duration(TimeSpan.FromSeconds(5))
                );
            myAnimation.AutoReverse = true;

            // Create a clock the for the animation.
            AnimationClock myClock = myAnimation.CreateClock();

            // Associate the clock the ScaleX and
            // ScaleY properties of the button's
            // ScaleTransform.
            myScaleTransform.ApplyAnimationClock(
                ScaleTransform.ScaleXProperty, myClock);
            myScaleTransform.ApplyAnimationClock(
                ScaleTransform.ScaleYProperty, myClock);
        }
    }
}
'
'    This example shows how to create and apply
'    an AnimationClock.
'


Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes
Imports System.Windows.Media.Animation


Namespace Microsoft.Samples.Animation.TimingBehaviors
    Public Class AnimationClockExample
        Inherits Page

        Private ReadOnly myScaleTransform As ScaleTransform

        Public Sub New()

            WindowTitle = "Opacity Animation Example"
            Background = Brushes.White
            Dim myStackPanel As New StackPanel With {
                .Margin = New Thickness(20)
            }

                ' Create a button that with a ScaleTransform.
                ' The ScaleTransform will animate when the
                ' button is clicked.
            Dim myButton As New Button With {
                .Margin = New Thickness(50),
                .HorizontalAlignment = HorizontalAlignment.Left,
                .Content = "Click Me"
            }
            myScaleTransform = New ScaleTransform(1,1)
            myButton.RenderTransform = myScaleTransform


            ' Associate an event handler with the
            ' button's Click event.
            AddHandler myButton.Click, AddressOf myButton_Clicked

            myStackPanel.Children.Add(myButton)
            Content = myStackPanel
        End Sub

        ' Create and apply and animation when the button is clicked.
        Private Sub myButton_Clicked(sender As Object, e As RoutedEventArgs)

            ' Create a DoubleAnimation to animate the
            ' ScaleTransform.
            Dim myAnimation As New DoubleAnimation(1, 5, New Duration(TimeSpan.FromSeconds(5))) With {
                .AutoReverse = True
            } ' "To" value -  "From" value

            ' Create a clock the for the animation.
            Dim myClock As AnimationClock = myAnimation.CreateClock()

            ' Associate the clock the ScaleX and
            ' ScaleY properties of the button's
            ' ScaleTransform.
            myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleXProperty, myClock)
            myScaleTransform.ApplyAnimationClock(ScaleTransform.ScaleYProperty, myClock)
        End Sub
    End Class
End Namespace

若要创建计时树并使用它对属性进行动画处理,请完成以下步骤。

  1. 使用 ParallelTimelineAnimationTimeline 对象创建计时树。

  2. 使用根ParallelTimelineCreateClock来创建一个ClockGroup

  3. 遍历ClockGroup中的Children,并应用其子Clock对象。 对于每个 AnimationClock 子级,请使用 ApplyAnimationClock 要进行动画处理的对象的方法,将 AnimationClock 应用于您指定的属性。

有关时钟对象的详细信息,请参阅 动画和计时系统概述

Per-Frame 动画:绕过动画和计时系统

如果需要完全绕过 WPF 动画系统,请使用此方法。 此方法的一种方案是物理动画,其中动画中的每个步骤都需要基于最后一组对象交互重新计算对象。

不能在样式、控件模板或数据模板内定义每帧动画。

若要逐帧动画,请注册包含要创建动画对象的Rendering事件。 每个帧调用一次此事件处理程序方法。 每次 WPF 将可视化树中持久呈现数据封送到合成树时,都会调用事件处理程序方法。

在事件处理程序中,执行动画效果所需的任何计算,并设置要使用这些值进行动画处理的对象的属性。

若要获取当前帧的呈现时间,可以将与此事件关联的 EventArgs 转换为 RenderingEventArgs,该对象中包含一个可用于获取当前帧呈现时间的 RenderingTime 属性。

有关详细信息,请参阅 Rendering 页面。

另请参阅