轉換概觀Transforms overview

了解如何藉由變更 UI 中元素的相對座標系統,在 Windows 執行階段 API 中使用轉換。Learn how to use transforms in the Windows Runtime API, by changing the relative coordinate systems of elements in the UI. 這可以用來調整個別 XAML 元素的外觀,例如在 x-y 空間中縮放、旋轉或轉換位置。This can be used to adjust the appearance of individual XAML elements, such as scaling, rotating, or transforming the position in x-y space.

什麼是轉換?What is a transform?

「轉換」定義了如何將點從一個座標空間對應或轉換到另一個座標空間。A transform defines how to map, or transform, points from one coordinate space to another coordinate space. 將轉換套用到 UI 元素時,會變更該 UI 元素轉譯為螢幕上 UI 一部分的方式。When a transform is applied to a UI element, it changes how that UI element is rendered to the screen as part of the UI.

轉換可分為四大類:轉譯、旋轉、縮放及扭曲 (傾斜)。Think of transforms in four broad classifications: translation, rotation, scaling and skew (or shear). 為了使用圖形 API 來變更 UI 元素的外觀,通常最簡單的方式就是建立一次只定義一個操作的轉換。For the purposes of using graphics APIs to change the appearance of UI elements, it's usually easiest to create transforms that define only one operation at a time. 因此,Windows 執行階段為這些轉換分類中的每一個都定義了個別的類別:So the Windows Runtime defines a discrete class for each of these transform classifications:

在這些當中,您最常針對 UI 案例使用的會是 TranslateTransformScaleTransformOf these, you're likely to use TranslateTransform and ScaleTransform most often for UI scenarios.

您可以將不同的轉換結合使用,而有兩個 Windows 執行階段類別支援這麼做:CompositeTransformTransformGroupYou can combine transforms, and there are two Windows Runtime classes that support this: CompositeTransform and TransformGroup. CompositeTransform 中,轉換的套用順序依序是:縮放、扭曲、旋轉、轉譯。In a CompositeTransform, transforms are applied in this order: scale, skew, rotate, translate. 如果您希望以不同的順序套用轉換,請以 TransformGroup 代替 CompositeTransformUse TransformGroup instead of CompositeTransform if you want the transforms applied in a different order. 如需詳細資訊,請參閱 CompositeTransformFor more info, see CompositeTransform.

轉換與配置Transforms and layout

在 XAML 配置中,版面配置階段完成之後才會套用轉換,因此是在套用轉換前,先完成可用空間計算與其他配置決策。In XAML layout, transforms are applied after the layout pass is complete, so available space calculations and other layout decisions have been made before the transforms are applied. 因為會先進行配置,所以如果您轉換位於 Grid 儲存格或是會在配置期間配置空間的類似配置容器中的元素,有時會收到非預期的結果。Because layout comes first, you'll sometimes get unexpected results if you transform elements that are in a Grid cell or similar layout container that allocates space during layout. 經過轉換的元素可能會顯示成被截斷或被遮住,因為它嘗試在分割其父容器內的空間時,繪製到未計算轉換後尺寸的區域。The transformed element may appear truncated or obscured because it's trying to draw into an area that didn't calculate the post-transform dimensions when dividing space within its parent container. 您可能需要對轉換結果進行實驗並調整一些設定。You may need to experiment with the transform results and adjust some settings. 例如,您可能需要變更 Center 屬性,或是宣告配置空間的固定像素度量,而不倚賴調適型配置與比例縮放,以確保父容器配置足夠的空間。For example, instead of relying on adaptive layout and star sizing, you may need to change the Center properties or declare fixed pixel measurements for layout space to make sure the parent allots enough space.

移轉注意事項: Windows Presentation Foundation (WPF) 已有在版面配置階段前先套用轉換的 LayoutTransform 屬性。Migration note: Windows Presentation Foundation (WPF) had a LayoutTransform property that applied transforms prior to the layout pass. 但 Windows 執行階段 XAML 不支援 LayoutTransform 屬性。But Windows Runtime XAML doesn't support a LayoutTransform property. (Microsoft Silverlight 也沒有此選項)。(Microsoft Silverlight didn't have this property either.)

