情节提要概述

本概述重点介绍如何在 Windows 动画中使用过渡和情节提要。 有关 Windows 动画组件的概述,请参阅 Windows 动画概述

本主题包含以下各节:

Transitions

过渡定义单个动画变量在特定时间间隔内的变化方式。 Windows 动画包括开发人员可应用于一个或多个动画变量的常见过渡库。 不同类型的转换具有不同的参数集,其中可能包括转换完成时的变量值、转换持续时间或基础数学函数特有的数量,例如加速或振荡范围。

所有转换共享两个隐式参数:初始值和初始速度 (数学函数的斜率) 。 这些值可由应用程序显式指定,但通常由动画管理器在切换开始时设置为动画变量的值和速度。

转换库

以下转换当前由转换库提供。 如果应用程序需要无法使用转换库指定的效果,开发人员可以通过为应用程序实现自定义内插器或使用来自第三方的转换库来创建其他类型的转换。

转换名称 说明
accelerate-decelerate
动画变量在给定持续时间内加速,然后减慢速度。
常量
动画变量在整个过渡过程中保持其初始值。
三次方
动画变量在给定的持续时间内从其初始值更改为具有指定最终速度的指定最终值。
离散
动画变量在指定延迟时间内保持其初始值,然后立即切换到指定的最终值,并在给定的保留时间内保持该值。
瞬时
动画变量会立即从其当前值更改为指定的最终值。
linear
动画变量在给定持续时间内从其初始值线性过渡到指定的最终值。
线性与速度
动画变量以线性方式从初始值转换为具有指定速度的指定最终值。
加速抛物线
动画变量从初始值转换为指定的最终值,具有指定的最终速度,并用指定的加速度更改其速度。
逆转
变量在给定持续时间内更改方向。 最终值将与初始值相同,最终速度将是初始速度的负值。
正弦从范围
变量在给定的持续时间内在给定值范围内振荡,具有指定的振荡周期。
正弦从速度
变量在给定的持续时间内以指定的振荡周期振荡。 振幅由变量的初始速度决定。
平滑停止
动画变量在最长持续时间内在指定的最终值处顺利停止。

下表包含每个转换的插图。

图示
从离散转换的速度转换的线性转换图的线性转换图的固定转换图的即时转换插图的插图
从加速转换的抛物线转换的插图,该图显示了平滑停止转换的三次转换图
弦转换速度转换的反转转换插图的插图,该图为从范围转换的正弦转换
增加和减速转换的插图

自定义转换

内插器定义数学函数,该函数确定动画变量在从初始值到最终值时如何随时间变化。 转换库中的每个转换都有一个关联的内插器对象,该对象由系统提供并实现内插器函数。 如果应用程序需要无法使用转换库指定的效果,则它可以通过为每个新转换实现内插器对象来实现一个或多个自定义转换。 内插器对象不能由应用程序直接使用,必须改为包装在关联的转换中。 转换工厂用于从内插器对象生成转换。 有关更多详细信息 ,请参阅 IUIAnimationInterpolatorIUIAnimationTransitionFactory

请注意,大多数应用程序将具有使用转换库所需的所有转换,因此不需要实现内插器。

情节提要

情节提要是一段时间内应用于一个或多个动画变量的过渡集合。 情节提要中的切换保证保持彼此同步,情节提要作为一个单元进行计划或取消。 创建所需的切换后,应用程序使用动画管理器创建情节提要,将切换效果添加到情节提要,相应地配置情节提要,并计划尽快播放。 动画管理器确定情节提要的实际开始时间,因为可能会与当前对相同变量进行动画处理的其他情节提要发生争用。

情节提要的总体持续时间取决于情节提要中切换的持续时间。 转换的持续时间不需要固定;它可以通过转换开始时动画变量的值和速度来确定。 因此,情节提要的持续时间也取决于其动画变量的状态。

以下示例假定已创建动画管理器、过渡库和计时器。 有关详细信息,请参阅 创建主动画对象。 这些示例还假定应用程序已使用 IUIAnimationManager::CreateAnimationVariable 方法创建了三个动画变量, (X、Y 和 Z) ,并使用 IUIAnimationTransitionLibrary 接口的方法之一 (T1、T3、T4 和 T5) 5 个转换。

生成简单的情节提要

若要生成简单的情节提要,请使用 IUIAnimationManager::CreateStoryboard 方法创建新的情节提要,使用 IUIAnimationTransitionLibrary::CreateLinearTransition 方法创建线性过渡 T1,并使用 IUIAnimationStoryboard::AddTransition 方法将 T1 转换应用于变量 X 并将生成的过渡添加到情节提要。

