情节提要动画Storyboarded animations

情节提要动画不仅仅是视觉动画。Storyboarded animations are not just animations in the visual sense. 情节提要动画是更改作为时间函数的依赖属性的值的一种方法。A storyboarded animation is a way to change the value of a dependency property as a function of time. 可能需要该动画库外部的情节提要动画的主要原因之一在于,需要定义控件的视觉状态并将其作为控件模板或页面定义的一部分。One of the main reasons you might need a storyboarded animation that's not from the animation library is to define the visual state for a control, as part of a control template or page definition.

与 Silverlight 和 WPF 之间的区别Differences with Silverlight and WPF

如果熟悉 Microsoft Silverlight 或 Windows Presentation Foundation (WPF),请阅读本节内容;否则,可以跳过本节。If you are familiar with Microsoft Silverlight or Windows Presentation Foundation (WPF), read this section; otherwise, you can skip it.

一般来说,在 Windows 运行时应用中创建情节提要动画与使用 Silverlight 或 WPF 创建动画类似。In general, creating storyboarded animations in a Windows Runtime app is like Silverlight or WPF. 但是也有一些重要的差异:But there are a number of important differences:

  • 情节提要动画不是为 UI 创建视觉动画的唯一方法,也不一定是应用开发人员这样做的最简便方法。Storyboarded animations are not the only way to visually animate a UI, nor are they necessarily the easiest way for app developers to do so. 不使用情节提要动画,它通常是使用主题动画和过渡动画的更好的设计做法。Rather than using storyboarded animations it's often a better design practice to use theme animations and transition animations. 这可以快速创建推荐的 UI 动画,而无需使用复杂的动画属性目标定位。These can quickly create recommended UI animations without getting into the intricacies of animation property targeting. 有关详细信息,请参阅动画概述For more info see Animations overview.
  • 在 Windows 运行时中,许多 XAML 控件包括主题动画和过渡动画,作为其内置行为的一部分。In the Windows Runtime, many XAML controls include theme animations and transition animations as part of their built-in behavior. 大多数情况下,WPF 和 Silverlight 控件没有默认的动画行为。For the most part, WPF and Silverlight controls didn't have a default animation behavior.
  • 如果动画系统确定自定义动画可能会在 UI 中引发不良性能,则并非所有你创建的自定义动画可以在 Windows 运行时应用中默认运行。Not all custom animations you create can run by default in a Windows Runtime app, if the animation system determines that the animation might cause bad performance in your UI. 系统确定可能会产生性能影响的动画称为从属动画Animations where the system determines there could be a performance impact are called dependent animations. 此动画是从属动画的原因是:动画的时钟直接根据 UI 线程运行,同时它也是活动用户输入和其他更新尝试将运行时更改应用到 UI 的位置。It's dependent because the clocking of your animation is directly working against the UI thread, which is also where active user input and other updates are trying to apply the runtime changes to UI. 在某些情况下,占用 UI 线程上大量系统资源的从属动画使应用看似无响应。A dependent animation that's consuming extensive system resources on the UI thread can make the app appear unresponsive in certain situations. 如果你的动画导致布局更改或可能影响 UI 线程的性能,则通常需要显式启用动画以观察其运行情况。If your animation causes a layout change or otherwise has the potential to impact performance on the UI thread, you often need to explicitly enable the animation to see it run. 这种情况下,特定动画类的 EnableDependentAnimation 属性就可以派上用场了。That's what the EnableDependentAnimation property on specific animation classes is for. 有关详细信息,请参阅从属动画和独立动画See Dependent and independent animations for more info.
  • 目前 Windows 运行时中不支持自定义缓动函数。Custom easing functions are not currently supported in the Windows Runtime.

定义情节提要动画Defining storyboarded animations

情节提要动画是更改作为时间函数的依赖属性的值的一种方法。A storyboarded animation is a way to change the value of a dependency property as a function of time. 创建动画的属性并不始终是直接影响你的应用的 UI 的属性。The property you are animating is not always a property that directly affects the UI of your app. 但由于 XAML 可以定义应用的 UI,因此通常它是你要创建动画的 UI 相关的属性。But since XAML is about defining UI for an app, usually it is a UI-related property you are animating. 例如,你可以创建 RotateTransform 的角度或按钮的背景颜色值的动画。For example, you can animate the angle of a RotateTransform, or the color value of a button's background.

你可能定义情节提要动画的一个主要原因是你是否是控件创作者或正在重新创建控件模板,并且正在定义视觉状态。One of the main reasons you might be defining a storyboarded animation is if you are a control author or are re-templating a control, and you are defining visual states. 有关详细信息,请参阅视觉状态的情节提要动画For more info, see Storyboarded animations for visual states.

无论你正在定义视觉状态还是应用的自定义动画,本主题中介绍的情节提要动画的概念和 API 基本上都适用于二者任一。Whether you are defining visual states or a custom animation for an app, the concepts and APIs for storyboarded animations that are described in this topic mostly apply to either.

为了创建动画,通过情节提要动画确定目标的属性必须是依赖属性In order to be animated, the property you are targeting with a storyboarded animation must be a dependency property. 依赖属性是 Windows 运行时 XAML 实现的关键特征。A dependency property is a key feature of the Windows Runtime XAML implementation. 最常见 UI 元素的可写属性通常作为依赖属性实现,以便你可以为其创建动画、应用数据绑定值或应用 Style 和确定具有 Setter 的属性为目标。The writeable properties of most common UI elements are typically implemented as dependency properties, so that you can animate them, apply data-bound values, or apply a Style and target the property with a Setter. 有关依赖属性工作原理的详细信息,请参阅依赖属性概述For more info about how dependency properties work, see Dependency properties overview.