或者,Windows 社區工具組會提供 LayoutTransformControl,可將矩陣轉換應用於應用程式的任何 FrameworkElement。As an alternative, the Windows Community Toolkit provides the LayoutTransformControl that applies Matrix transformations on any FrameworkElement of your application.

將轉換套用到 UI 元素Applying a transform to a UI element

當您將轉換套用到物件時,一般是用來設定 UIElement.RenderTransform 屬性。When you apply a transform to an object, you typically do so to set the property UIElement.RenderTransform. 設定這個屬性實際上並不會將物件依像素逐步變更。Setting this property does not literally change the object pixel by pixel. 這個屬性實際上所做的是在該物件所在的區域座標空間內套用轉換。What the property really does is apply the transform within the local coordinate space in which that object exists. 然後,轉譯邏輯與操作 (配置後) 會轉譯經過結合的座標空間,看起來就像物件已變更了外觀且可能變更其配置位置 (如果已套用 TranslateTransform)。Then the rendering logic and operation (post-layout) renders the combined coordinate spaces, making it look like the object has changed appearance and also potentially its layout position (if TranslateTransform was applied).

根據預設,每個轉譯轉換都是以目標物件之區域座標系統的原點做為中心—即 (0,0)。By default, each render transform is centered at the origin of the target object's local coordinate system—its (0,0). 唯一的例外是 TranslateTransform,它沒有中心屬性可供設定,因為不論其中心在哪裡,轉譯效果都相同。The only exception is a TranslateTransform, which has no center properties to set because the translation effect is the same regardless of where it is centered. 但就其他轉換而言,每個都有可設定 CenterXCenterY 值的屬性。But the other transforms each have properties that set CenterX and CenterY values.

每當您以 UIElement.RenderTransform 來使用轉換時,請記住在會影響轉換行為的 UIElement 上有另一個屬性:RenderTransformOriginWhenever you use transforms with UIElement.RenderTransform, remember that there's another property on UIElement that affects how the transform behaves: RenderTransformOrigin. RenderTransformOrigin 所宣告的是整個轉換應該要套用到元素的預設 (0,0) 點,還是要套用到該元素之相對座標空間中的某個其他原始點。What RenderTransformOrigin declares is whether the whole transform should apply to the default (0,0) point of an element or to some other origin point within the relative coordinate space of that element. 就一般元素來說,(0,0) 會將轉換置於左上角。For typical elements, (0,0) places the transform to the top left corner. 視您想要獲得的效果而定,可以選擇變更 RenderTransformOrigin,而不是調整轉換上的 CenterXCenterY 值。Depending on what effect you want, you might choose to change RenderTransformOrigin rather than adjusting the CenterX and CenterY values on transforms. 請注意,如果您同時套用了 RenderTransformOriginCenterX / CenterY 值,結果可能會相當混淆,尤其是當您以動畫顯示這當中任何一個值的時候。Note that if you apply both RenderTransformOrigin and CenterX / CenterY values, the results can be pretty confusing, especially if you're animating any of the values.