此过程生成一个简单的情节提要,如下图所示。 情节提要包含一个过渡 T1,以便变量 X 的值在固定的持续时间内线性变化。

显示具有固定持续时间的简单情节提要的插图

请注意,对于这样一个简单的方案,另一个选项是使用 IUIAnimationManager::ScheduleTransition 方法。

使用Context-Sensitive持续时间

虽然某些切换具有固定的持续时间,但其他转换的持续时间取决于转换开始时动画变量的初始值或速度。 例如, IUIAnimationTransitionLibrary::CreateLinearTransitionFromSpeed 方法创建一个过渡,其持续时间与动画变量的初始值与指定最终值之间的差异成正比。 在此插图和其余插图中,具有任意持续时间的此类切换用问号 () 显示,其实际持续时间在情节提要播放时确定。

显示持续时间未知的简单情节提要的插图

构建更复杂的情节提要

创建情节提要并添加单个切换 T1 后,可以通过再次调用 IUIAnimationStoryboard::AddTransition 方法为 X 变量追加第二个切换,但使用 T2 而不是 T1。

假设 T2 切换的持续时间与上下文相关,则情节提要现在包含两个任意持续时间的背靠背切换,这些切换会影响变量 X。

显示包含同一变量上的两个切换的情节提要的插图

使用变量 Y 和过渡 T3 再次调用 AddTransition 会在情节提要的开头添加第三个切换。 根据情节提要播放时的 X 和 Y 的值,T3 可能在 T1 之后甚至 T2 之后结束。

显示包含跨多个变量的切换的情节提要的插图

使用关键帧

若要在情节提要开头的偏移量处添加切换,必须先添加关键帧。 关键帧表示时间上的即时,它们本身对情节提要的行为没有影响。 每个情节提要都有一个隐式关键帧,表示情节提要的开头,UI_ANIMATION_KEYFRAME_STORYBOARD_START;可以通过使用 UI_ANIMATION_KEYFRAME_STORYBOARD_START 调用 IUIAnimationStoryboard::AddKeyframeAtOffset 方法,在起始偏移量处添加新的关键帧。

添加关键帧的偏移量始终相对于另一个关键帧。 下图显示了添加 keyframe1 和转换 T4 的结果,这些操作应用于变量 Z,与 keyframe1 保持一致,并使用固定持续时间创建。 当然,由于其他转换的持续时间尚不得而知,因此 T4 可能不是最后一次转换完成。

显示添加在关键帧对齐的过渡的插图

还可以使用 IUIAnimationStoryboard::AddKeyframeAfterTransition 方法将关键帧放置在转换的末尾。 下图显示了在 T1 之后添加 keyframe2 和在 T2 之后添加 keyframe3 的结果。

显示各种转换后添加关键帧的插图

由于 T1 和 T2 的持续时间在情节提要播放之前是未知的,因此直到那时才会确定关键帧 2 和关键帧 3 的偏移量。 因此,keyframe2 甚至 keyframe3 可以早于 keyframe1 出现。

通过使用 IUIAnimationStoryboard::AddTransitionBetweenKeyframes 方法,转换的开始和结束都可以与关键帧保持一致。 下图显示了在关键帧 2 和关键帧 3 之间在变量 Y 上添加第五个转换 T5 的结果。 这会更改 T5 的持续时间,使其更长或更短,具体取决于关键帧 2 和关键帧 3 的相对偏移量。

显示关键帧之间转换的加载项的插图

保存变量

如果 T4 在 T2 和 T5 之后结束,则情节提要停止对变量 X 和 Y 进行动画处理,使它们可供其他情节提要进行动画处理。 但是,应用程序可以调用 IUIAnimationStoryboard::HoldVariable 方法,以请求情节提要保存部分或所有在其最终值上动画处理的变量,直到情节提要完成。 下图显示了 T4 最后完成时保留 X 和 Z 的结果。 请注意,情节提要在其最终值上保留 X,直到情节提要完成。 保留对 Z 没有影响,因为情节提要在 T4 完成后结束。

显示最终值处保留变量的插图,直到情节提要完成

即使此情节提要未保留 Y,其值在 T5 完成后不会更改,除非另一个情节提要对其进行动画处理。 由于 Y 未保留,因此任何其他情节提要(无论优先级如何)都可以在 T5 完成后对 Y 进行动画处理。 相比之下,由于持有 X,因此优先级较低的情节提要在完成此情节提要之前无法对 X 进行动画处理。

当情节提要开始播放时,所有这些插图都假定变量的任意当前值集。 如果遇到其他值,则上下文相关转换的持续时间可能会有所不同,如下图所示。

