本文將深入探討如何利用 InteractionTracker 的 InertiaModifier 功能,創造能在 WinUI 應用程式中自動吸附到指定點的動態體驗。
在 WinUI 應用程式中, InteractionTracker 相關的慣性修飾符類型都在 Microsoft.UI.Composition.Interactions 命名空間中。
先決條件
在這裡,我們假設你已經熟悉這些文章中討論的概念:
什麼是吸附點?它們為什麼有用?
在打造自訂操作體驗時,有時在可捲動/可縮放的畫布中建立專門 的位置點 會很有幫助,讓 InteractionTracker 永遠停留在這些位置。 這些通常稱為 彈跳點。
請注意以下範例中,捲動會讓介面在不同圖片之間處於尷尬的位置:
如果你加上吸附點,當你停止在圖片間滾動時,它們會「吸附」到指定位置。 有了 snap points,讓瀏覽圖片的體驗更加乾淨且反應靈敏。
互動追蹤器與慣性修正器
在使用 InteractionTracker 建立客製化操作體驗時,你可以利用 InertiaModifiers 創造快點移動體驗。 InertiaModifier 本質上是讓你定義 InteractionTracker 進入慣性狀態時,如何或從哪裡抵達目的地的方式。 你可以套用 InertiaModifier 來影響 InteractionTracker 的 X 或 Y 位置或縮放屬性。
慣性修正器有三種類型:
- InteractionTrackerInertiaRestingValue – 一種在互動或程式速度後調整最終靜止位置的方法。 預先設定的動作會將 InteractionTracker 帶到該位置。
- InteractionTrackerInertiaMotion – 一種定義互動追蹤器在互動或程式速度後執行的特定動作的方式。 最終位置將由此運動推導出。
- InteractionTrackerInertiaNaturalMotion – 一種以物理動畫定義互動或程式速度後最終靜止位置的方法(NaturalMotionAnimation)。
進入慣性階段時,InteractionTracker 會評估分配給它的每個 InertiaModifier,並判斷是否有任何一個是適用的。 這表示你可以為 InteractionTracker 建立並指派多個 InertiaModifier。 但在定義每一個時,你需要做以下幾點:
- 定義「條件」(Condition)——一個表達式,用於定義何時應套用這個特定的慣性修正子(InertiaModifier)的條件陳述。 這通常需要查看 InteractionTracker 的 NaturalRestingPosition(在預設慣性條件下的目標位置)。
- 定義靜止值/動作/自然運動——定義當條件達成時所發生的實際靜止值表達式、動作表達式或自然動態動畫。
備註
慣性修正器的條件面向只會在 InteractionTracker 進入慣性時評估一次。 然而,只有 InertiaMotion 的動作表達式每幀會針對條件為真的修飾符進行評估。
範例
現在我們來看看如何利用 InertiaModifiers 創造一些「吸附點」功能體驗,以重現圖像畫布的滾動效果。 在這個例子中,每次操作都可能通過單一影像——這通常稱為單一強制捕捉點。
讓我們先設定 InteractionTracker、VisualInteractionSource 以及能利用 InteractionTracker 位置的表達式。
private void SetupInput()
{
_tracker = InteractionTracker.Create(_compositor);
_tracker.MinPosition = new Vector3(0f);
_tracker.MaxPosition = new Vector3(3000f);
_source = VisualInteractionSource.Create(_root);
_source.ManipulationRedirectionMode =
VisualInteractionSourceRedirectionMode.CapableTouchpadOnly;
_source.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia;
_tracker.InteractionSources.Add(_source);
var scrollExp = _compositor.CreateExpressionAnimation("-tracker.Position.Y");
scrollExp.SetReferenceParameter("tracker", _tracker);
ElementCompositionPreview.GetElementVisual(scrollPanel).StartAnimation("Offset.Y", scrollExp);
}
接著,由於「單一強制吸附點」行為會讓內容往上或往下移動,你需要兩個不同的慣性調整:一個是將可滾動內容向上移動,另一個是向下移動。
// Snap-Point to move the content up
var snapUpModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);
// Snap-Point to move the content down
var snapDownModifier = InteractionTrackerInertiaRestingValue.Create(_compositor);
是否向上或向下切換,取決於 InteractionTracker 自然落點相對於快照距離(即快照位置之間的距離)而定。 如果超過半點,就往下移動,否則往上移動。 (在此範例中,你將吸附距離儲存在 PropertySet 中)
// Is NaturalRestingPosition less than the halfway point between Snap Points?
snapUpModifier.Condition = _compositor.CreateExpressionAnimation(
"this.Target.NaturalRestingPosition.y < (this.StartingValue - " +
"mod(this.StartingValue, prop.snapDistance) + prop.snapDistance / 2)");
snapUpModifier.Condition.SetReferenceParameter("prop", _propSet);
// Is NaturalRestingPosition greater than the halfway point between Snap Points?
snapDownModifier.Condition = _compositor.CreateExpressionAnimation(
"this.Target.NaturalRestingPosition.y >= (this.StartingValue - " +
"mod(this.StartingValue, prop.snapDistance) + prop.snapDistance / 2)");
snapDownModifier.Condition.SetReferenceParameter("prop", _propSet);
這張圖為所發生的邏輯提供了視覺化的描述:
現在你只需要為每個慣性修正器定義靜止值:可以將 InteractionTracker 的位置移至前一個或下一個吸附位置。
snapUpModifier.RestingValue = _compositor.CreateExpressionAnimation(
"this.StartingValue - mod(this.StartingValue, prop.snapDistance)");
snapUpModifier.RestingValue.SetReferenceParameter("prop", _propSet);
snapDownModifier.RestingValue = _compositor.CreateExpressionAnimation(
"this.StartingValue + prop.snapDistance - mod(this.StartingValue, " +
"prop.snapDistance)");
snapDownModifier.RestingValue.SetReferenceParameter("prop", _propSet);
最後,將 InertiaModifiers 加入 InteractionTracker。 當 InteractionTracker 進入 InertiaState 時,會檢查你的 InertiaModifiers 條件,判斷是否需要修改位置。
var modifiers = new InteractionTrackerInertiaRestingValue[] {
snapUpModifier, snapDownModifier };
_tracker.ConfigurePositionYInertiaModifiers(modifiers);