基於點擊測試目的,已套用轉換的物件會在 x-y 空間中以和其視覺外觀一致的預期方式,繼續回應輸入。For hit-testing purposes, an object to which a transform is applied continues to respond to input in an expected way that's consistent to its visual appearance in x-y space. 例如,如果您已使用 TranslateTransformRectangle 在 UI 中橫向移動 400 像素,當使用者按下 Rectangle 以視覺方式出現的點時,該 Rectangle 會回應 PointerPressed 事件。For example, if you've used a TranslateTransform to move a Rectangle 400 pixels laterally in the UI, that Rectangle responds to PointerPressed events when the user presses the point where the Rectangle appears visually. 如果使用者按下 Rectangle 在轉譯前的區域,您並不會收到錯誤事件。You won't get false events if the user presses the area where the Rectangle was before being translated. 對任何影響點擊測試的 z-index 考量來說,套用轉換並不會帶來任何不同;規範哪個元素處理在 x-y 空間點的輸入事件的 z-index 仍然使用容器中宣告的子系順序進行評估。For any z-index considerations that affect hit testing, applying a transform makes no difference; the z-index that governs which element handles input events for a point in x-y space is still evaluated using the child order as declared in a container. 雖然對於 Canvas 物件的子元素而言,您可以透過將 Canvas.ZIndex 附加屬性套用到子元素以調整順序,但該順序通常會與您在 XAML 中宣告元素的順序相同。That order is usually the same as the order in which you declare the elements in XAML, although for child elements of a Canvas object you can adjust the order by applying the Canvas.ZIndex attached property to child elements.

其他轉換屬性Other transform properties

以動畫顯示轉換Animating a transform

Transform 物件可以用動畫顯示。Transform objects can be animated. 若要以動畫顯示 Transform,請將相容類型的動畫套用到您想要以動畫顯示的屬性。To animate a Transform, apply an animation of a compatible type to the property you want to animate. 因為所有轉換屬性都是 Double 類型,這通常表示您正使用 DoubleAnimationDoubleAnimationUsingKeyFrames 物件定義動畫。This typically means you're using DoubleAnimation or DoubleAnimationUsingKeyFrames objects to define the animation, because all of the transform properties are of type Double. 影響用於 UIElement.RenderTransform 值之轉換的動畫並不會被視為相依式動畫,即使它們的持續時間並不為零也一樣。Animations that affect a transform that's used for a UIElement.RenderTransform value are not considered to be dependent animations, even if they have a nonzero duration. 如需有關相依式動畫的詳細資訊,請參閱腳本動畫For more info about dependent animations, see Storyboarded animations.

如果您的動畫屬性會產生在純視覺外觀上轉換的類似效果,例如以動畫顯示 FrameworkElementWidthHeight 而不套用 TranslateTransform,則這類動畫幾乎一律會視為相依式動畫。If you animate properties to produce an effect similar to a transform in terms of the net visual appearance—for example, animating the Width and Height of a FrameworkElement rather than applying a TranslateTransform—such animations are almost always treated as dependent animations. 您將必須啟用動畫,而該動畫可能會有明顯的效能問題,尤其是當您嘗試在以動畫顯示物件時支援使用者互動的情況中。You'd have to enable the animations and there could be significant performance issues with the animation, especially if you're trying to support user interaction while that object is being animated. 基於該理由,建議使用轉換並以動畫顯示,而不要以動畫顯示動畫會被視為相依式動畫的任何其他屬性。For that reason it's preferable to use a transform and animate it rather than animating any other property where the animation would be treated as a dependent animation.

若要以轉換為目標,必須要有一個現有的 Transform 做為 RenderTransform 的值。To target the transform, there must be an existing Transform as the value for RenderTransform. 您一般會將適當轉換類型的元素放在初始 XAML 中,有時並不在該轉換上設定任何屬性。You typically put an element for the appropriate transform type in the initial XAML, sometimes with no properties set on that transform.

您一般會使用間接目標設定技術將動畫套用到轉換的屬性。You typically use an indirect targeting technique to apply animations to the properties of a transform. 如需有關間接目標設定語法的詳細資訊,請參閱腳本動畫屬性路徑語法For more info about indirect targeting syntax, see Storyboarded animations and Property-path syntax.

控制項的預設樣式有時會將轉換的動畫定義為它們視覺狀態行為的一部分。Default styles for controls sometimes define animations of transforms as part of their visual-state behavior. 例如,ProgressRing 的視覺狀態會使用以動畫顯示的 RotateTransform 值來旋轉環圈中的點。For example, the visual states for ProgressRing use animated RotateTransform values to "spin" the dots in the ring.