大多数情况下,通过编写 XAML 来定义情节提要动画。Most of the time, you define a storyboarded animation by writing XAML. 如果你使用了工具,例如 Microsoft Visual Studio,则该工具将会为你生成 XAML。If you use a tool such as Microsoft Visual Studio, it will produce the XAML for you. 也可以使用代码定义情节提要动画,但这种方法并不常见。It's possible to define a storyboarded animation using code too, but that's less common.

让我们来看个简单示例。Let's look at a simple example. 在此 XAML 示例中,在特定的 Rectangle 对象上为 Opacity 属性创建动画。In this XAML example, the Opacity property is animated on a particular Rectangle object.

<Page ...>
  <Page.Resources>
    <!-- Storyboard resource: Animates a rectangle's opacity. -->
    <Storyboard x:Name="myStoryboard">
      <DoubleAnimation
        Storyboard.TargetName="MyAnimatedRectangle"
        Storyboard.TargetProperty="Opacity"
        From="1.0" To="0.0" Duration="0:0:1"/>
    </Storyboard>
  </Page.Resources>

  <!--Page root element, UI definition-->
  <Grid>
    <Rectangle x:Name="MyAnimatedRectangle"
      Width="300" Height="200" Fill="Blue"/>
  </Grid>
</Page>

确定要实现动画的对象Identifying the object to animate

在前面的示例中,情节提要为 RectangleOpacity 属性创建了动画。In the previous example, the storyboard was animating the Opacity property of a Rectangle. 你没有在对象本身上声明动画。You don't declare the animations on the object itself. 而是在情节提要的动画定义内声明了动画。Instead, you do this within the animation definition of a storyboard. 情节提要通常在 XAML 中定义,不在要创建动画的对象的 XAML UI 定义的紧邻位置。Storyboards are usually defined in XAML that's not in the immediate vicinity of the XAML UI definition of the object to animate. 而它们通常会设置为 XAML 资源。Instead, they're usually set up as a XAML resource.

若要将动画连接到目标,则按其标识的编程名称来引用目标。To connect an animation to a target, you reference the target by its identifying programming name. 你应始终在 XAML UI 定义中应用 x:Name 属性以命名要创建动画的对象。You should always apply the x:Name attribute in the XAML UI definition to name the object that you want to animate. 然后,通过在动画定义中设置 Storyboard.TargetName 确定要创建动画的对象目标。You then target the object to animate by setting Storyboard.TargetName within the animation definition. 对于 Storyboard.TargetName 的值,使用目标对象的名称字符串,它是你之前设置的名称并在其他位置具有 x:Name 属性。For the value of Storyboard.TargetName, you use the name string of the target object, which is what you set earlier and elsewhere with x:Name attribute.

确定要创建动画的依赖属性目标Targeting the dependency property to animate

在动画中为 Storyboard.TargetProperty 设置一个值。You set a value for Storyboard.TargetProperty in the animation. 这将确定要为哪个目标对象的特定属性创建动画。This determines which specific property of the targeted object is animated.

有时,你需要确定不是目标对象的直接属性的属性目标,而它可能嵌套在对象属性关系的更深位置。Sometimes you need to target a property that's not an immediate property of the target object, but that is nested more deeply in an object-property relationship. 你通常需要执行此操作以便深入到构成对象和属性值的集中,直至你可以引用可创建动画的属性类型为止(DoublePointColor)。You often need to do this in order to drill down into a set of contributing object and property values until you can reference a property type that can be animated (Double, Point, Color). 此概念称为间接目标,采用此方式确定属性目标的语法称为属性路径This concept is called indirect targeting, and the syntax for targeting a property in this way is known as a property path.

下面提供了一个示例。Here's an example. 情节提要动画的一个常见方案是更改部分应用 UI 或控件的颜色,以便表明控件处于特定状态。One common scenario for a storyboarded animation is to change the color of a part of an app UI or control in order to represent that the control is in a particular state. 说明你希望为 TextBlockForeground 创建动画,以便它从红色变为绿色。Say you want to animate the Foreground of a TextBlock, so that it turns from red to green. 你预期包括 ColorAnimation,这非常正确。You'd expect that a ColorAnimation is involved, and that's correct. 但是,UI 元素上的任何影响对象颜色属性的类型实际上都不是 ColorHowever, none of the properties on UI elements that affect the object's color are actually of type Color. 而是类型 BrushInstead, they're of type Brush. 因此,你实际上要创建动画的目标是 SolidColorBrush 类的 Color 属性,它通常是用于与颜色相关的这些 UI 属性的 Brush 派生的类型。So what you actually need to target for animation is the Color property of the SolidColorBrush class, which is a Brush-derived type that's typically used for these color-related UI properties. 下面是形成动画的属性目标的属性路径的示例:And here's what that looks like in terms of forming a property path for your animation's property targeting:

<Storyboard x:Name="myStoryboard">
  <ColorAnimation
    Storyboard.TargetName="tb1"
    Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
    From="Red" To="Green"/>
</Storyboard>

下面介绍如何根据其组成考虑此语法:Here's how to think of this syntax in terms of its parts:

  • 每组 () 括号包含一个属性名称。Each set of () parentheses encloses a property name.
  • 在属性名称内,有一个点,该点分隔开类型名称和属性名称,以使你标识的属性清晰明确。Within the property name, there's a dot, and that dot separates a type name and a property name, so that the property you're identifying is unambiguous.
  • 中间的点(即,不在括号内的点)是一个步骤。The dot in the middle, the one that's not inside parentheses, is a step. 这是按语法进行解释的,意思是,获取第一个属性(它是一个对象)的值,进入其对象模型,然后确定第一个属性值的特定子属性目标。This is interpreted by the syntax to mean, take the value of the first property (which is an object), step into its object model, and target a specific sub-property of the first property's value.

