關聯式動畫Relation based animations

本文簡要概述如何使用 Composition ExpressionAnimations 製作關聯式動畫。This article provides a brief overview of how to make relation-based animations using Composition ExpressionAnimations.

動態關聯式體驗Dynamic Relation-based Experiences

在應用程式中建置動作體驗時,有時候動作不是以時間為基礎,而是依賴其他物件上的屬性。When building out motion experiences in an app, there are times when the motion is not time-based, but rather dependent on a property on another object. KeyFrameAnimations 就無法輕鬆表達這些動作體驗類型。KeyFrameAnimations are not able to express these types of motion experiences very easily. 在這些具體情況下,動作不再需要分離和預先定義。In these specific instances, motion no longer needs to be discrete and pre-defined. 而是可以根據動作與其他物件屬性的關係,動態調整動作。Instead, the motion can dynamically adapt based on its relationship to other object properties. 例如,您可以根據物件的水平位置,來為物件的不透明度設定動畫效果。For example, you can animate the opacity of an object based on its horizontal position. 其他範例包括「固定式標頭」和「視差」等動作體驗。Other examples include motion experiences like Sticky Headers and Parallax.

這些動作體驗類型可讓您建立感覺更連貫的 UI,而不是個別無關聯的 UI。These types of motion experiences let you create UI that feels more connected, instead of feeling singular and independent. 對於使用者,這可提供動態 UI 體驗印象。To the user, this gives the impression of a dynamic UI experience.



使用 ExpressionAnimationsUsing ExpressionAnimations

若要建立關聯式動作體驗,您可以使用 ExpressionAnimation 類型。To create relation-based motion experiences, you use the ExpressionAnimation type. ExpressionAnimations (或簡稱 Expressions) 是一種新動畫類型,可讓您表達數學關係 - 系統使用此關係來計算每個畫面中動畫屬性的值。ExpressionAnimations (or Expressions for short), are a new type of animation that let you express a mathematical relationship – a relationship that the system uses to calculate the value of an animating property every frame. 換句話說,Expressions 是單純的數學方程式,定義每個畫面中動畫屬性的所需值。Put another way, Expressions are simply a mathematical equation that defines the desired value of an animating property per frame. Expressions 是多功能元件,可用於多種不同的案例,其中包括:Expressions are a very versatile component that can be used across a wide variety of scenarios, including:

使用 ExpressionAnimations 時,有幾件事值得事先一提:When working with ExpressionAnimations, there are a couple of things worth mentioning up front:

  • 永不結束 – 與其 KeyFrameAnimation 同層級不同,Expressions 沒有有限期間。Never Ending – unlike its KeyFrameAnimation sibling, Expressions don’t have a finite duration. 因為 Expressions 是數學關係,它們是不斷「執行」的動畫。Because Expressions are mathematical relationships, they are animations that are constantly "running". 您可以選擇停止這些動畫。You have the option to stop these animations if you choose.
  • 執行但不一定評估 – 對於不斷執行的動畫,永遠要顧慮到效能問題。Running, but not always evaluating – performance is always a concern with animations that are constantly running. 但您不用擔心,系統很聰明,只會在 Expression 的輸入或參數變更時才重新評估。No need to worry though, the system is smart enough that the Expression will only re-evaluate if any of its inputs or parameters have changed.
  • 解析至正確的物件類型 – 因為 Expressions 是數學關係,請務必確定定義 Expression 的方程式解析為與目標動畫屬性相同的類型。Resolving to the right object type – Because Expressions are mathematical relationships, it is important to make sure that the equation that defines the Expression resolves to the same type of the property being targeted by the animation. 例如,如果將位移產生動畫效果,您的 Expression 應該解析為 Vector3 類型。For example, if animating Offset, your Expression should resolve to a Vector3 type.

Expression 的元件Components of an Expression

建置 Expression 的數學關係時,有數個核心元件:When building the mathematical relationship of an Expression, there are several core components:

  • 參數 - 代表常數值或參考其他 Composition 物件的值。Parameters – values representing constant values or references to other Composition objects.
  • 數學運算子 – 一般數學運算子:加號 (+)、減號 (-)、乘號 (*)、除號 (/),將參數連接起來以形成方程式。Mathematical Operators – the typical mathematical operators plus(+), minus(-), multiply(*), divide(/) that join together parameters to form an equation. 也包含條件式運算子,例如大於 (>)、等於 (==)、三元運算子 (condition ?Also included are conditional operators such as greater than(>), equal(==), ternary operator (condition ? ifTrue : ifFalse) 等。ifTrue : ifFalse), etc.
  • 數學函數 – 根據 System.Numerics 的數學函數/捷徑。Mathematical Functions – mathematical functions/shortcuts based on System.Numerics. 如需完整的支援函數清單,請參閱 ExpressionAnimationFor a full list of supported functions, see ExpressionAnimation.