以下是一個如何以動畫顯示轉換的簡單範例。Here's a simple example of how to animate a transform. 在這種情況下,是以動畫來顯示 RotateTransformAngle,將 Rectangle 繞著其視覺中心就地旋轉。In this case, it's animating the Angle of a RotateTransform to spin a Rectangle in place around its visual center. 這個範例指名了 RotateTransform,因此不需要間接動畫目標設定,但是您可以選擇不指名轉換、指名套用轉換的元素,然後使用間接目標設定 (例如 (UIElement.RenderTransform).(RotateTransform.Angle))。This example names the RotateTransform so doesn't need indirect animation targeting, but you could alternatively leave the transform unnamed, name the element that the transform's applied to, and use indirect targeting such as (UIElement.RenderTransform).(RotateTransform.Angle).

<StackPanel Margin="15">
  <StackPanel.Resources>
    <Storyboard x:Name="myStoryboard">
      <DoubleAnimation
       Storyboard.TargetName="myTransform"
       Storyboard.TargetProperty="Angle"
       From="0" To="360" Duration="0:0:5" 
       RepeatBehavior="Forever" />
    </Storyboard>
  </StackPanel.Resources>
  <Rectangle Width="50" Height="50" Fill="RoyalBlue"
   PointerPressed="StartAnimation">
    <Rectangle.RenderTransform>
      <RotateTransform x:Name="myTransform" Angle="45" CenterX="25" CenterY="25" />
    </Rectangle.RenderTransform>
  </Rectangle>
</StackPanel>
void StartAnimation (object sender, RoutedEventArgs e) {
    myStoryboard.Begin();
}

說明執行階段的參考座標框架Accounting for coordinate frames of reference at run time

UIElement 有一個名為 TransformToVisual, 的方法,這個方法可以產生將兩個 UI 元素的參考座標框架相互關聯的 TransformUIElement has a method named TransformToVisual, which can generate a Transform that correlates the coordinate frames of reference for two UI elements. 如果您將根視覺項目當做第一個參數來傳遞,便可以使用這個方法將元素與應用程式的預設參考座標框架做比較。You can use this to compare an element to the app's default coordinate frame of reference if you pass the root visual as the first parameter. 如果您已經從不同元素擷取輸入事件,或正嘗試在不實際要求版面配置階段的情況下預測配置行為,這就有用處。This can be useful if you've captured an input event from a different element, or if you are trying to predict layout behavior without actually requesting a layout pass.

從指標事件取得的事件資料可提供 GetCurrentPoint 方法的存取權,您可以在該方法指定 relativeTo 參數,以將參考的座標框架變更成特定的元素,而非應用程式預設值。Event data obtained from pointer events provides access to a GetCurrentPoint method, where you can specify a relativeTo parameter to change the coordinate frame of reference to a specific element rather than the app default. 這種方法只是在內部套用轉譯轉換,並在建立傳回的 PointerPoint 物件時,為您轉換 x-y 座標資料。This approach simply applies a translate transform internally and transforms the x-y coordinate data for you when it creates the returned PointerPoint object.

從數學觀點描述轉換Describing a transform mathematically

轉換可以用轉換矩陣來描述。A transform can be described in terms of a transformation matrix. 3×3 矩陣可用來描述二維 x-y 平面的轉換。A 3×3 matrix is used to describe the transformations in a two-dimensional, x-y plane. 仿射轉換矩陣可以相乘來形成任何數目的線性轉換 (例如旋轉與扭曲 (傾斜)),後面再接著轉譯。Affine transformation matrices can be multiplied to form any number of linear transformations, such as rotation and skew (shear), followed by translation. 仿射轉換矩陣的最終欄位等於 (0, 0, 1),因此,您只需要以數學描述指定前兩個欄位中的成員。The final column of an affine transformation matrix is equal to (0, 0, 1), so you need to specify only the members of the first two columns in the mathematical description.

