动画概述

Windows Presentation Foundation (WPF) 提供了一组功能强大的图形和布局功能,使你能够创建有吸引力的用户界面和吸引人的文档。 动画可以使有吸引力的用户界面更加壮观和可用。 只需对背景色进行动画处理或应用动画 Transform,即可创建戏剧性的屏幕过渡或提供有用的视觉提示。

本概述介绍 WPF 动画和计时系统。 它通过使用故事板来重点介绍 WPF 对象的动画。

动画介绍

动画是通过快速循环浏览一系列图像创建的错觉,每个图像与上一个图像略有不同。 大脑将图像组视为一个不断变化的场景。 在电影中,这种错觉是通过使用摄影机,每秒钟录制许多帧或照片来创建的。 当帧由投影仪放映时,观众会看到动态影像。

计算机上的动画类似。 例如,使矩形的绘图淡出视图的程序可能如下所示。

  • 程序创建计时器。

  • 程序会以设置的间隔检查计时器,以查看已用了多少时间。

  • 每次程序检查计时器时,它都会根据所花费的时间计算矩形的当前不透明度值。

  • 然后,程序使用新值更新矩形并重新绘制该矩形。

在 WPF 之前,Microsoft Windows 开发人员必须创建和管理自己的计时系统或使用特殊的自定义库。 WPF 包括一个高效的计时系统,该系统通过托管代码和 XAML 公开,并深入集成到 WPF 框架中。 WPF 动画可轻松对控件和其他图形对象进行动画处理。

WPF 处理管理计时系统并有效地重新绘制屏幕的所有幕后工作。 它提供定时类,帮助您专注于想要创建的效果,而不是实现这些效果的具体操作。 WPF 还通过公开类可以继承的动画基类来生成自定义动画,从而轻松创建自己的动画。 这些自定义动画获得了标准动画类的许多性能优势。

WPF 属性动画系统

如果了解有关计时系统的一些重要概念,WPF 动画更易于使用。 最重要的是,在 WPF 中,通过对其各个属性应用动画来对对象进行动画处理。 例如,若要使框架元素增长,请对其 WidthHeight 属性进行动画处理。 若要使对象从视图中淡出,请对其 Opacity 属性进行动画处理。

若要使属性具有动画功能,它必须满足以下三个要求:

  • 它必须是依赖属性。

  • 它必须属于一个继承自 DependencyObject 类并实现 IAnimatable 接口的类。

  • 必须有一个兼容的动画类型可用。 (如果 WPF 不提供一个,则可以创建自己的。请参阅 自定义动画概述

WPF 包含许多具有 IAnimatable 属性的对象。 控件(如 ButtonTabControl)以及 Panel 对象 Shape 也继承自 DependencyObject。 它们的大多数属性都是依赖属性。

几乎可以在任何地方使用动画,其中包括样式和控件模板。 动画不必是视觉对象;如果对象符合本节中所述的条件,则可以对不属于用户界面的对象进行动画处理。

示例:使元素淡入和淡出视野

此示例演示如何使用 WPF 动画对依赖属性的值进行动画处理。 它使用一种生成Double值的DoubleAnimation动画类型,以对RectangleOpacity属性进行动画处理。 因此,Rectangle 在视图中时隐时现。

示例的第一部分创建一个 Rectangle 元素。 后续步骤演示如何创建动画并将其应用于矩形 Opacity 的属性。

下面演示如何在 XAML 中创建Rectangle元素StackPanel

<StackPanel Margin="10">
    <Rectangle
        Name="MyRectangle"
        Width="100" 
        Height="100"
        Fill="Blue">
    </Rectangle>
</StackPanel>

StackPanel中创建Rectangle元素的代码演示。

var myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);

var myRectangle = new Rectangle();
myRectangle.Name = "myRectangle";
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
myPanel.Children.Add(myRectangle);
this.Content = myPanel;
Dim myPanel As New StackPanel()
myPanel.Margin = New Thickness(10)

Dim myRectangle As New Rectangle()
myRectangle.Name = "myRectangle"
Me.RegisterName(myRectangle.Name, myRectangle)
myRectangle.Width = 100
myRectangle.Height = 100
myRectangle.Fill = Brushes.Blue

myPanel.Children.Add(myRectangle)
Me.Content = myPanel