显示更改用于上图的初始条件的结果的插图

在此方案中,T5 在 T3 完成之前开始,因此 T3 会进行剪裁。 由于 T4 的完成时间早于 T2 和 T5,因此 Z 的值将一直保留到情节提要的末尾。 通常,情节提要开始播放时变量的值和速度可能会影响情节提要的关键帧顺序以及情节提要的整体长度和形状。

计划情节提要

在安排情节提要时,其开始时间取决于情节提要的大纲和当前在计划中的情节提要的大纲。 具体而言,情节提要对每个单独变量进行动画处理的第一个和最后一个时刻决定了两个情节提要是否以及何时发生冲突,但内部切换的内部细节并不重要。

下图显示了情节提要的轮廓,该情节提要具有 5 个过渡,对三个变量进行动画处理。

插图显示具有五个过渡的情节提要动画三个变量

Windows 动画平台的一个基石是,它支持在必要时让一个动画在另一个动画开始之前完成。 虽然这消除了许多逻辑问题,但它也会在 UI 中引入任意延迟。 为了解决此问题,应用程序可以使用 IUIAnimationStoryboard::SetLongestAcceptableDelay 方法为情节提要启动指定最长的可接受延迟,动画管理器使用此信息在指定的延迟期过去之前计划情节提要。 计划情节提要时,动画管理器将确定是否必须先取消、剪裁、结束和/或压缩其他情节提要。

应用程序可以注册一个处理程序,该处理程序将在情节提要的状态更改时调用。 这使应用程序能够在情节提要开始播放、运行到完成、完全从计划中删除或由于优先级较高的情节提要中断而无法完成时做出响应。 若要识别传递到情节提要事件处理程序 (或优先级比较) ,应用程序可以使用 IUIAnimationStoryboard::SetTag 方法将标记应用于情节提要,类似于可用于标识变量的情节提要。 与情节提要重用一样,开发人员在使用标记识别情节提要时必须谨慎,并确保在用户操作导致许多情节提要排队时不会出现歧义。

以下示例演示了尝试计划本主题前面部分中生成的情节提要的两种变体。

在此方案中,已安排六个情节提要 A 到 F 来对变量 W、X、Y 和 Z 进行动画处理,但只有 A 和 B 已开始播放。 新的情节提要标记为 G,其最长可接受延迟设置为下图所示的持续时间。

显示向现有计划添加新情节提要的插图

应用程序已注册了包含以下逻辑的优先级比较:

  • G 只能取消 C 和 E,并且只能用于防止故障。
  • G 只能剪裁 A、C、E 和 F,并且只能防止故障。
  • 任何情节提要都可以压缩任何其他情节提要 (压缩始终只是为了防止故障) 。

注意

限定符“仅用于防止失败”意味着仅当 priorityEffect 参数UI_ANIMATION_PRIORITY_EFFECT_FAILURE时,已注册的优先级比较才会返回 S_OK。 有关详细信息,请参阅 IUIAnimationPriorityComparison::HasPriority 方法。

若要在最长可接受延迟过前启动 G,动画管理器必须执行以下操作:

  • 剪裁 F
  • 取消 E

取消 E 时,将发现 D 和 F 并还原其原始轮廓:

显示原始轮廓的插图

动画管理器无需取消或剪裁 C 即可在其最长可接受延迟之前进行计划,因此 C 和 G 会议将确定 G 开始的时间。

显示 f 已修整以允许 c 和 g 满足的插图

成功安排 G 后,可以确定其转换的持续时间,因此可以知道其大纲的其余部分。 但是,如果随后从计划中删除另一个情节提要,大纲可能会更改。

作为第二个示例,请考虑上述方案,但为 G 指定了较短的可接受延迟。

图中显示了前面的方案,但 g 的可接受延迟时间较短

在这种情况下,将执行以下操作:

  • 剪裁 F
  • 取消 E
  • 取消 C

此外,动画管理器必须按显示的量压缩 D,以使 G 在其最长的可接受延迟后启动,且不晚启动。

图示显示必须压缩 d 才能使 g 在最长可接受延迟时启动的位置

为了保留它们的相对计时,A、B 和 F 也会压缩。

显示 a、b、d 和 f 压缩的插图

但是,不显示) (不相关的变量上的情节提要不会被压缩。

同样,G 的大纲现在已知,并且与第一个方案中的结果不同,因为 G 开始时变量具有不同的值。

IUIAnimationManager

IUIAnimationPriorityComparison

IUIAnimationStoryboard

IUIAnimationTransitionLibrary