属性动画技术概述
本主题介绍了处理动画属性的不同方法:情节提要、本地动画、时钟和基于帧的动画。
先决条件
若要了解本主题,应熟悉动画概述中描述的基本动画功能。
动画处理的不同方法
由于动画处理属性存在多种不同的方案,因此,WPF 为动画处理属性提供了几种方法。
对于每种方法,下表指明了它是否可以基于实例在样式、控件模板或数据模板中使用;它是否可以在 XAML 中使用;以及该方法是否使你能够以交互方式控制动画。 “基于实例”是指直接将动画或情节提要应用于对象实例(而不是在样式、控件模板或数据模板中应用)的技术。
动画技术 | 方案 | 支持 XAML | 可以交互方式控制 |
---|---|---|---|
情节提要动画 | 基于实例、Style、ControlTemplate、DataTemplate | 是 | 是 |
本地动画 | 基于实例 | 否 | 否 |
时钟动画 | 基于实例 | 否 | 是 |
基于帧的动画 | 基于实例 | 否 | 空值 |
情节提要动画
如果想在 XAML 中定义和应用动画、在动画开始后以交互方式控制动画、创建复杂的动画树或在 Style、ControlTemplate 或 DataTemplate 中进行动画处理,请使用 Storyboard。 对于要由 Storyboard 进行动画处理的对象,它必须是 FrameworkElement 或 FrameworkContentElement,或者它必须用于设置 FrameworkElement 或 FrameworkContentElement。 有关详细信息,请参阅情节提要概述。
Storyboard 是一种特殊类型的容器 Timeline,它为其所包含的动画提供目标信息。 若要使用 Storyboard 进行动画处理,请完成以下三个步骤。
声明 Storyboard 和一个或多个动画。
使用 TargetName 和 TargetProperty 附加属性来指定每个动画的目标对象和属性。
(仅限代码)为 FrameworkElement 或 FrameworkContentElement 定义 NameScope。 使用该 FrameworkElement 或 FrameworkContentElement.注册要进行动画处理的对象的名称。
开始 Storyboard。
开始 Storyboard 会将动画应用到它们进行动画处理的属性并启动它们。 有两种开始 Storyboard 的方法:可以使用 Storyboard 类提供的 Begin 方法,或者使用 BeginStoryboard 操作。 使用 BeginStoryboard 操作是在 XAML 中进行动画处理的唯一方法。 可以在 EventTrigger、Trigger 属性或 DataTrigger 中使用 BeginStoryboard 操作。
下表显示了支持 Storyboard 开始技术的不同位置:基于实例、样式、控件模板和数据模板。
情节提要开始时使用… | 基于实例 | 样式 | 控件模板 | 数据模板 | 示例 |
---|---|---|---|---|---|
BeginStoryboard 和 EventTrigger | 是 | 是 | 是 | 是 | 使用情节提要对属性进行动画处理 |
BeginStoryboard 和 Trigger 属性 | 否 | 是 | 是 | 是 | 在属性值更改时触发动画 |
BeginStoryboard 和 DataTrigger | 否 | 是 | 是 | 是 | 如何:在数据更改时触发动画 |
Begin 方法 | 是 | No | No | 否 | 使用情节提要对属性进行动画处理 |
有关 Storyboard 对象的详细信息,请参阅 Storyboard 概述。
本地动画
本地动画提供了一种快捷方式,用于动画处理任何 Animatable 对象的依赖属性。 如果想要将单一动画应用到属性中,可以使用本地动画,并且动画启动后不需要以交互方式控制动画。 与 Storyboard 动画不同,本地动画可以对与 FrameworkElement 或 FrameworkContentElement.无关联的对象进行动画处理。 你也无需为这种类型的动画定义 NameScope。
本地动画可能仅在代码中使用,无法在样式、控件模板或数据模板中定义。 本地动画启动后,无法以交互方式控制。
若要使用本地动画进行动画处理,应完成以下步骤。
创建一个 AnimationTimeline 对象。
使用要进行动画处理的对象的 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
时钟动画
如果想在不使用 Storyboard 的情况下进行动画处理,并且想在动画启动后创建复杂的计时树或以交互方式控制动画,请使用 Clock 对象。 可以使用 Clock 对象来动画处理任何 Animatable 对象的依赖属性。
无法在样式、控件模板或数据模板中直接使用 Clock 对象来进行动画处理。 (动画和计时系统实际上的确使用 Clock 对象在样式、控件模板或数据模板中进行动画处理,但它必须从 Storyboard 中为你创建这些 Clock 对象。有关 Storyboard 对象和 Clock 对象之间的关系的详细信息,请参阅动画和计时系统概述。)
若要将单个 Clock 应用到属性,请完成以下步骤。
创建一个 AnimationTimeline 对象。
使用 AnimationTimeline 的 CreateClock 方法以创建 AnimationClock。
使用要进行动画处理的对象的 ApplyAnimationClock 方法以将 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
如果想要创建一个计时树并用其处理动画属性,应完成以下几个步骤。
使用 ParallelTimeline 和 AnimationTimeline 对象以创建计时树。
使用 ParallelTimeline 根的 CreateClock 以创建 ClockGroup。
循环访问 ClockGroup 的 Children 并应用其子 Clock 对象。 对于每个 AnimationClock 子项,请使用想要进行动画处理的对象的 ApplyAnimationClock 方法以将 AnimationClock 应用到所指定的属性
有关时钟对象的详细信息,请参阅动画和计时系统概述。
基于帧的动画:绕过动画和计时系统
如果需要完全绕过 WPF 动画系统,请使用此方法。 此方法的一个方案是物理动画,其中的每个动画步骤都要求基于最后一组对象交互来重新计算。
基于帧的动画无法在样式、控件模板或数据模板内定义。
若要逐帧进行动画处理,应注册对象的 Rendering 事件,该对象包含想要进行动画处理的对象。 每帧会调用一次此事件处理程序方法。 每次 WPF 将可视化树中的持久呈现数据封送到复合树时,都将调用事件处理程序方法。
在事件处理程序中,执行动画效果所需的任何计算,并设置想要使用这些值进行动画处理的对象的属性。
若要获取当前帧的呈现时间,可以将与此事件相关联的 EventArgs 强制转换为 RenderingEventArgs,这将提供可用于获取当前帧的呈现时间的 RenderingTime 属性。
有关更多信息,请参阅 Rendering 页。