第 1 部分:创建 DoubleAnimation

使元素淡入和淡出视图的一种方法是对其 Opacity 属性进行动画处理。 由于该 Opacity 属性的类型为类型 Double,因此需要生成双精度值的动画。 DoubleAnimation 是其中一种动画。 在两个双精度值之间创建DoubleAnimation转换。 若要指定其起始值,请设置其 From 属性。 若要指定其结束值,请设置其 To 属性。

  1. 不透明值 1.0 使对象完全不透明,不透明度值 0.0 使其完全不可见。 要使动画从1.0过渡到0.0,请将其From属性设置为1.0,并将其To属性设置为0.0。 下面演示如何在 XAML 中创建一个 DoubleAnimation

    <DoubleAnimation From="1.0" To="0.0" />
    

    下面演示如何在代码中创建一个 DoubleAnimation

    var myDoubleAnimation = new DoubleAnimation();
    myDoubleAnimation.From = 1.0;
    myDoubleAnimation.To = 0.0;
    
    Dim myDoubleAnimation As New DoubleAnimation()
    myDoubleAnimation.From = 1.0
    myDoubleAnimation.To = 0.0
    
  2. 接下来,您需要指定一个 Duration。 动画 Duration 指定从起始值到目标值所需的时间。 下面演示如何在 XAML 中将 Duration 设置为 5 秒。

    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" />
    

    下面演示如何在代码中将 Duration 设置为 5 秒。

    myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
    
    myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
    
  3. 前面的代码展示了一个从 1.0 过渡到 0.0 的动画,使目标元素从完全不透明逐渐变为完全不可见。 若要使元素消失后重新淡入视图,请将动画的属性设置为 AutoReversetrue。 若要使动画无限期重复,请将其 RepeatBehavior 属性设置为 Forever。 下面演示如何在 XAML 中设置 AutoReverseRepeatBehavior 属性。

    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever"/>
    

    下面演示如何在代码中设置 AutoReverseRepeatBehavior 属性。

    myDoubleAnimation.AutoReverse = true;
    myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
    
    myDoubleAnimation.AutoReverse = True
    myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever
    

第 2 部分:创建故事板

若要向对象应用动画,请创建一个Storyboard并使用TargetNameTargetProperty附加属性来指定要进行动画处理的对象和属性。

  1. 创建Storyboard并将动画添加为其子级。 下面演示如何在 XAML 中创建 Storyboard

    <Storyboard>
        <DoubleAnimation
            From="1.0" To="0.0" Duration="0:0:1" 
            AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    若要创建 Storyboard 代码中,请在类级别声明变量 Storyboard

    public partial class MainWindow : Window
    {
        private Storyboard myStoryboard;
    
    Class MainWindow
    
        Private myStoryboard As Storyboard
    

    然后初始化 Storyboard,并将动画添加为其子级。

    myStoryboard = new Storyboard();
    myStoryboard.Children.Add(myDoubleAnimation);
    
    myStoryboard = New Storyboard()
    myStoryboard.Children.Add(myDoubleAnimation)
    
  2. Storyboard必须知道在哪里应用动画。 使用 Storyboard.TargetName 附加属性指定要进行动画处理的对象。 下面演示如何在 XAML 中将目标名称DoubleAnimation设置为MyRectangle

    <Storyboard>
        <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            From="1.0" To="0.0" Duration="0:0:1" 
            AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    下面演示如何在代码中将目标名称DoubleAnimation设置为MyRectangle

    Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
    
    Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)
    
  3. 使用TargetProperty附加属性来指定要进行动画处理的属性。 下面演示如何将动画配置为以 XAML 中的Opacity属性为目标Rectangle

    <Storyboard>
        <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0.0" Duration="0:0:5" 
            AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    下面演示了动画如何配置为以代码中的属性Rectangle为目标Opacity

    Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));
    
    Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.OpacityProperty))
    

有关语法和其他示例的详细信息 TargetProperty ,请参阅 情节提要概述

第 3 部分(XAML):将动画板与触发器结合

