共用方式為


彈簧動畫

本文說明如何使用彈簧 NaturalMotionAnimations。

必要條件

在這裡,我們假設您已熟悉下列文章中討論的概念:

為什麼是彈簧?

彈簧是我們在實際生活中某個時機都經歷過的常見動作體驗:從彈簧圈玩具,到物理教室裡用彈簧綁住物體的經驗。 彈簧的振蕩動作經常在那些觀察者的內心,激起俏皮和輕鬆的情感反應。 因此,彈簧的動作就這樣妥善地轉譯成應用程式 UI,滿足想要建立更活潑動作體驗的人士,為終端使用者帶來比傳統三次方貝茲更「彈跳」的體驗。 在這些情況下,彈簧動作不僅會建立更活潑的動作體驗,還能協助吸引人們對新內容或目前動畫內容的注意。 視應用程式品牌或動作語言而定,振蕩動作可能更多音效且更顯目,但在其他情況下則可能更不自然。

使用 spring 動畫的動作使用立方貝塞爾動畫的動作

在 UI 中使用彈簧

如先前所述,彈簧可以是一個實用的動作,能整合到您的應用程式中,引起非常熟悉且俏皮的 UI 體驗。 UI 中彈簧的常見用法如下:

彈簧用法描述 視覺效果範例
讓動作體驗「彈跳」並且看起來更活潑。 (以動畫進行縮放) 使用春季動畫調整動作
讓動作體驗巧妙地感到更有精力 (以動畫進行位移) 使用彈簧動畫的位移動作

在這些案例中,可以藉由「彈跳到」新的值並在周圍振蕩,或以一些初始速度在目前值周圍振蕩,來引發彈簧動作效果。

Spring 動畫振蕩

定義您的彈簧動作

您可以使用 NaturalMotionAnimation API 來建立彈簧體驗。 具體而言,您會使用 Compositor 的 Create* 方法來建立 SpringNaturalMotionAnimation。 然後您就可以定義動作的下列屬性:

  • DampingRatio – 表示動畫中使用的彈簧動作阻尼程度。
阻尼比率值 描述
DampingRatio = 0 沒有阻尼 – 彈簧會振蕩很長一段時間
0 < DampingRatio < 1 欠阻尼 - 彈簧會振蕩,程度從些微到劇烈。
DampingRatio = 1 臨界阻尼 – 彈簧不會執行振蕩。
DampingRation > 1 過阻尼 – 彈簧將快速到達其最終停止狀態,突然減速,沒有振蕩
  • Period – 週期,彈簧執行單次振蕩所花費的時間。
  • Final / Starting Value – 定義彈簧動作的起始和結束位置 (如果未定義,起始值及/或最終值將是目前的值)。
  • Initial Velocity – 初始速度,以程式設計方式設定動作的初始速度。

您也可以定義一組與 KeyFrameAnimations 相同的動作屬性:

  • DelayTime / Delay Behavior
  • StopBehavior

在以動畫進行位移和縮放/大小的常見案例中,Windows 設計小組針對不同類型彈簧的 DampingRatio 和 Period 建議下列的值:

屬性 一般彈簧 帶有阻尼的彈簧 較少阻尼的彈簧
Offset 阻尼比率 = 0.8
週期 = 50 ms
阻尼比率 = 0.85
週期 = 50 ms
阻尼比率 = 0.65
週期 = 60 ms
縮放/大小 阻尼比率 = 0.7
週期 = 50 ms
阻尼比率 = 0.8
週期 = 50 ms
阻尼比率 = 0.6
週期 = 60 ms

定義屬性之後,您就可以將 Spring NaturalMotionAnimation 傳遞至 CompositionObject 的 StartAnimation 方法或 InteractionTracker InertiaModifier 的 Motion 屬性。

範例

在此範例中,您會建立瀏覽和畫布 UI 體驗,當使用者按一下展開按鈕時,瀏覽窗格會透過彈簧、振蕩動作以動畫方式展開。

按兩下的 Spring 動畫

首先,定義按下事件內的彈簧動畫,來處理瀏覽窗格出現的時機。 接著,您可以使用 InitialValueExpression 功能來定義動畫的屬性,以使用 Expression 來定義 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 Animation,並使用 InteractionTracker 將其傳遞至 InertiaModifier。 如需 InputAnimations 和 InteractionTracker 的詳細資訊,請參閱使用 InteractionTracker 自訂操作體驗。 我們會假設,您已為此程式碼範例設定 InteractionTracker 和 VisualInteractionSource。 我們會將重點放在建立將採用 NaturalMotionAnimation 的 InertiaModifiers,在此案例中為彈簧。

// 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。