下面是动画目标方案的列表,你可能从中使用间接属性目标,以及与你将使用的语法类似的某些属性路径字符串:Here's a list of animation targeting scenarios where you'll probably be using indirect property targeting, and some property path strings that approximates the syntax you'll use:

你将发现某些示例使用方括号来包含数字。You'll notice some of these examples use square brackets around numbers. 这是一种索引器。This is an indexer. 它指示它前面的属性名称具有用作值的一个集合,并且你需要该集合中的一项(按照从零开始的索引标识)。It indicates that the property name preceding it has a collection as value, and that you want an item (as identified by a zero-based index) from within that collection.

你还可以为 XAML 附加的属性创建动画。You can also animate XAML attached properties. 始终在括号内包含附加属性的全称,例如 (Canvas.Left)Always enclose the full attached property name in parentheses, for example (Canvas.Left). 有关详细信息,请参阅创建 XAML 附加属性的动画For more info, see Animating XAML attached properties.

有关如何使用属性的间接目标的属性路径来实现动画的详细信息,请参阅 Property-path 语法Storyboard.TargetProperty 附加属性For more info on how to use a property path for indirect targeting of the property to animate, see Property-path syntax or Storyboard.TargetProperty attached property.

动画类型Animation types

Windows 运行时动画系统具有情节提要动画可以应用于的三种特定类型:The Windows Runtime animation system has three specific types that storyboarded animations can apply to:

对于对象引用值,还存在通用化 Object 动画类型,我们将在后面部分对此进行讨论。There's also a generalized Object animation type for object reference values, which we'll discuss later.

指定动画化的值Specifying the animated values

到目前为止,我们已经向你介绍了如何确定要创建动画的对象和属性目标,但尚未介绍动画运行时会对属性值执行的操作。So far we've shown you how to target the object and the property to animate, but haven't yet described what the animation does to the property value when it runs.

我们介绍的动画类型有时也称为 From/To/By 动画。The animation types we've described are sometimes referred to as From/To/By animations. 这表示,动画使用一个或多个来自动画定义的以下输入来随时间更改属性的值:This means that the animation is changing the value of a property, over time, using one or more of these inputs that come from the animation definition:

  • 值从 From 值开始。The value starts at the From value. 如果你没有指定 From 值,则起始值是动画运行前那个时刻动画化属性具有的任意值。If you don't specify a From value, the starting value is whatever value the animated property has at the time before the animation runs. 它可能是一个默认值,样式或模板中的值,或是 XAML UI 定义或应用代码特别应用的值。This might be a default value, a value from a style or template, or a value specifically applied by a XAML UI definition or app code.
  • 在动画结尾处,值为 To 值。At the end of the animation, the value is the To value.
  • 或者,若要指定与起始值相对的结束值,请设置 By 属性。Or, to specify an ending value relative to the starting value, set the By property. 最好是设置此值,而非 To 属性。You'd set this instead of the To property.
  • 如果你没有指定 To 值或 By 值,则结束值是动画运行前那个时刻动画化属性具有的任意值。If you don't specify a To value or a By value, the ending value is whatever value the animated property has at the time before the animation runs. 在这种情况下,最好有 From 值,因为如果不指定该值,则动画将不会更改值;其起始值和结束值是同一个值。In this case you'd better have a From value because otherwise the animation won't change the value at all; its starting and ending values are both the same.
  • 动画通常具有至少其中一个 FromByTo,但绝不会同时有三个值。An animation typically has at least one of From, By or To but never all three.

让我们重新复习下以前的 XAML 示例,再次看看 FromTo 值,以及 DurationLet's revisit the earlier XAML example and look again at the From and To values, and the Duration. 本例创建 Opacity 属性的动画,并且 Opacity 的属性类型为 DoubleThe example is animating the Opacity property, and the property type of Opacity is Double. 因此,此处要使用的动画为 DoubleAnimationSo the animation to use here is DoubleAnimation.

From="1.0" To="0.0" 指定动画何时运行,Opacity 属性在值 1 处开始并且创建动画直至 0 处。specifies that when the animation runs, the Opacity property starts at a value of 1 and animates to 0. 换句话说,根据这些 Double 值对 Opacity 属性产生作用,此动画将对象从不透明开始,然后逐渐变成透明形式。In other words, in terms of what these Double values mean to the Opacity property, this animation will cause the object to start opaque and then fade to transparent.

...
<Storyboard x:Name="myStoryboard">
  <DoubleAnimation
    Storyboard.TargetName="MyAnimatedRectangle"
    Storyboard.TargetProperty="Opacity"
    From="1.0" To="0.0" Duration="0:0:1"/>
</Storyboard>
...

Duration="0:0:1" 指定动画持续的时间,即矩形淡化的速度。specifies how long the animation lasts, that is, how fast the rectangle fades. Duration 属性采用以下形式指定:hours:minutes:secondsA Duration property is specified in the form of hours:minutes:seconds. 此示例中持续时间为一秒。The time duration in this example is one second.

有关 Duration 值和 XAML 语法的详细信息,请参阅 DurationFor more info about Duration values and the XAML syntax, see Duration.

备注

对于我们展示的示例,如果你确定要创建动画对象的起始状态的 Opacity 始终等于 1(无论通过默认值还是显式设置),则可以忽略 From 值,动画可使用隐式起始值,并且结果相同。For the example we showed, if you were sure that the starting state of the object being animated has Opacity always equal to 1, either through the default or an explicit set, you could omit the From value, the animation would use the implicit starting value, and the result would be the same.