Expressions 也支援一組關鍵字 - 只有在 ExpressionAnimation 系統中才具有不同意義的特殊片語。Expressions also support a set of keywords – special phrases that have distinct meaning only within the ExpressionAnimation system. 這些會列在 (以及數學函數的完整清單) ExpressionAnimation 文件中。These are listed (along with the full list of math functions) in the ExpressionAnimation documentation.

使用 ExpressionBuilder 建立 ExpressionsCreating Expressions with ExpressionBuilder

在 UWP 應用程式中建立運算式有兩個選項:There are two options for building Expressions in your UWP app:

  1. 透過官方的公用 API,將方程式建立為字串。Build the equation as a string via the official, public API.
  2. 透過 Windows 社群工具組隨附的 r 工具,在型別安全物件模型中建立方程式。Build the equation in a type-safe object model via the ExpressionBuilder tool included with the Windows Community Toolkit.

針對本文的目的,我們將使用 ExpressionBuilder 定義 Expressions。For the sake of this document, we will define our Expressions using ExpressionBuilder.


參數組成 Expression 的核心。Parameters make up the core of an Expression. 有兩種類型的參數:There are two types of parameters:

  • 常數:這些是代表類型 System.Numeric 變數的參數。Constants: these are parameters representing typed System.Numeric variables. 動畫開始時會指派值給這些參數。These parameters get their values assigned once when the animation is started.
  • 參考:這些是代表 CompositionObjects 參考的參數,這些參數會在動畫開始後持續取得更新的值。References: these are parameters representing references to CompositionObjects – these parameters continuously get their values updated after an animation is started.

一般而言,參考是如何動態變更 Expression 輸出的主要層面。In general, References are the main aspect for how an Expression’s output can dynamically change. 隨著這些參考變更,Expression 的輸出也會變更做為結果。As these references change, the output of the Expression changes as a result. 如果您使用字串建立 Expression 或在範本案例中使用 (使用您的 Expression 以多個 CompositionObjects 做為目標),您將需要命名,並設定參數的值。If you create your Expression with Strings or use them in a templating scenario (using your Expression to target multiple CompositionObjects), you will need to name and set the values of your parameters. 如需詳細資訊,請參閱「範例」區段。See the Example section for more info.

使用 KeyFrameAnimationsWorking with KeyFrameAnimations

Expressions 也可以搭配 KeyFrameAnimations 使用。Expressions can also be used with KeyFrameAnimations. 在這些情況中,您想使用 Expression 在某個時間點定義 KeyFrame,這類 KeyFrames 稱為 ExpressionKeyFrames。In these instances, you want to use an Expression to define the value of a KeyFrame at a time spot – these types KeyFrames are called ExpressionKeyFrames.

KeyFrameAnimation.InsertExpressionKeyFrame(Single, String)
KeyFrameAnimation.InsertExpressionKeyFrame(Single, ExpressionNode)