使用事件触发器是在 XAML 中应用和启动 Storyboard 的最简单方法。 本部分说明如何在 XAML 中将 Storyboard 与触发器相关联。

  1. 创建一个 BeginStoryboard 对象并将故事板与它相关联。 一种 BeginStoryboard 是一种 TriggerAction,用于启动和推动 Storyboard

    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Storyboard.TargetName="MyRectangle" 
          Storyboard.TargetProperty="Opacity"
          From="1.0" To="0.0" Duration="0:0:5" 
          AutoReverse="True" RepeatBehavior="Forever" />
      </Storyboard>
    </BeginStoryboard>
    
  2. 创建一个 EventTrigger ,然后将 BeginStoryboard 添加到其 Actions 集合中。 将 RoutedEventEventTrigger 属性设置为要启动的路由事件 Storyboard。 (有关路由事件的详细信息,请参阅 路由事件概述

    <!-- Animates the rectangle's opacity. -->
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0.0" Duration="0:0:5" 
            AutoReverse="True" RepeatBehavior="Forever" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
    
  3. 将矩形 EventTrigger 添加到 Triggers 集合中。

    <Rectangle
      Name="MyRectangle"
      Width="100" 
      Height="100"
      Fill="Blue">
      <Rectangle.Triggers>
        <!-- Animates the rectangle's opacity. -->
        <EventTrigger RoutedEvent="Rectangle.Loaded">
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation
                Storyboard.TargetName="MyRectangle" 
                Storyboard.TargetProperty="Opacity"
                From="1.0" To="0.0" Duration="0:0:5" 
                AutoReverse="True" RepeatBehavior="Forever" />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>
    

第 3 部分(代码):将情节提要与事件处理程序相关联

在代码中应用和启动 Storyboard 的最简单方法是使用事件处理程序。 本部分演示如何在代码中将 Storyboard 与事件处理程序关联起来。

  1. 注册 Loaded 矩形的事件。

    myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
    
    AddHandler myRectangle.Loaded, AddressOf myRectangleLoaded
    
  2. 声明事件处理程序。 在事件处理程序中,使用 Begin 方法应用故事板。

    private void myRectangleLoaded(object sender, RoutedEventArgs e)
    {
        myStoryboard.Begin(this);
    }
    
    Private Sub myRectangleLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        myStoryboard.Begin(Me)
    End Sub
    

完整的示例

下面显示如何在 XAML 中创建一个渐现和渐隐的矩形。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel Margin="10">
            <Rectangle
                Name="MyRectangle"
                Width="100" 
                Height="100"
                Fill="Blue">
                <Rectangle.Triggers>
                    <!-- Animates the rectangle's opacity. -->
                    <EventTrigger RoutedEvent="Rectangle.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetName="MyRectangle" 
                                    Storyboard.TargetProperty="Opacity"
                                    From="1.0" To="0.0" Duration="0:0:5" 
                                    AutoReverse="True" RepeatBehavior="Forever" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Rectangle.Triggers>
            </Rectangle>
        </StackPanel>
    </Grid>
</Window>

下面演示如何在代码中创建一个可淡入淡出的矩形。

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

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        private Storyboard myStoryboard;

        public MainWindow()
        {
            InitializeComponent();

            StackPanel myPanel = new StackPanel();
            myPanel.Margin = new Thickness(10);

            Rectangle myRectangle = new Rectangle();
            myRectangle.Name = "myRectangle";
            this.RegisterName(myRectangle.Name, myRectangle);
            myRectangle.Width = 100;
            myRectangle.Height = 100;
            myRectangle.Fill = Brushes.Blue;

            DoubleAnimation myDoubleAnimation = new DoubleAnimation();
            myDoubleAnimation.From = 1.0;
            myDoubleAnimation.To = 0.0;
            myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
            myDoubleAnimation.AutoReverse = true;
            myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            myStoryboard = new Storyboard();
            myStoryboard.Children.Add(myDoubleAnimation);
            Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
            Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));

            // Use the Loaded event to start the Storyboard.
            myRectangle.Loaded += new RoutedEventHandler(myRectangleLoaded);
            myPanel.Children.Add(myRectangle);
            this.Content = myPanel;
        }

        private void myRectangleLoaded(object sender, RoutedEventArgs e)
        {
            myStoryboard.Begin(this);
        }
    }
}
Imports System.Windows.Media.Animation

