本主题介绍用于对属性进行动画处理的不同方法:情节提要、本地动画、时钟和每帧动画。
先决条件
若要了解本主题,应熟悉 动画概述中所述的基本动画功能。
动画处理的不同方法
由于有多种属性动画化的场景,WPF 提供了多种属性动画化的方法。
对于每个方法,下表指示是否可以在样式、控件模板或数据模板中使用每个实例;是否可以在 XAML 中使用;以及该方法是否允许你以交互方式控制动画。 “Per-Instance”是指一种将动画或故事板直接应用于对象实例的技术,而不是应用于样式、控件模板或数据模板中。
动画技术 | 情境 | 支持 XAML | 交互式可控制 |
---|---|---|---|
情节提要动画 | 每个实例、Style、ControlTemplate、DataTemplate | 是的 | 是的 |
本地动画 | 每个实例 | 否 | 否 |
时钟动画 | 每个实例 | 否 | 是的 |
每帧动画 | 每个实例 | 否 | 无 |
情节提要动画
在您想在 XAML 中定义和应用动画、在动画启动后互动地控制它们、创建复杂的动画树、或在Style、ControlTemplate或DataTemplate中进行动画时,请使用Storyboard。 要使对象由某个Storyboard进行动画处理,它必须是一个FrameworkElement或FrameworkContentElement,或者必须用于设置FrameworkElement或FrameworkContentElement。 有关更多详细信息,请参阅 情节提要概述。
A Storyboard 是一种特殊类型的容器 Timeline ,它为它包含的动画提供目标信息。 若要使用 a Storyboard进行动画处理,请完成以下三个步骤。
声明一个 Storyboard 并声明一个或多个动画。
TargetName TargetProperty使用附加属性指定每个动画的目标对象和属性。
(仅限代码)为 FrameworkElement 或 FrameworkContentElement 定义一个 NameScope。 注册动画对象的名称与FrameworkElement或FrameworkContentElement一起。
开始 Storyboard。
启动Storyboard后,对其动画属性应用动画并开始动画。 有两种方法可以开始Storyboard:可以使用Storyboard类提供的Begin方法,或者使用BeginStoryboard动作。 在 XAML 中进行动画处理的唯一方法是使用 BeginStoryboard 动作。 BeginStoryboard动作可以用于EventTrigger、Trigger属性或DataTrigger中。
下表显示了支持每个 Storyboard 开始技术的不同位置:每个实例、样式、控件模板和数据模板。
故事板已经开始使用… | 每个实例 | 风格 | 控件模板 | 数据模板 | 示例: |
---|---|---|---|---|---|
BeginStoryboard 和 EventTrigger | 是的 | 是的 | 是的 | 是的 | 使用故事板为属性添加动画效果 |
BeginStoryboard 和属性 Trigger | 否 | 是的 | 是的 | 是的 | 当属性值更改时触发动画 |
BeginStoryboard 和 a DataTrigger | 否 | 是的 | 是的 | 是的 | 如何:在数据更改时触发动画 |
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.
*/
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 属性应用于属性,请完成以下步骤。
创建一个 AnimationTimeline 对象。
使用要进行动画处理的对象的方法,把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 应用于您指定的属性。
有关时钟对象的详细信息,请参阅 动画和计时系统概述。
Per-Frame 动画:绕过动画和计时系统
如果需要完全绕过 WPF 动画系统,请使用此方法。 此方法的一种方案是物理动画,其中动画中的每个步骤都需要基于最后一组对象交互重新计算对象。
不能在样式、控件模板或数据模板内定义每帧动画。
若要逐帧动画,请注册包含要创建动画对象的Rendering事件。 每个帧调用一次此事件处理程序方法。 每次 WPF 将可视化树中持久呈现数据封送到合成树时,都会调用事件处理程序方法。
在事件处理程序中,执行动画效果所需的任何计算,并设置要使用这些值进行动画处理的对象的属性。
若要获取当前帧的呈现时间,可以将与此事件关联的 EventArgs 转换为 RenderingEventArgs,该对象中包含一个可用于获取当前帧呈现时间的 RenderingTime 属性。
有关详细信息,请参阅 Rendering 页面。