不過,與 ExpressionAnimations 不同,ExpressionKeyFrames 僅會在 KeyFrameAnimation 開始時評估一次。However, unlike ExpressionAnimations, ExpressionKeyFrames are evaluated only once when the KeyFrameAnimation is started. 請記住,您不會傳遞 ExpressionAnimation 做為 KeyFrame 的值,而是做為字串 (如果您使用 ExpressionBuilder 則為 ExpressionNode)。Keep in mind, you do not pass in an ExpressionAnimation as the value of the KeyFrame, rather a string (or an ExpressionNode, if you're using ExpressionBuilder).


現在讓我們逐步解說使用 Expressions 的範例,尤其是 Windows UI 範例庫中的 PropertySet 範例。Let's now walk through an example of using Expressions, specifically the PropertySet sample from the Windows UI Sample Gallery. 我們接下來將看看 Expression 管理藍球軌道運動的行為。We'll look at the Expression managing the orbit motion behavior of the blue ball.


有三個元件在播放總體體驗:There are three components at play for the total experience:

  1. KeyFrameAnimation,讓紅球的 Y 位移產生動畫效果。A KeyFrameAnimation, animating the Y Offset of the red ball.
  2. 使用 Rotation 屬性的 PropertySet,協助驅動軌道,由另一個 KeyFrameAnimation 產生動畫效果。A PropertySet with a Rotation property that helps drives the orbit, animated by another KeyFrameAnimation.
  3. 驅動藍球位移的 ExpressionAnimation,參考紅球位移和 Rotation 屬性以保持完美軌道。An ExpressionAnimation that drives the Offset of the blue ball referencing the Red Ball Offset and the Rotation property to maintain a perfect orbit.

我們將重點放在 #3 定義的 ExpressionAnimation。We’ll be focusing on the ExpressionAnimation defined in #3. 我們也會使用 ExpressionBuilder 類別來建構這個 Expression。We will also be using the ExpressionBuilder classes to construct this Expression. 結尾會列出透過字串建置此體驗的程式碼。A copy of the code used to build this experience via Strings is listed at the end.

在此方程式中,您必須從 PropertySet 參考兩個屬性,一個是中心點位移,另一個是旋轉。In this equation, there are two properties you need to reference from the PropertySet; one is a centerpoint offset and the other is the rotation.

var propSetCenterPoint =

// This rotation value will animate via KFA from 0 -> 360 degrees
var propSetRotation = _propertySet.GetReference().GetScalarProperty("Rotation");

接下來,您需要定義負責實際軌道旋轉的 Vector3 元件。Next, you need to define the Vector3 component that accounts for the actual orbiting rotation.

var orbitRotation = EF.Vector3(
    EF.Cos(EF.ToRadians(propSetRotation)) * 150,
    EF.Sin(EF.ToRadians(propSetRotation)) * 75, 0);


EF 這是用來定義 ExpressionFunctions 的速記「using」標記法。EF is a shorthand "using" notation to define ExpressionFunctions.

using EF = Microsoft.Toolkit.Uwp.UI.Animations.Expressions.ExpressionFunctions;

最後,將這些元件結合在一起,並參考紅球的位置來定義數學關係。Finally, combine these components together and reference the position of the Red Ball to define the mathematical relationship.

var orbitExpression = redSprite.GetReference().Offset + propSetCenterPoint + orbitRotation;
blueSprite.StartAnimation("Offset", orbitExpression);

假設您想要使用相同 Expression 但搭配另外兩個視覺效果,這表示 2 組軌道圈。In a hypothetical situation, what if you wanted to use this same Expression but with two other Visuals, meaning 2 sets of orbiting circles. 使用 CompositionAnimations,您可以重複使用動畫與並以多個 CompositionObjects 做為目標。With CompositionAnimations, you can re-use the animation and target multiple CompositionObjects. 將此 Expression 用於其他軌道案例時,您只需要變更對視覺效果的參考。The only thing you need to change when you use this Expression for the additional orbit case is the reference to the Visual. 我們將這稱為「範本化」。We call this templating.

在此案例中,您修改稍早建置的 Expression。In this case, you modify the Expression you built earlier. 您建立具有名稱的參考然後指定不同的值,而不是「取得」CompositionObject 的參考:Rather than "getting" a reference to the CompositionObject, you create a reference with a name and then assign different values:

var orbitExpression = ExpressionValues.Reference.CreateVisualReference("orbitRoundVisual");
orbitExpression.SetReferenceParameter("orbitRoundVisual", redSprite);
blueSprite.StartAnimation("Offset", orbitExpression);
// Later on … use same Expression to assign to another orbiting Visual
orbitExpression.SetReferenceParameter("orbitRoundVisual", yellowSprite);
greenSprite.StartAnimation("Offset", orbitExpression);

以下是透過公用 API 使用字串定義 Expression 的程式碼。Here is the code if you defined your Expression with Strings via the public API.

ExpressionAnimation expressionAnimation =
compositor.CreateExpressionAnimation("visual.Offset + " +
"propertySet.CenterPointOffset + " +
"Vector3(cos(ToRadians(propertySet.Rotation)) * 150," + "sin(ToRadians(propertySet.Rotation)) * 75, 0)");
 var propSetCenterPoint = _propertySet.GetReference().GetVector3Property("CenterPointOffset");
 var propSetRotation = _propertySet.GetReference().GetScalarProperty("Rotation");
expressionAnimation.SetReferenceParameter("propertySet", _propertySet);
expressionAnimation.SetReferenceParameter("visual", redSprite);