From/To/By 可以为空From/To/By are nullable

我们之前提到过,你可以忽略 FromToBy,并因此使用当前非动画化的值作为缺失值的替代值。We mentioned previously that you can omit From, To or By and thus use current non-animated values as substitutes for a missing value. 动画的 FromToBy 属性的类型不能猜测。From, To, or By properties of an animation aren't of the type you might guess. 例如,DoubleAnimation.To 属性的类型不是 DoubleFor example the type of the DoubleAnimation.To property isn't Double. 而是 DoubleNullableInstead, it's a Nullable for Double. 并且其默认值为 null,而不是 0。And its default value is null, not 0. null 值是动画系统区别你没有特别为 FromToBy 属性设置值的方式。That null value is how the animation system distinguishes that you haven't specifically set a value for a From, To, or By property. VisualC + + 组件扩展 (C + + CX) 不具有Nullable类型,因此它改为使用IReferenceVisualC++ component extensions (C++/CX) doesn't have a Nullable type, so it uses IReference instead.

动画的其他属性Other properties of an animation

本节中接下来介绍的属性全部是可选的,因为它们具有适合于大部分动画的默认值。The next properties described in this section are all optional in that they have defaults that are appropriate for most animations.

AutoReverseAutoReverse

如果你没有在动画中指定 AutoReverseRepeatBehavior,则该动画将运行一次,并且运行持续时间为 Duration 中指定的值。If you don't specify either AutoReverse or RepeatBehavior on an animation, that animation will run once, and run for the time specified as the Duration.

AutoReverse 属性指定在时间线达到其 Duration 的结尾处后是否反向播放。The AutoReverse property specifies whether a timeline plays in reverse after it reaches the end of its Duration. 如果将其设置为 true,则动画在达到其声明的 Duration 的结尾处后反向播放,从其结束值 (To) 起更改值直至返回其起始值 (From)。If you set it to true, the animation reverses after it reaches the end of its declared Duration, changing the value from its ending value (To) back to its starting value (From). 这意味着,动画有效运行时间是其 Duration 的两倍。This means that the animation effectively runs for double the time of its Duration.

RepeatBehaviorRepeatBehavior

RepeatBehavior 属性指定时间线播放的次数,或是时间线应在其范围内重复的较长持续时间。The RepeatBehavior property specifies either how many times a timeline plays, or a larger duration that the timeline should repeat within. 默认情况下,时间线具有“1x”的迭代计数,这表示它播放其 Duration 的一次倍数,并且不再重复。By default, a timeline has an iteration count of "1x", which means it plays one time for its Duration and does not repeat.

你可能会使动画运行多个迭代。You can cause the animation to run multiple iterations. 例如,值“3x”将使动画运行三次。For example, a value of "3x" causes the animation to run three times. 或者,可以为 RepeatBehavior 指定不同的 DurationOr, you can specify a different Duration for RepeatBehavior. Duration 应长于动画本身的 Duration 方才有效。That Duration should be longer than the Duration of the animation itself to be effective. 例如,对于具有“0:0:2”的 Duration 的动画,如果你指定“0:0:10”的 RepeatBehavior,则该动画重复五次。For example, if you specify a RepeatBehavior of "0:0:10", for an animation that has a Duration of "0:0:2", that animation repeats five times. 如果这些数不能被整除,动画将在到达 RepeatBehavior 时间时被截断,此时动画可能正在播放中。If these don't divide evenly, the animation gets truncated at the time that the RepeatBehavior time is reached, which might be partway through. 最后,你可以指定特殊值“永远”,这将使动画无限期运行直至被故意停止。Finally, you can specify the special value "Forever", which causes the animation to run infinitely until it's deliberately stopped.

有关 RepeatBehavior 值和 XAML 语法的详细信息,请参阅 RepeatBehaviorFor more info about RepeatBehavior values and the XAML syntax, see RepeatBehavior.

FillBehavior="Stop"FillBehavior="Stop"

默认情况下,当动画结束时,即使在超过其持续时间后,动画将属性值保留为最终 ToBy 修改的值。By default, when an animation ends, the animation leaves the property value as the final To or By-modified value even after its duration is surpassed. 但是,如果你将 FillBehavior 属性的值设置为 FillBehavior.Stop,则动画化值的值将还原为应用动画前的任意值,或者更精确些还原为按照依赖属性系统(有关此区别的详细信息,请参阅依赖属性概述)确定的当前有效值。However, if you set the value of the FillBehavior property to FillBehavior.Stop, the value of the animated value reverts to whatever the value was before the animation was applied, or more precisely to the current effective value as determined by the dependency property system (for more info on this distinction, see Dependency properties overview).

BeginTimeBeginTime

默认情况下,动画的 BeginTime 为“0:0:0”,因此动画在其包含的 Storyboard 运行后立刻开始运行。By default, the BeginTime of an animation is "0:0:0", so it begins as soon as its containing Storyboard runs. 如果 Storyboard 包含多个动画并且你希望错开其他动画与初始动画的起始时间,或者希望有意创建短时延迟,则可以更改此值。You might change this if the Storyboard contains more than one animation and you want to stagger the start times of the others versus an initial animation, or to create a deliberate short delay.

SpeedRatioSpeedRatio

