通過使用變換(transform),許多繪圖任務将更趨簡單;變換是通過不加通告地切換形狀或元素使用的坐标系統來改變形狀或元素繪制方式的對象。在WPF中,變換由繼承自System.Windows.Media.Transform抽象類的類表示。下表列出了這些類。
表 變換類

從技術角度看,所有變換都使用矩陣數學改變形狀的坐标。不過,使用預先建構好的變換,如TranslateTransform、RotateTransform、ScaleTransform以及SkewTransform,比使用MatrixTransform并嘗試為希望執行的操作構造正确的矩陣更簡單的多。當使用TransformGroup執行一系列變換時,WPF将所有變換融合到單獨的MatrixTransform變換中以確定獲得最佳性能。
所有變換(通過Transform類)繼承自Freezable類,這意味着它們支援自動更改通知功能。如果改變了在形狀中使用的變換,形狀會立即重新繪制自身。
變換是那些在不同上下文中非常有用的古怪概念中的一個。下面例舉幾個例子:
- 傾斜形狀。到目前為止已經介紹了水準對齊的矩形、橢圓、直線以及多邊形。使用RotateTransform變換,可轉動坐标系統,使建立特定的形狀更容易。
- 重複形狀。許多圖畫是在不同的位置使用類似的形狀建構的。使用變換,可先繪制一個形狀,然後移動、旋轉、縮放該形狀,以及執行其他操作。
- 動畫。通過變換,可建立大量精緻的效果。例如,旋轉形狀、将形狀從一個地方移到另一個地方,以及動态扭曲形狀。
一、變換形狀
為變換形狀,将RenderTransform屬性指定為希望使用的變換隊形。根據使用的變換隊形,需要填充不同的屬性以配置變換隊形。
例如,如果旋轉形狀,需要使用RotateTransform變換,并以度為機關提供旋轉角度。下面的示例将舉行旋轉25°:
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" />
</Rectangle.RenderTransform>
</Rectangle>
采用這種方式旋轉形狀時,是圍繞形狀的原點進行旋轉的(左上角)。下圖示範了繞形狀原點旋轉25°、50°、75°以及100°的效果。
<Window x:Class="Drawing.RotateShape"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RotateShape" Height="427" Width="332"
>
<Canvas>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="50" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="75" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="100" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</Window>
RotateShape
有時候希望繞不同的點旋轉形狀。與其他許多變換類一樣,RotateTransform變換也提供了CenterX和CentertY屬性。可以用這些屬性指定将進行旋轉的中心。下面的矩形使用該方法繞其中心點旋轉自身25°:
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
采用這種方式旋轉形狀時,是圍繞形狀的原點進行旋轉的(中心)。下圖示範了繞形狀原點旋轉25°、50°、75°以及100°的效果。
<Window x:Class="Drawing.RotateShape"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RotateShape" Height="427" Width="332"
>
<Canvas>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="50" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="75" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="100" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</Window>
使用RotateTransform的CenterX和CenterY屬性時存在明顯的限制。這些屬性是使用絕對坐标定義的,這意味着需要了解繪制内容的中心店的準确位置。如果正在顯示動态内容(例如,可變次元的圖檔或改變尺寸的元素),就會出現問題。幸運的是,WPF通過友善的RenderTransformOrigin屬性,為這個問題提供了解決方法,是以形狀都支援RenderTransformOrign屬性。該屬性使用相對坐标系統設定中心點,下該對坐标系統在兩個方向上的範圍都是從0到1。換句話說,點(0,0)被指定為左上角,點(1,1)表示右下角(如果形狀區域不是正方形,那麼會相應地拉伸坐标系統)。
借助于RenderTransformOrigin屬性,可使用如下所示的标記,繞中心點旋轉任意形狀:
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="75" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
因為不管形狀的尺寸是多少,點(0.5,0.5)都表示形狀中心,是以上面的标記可以工作。實際上,RenderTransformOrigin屬性通常比CenterX和CenterY屬性更有用,盡管根據需要可以使用兩者中的一個,或者同時使用兩者。
二、變換元素
RenderTransform和RenderTransformOrigin屬性并不限制隻能用于形狀。實際上,Shape類的這些屬性從UIElement類繼承而來,這意味着所有WPF元素都支援這兩個屬性,包括按鈕、文本框、TextBlock控件、充滿内容的整個布局容器等。令人感到驚訝的是,可旋轉、扭曲以及縮放WPF使用者界面中的任意一部分。
RenderTransform不是在WPF基類中定義的唯一與變換相關的屬性。FrameworkElement類還定義了LayoutTransform屬性。LayoutTransform屬性以相同的方式變換元素,但在布局之前執行其工作。這種情況的開銷雖然更大些,但如果使用布局容器為一組控件提供自動布局功能,這種方式是很關鍵的(Shape類也提供了LayoutTransform屬性,但很少需要使用該屬性,是以通常使用容器(如Canvas面闆)明确地放置形狀,而不是使用自動布局)。
為了解兩者的差別,分析下圖中顯示的視窗,該視窗包含兩個StackPanel容器(由陰影區域表示),這兩個容器都包含一個選擇過的按鈕和一個正常的按鈕。在第一個StackPanel容器中,選擇的按鈕使用RenderTransform方法。該StackPanel容器在對兩個按鈕進行布局時,第一個按鈕正常定位,并且在即将呈現之前旋轉該按鈕。是以,選擇過的按鈕被重疊在下面。在第二個StackPanel容器中,選擇過的按鈕使用LayoutTransform方法。StackPanel容器擷取到選項後按鈕所需的邊界,并相應地布局第二個按鈕。
<Window x:Class="Drawing.RotateElement"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RotateElement" Height="314" Width="305"
>
<StackPanel>
<StackPanel Margin="25" Background="LightYellow">
<Button Padding="5" HorizontalAlignment="Left">
<Button.RenderTransform>
<RotateTransform Angle="35" CenterX="45" CenterY="5" />
</Button.RenderTransform>
<Button.Content>I'm rotated 35 degrees</Button.Content>
</Button>
<Button Padding="5" HorizontalAlignment="Left">I'm not</Button>
</StackPanel>
<StackPanel Margin="25" Background="LightYellow">
<Button Padding="5" HorizontalAlignment="Left">
<Button.LayoutTransform>
<RotateTransform Angle="35" CenterX="45" CenterY="5" />
</Button.LayoutTransform>
<Button.Content>I'm rotated 35 degrees</Button.Content>
</Button>
<Button Padding="5" HorizontalAlignment="Left">I'm not</Button>
</StackPanel>
</StackPanel>
</Window>
RotateElement
隻有很少幾個元素不能被變換,因為他們的呈現工作并非由WPF本身負責。不能被變換的元素的兩個例子是WindowsFormHost和WebBrower元素,WindowsFormHost元素用于在WPF視窗中放置Windows窗體控件,WebBrower元素用于顯示HTML内容。
在一定程度上,當設定LayoutTransform或RenderTransform屬性時,WPF元素不知道它們正在被修改。特别是,變換不會影響元素的ActualHeight和ActualWidth屬性,它們仍記錄着變換之前的值。這正是WPF能夠保證流失布局以及外邊距繼續以相同的方式工作的部分原理,即使應用了一個或多個變換也同樣如此。
作者:Peter Luo
出處:https://www.cnblogs.com/Peter-Luo/
本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,并保留此段聲明,否則保留追究法律責任的權利。