如果您具有數學背景,或是熟悉也使用矩陣描述座標空間轉換的圖形程式設計技術,那麼轉換的數學描述可能對您很有用。The mathematical description of a transform might be useful to you if you have a mathematical background or a familiarity with graphics-programming techniques that also use matrices to describe transformations of coordinate space. 有一個 Transform 衍生類別可讓您以轉換的 3×3 矩陣來直接表示該轉換:MatrixTransformThere's a Transform-derived class that enables you to express a transformation directly in terms of its 3×3 matrix: MatrixTransform. MatrixTransform 具有 Matrix 屬性,這個屬性有一個包含下列六個屬性的結構:M11M12M21M22OffsetXOffsetYMatrixTransform has a Matrix property, which holds a structure that has six properties: M11, M12, M21, M22, OffsetX and OffsetY. 每個 Matrix 屬性都使用一個 Double 值,並且對應至仿射轉換矩陣的六個相關值 (第 1 與第 2 欄)。Each Matrix property uses a Double value and corresponds to the six relevant values (columns 1 and 2) of an affine transformation matrix.

M11M11 M12M12 00
M21M21 M22M22 00
OffsetXOffsetX OffsetYOffsetY 11

任何您能夠以 TranslateTransformScaleTransformRotateTransformSkewTransform 物件描述的轉換,都能夠同樣以 MatrixTransform 搭配 Matrix 值來描述。Any transform that you could describe with a TranslateTransform, ScaleTransform, RotateTransform, or SkewTransform object could be described equally by a MatrixTransform with a Matrix value. 但是您一般只會使用 TranslateTransform 及其他類別,因為與設定 Matrix 中的向量元件相比,將這些轉換類別的相關屬性概念化會比較容易。But you typically just use TranslateTransform and the others because the properties on those transform classes are easier to conceptualize than setting the vector components in a Matrix. 以動畫顯示轉換的個別屬性也同樣比較容易;Matrix 實際上是一個結構而不是 DependencyObject,因此無法支援以動畫顯示的個別值。It's also easier to animate the discrete properties of transforms; a Matrix is actually a structure and not a DependencyObject, so it can't support animated individual values.

有些可讓您套用轉換操作功能的 XAML 設計工具會將結果序列化為 MatrixTransformSome XAML design tools that enable you to apply transformation operations will serialize the results as a MatrixTransform. 在這種情況下,最好再次使用相同的設計工具變更轉換效果,並將 XAML 再次序列化,而不要自行嘗試直接操縱 XAML 中的 Matrix 值。In this case it may be best to use the same design tool again to change the transformation effect and serialize the XAML again, rather than trying to manipulate the Matrix values yourself directly in the XAML.

3D 轉換3-D transforms

在 Windows 10 中,XAML 導入新屬性 UIElement.Transform3D,可讓使用者建立 UI 的 3D 效果。In Windows 10, XAML introduced a new property, UIElement.Transform3D, that can be used to create 3D effects with UI. 若要執行這項操作,請使用 PerspectiveTransform3D 將共用 3D 透視或「相機」新增至場景,然後使用 CompositeTransform3D 在 3D 空間中轉換元素,就如同使用 CompositeTransform 般。To do this, use PerspectiveTransform3D to add a shared 3D perspective or "camera" to your scene, and then use CompositeTransform3D to transform an element in 3D space, like you would use CompositeTransform. 如需有關 3D 轉換實作方式的討論,請參閱 UIElement.Transform3DSee UIElement.Transform3D for a discussion of how to implement 3D transforms.

如需僅套用至單一物件的簡易型 3D 效果,則可使用 UIElement.Projection 屬性。For simpler 3D effects that only apply to a single object, the UIElement.Projection property can be used. 使用 PlaneProjection 做為此屬性的值,其等同於將固定透視轉換與一或多個 3D 轉換套用至元素。Using a PlaneProjection as the value for this property is equivalent to applying a fixed perspective transform and one or more 3D transforms to the element. XAML UI 的 3D 透視效果中,會深入詳述有關此轉換類型的資訊。This type of transform is described in more detail in 3-D perspective effects for XAML UI.

相關主題Related topics