如果在一个 Storyboard 中有多个动画,则可以更改一个或多个动画相对于 Storyboard 的时间比。If you have more than one animation in a Storyboard you can change the time rate of one or more of the animations relative to the Storyboard. 这是父 Storyboard,最终控制 Duration 时间在动画运行期间的消逝方式。It's the parent Storyboard that ultimately controls how the Duration time elapses while the animations run. 此属性不常用。This property isn't used very often. 有关详细信息,请参阅 SpeedRatioFor more info see SpeedRatio.

Storyboard 中定义多个动画Defining more than one animation in a Storyboard

Storyboard 的内容可以是多个动画定义。The contents of a Storyboard can be more than one animation definition. 如果将相关的动画应用到同一目标对象的两个属性,则可以具有多个动画。You might have more than one animation if you are applying related animations to two properties of the same target object. 例如,你可以同时更改用作 UI 元素的 RenderTransformTranslateTransformTranslateXTranslateY 属性;这将使元素沿对角线转换。For example, you might change both the TranslateX and TranslateY properties of a TranslateTransform used as the RenderTransform of a UI element; this will cause the element to translate diagonally. 你需要两个不同的动画才能完成该操作,但你可能希望两个动画属于同一 Storyboard,因为你始终希望这两个动画同时运行。You need two different animations to accomplish that, but you might want the animations to be part of the same Storyboard because you always want those two animations to be run together.

动画无需是同一类型,或确定同一对象目标。The animations don't have to be the same type, or target the same object. 他们可以有不同的持续时间,并且无需共享任何属性值。They can have different durations, and don't have to share any property values.

当父 Storyboard 运行时,其中的每个动画都将运行。When the parent Storyboard runs, each of the animations within will run too.

实际上,Storyboard 类具有许多与动画类型具有的相同的动画属性,因为二者共享 Timeline 基类。The Storyboard class actually has a lot of the same animation properties as the animation types do, because both share the Timeline base class. 因此,Storyboard 可以具有 RepeatBehaviorBeginTimeThus, a Storyboard can have a RepeatBehavior, or a BeginTime. 你通常不会在 Storyboard 上设置它们,但除非你希望所有包含的动画都具有该行为。You don't usually set these on a Storyboard though unless you want all the contained animations to have that behavior. 一般来说,与在 Storyboard 上设置一样,任何 Timeline 属性都会应用到其所有子动画。As a general rule, any Timeline property as set on a Storyboard applies to all its child animations. 如果未设置,则 Storyboard 具有通过包含的动画的最长 Duration 值计算而来的隐式持续时间。If let unset, the Storyboard has an implicit duration that's calculated from the longest Duration value of the contained animations. 如果 Storyboard 上显式设置的 Duration 少于其子动画之一的持续时间,则将导致动画被截断,而这通常不是期望的效果。An explicitly set Duration on a Storyboard that's shorter than one of its child animations will cause that animation to get cut off, which isn't usually desirable.

情节提要无法包含尝试确定同一对象上的同一属性目标和创建其动画的两个动画。A storyboard can't contain two animations that attempt to target and animate the same property on the same object. 如果你尝试这样做,则将在情节提要尝试运行时遇到运行时错误。If you try this, you'll get a runtime error when the storyboard tries to run. 即使在动画在时间上没有重叠的情况下,此限制也适用,因为 BeginTime 值和持续时间明显不同。This restriction applies even if the animations don't overlap in time because of deliberately different BeginTime values and durations. 如果你确实希望对一个情节提要中的同一属性应用更复杂的动画时间线,则实现方法为使用关键帧动画。If you really want to apply a more complex animation timeline to the same property in a single storyboard, the way to do this is to use a key-frame animation. 请参阅关键帧和缓动函数动画See Key-frame and easing function animations.

如果这些输入来自多个情节提要,则动画系统可以将多个动画应用到一个属性的值中。The animation system can apply more than one animation to the value of a property, if those inputs come from multiple storyboards. 专门将此行为用于同时运行的情节提要并不常见。Using this behavior deliberately for simultaneously running storyboards isn't common. 但是,应用于控件属性的应用定义的动画可以修改之前作为该控件的视觉状态模型一部分运行的动画的 HoldEnd 值。However it's possible that an app-defined animation that you apply to a control property will be modifying the HoldEnd value of an animation that was previously run as part of the control's visual state model.

将情节提要定义为资源Defining a storyboard as a resource

Storyboard 是放入动画对象的容器。A Storyboard is the container that you put animation objects in. 通常会在页面级别的 ResourcesApplication.Resources 中将 Storyboard 定义为要创建动画的对象可用的资源。You typically define the Storyboard as a resource that is available to the object that you want to animate, either in page-level Resources or Application.Resources.

下一示例介绍如何将上一示例 Storyboard 包含在页面级别的 Resources 定义中,其中 Storyboard 为根 Page 的键控资源。This next example shows how the previous example Storyboard would be contained in a page-level Resources definition, where the Storyboard is a keyed resource of the root Page. 请注意 x:Name 属性Note the x:Name attribute. 此属性是你定义 Storyboard 的变量名称的方式,以便以后 XAML 中的其他元素以及代码可以参考 StoryboardThis attribute is how you define a variable name for the Storyboard, so that other elements in XAML as well as code can refer to the Storyboard later.

<Page ...>
  <Page.Resources>
    <!-- Storyboard resource: Animates a rectangle's opacity. -->
    <Storyboard x:Name="myStoryboard">
      <DoubleAnimation
        Storyboard.TargetName="MyAnimatedRectangle"
        Storyboard.TargetProperty="Opacity"
        From="1.0" To="0.0" Duration="0:0:1"/>
    </Storyboard>
  </Page.Resources>
  <!--Page root element, UI definition-->
  <Grid>
    <Rectangle x:Name="MyAnimatedRectangle"
      Width="300" Height="200" Fill="Blue"/>
  </Grid>