Class MainWindow

    Private myStoryboard As Storyboard

    Public Sub New()
        InitializeComponent()

        Dim myPanel As New StackPanel()
        myPanel.Margin = New Thickness(10)

        Dim myRectangle As New Rectangle()
        myRectangle.Name = "myRectangle"
        Me.RegisterName(myRectangle.Name, myRectangle)
        myRectangle.Width = 100
        myRectangle.Height = 100
        myRectangle.Fill = Brushes.Blue

        Dim myDoubleAnimation As New DoubleAnimation()
        myDoubleAnimation.From = 1.0
        myDoubleAnimation.To = 0.0
        myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))
        myDoubleAnimation.AutoReverse = True
        myDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever

        myStoryboard = New Storyboard()
        myStoryboard.Children.Add(myDoubleAnimation)
        Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)
        Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.OpacityProperty))

        ' Use the Loaded event to start the Storyboard.
        AddHandler myRectangle.Loaded, AddressOf myRectangleLoaded

        myPanel.Children.Add(myRectangle)
        Me.Content = myPanel
    End Sub

    Private Sub myRectangleLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
        myStoryboard.Begin(Me)
    End Sub

End Class

动画类型

由于动画生成属性值,因此不同的属性类型存在不同的动画类型。 要为使用 Double 值的属性(如 Width 元素的属性)进行动画处理,请使用能够产生 Double 值的动画。 若要为需要Point的属性添加动画效果,请使用生成Point值的动画,以此类推。 由于不同属性类型的数量,命名空间中 System.Windows.Media.Animation 有多个动画类。 幸运的是,它们遵循严格的命名约定,可以轻松地区分它们:

  • < 类型>动画

    这些动画称为“From/To/By”或“basic”动画,在起始值和目标值之间进行动画处理,或者向其起始值添加偏移值。

    • 若要指定起始值,请设置动画的 From 属性。

    • 若要指定结束值,请设置动画的 To 属性。

    • 若要指定偏移值,请设置动画的 By 属性。

    本概述中的示例使用这些动画,因为它们是最简单的用法。 From/To/By 动画的详细信息请参见 From/To/By Animations Overview。

  • < 类型>AnimationUsingKeyFrames

    关键帧动画比 From/To/By 动画更强大,因为你可以指定任意数量的目标值,甚至可以控制其内插方法。 某些类型只能使用关键帧动画进行动画。 Key-Frame 动画概述中详细介绍了关键帧动画。

  • < 类型>AnimationUsingPath

    路径动画允许您使用几何路径来生成动画的数值。

  • < 类型>AnimationBase

    抽象类,当你实现它时,对<Type>值进行使动画化。 此类用作<Type>Animation 和<Type>AnimationUsingKeyFrames 类的基类。 仅当想要创建自己的自定义动画时,才必须直接处理这些类。 否则,请使用 <类型>动画或关键帧<类型>动画。

在大多数情况下,需要使用 <类型>动画类,例如 DoubleAnimationColorAnimation

下表显示了几种常见的动画类型和它们使用的一些属性。

属性类型 对应的基本“从/至/由”动画 相应的关键帧动画 相应的路径动画 用法示例
Color ColorAnimation ColorAnimationUsingKeyFrames 没有 ColorSolidColorBrushGradientStop 进行动画处理。
Double DoubleAnimation DoubleAnimationUsingKeyFrames DoubleAnimationUsingPath 通过对WidthHeight,来实现DockPanelButton的动画效果。
Point PointAnimation PointAnimationUsingKeyFrames PointAnimationUsingPath Center . EllipseGeometry. 的位置进行动画处理。
String 没有 StringAnimationUsingKeyFrames 没有 TextTextBlock或者ContentButton进行动画处理。

动画即时间线

所有动画类型都继承自 Timeline 该类;因此,所有动画都是专用类型的时间线。 Timeline 定义了一个时间段。 可以指定时间线的 计时行为:它Duration、它的重复次数,甚至时间的进度速度。

由于动画是一个 Timeline,因此它还表示时间段。 动画在其指定的时间段(或 Duration)内推进时,还会计算输出值。 当动画进行或“播放”时,它会更新它与之关联的属性。

三个常用的计时属性,DurationAutoReverse以及RepeatBehavior

Duration 属性

如前所述,时间线表示时间段。 该段的长度由 Duration 时间线(通常通过使用 TimeSpan 值指定)确定。 当时间线到达其持续时间的末尾时,它已完成迭代。

