弹簧动画

本文介绍如何使用 Spring NaturalMotionAnimations。

先决条件

我们在此假设你熟悉这些文章中所述的概念:

为什么是泉水?

斯普林斯是一种常见的运动体验,我们在生活中的某个时刻都经历过:从闪烁的玩具到物理教室体验与春天绑在一起。 春天的振荡动作经常煽动那些观察它的人的俏皮和轻心的情感反应。 因此,春天的运动很好地转化为应用程序 UI,对于那些希望创建一个活泼的运动体验,“流行”更多的最终用户比传统的立方贝塞尔。 在这些情况下,春季运动不仅创造了一个活泼的运动体验,而且还有助于引起人们对新内容或当前动画内容的注意。 根据应用程序品牌或运动语言,振荡更为明显,但在其他情况下,振荡更为微妙。

具有春季动画的动作使用立方贝塞尔动画进行运动

在 UI 中使用泉

如前所述,泉是一个有用的动作,可以集成到应用中,以引入非常熟悉和俏皮的 UI 体验。 UI 中的普林斯的常见用法包括:

Spring Usage Description 视觉对象示例
制作动作体验“流行”,看起来更生动。 (动画缩放) 使用春季动画缩放运动
使运动体验巧妙地感觉更精力充沛 (动画偏移) 使用春季动画偏移运动

在上述每个情况下,可以通过“跳到”和在新的值周围振荡或以一些初始速度振荡其当前值来触发春季运动。

春季动画振荡

定义春季运动

使用 NaturalMotionAnimation API 创建春季体验。 具体而言,使用 Compositor 中的 Create* 方法创建 SpringNaturalMotionAnimation。 然后,可以定义运动的以下属性:

  • DampingRatio - 表示动画中使用的春季运动的阻尼级别。
抑制比率值 说明
DampingRatio = 0 未采样 - 春天将振荡很长时间
0 < DampingRatio < 1 不足 - 春天将振荡从一点点到很多。
DampingRatio = 1 严重采样 - 春天不会执行振荡。
DampingRation > 1 过度采样 - 春天将迅速到达其目的地与突然减速,没有振荡
  • 时间段 - 执行单个振荡需要春天的时间。
  • Final /Starting Value – 定义的春季运动的起始和结束位置(如果未定义,起始值和/或最终值将是当前值)。
  • 初始速度 - 运动的初始速度编程。

还可以定义与 KeyFrameAnimations 相同的动作的一组属性:

  • DelayTime/Delay 行为
  • StopBehavior

在对偏移量和缩放/大小进行动画处理时,Windows 设计团队针对不同类型的弹簧推荐以下值:

properties 普通春季 受阻的春天 减少受阻的春天
Offset 阻尼比率 = 0.8
句点 = 50 毫秒
阻尼比率 = 0.85
句点 = 50 毫秒
阻尼比率 = 0.65
句点 = 60 毫秒
缩放/大小 阻尼比率 = 0.7
句点 = 50 毫秒
阻尼比率 = 0.8
句点 = 50 毫秒
阻尼比率 = 0.6
句点 = 60 毫秒

定义属性后,即可将 spring NaturalMotionAnimation 传递到 CompositionObject 的 StartAnimation 方法或 InteractionTracker InertiaModifier 的 Motion 属性。

示例

在此示例中,你将创建一个导航和画布 UI 体验,当用户单击展开按钮时,导航窗格会以一个春天的振荡运动进行动画处理。

单击时的 Spring 动画

首先,在单击的事件中定义当导航窗格出现时的春季动画。 然后,使用 InitialValueExpression 功能定义动画的属性,以使用表达式定义 FinalValue。 还可以跟踪窗格是否已打开,并在准备就绪时启动动画。

private void Button_Clicked(object sender, RoutedEventArgs e)
{
 _springAnimation = _compositor.CreateSpringScalarAnimation();
 _springAnimation.DampingRatio = 0.75f;
 _springAnimation.Period = TimeSpan.FromSeconds(0.5);

 if (!_expanded)
 {
 _expanded = true;
 _propSet.InsertBoolean("expanded", true);
 _springAnimation.InitialValueExpression["FinalValue"] = "this.StartingValue + 250";
 } else
 {
 _expanded = false;
 _propSet.InsertBoolean("expanded", false);
_springAnimation.InitialValueExpression["FinalValue"] = "this.StartingValue - 250";
 }
 _naviPane.StartAnimation("Offset.X", _springAnimation);
}

现在,如果想要将此动作绑定到输入,该怎么办? 那么,如果最终用户轻扫,窗格会发出 Spring 运动? 更重要的是,如果用户更难或更快轻扫,则动作会根据最终用户的速度进行调整。

轻扫时的 Spring 动画

为此,可以采用同一 Spring Animation 并将其传递给 InteractionTracker 的惯性Modifier。 有关 InputAnimations 和 InteractionTracker 的详细信息,请参阅 InteractionTracker 的自定义操作体验。 我们假设在本代码示例中,你已设置 InteractionTracker 和 VisualInteractionSource。 我们将重点创建将采用 NaturalMotionAnimation 的惯性分子,在本例中为春季。

// InteractionTracker and the VisualInteractionSource previously setup
// The open and close ScalarSpringAnimations defined earlier
private void SetupInput()
{
 // Define the InertiaModifier to manage the open motion
 var openMotionModifer = InteractionTrackerInertiaNaturalMotion.Create(compositor);

 // Condition defines to use open animation if panes in non-expanded view
 // Property set value to track if open or closed is managed in other part of code
 openMotionModifer.Condition = _compositor.CreateExpressionAnimation(
"propset.expanded == false");
 openMotionModifer.Condition.SetReferenceParameter("propSet", _propSet);
 openMotionModifer.NaturalMotion = _openSpringAnimation;

 // Define the InertiaModifer to manage the close motion
 var closeMotionModifier = InteractionTrackerInertiaNaturalMotion.Create(_compositor);

 // Condition defines to use close animation if panes in expanded view
 // Property set value to track if open or closed is managed in other part of code
 closeMotionModifier.Condition = 
_compositor.CreateExpressionAnimation("propSet.expanded == true");
 closeMotionModifier.Condition.SetReferenceParameter("propSet", _propSet);
 closeMotionModifier.NaturalMotion = _closeSpringAnimation;

 _tracker.ConfigurePositionXInertiaModifiers(new 
InteractionTrackerInertiaNaturalMotion[] { openMotionModifer, closeMotionModifier});

 // Take output of InteractionTracker and assign to the pane
 var exp = _compositor.CreateExpressionAnimation("-tracker.Position.X");
 exp.SetReferenceParameter("tracker", _tracker);
 ElementCompositionPreview.GetElementVisual(pageNavigation).
StartAnimation("Translation.X", exp);
}

现在,UI 中同时具有编程和输入驱动的春季动画!

总之,在应用中使用春季动画的步骤:

  1. 从 Compositor 创建 SpringAnimation。
  2. 如果需要非默认值,请定义 SpringAnimation 的属性:
    • DampingRatio
    • 周期
    • 最终值
    • 初始值
    • 初速度
  3. 分配给目标。
    • 如果要对 CompositionObject 属性进行动画处理,请将 SpringAnimation 作为参数传递给 StartAnimation。
    • 如果要与输入一起使用,请将 InertiaModifier 的 NaturalMotion 属性设置为 SpringAnimation。