</Page>

在 XAML 文件(例如 page.xaml 或 app.xaml)的 XAML 根上定义资源是在 XAML 中组织键控资源的常用做法。Defining resources at the XAML root of a XAML file such as page.xaml or app.xaml is a common practice for how to organize keyed resources in your XAML. 还可以将资源分为单独的文件,然后将其合并到应用或页面中。You also can factor resources into separate files and merge them into apps or pages. 有关详细信息,请参阅 ResourceDictionary 和 XAML 资源参考For more info, see ResourceDictionary and XAML resource references.

备注

Windows 运行时 XAML 支持使用 x:Key 属性x:Name 属性标识资源。Windows Runtime XAML supports identifying resources either using the x:Key attribute or the x:Name attribute. 使用 x:Name 属性对于 Storyboard 更常见,因为你最终会需要按变量名称引用它,以便你可以调用其 Begin 方法和运行动画。Using x:Name attribute is more common for a Storyboard, because you'll want to reference it by variable name eventually, so that you can call its Begin method and run the animations. 如果你确实要使用 x:Key 属性,则需要使用 ResourceDictionary 方法(例如 Item 索引器)来作为键控资源检索它,然后将检索的对象转换为 Storyboard 以使用 Storyboard 方法。If you do use x:Key attribute, you'll need to use ResourceDictionary methods such as the Item indexer to retrieve it as a keyed resource and then cast the retrieved object to Storyboard to use the Storyboard methods.

视觉状态的情节提要Storyboards for visual states

在为控件的可视外观声明视觉状态动画时,你还可将动画放在 Storyboard 单元中。You also put your animations within a Storyboard unit when you are declaring the visual state animations for a control's visual appearance. 在此情况下,你定义的 Storyboard 元素位于 VisualState 容器中,此容器嵌套在 Style(作为键控资源的 Style)中更深层的位置。In that case the Storyboard elements you define go into a VisualState container that's nested more deeply in a Style (it's the Style that is the keyed resource). 在此情况下,不需要对 Storyboard 使用键或名称,因为它是一种 VisualState,其中包含 VisualStateManager 可以调用的目标名称。You don't need a key or name for your Storyboard in this case because it's the VisualState that has a target name that the VisualStateManager can invoke. 控件的样式通常分为单独的 XAML ResourceDictionary 文件,而不是放在特定页面或应用的 Resources 集合中。The styles for controls are often factored into separate XAML ResourceDictionary files rather than placed in a page or app Resources collection. 有关详细信息,请参阅视觉状态的情节提要动画For more info, see Storyboarded animations for visual states.

从属动画和独立动画Dependent and independent animations

在此处,我们需要引入某些有关动画系统工作原理的重要知识点。At this point we need to introduce some important points about how the animation system works. 特别是,动画在基础方面与 Windows 运行时应用在屏幕上呈现的方式以及该呈现使用处理线程的方式的相互影响。In particular, animation interacts fundamentally with how a Windows Runtime app renders to the screen, and how that rendering uses processing threads. Windows 运行时应用始终具有一个主 UI 线程,并且此线程负责使用当前信息更新屏幕。A Windows Runtime app always has a main UI thread, and this thread is responsible for updating the screen with current information. 另外,Windows 运行时应用具有一个合成线程,该线程用于预先计算布局然后紧接着显示布局。In addition, a Windows Runtime app has a composition thread, which is used for precalculating layouts immediately before they are shown. 创建 UI 动画时可能会为 UI 线程带来大量的工作。When you animate the UI, there's potential to cause a lot of work for the UI thread. 系统必须在两次刷新之间的相当短的时间间隔内重新绘制屏幕的大量区域。The system must redraw large areas of the screen using fairly short time intervals between each refresh. 对于捕捉动画化属性的最新属性值,这是必需的。This is necessary for capturing the latest property value of the animated property. 如果你不多加注意,则动画可能会使 UI 的响应速度下降,或者将影响也位于同一 UI 线程上的其他应用功能的性能。If you're not careful, there's risk that an animation can make the UI less responsive, or will impact performance of other app features that are also on the same UI thread.

确定具有降低 UI 线程性能的某些风险的各种动画被称为从属动画The variety of animation that is determined to have some risk of slowing down the UI thread is called a dependent animation. 不受此风险限制的动画为独立动画An animation not subject to this risk is an independent animation. 从属动画和独立动画之间的区别并不仅仅由动画类型(DoubleAnimation 等)确定,如我们之前所述。The distinction between dependent and independent animations isn't just determined by animation types (DoubleAnimation and so on) as we described earlier. 相反,它由创建动画的特定属性以及其他因素(例如,控件的继承和组合)确定。Instead, it's determined by which specific properties you are animating, and other factors like inheritance and composition of controls. 在某些情况下,虽然动画确实更改了 UI,但该动画只对 UI 线程产生最小的影响,并且可以转而由合成线程作为独立动画进行处理。There are circumstances where even if an animation does change UI, the animation can have minimal impact to the UI thread, and can instead be handled by the composition thread as an independent animation.

如果某个动画具有以下特征的任意特征,则该动画为独立动画:An animation is independent if it has any of these characteristics:

警告

要让动画被视为独立动画,必须显式设置 Duration="0"In order for your animation to be treated as independent, you must explicitly set Duration="0". 例如,如果从此 XAML 中删除 Duration="0",动画将被视为从属动画,即使框架的 KeyTime 是“0:0:0”。For example, if you remove Duration="0" from this XAML, the animation is treated as dependent, even though the KeyTime of the frame is "0:0:0".

<Storyboard>
  <DoubleAnimationUsingKeyFrames
    Duration="0"
    Storyboard.TargetName="Button2"
    Storyboard.TargetProperty="Width">
    <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="200"/>
  </DoubleAnimationUsingKeyFrames>
</Storyboard>

如果你的动画不符合这些条件,则它可能是从属动画。If your animation doesn't meet these criteria, it's probably a dependent animation. 默认情况下,动画系统不运行从属动画。By default, the animation system won't run a dependent animation. 因此在开发和测试过程中,你甚至不会看到动画运行。So during the process of developing and testing, you might not even be seeing your animation running. 你仍可以使用此动画,但必须专门启用每个此类从属动画。You can still use this animation, but you must specifically enable each such dependent animation. 若要启用你的动画,请将动画对象的 EnableDependentAnimation 设置为 trueTo enable your animation, set the EnableDependentAnimation property of the animation object to true. (代表动画的每个 Timeline 子类都具有属性的不同实现方式,但它们全部称为 EnableDependentAnimation。)(Each Timeline subclass that represents an animation has a different implementation of the property but they're all named EnableDependentAnimation.)