动画使用其 Duration 属性来确定其当前值。 如果未为动画指定 Duration 值,则它使用 1 秒(默认值)。

以下语法显示了该 Duration 属性的可扩展应用程序标记语言(XAML)属性语法的简化版本。

小时:分钟:

下表显示了多个 Duration 设置及其生成的值。

设置 生成的值
0:0:5.5 5.5 秒。
0:30:5.5 30 分 5.5 秒。
1:30:5.5 1 小时 30 分钟和 5.5 秒。

在代码中指定Duration的一种方法是使用FromSeconds方法创建TimeSpan,然后使用该TimeSpan声明一个新Duration结构。

有关 Duration 值和完整的可扩展应用程序标记语言(XAML)语法的详细信息,请参阅 Duration 结构。

自动反转

AutoReverse 属性指定时间线在到达其 Duration末尾后是否向后播放。 如果将此动画属性设置为 true,则动画在动画到达其 Duration末尾后反向播放,从其结束值播放回其起始值。 默认情况下,此属性为 false.

重复行为

RepeatBehavior 属性指定时间线播放的次数。 默认情况下,时间线具有迭代计数 1.0,这意味着它们一次播放,根本不重复。

有关这些属性和其他属性的详细信息,请参阅 计时行为概述

对属性应用动画

前面的部分介绍不同类型的动画及其计时属性。 本部分介绍如何将动画应用于要进行动画处理的属性。 Storyboard 对象提供了将动画应用于属性的一种方法。 Storyboard 是一个 容器时间线,为其包含的动画提供目标信息。

瞄准对象和属性

Storyboard 类提供 TargetNameTargetProperty 附加属性。 通过设置动画属性,指定动画内容。 但是,在动画可以面向对象之前,通常必须为对象指定一个名称。

将名称分配给 FrameworkElement 不同于向对象分配名称 Freezable 。 大多数控件和面板都是框架元素;但是,大多数纯粹的图形对象(如画笔、转换和几何图形)都是可冻结的对象。 如果不确定类型是类型还是类型FrameworkElementFreezable,请参阅其参考文档的“继承层次结构”部分。

  • 若要创建 FrameworkElement 动画目标,可以通过设置其 Name 属性为其命名。 在代码中,您还必须使用 RegisterName 方法将元素名称注册到其所属的页面。

  • Freezable若要使对象成为 XAML 中的动画目标,请使用 x:Name 指令为其分配名称。 在代码中,只需使用 RegisterName 方法将对象注册到其所属的页面。

以下部分提供了在 XAML 和代码中命名元素的示例。 有关命名和定位的详细信息,请参阅 情节提要概述

应用和启动分镜头脚本

若要在 XAML 中启动 Storyboard,请将其关联到 EventTrigger。 发生指定事件时,一个 EventTrigger 对象描述要采取的操作。 其中一个动作可以是用于 BeginStoryboard 启动情节提要的动作。 事件触发器的概念与事件处理程序类似,因为它们使你能够指定应用程序如何响应特定事件。 与事件处理程序不同,可以在 XAML 中完全描述事件触发器;不需要其他代码。

如果要在代码中启动Storyboard,可以使用EventTrigger或使用Storyboard类的Begin方法。

以交互方式控制动画脚本

前面的示例演示了如何在事件发生时启动 Storyboard 事件。 还可以以交互方式控制其启动后: Storyboard 可以暂停、恢复、停止、将其移动到其填充期、查找和删除 Storyboard。 有关详细信息以及演示如何以交互方式控制 Storyboard 的示例,请参阅 故事板概述

动画结束后会发生什么情况?

FillBehavior 属性指定时间线在结束时的行为方式。 默认情况下,时间线在结束时开始 Filling 。 最终输出值由 Filling 保持的动画。

上一个示例中的DoubleAnimation未结束,因为它的RepeatBehavior属性被设置为Forever。 以下示例使用类似的动画对矩形进行动画处理。 与前面的示例不同,RepeatBehaviorAutoReverse此动画的属性保留在其默认值处。 因此,动画在 5 秒内从 1 到 0 进行,然后停止。

<Rectangle
  Name="MyRectangle"
  Width="100" 
  Height="100"
  Fill="Blue">
  <Rectangle.Triggers>

    <!-- Animates the rectangle's opacity. -->
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation
            Storyboard.TargetName="MyRectangle" 
            Storyboard.TargetProperty="Opacity"
            From="1.0" To="0" Duration="0:0:5" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 1.0
