属性动画技术概述
本主题描述对属性进行动画处理的不同方法:演示图板、本地动画、时钟以及基于帧的动画。
先决条件
若要了解本主题,您应当熟悉动画概述中介绍的基本动画功能。
不同的动画处理方式
由于对属性进行动画处理有多种不同的方案,因此 WPF 为属性的动画处理提供了多种方法。
下表指示每种方法是否可基于实例使用;是否可用于样式、控件模板或数据模板;是否可用于 XAML 以及是否可以使用该方法以交互方式控制动画。 “基于实例”指的是直接将动画或演示图板应用于对象实例(而不是在样式、控件模板或数据模板中应用)的技术。
动画技术 |
方案 |
支持 XAML |
可交互控制 |
---|---|---|---|
演示图板动画 |
是 |
是 |
|
本地动画 |
基于实例 |
否 |
否 |
时钟动画 |
基于实例 |
否 |
是 |
基于帧的动画 |
基于实例 |
否 |
不可用 |
演示图板动画
在以下情形中使用 Storyboard:要在 XAML 中定义并应用动画;在动画开始之后以交互的方式控制动画;创建一个复杂的动画树;或者在 Style、ControlTemplate 或 DataTemplate 中进行动画处理。 对于需要通过 Storyboard 进行动画处理的对象,它必须是 FrameworkElement 或 FrameworkContentElement,或者它必须用于设置 FrameworkElement 或 FrameworkContentElement。 有关更多详细信息,请参见演示图板概述。
Storyboard 是一种为其所包含的动画提供目标信息的特殊类型的容器 Timeline。 若要使用 Storyboard 进行动画处理,需要完成下列三个步骤。
声明一个 Storyboard 以及一个或多个动画。
使用 TargetName 和 TargetProperty 附加属性指定每个动画的目标对象和属性。
(仅限代码)为 FrameworkElement 或 FrameworkContentElement 定义一个 NameScope。 对将要与该 FrameworkElement 或 FrameworkContentElement 进行动画处理的对象名称进行注册。
启动 Storyboard。
启动 Storyboard 会将动画应用到它们进行动画处理的属性并将其启动。 启动 Storyboard 的方法有两种:使用 Storyboard 类提供的 Begin 方法,或者使用 BeginStoryboard 操作。 在 XAML 中进行动画处理的唯一方法是使用 BeginStoryboard 操作。BeginStoryboard 操作可用于 EventTrigger、属性 Trigger 或 DataTrigger。
下表列出了支持每个 Storyboard 开始技术的不同方面:基于实例、样式、控件模板和数据模板。
开始演示图板时使用… |
基于实例 |
样式 |
控件模板 |
数据模板 |
示例 |
---|---|---|---|---|---|
是 |
是 |
是 |
是 |
||
否 |
是 |
是 |
是 |
||
否 |
是 |
是 |
是 |
||
Begin 方法 |
是 |
否 |
否 |
否 |
有关 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.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Imports System
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
/*
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.
*/
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;
};
};
}
}
}
}
时钟动画
在以下情形中使用 Clock 对象:在不使用 Storyboard 的情况下需要进行动画处理;在动画启动后需要创建复杂的计时树或需要以交互方式控制动画。 可以使用 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.
'
Imports System
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 myScaleTransform As ScaleTransform
Public Sub New()
Me.WindowTitle = "Opacity Animation Example"
Me.Background = Brushes.White
Dim myStackPanel As New StackPanel()
myStackPanel.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()
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.
AddHandler myButton.Click, AddressOf myButton_Clicked
myStackPanel.Children.Add(myButton)
Me.Content = myStackPanel
End Sub
' Create and apply and animation when the button is clicked.
Private Sub myButton_Clicked(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Create a DoubleAnimation to animate the
' ScaleTransform.
Dim myAnimation As New DoubleAnimation(1, 5, New Duration(TimeSpan.FromSeconds(5))) ' "To" value - "From" value
myAnimation.AutoReverse = True
' 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
/*
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);
}
}
}
若要创建一个计时树并用其对属性进行动画处理,需要完成以下步骤。
使用 ParallelTimeline 和 AnimationTimeline 对象来创建计时树。
使用根 ParallelTimeline 的 CreateClock 来创建 ClockGroup。
循环访问 ClockGroup 的 Children 并应用其 Clock 子对象。 对于每个 AnimationClock 子级,使用需要对其进行动画处理的对象的 ApplyAnimationClock 方法将 AnimationClock 应用到您指定的属性。
有关 Clock 对象的更多信息,请参见动画和计时系统概述。
基于帧的动画:跳过动画和计时系统
当需要完全绕过 WPF 动画系统时使用此方法。 此方法的一个方案是物理动画,其中动画中的每一步都需要基于最后一组对象交互重新计算对象。
基于帧的动画无法在样式、控件模板或数据模板中进行定义。
若要逐帧进行动画处理,您应注册对象(该对象包含需要进行动画处理的对象)的 Rendering 事件。 每帧调用一次此事件处理程序方法。 每次 WPF 将可视化树中的保留呈现数据封送到组合树中时,都会调用您的事件处理程序方法。
在事件处理程序中,需要对动画效果执行任意的计算,并设置需要使用这些值进行动画处理的对象的属性。
若要获取当前帧的显示时间,可以将与此事件相关的 EventArgs 强制转换为 RenderingEventArgs,从而提供可用于获取当前帧呈现时间的 RenderingTime 属性。
有关更多信息,请参见 Rendering 页。