对于启用从属动画,应用开发人员要承担的要求为,动画系统的设计意识以及开发经验。The requirement of enabling dependent animations falling onto the app developer is a conscious design aspect of the animation system and the development experience. 我们希望开发人员要了解动画对 UI 的响应性方面的性能成本。We want developers to be aware that animations do have a performance cost for the responsiveness of your UI. 性能较低的动画在全面的应用中很难隔离和调试。Poorly performing animations are difficult to isolate and debug in a full-scale app. 因此,最好仅打开你确实要用于应用的 UI 体验的从属动画。So it's better to turn on only the dependent animations you really need for your app's UI experience. 我们不希望由于使用大量循环的装饰性动画而导致容易损失应用的性能。We didn't want to make it too easy to compromise your app's performance because of decorative animations that use a lot of cycles. 有关动画的性能使用技巧的详细信息,请参阅优化动画和媒体For more info on performance tips for animation, see Optimize animations and media.

作为一名应用开发人员,你还可以选择应用应用级设置,该设置始终禁用从属动画,甚至禁用其中 EnableDependentAnimationtrue 的那些动画。As an app developer, you can also choose to apply an app-wide setting that always disables dependent animations, even those where EnableDependentAnimation is true. 请参阅 Timeline.AllowDependentAnimationsSee Timeline.AllowDependentAnimations.

提示

如果你使用 Visual Studio 为控件创作视觉状态,则设计人员将会在你尝试将从属动画应用到视觉状态属性时生成警告。If you are composing visual states for a control using Visual Studio, the designer will produce warnings whenever you attempt to apply a dependent animation to a visual state property.

启动动画和控制动画Starting and controlling an animation

到目前为止,我们向你展示的所有内容实际上都不会导致动画运行或应用!Everything we've shown you so far doesn't actually cause an animation to run or be applied! 在动画启动和运行前,动画在 XAML 中声明的值更改都是潜在的并且尚未发生。Until the animation is started and is running, the value changes that an animation is declaring in XAML are latent and won't happen yet. 你必须采用某些与应用生存期或用户体验相关的方法来显式启动动画。You must explicitly start an animation in some way that's related to the app lifetime or the user experience. 最简单的方法是,你可以通过在作为该动画的父动画的 Storyboard 上调用 Begin 方法来启动一个动画。At the simplest level, you start an animation by calling the Begin method on the Storyboard that's the parent for that animation. 你不能直接通过 XAML 调用方法,因此无论你采用哪种方法启动动画,你都将通过代码来完成。You can't call methods from XAML directly, so whatever you do to enable your animations, you'll be doing it from code. 它将是页面的代码隐藏或是应用的组件,或许是控件的逻辑(如果你定义自定义控件类)。That will either be the code-behind for the pages or components of your app, or perhaps the logic of your control if you're defining a custom control class.

通常来说,你将调用 Begin 并仅仅让动画运行直至其持续时间结束。Typically, you'll call Begin and just let the animation run to its duration completion. 但是,你也可以使用 PauseResumeStop 方法在运行时控制 Storyboard,以及用于更先进的动画控制方案的其他 API。However, you can also use Pause, Resume and Stop methods to control the Storyboard at run-time, as well as other APIs that are used for more advanced animation control scenarios.

当你在包含无限重复 (RepeatBehavior="Forever") 的动画的情节提要上调用 Begin 时,该动画将一直运行,除非停止加载包含该动画的页面或者专门调用 PauseStopWhen you call Begin on a storyboard that contains an animation that repeats infinitely (RepeatBehavior="Forever"), that animation runs until the page containing it is unloaded, or you specifically call Pause or Stop.

通过应用代码启动动画Starting an animation from app code

你可以自动启动动画,也可以通过响应用户操作来启动动画。You can either start animations automatically, or in response to user actions. 对于自动方案,通常使用对象生存期事件(例如 Loaded)来用作动画触发器。For the automatic case, you typically use an object lifetime event such as Loaded to act as the animation trigger. Loaded 事件是用于此方法的适合事件,因为此时 UI 已准备好交互,并且由于另一部分的 UI 仍处于加载状态因此动画的开始部分不会被截断。The Loaded event is a good event to use for this because at that point the UI is ready for interaction, and the animation won't be cut off at the beginning because another part of UI was still loading.

在此示例中,PointerPressed 事件附加到矩形,因此当用户单击矩形时,动画即开始。In this example, the PointerPressed event is attached to the rectangle so that when the user clicks the rectangle, the animation begins.

