彈簧動畫
本文說明如何使用彈簧 NaturalMotionAnimations。
必要條件
在這裡,我們假設您已熟悉下列文章中討論的概念:
為什麼是彈簧?
彈簧是我們在實際生活中某個時機都經歷過的常見動作體驗:從彈簧圈玩具,到物理教室裡用彈簧綁住物體的經驗。 彈簧的振蕩動作經常在那些觀察者的內心,激起俏皮和輕鬆的情感反應。 因此,彈簧的動作就這樣妥善地轉譯成應用程式 UI,滿足想要建立更活潑動作體驗的人士,為終端使用者帶來比傳統三次方貝茲更「彈跳」的體驗。 在這些情況下,彈簧動作不僅會建立更活潑的動作體驗,還能協助吸引人們對新內容或目前動畫內容的注意。 視應用程式品牌或動作語言而定,振蕩動作可能更多音效且更顯目,但在其他情況下則可能更不自然。
在 UI 中使用彈簧
如先前所述,彈簧可以是一個實用的動作,能整合到您的應用程式中,引起非常熟悉且俏皮的 UI 體驗。 UI 中彈簧的常見用法如下:
彈簧用法描述 | 視覺效果範例 |
---|---|
讓動作體驗「彈跳」並且看起來更活潑。 (以動畫進行縮放) | |
讓動作體驗巧妙地感到更有精力 (以動畫進行位移) |
在這些案例中,可以藉由「彈跳到」新的值並在周圍振蕩,或以一些初始速度在目前值周圍振蕩,來引發彈簧動作效果。
定義您的彈簧動作
您可以使用 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 體驗,當使用者按一下展開按鈕時,瀏覽窗格會透過彈簧、振蕩動作以動畫方式展開。
首先,定義按下事件內的彈簧動畫,來處理瀏覽窗格出現的時機。 接著,您可以使用 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 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 中同時有一個以程式設計方式和輸入驅動的彈簧動畫!
綜上所述,在應用程式中使用彈簧動畫的步驟如下:
- 從 Compositor 建立 SpringAnimation。
- 定義 SpringAnimation 的屬性 (如果您想要非預設值):
- DampingRatio
- 期間
- 最終值
- 初始值
- 初始速度
- 指派給目標。
- 如果您要建立 CompositionObject 屬性的動畫效果,請將 SpringAnimation 當做參數傳遞至 StartAnimation。
- 如果您想要搭配輸入使用,請將 InertiaModifier 的 NaturalMotion 屬性設定為 SpringAnimation。