myDoubleAnimation.To = 0.0
myDoubleAnimation.Duration = New Duration(TimeSpan.FromSeconds(5))

由于它FillBehavior的值未从其默认值HoldEnd更改,因此动画在结束时保留其最终值0。 因此,矩形的Opacity在动画结束后保持为0。 如果将矩形设置为 Opacity 另一个值,则代码似乎不起作用,因为动画仍在影响 Opacity 该属性。

重新获得对代码中动画属性的控制的一种方法是使用 BeginAnimation 该方法并为参数指定 null AnimationTimeline 。 有关详细信息及示例,请参阅在使用情节提要对属性进行动画处理后设置该属性

请注意,尽管设置具有 ActiveFilling 动画的属性值似乎不起作用,但属性值确实会更改。 有关详细信息,请参阅 动画和计时系统概述

数据绑定和动画处理

大多数动画属性都可以绑定数据或设置动画;例如,可以对 Duration 的属性进行 DoubleAnimation 动画处理。 但是,由于计时系统的工作方式,数据绑定或动画动画的行为与其他数据绑定或动画对象不同。 为了了解其行为,它有助于了解将动画应用于属性的含义。

请参阅上一部分中的示例,该示例演示如何对矩形进行动画处理 Opacity 。 加载上一示例中的矩形时,其事件触发器将应用 Storyboard。 计时系统会创建 Storyboard 及其动画的副本。 这些副本是冻结的(只读的),对象 Clock 是从它们创建的。 这些时钟执行对目标属性进行动画处理的实际工作。

计时系统为DoubleAnimation创建时钟,并将其应用于由DoubleAnimationTargetNameTargetProperty指定的对象和属性。 在这种情况下,计时系统将时钟应用于 Opacity 名为“MyRectangle”的对象的属性。

尽管也为 Storyboard 创建了一个时钟,但该时钟未应用于任何属性。 其用途是控制其子时钟,即为该 DoubleAnimation时钟创建的时钟。

要使动画反映数据绑定或动画更改,必须重新生成其时钟。 时钟不会自动重新生成。 若要使动画反映更改,请使用 BeginStoryboardBegin 方法重新应用其情节提要。 使用这些方法之一时,动画将重启。 在代码中,可以使用 Seek 方法将故事板移回到以前的位置。

有关数据绑定动画的示例,请参阅 关键样条动画示例。 有关动画和计时系统工作原理的详细信息,请参阅 动画和计时系统概述

其他动画处理方式

本概述中的示例演示如何使用动画脚本创建动画。 使用代码时,可以通过其他几种方式进行动画处理。 有关详细信息,请参阅 属性动画技术概述

动画示例

以下示例可帮助你开始向应用程序添加动画。

标题 DESCRIPTION
动画和计时系统概述 描述计时系统如何使用 TimelineClock 类来创建动画。
动画提示和技巧 列出解决动画问题(例如性能)的有用提示。
自定义动画概述 介绍如何使用关键帧、动画类或每帧回调扩展动画系统。
从/到/按动画概述 介绍如何创建在两个值之间切换的动画。
Key-Frame 动画概述 介绍如何创建具有多个目标值的动画,包括控制内插方法的功能。
缓动函数 介绍如何将数学公式应用于动画以获取现实行为,例如弹跳。
路径动画概述 介绍如何沿着复杂路径移动或旋转对象。
属性动画技术概述 使用动画脚本、本地动画、时钟和逐帧动画描述属性动画。
演示图板概述 介绍如何将情节提要与多个时间线配合使用来创建复杂的动画。
计时行为概述 描述 Timeline 动画中使用的类型和属性。
计时事件概述 描述可用于 TimelineClock 对象的事件,这些事件可以在时间线上的各种时间点,例如开始、暂停、恢复、跳过或停止,执行代码。
操作说明主题 包含用于在应用程序中使用动画和时间线的代码示例。
时钟使用指南 包含用于在应用程序中使用该 Clock 对象的代码示例。
关键帧操作说明主题 包含用于在应用程序中使用关键帧动画的代码示例。
路径动画操作说明主题 包含用于在应用程序中使用路径动画的代码示例。

参考文献