<Rectangle PointerPressed="Rectangle_Tapped"
  x:Name="MyAnimatedRectangle"
  Width="300" Height="200" Fill="Blue"/>

事件处理程序通过使用 StoryboardBegin 方法来启动 Storyboard(动画)。The event handler start the Storyboard (the animation) by using the Begin method of the Storyboard.

myStoryboard.Begin();
myStoryboard().Begin();
myStoryboard->Begin();
myStoryBoard.Begin()

如果你希望在动画应用完值之后运行其他逻辑,你可以处理 Completed 事件。You can handle the Completed event if you want other logic to run after the animation has finished applying values. 同样,要对属性系统/动画交互进行故障排除,GetAnimationBaseValue 方法可能十分有用。Also, for troubleshooting property system/animation interactions, the GetAnimationBaseValue method can be useful.

提示

在你为应用方案编写代码(其中会从应用代码启动动画)时,你可能希望再次查看动画或转换是否已存在于 UI 方案的动画库中。Whenever you are coding for an app scenario where you are starting an animation from app code, you might want to review again whether an animation or transition already exists in the animation library for your UI scenario. 库动画使得所有 Windows 运行时应用间的 UI 体验更加一致,并且更易于使用。The library animations enable a more consistent UI experience across all Windows Runtime apps, and are easier to use.

视觉状态的动画Animations for visual states

用于定义控件的视觉状态的 Storyboard 的运行行为不同于应用直接运行情节提要的方式。The run behavior for a Storyboard that's used to define a control's visual state is different from how an app might run a storyboard directly. 当应用到 XAML 中的视觉状态时,Storyboard 是包含的 VisualState 的元素,并且可以通过使用 VisualStateManager API 将该状态作为整体进行控制。As applied to a visual state definition in XAML, the Storyboard is an element of a containing VisualState, and the state as a whole is controlled by using the VisualStateManager API. 当控件使用包含的 VisualState 时,其中的任何动画都将根据其动画值和 Timeline 属性运行。Any animations within will run according to their animation values and Timeline properties when the containing VisualState is used by a control. 有关详细信息,请参阅视觉状态的情节提要For more info, see Storyboards for visual states. 对于视觉状态,显示的 FillBehavior 是不同的。For visual states, the apparent FillBehavior is different. 如果视觉状态更改为另一个状态,则之前视觉状态及其动画应用的所有属性更改都将被取消,即使在新的视觉状态没有专门将新的动画应用到属性的情况下也是如此。If a visual state is changed to another state, all the property changes applied by the previous visual state and its animations are canceled, even if the new visual state doesn't specifically apply a new animation to a property.

StoryboardEventTriggerStoryboard and EventTrigger

存在启动动画的一种方法,该方法可以在 XAML 中完全声明。There is one way to start an animation that can be declared entirely in XAML. 但是,此技术目前不再被广泛使用。However, this technique isn't widely used anymore. 它是来自 WPF 和早期版本的 Silverlight(在 VisualStateManager 支持之前)中的旧语法。It's a legacy syntax from WPF and early versions of Silverlight prior to VisualStateManager support. 鉴于导入/兼容性原因,此 EventTrigger 语法在 Windows 运行时 XAML 中仍然有效,但仅用于基于 FrameworkElement.Loaded 事件的触发行为;尝试触发其他事件将引发异常或无法编译。This EventTrigger syntax still works in Windows Runtime XAML for import/compatibility reasons, but only works for a trigger behavior based on the FrameworkElement.Loaded event; attempting to trigger off other events will throw exceptions or fail to compile. 有关详细信息,请参阅 EventTriggerBeginStoryboardFor more info, see EventTrigger or BeginStoryboard.

创建 XAML 附加属性的动画Animating XAML attached properties

这不是一个常见情形,但你可以将动画值应用到 XAML 附加属性。It's not a common scenario, but you can apply an animated value to a XAML attached property. 有关哪些附加属性及其工作原理的详细信息,请参阅附加属性概述For more info on what attached properties are and how they work, see Attached properties overview. 确定附加属性目标需要括号中包含属性名的 Property-path语法Targeting an attached property requires a property-path syntax that encloses the property name in parentheses. 你可以通过使用应用不连续整数值的 ObjectAnimationUsingKeyFrames 创建内置附加属性的动画,如 Canvas.ZIndexYou can animate the built-in attached properties such as Canvas.ZIndex by using an ObjectAnimationUsingKeyFrames that applies discrete integer values. 不过,Windows 运行时 XAML 实现的现有局限性是无法创建自定义附加属性的动画。However, an existing limitation of the Windows Runtime XAML implementation is that you cannot animate a custom attached property.

更多动画类型,以及了解有关创建 UI 动画的后续步骤More animation types, and next steps for learning about animating your UI

到目前为止,我们已经介绍了在两个值之间创建动画的自定义动画,然后在动画运行期间根据需要采用线性方式插入值。Up to now, we've shown the custom animations that are animating between two values, and then linearly interpolating the values as necessary while the animation runs. 它们被称为 From/To/By 动画。These are called From/To/By animations. 但还有另一种动画类型可以帮助你声明介于起始和结束之间的中间值。But there's another animation type that enables you to declare intermediate values that fall between the start and end. 它们被称为关键帧动画These are called key-frame animations. 还有一种方法可以在 From/To/By 动画或关键帧动画上改变插入逻辑。There's also a way to alter the interpolation logic on either a From/To/By animation or a key-frame animation. 这将涉及缓动函数的应用。This involves applying an easing function. 有关这些概念的详细信息,请参阅关键帧和缓动函数动画For more info on these concepts, see Key-frame and easing function animations.