現代 App 介面離不開流暢的動畫與立體視覺效果。WinRT/XAML 提供了強大的 2D 變換、3D 平面投影、裁剪 與 像素對齊 機制,且均在 GPU 合成層執行,效能極佳。本文將逐一解析 RenderTransform、Projection、Clip、UseLayoutRounding 的核心用法與實戰技巧。
UIElement.RenderTransform 接受任意 Transform 衍生類別,作用於繪製階段,不影響佈局佔用空間。常用變換類別:
| 類別 | 功能 | 關鍵屬性 |
|---|---|---|
RotateTransform | 順時針旋轉 | Angle、CenterX、CenterY |
TranslateTransform | 平移位移 | X、Y |
ScaleTransform | 縮放 | ScaleX、ScaleY、CenterX、CenterY |
SkewTransform | 扭曲/傾斜(模擬 3D 深度) | AngleX、AngleY、CenterX、CenterY |
TransformGroup | 多重變換組合(依順序套用) | Children 集合 |
CompositeTransform | 單一物件整合所有 2D 變換(效能最佳) | Rotation、ScaleX/Y、SkewX/Y、TranslateX/Y、CenterX/Y |
MatrixTransform | 3×3 仿射矩陣,完全自訂 | Matrix="m11,m12,m21,m22,offsetX,offsetY" |
以元素自身寬高為單位(0~1)指定變換中心點,預設 (0,0) 為左上角,(0.5,0.5) 為中心。配合 RotateTransform 等無需手動計算 CenterX/Y。
<Grid Margin="120 0 0 0">
<!-- 1. RotateTransform 指定中心點 -->
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<RotateTransform Angle="15" CenterX="100" CenterY="50"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 2. RenderTransformOrigin + RotateTransform -->
<Grid Margin="400 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3"
RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="15"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 3. TranslateTransform 平移 -->
<Grid Margin="800 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<TranslateTransform X="100" Y="10"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 4. ScaleTransform 縮放 -->
<Grid Margin="0 200 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="1.1" ScaleY="1.3" CenterX="100" CenterY="50"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 5. SkewTransform 扭曲 -->
<Grid Margin="400 200 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<SkewTransform AngleX="30" AngleY="5" CenterX="0" CenterY="0"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 6. TransformGroup 組合:先平移再旋轉 -->
<Grid Margin="800 200 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<TransformGroup>
<TranslateTransform X="100" Y="10"/>
<RotateTransform Angle="15" CenterX="100" CenterY="50"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 7. CompositeTransform 一次搞定 -->
<Grid Margin="0 400 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<CompositeTransform SkewX="30" Rotation="60" ScaleX="0.6" ScaleY="0.3"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
<!-- 8. MatrixTransform 矩陣 -->
<Grid Margin="400 400 0 0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.RenderTransform>
<MatrixTransform Matrix="1, 0.5, 0, 1, 30, 10"/>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
</Grid>
UIElement.Projection 支援兩種投影:
| 分類 | 屬性 | 說明 |
|---|---|---|
| 旋轉 | RotationX | 繞 X 軸旋轉(垂直翻轉) |
RotationY | 繞 Y 軸旋轉(水平翻轉) | |
RotationZ | 繞 Z 軸旋轉(平面旋轉,等同 RenderTransform 旋轉) | |
| 旋轉中心 | CenterOfRotationX | 相對位置 0~1,預設 0.5 |
CenterOfRotationY | 相對位置 0~1,預設 0.5 | |
CenterOfRotationZ | 相對位置,預設 0 | |
| 全域位移 | GlobalOffsetX/Y/Z | 相對螢幕座標系位移 |
| 局部位移 | LocalOffsetX/Y/Z | 相對元素自身旋轉後的座標系位移 |
<Grid Margin="120 0 0 0">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Rectangle Width="200" Height="100" Stroke="Blue" StrokeThickness="3" StrokeDashArray="3,1"/>
<Rectangle Width="200" Height="100" Fill="Yellow" Stroke="Red" StrokeThickness="3" Opacity="0.3">
<Rectangle.Projection>
<PlaneProjection x:Name="planeProjection"/>
</Rectangle.Projection>
</Rectangle>
</Grid>
<StackPanel>
<TextBlock Text="RotationX:" Margin="0 10 0 0"/>
<Slider Width="150" Minimum="0" Maximum="360"
Value="{Binding ElementName=planeProjection, Path=RotationX, Mode=TwoWay}"/>
<TextBlock Text="RotationY:" Margin="0 -10 0 0"/>
<Slider Width="150" Minimum="0" Maximum="360"
Value="{Binding ElementName=planeProjection, Path=RotationY, Mode=TwoWay}"/>
<TextBlock Text="RotationZ:" Margin="0 -10 0 0"/>
<Slider Width="150" Minimum="0" Maximum="360"
Value="{Binding ElementName=planeProjection, Path=RotationZ, Mode=TwoWay}"/>
<TextBlock Text="LocalOffsetX:" Margin="0 -10 0 0"/>
<Slider Width="150" Minimum="-150" Maximum="150"
Value="{Binding ElementName=planeProjection, Path=LocalOffsetX, Mode=TwoWay}"/>
<!-- 其餘 LocalOffsetY/Z、GlobalOffsetX/Y/Z 同理 -->
</StackPanel>
</Grid>
💡 實務技巧:LocalOffsetZ 可產生「元素浮出/陷入螢幕」的視覺層次感;配合 RotationY 可實現翻書、輪播等 3D 效果。
UIElement.Clip 僅接受 RectangleGeometry(WinRT 限制),定義可見矩形區域,超出部分不繪製、不命中測試。
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Width="200" Height="100" Fill="Red"/>
<Rectangle Width="200" Height="100" Fill="Green">
<Rectangle.Clip>
<RectangleGeometry Rect="10 10 50 50"/> <!-- X Y Width Height -->
</Rectangle.Clip>
</Rectangle>
</Grid>
💡 進階用法:動畫改變 RectangleGeometry.Rect 可實現「刮刮樂」、「漸漸顯示」等特效。
當元素的 Margin、Width/Height、RenderTransform 導致邊緣落在半像素時,預設 UseLayoutRounding="True" 會自動四捨五入到整像素,避免抗鋸齒模糊;設為 False 則保留亞像素精度(可能導致邊框虛實不一)。
<StackPanel Margin="120 0 0 0">
<!-- UseLayoutRounding=True:外邊距會四捨五入,左右/上下可能不等 -->
<Grid Width="200" Height="200" HorizontalAlignment="Left" UseLayoutRounding="True">
<Border BorderBrush="#FF884909" Background="#FFFBECA3" BorderThickness="1"/>
<Border BorderBrush="#FF884909" Background="#FFFBECA3" BorderThickness="1" Margin="1.6"/>
</Grid>
<!-- UseLayoutRounding=False:保留 1.6 像素,邊距相等但可能模糊 -->
<Grid Width="200" Height="200" Margin="0 10 0 0" HorizontalAlignment="Left" UseLayoutRounding="False">
<Border BorderBrush="#FF884909" Background="#FFFBECA3" BorderThickness="1"/>
<Border BorderBrush="#FF884909" Background="#FFFBECA3" BorderThickness="1" Margin="1.6"/>
</Grid>
</StackPanel>
True(系統預設),確保文字、邊框銳利False,結束後恢復 True本文涵蓋了控件視覺變換的完整工具箱:
CompositeTransform 效能最佳,RenderTransformOrigin 簡化中心點設定PlaneProjection 輕鬆實現 3D 旋轉/位移,LocalOffsetZ 創造景深RectangleGeometry 裁剪可見區域,可做動畫特效善用這些 GPU 加速屬性,能以極低成本打造流暢、立體、專業的現代 App 介面。