指針驅動動畫

本文說明如何在 WinUI 和 Windows App SDK 應用程式中使用指標的位置,創造動態的「黏在游標上」體驗。

先決條件

在這裡,我們假設你已經熟悉這些文章中討論的概念:

為什麼要創建指針位置驅動的體驗?

Fluent 設計語言中,觸控並非與 UI 互動的唯一方式。 由於 WinUI 應用程式可以跨越多種裝置型態,最終使用者會與滑鼠、筆等其他輸入模式的應用程式互動。 利用這些其他輸入方式的定位數據,能讓最終用戶感受到與你的應用程式更緊密的連結。

指標位置驅動體驗讓你能利用指標輸入模式在螢幕上的位置,為你的應用程式創造額外的動態與使用者介面體驗。 這些經驗通常能為終端使用者提供額外的背景資訊與回饋,了解使用者的行為與結構。 體驗不再是單向的流向,而是開始變成雙向的流動,終端使用者可用不同的輸入方式提供意見,應用程式介面也能做出回應。

一些範例包括:

  • 聚光燈的位置動畫化,以跟隨游標移动

    指標聚光燈範例

  • 根據指標的位置旋轉影像

    指標旋轉範例

使用 PointerPositionPropertySet

你可以透過使用 PointerPositionPropertySet 來創造這些體驗。 這個 PropertySet 是為 UIElement 建立的,用以在 UIElement 被成功命中測試時維持滑鼠指標的位置。 位置值相對於 UIElement 的座標空間( <0,0> 為 UIElement 的左上角)。 接著你可以利用動畫中設定的這個屬性來驅動另一個屬性的動作。

對於不同的指針輸入方式,輸入可能處於多種狀態,而這些狀態會影響位置的變化:懸停、按下、按下並移動。 PointerPositionPropertySet 只維持滑鼠和筆在懸停、按下及按下並移動狀態中的指標位置。

一般開始步驟:

  1. 識別 UIElement,你希望指標的位置被追蹤。
  2. 透過 ElementCompositionPreview 存取 PointerPositionPropertySet。
  3. 建立一個 ExpressionAnimation,參考 PropertySet 中的 Position 屬性。
    • 別忘了設定你的參考參數!
  4. 用 ExpressionAnimation 鎖定 CompositionObject 的屬性。

備註

建議您將從 GetPointPositionPropertySet 方法回傳的 PropertySet 指派到類別變數。 這確保屬性集合不會被垃圾回收機制清除,因此不會對其所引用的 ExpressionAnimation 產生任何影響。 ExpressionAnimations 不會維持對方程式中任何物件的強烈參考。

範例

讓我們來看看一個範例,如何利用滑鼠與筆的懸停位置輸入模式來動態旋轉影像。

指標旋轉範例

這張圖片是 UIElement,所以我們先取得 PointerPositionPropertySet 的參考

_pointerPositionPropSet = ElementCompositionPreview.GetPointerPositionPropertySet(element);

在這個範例中,你會有兩個表達式在交互作用:

  • 表達式中,影像根據指標距離影像中心的遠近進行旋轉。 距離越遠,旋轉越多。
  • 一個表達式,旋轉軸會根據指標的位置改變。 你希望旋轉軸與位置的向量垂直。

這裡,你定義兩個表達式,一個針對 RotationAngle 屬性,另一個針對 RotationAxis 屬性。 你參考 PointerPositionPropertySet 就像其他 PropertySet 一樣。

在這個範例中,你是使用 ExpressionBuilder 類別來建構表達式。

// using EF = ExpressionBuilder.ExpressionFunctions;
// || DEFINE THE EXPRESSION FOR THE ROTATION ANGLE ||
var hoverPosition = _pointerPositionPropSet.GetSpecializedReference
<PointerPositionPropertySetReferenceNode>().Position;
var angleExpressionNode =
EF.Conditional(
 hoverPosition == new Vector3(0, 0, 0),
 ExpressionValues.CurrentValue.CreateScalarCurrentValue(),
 35 * ((EF.Clamp(EF.Distance(center, hoverPosition), 0, distanceToCenter) % distanceToCenter) / distanceToCenter));
_tiltVisual.StartAnimation("RotationAngleInDegrees", angleExpressionNode);

// || DEFINE THE EXPRESSION FOR THE ROTATION AXIS ||
var axisAngleExpressionNode = EF.Vector3(
-(hoverPosition.Y - center.Y) * EF.Conditional(hoverPosition.Y == center.Y, 0, 1),
 (hoverPosition.X - center.X) * EF.Conditional(hoverPosition.X == center.X, 0, 1),
 0);
_tiltVisual.StartAnimation("RotationAxis", axisAngleExpressionNode);

另請參閱