【WPF學習】第四十一章 變換

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

表 變換類佈局

   從技術角度看,全部變換都使用矩陣數學改變形狀的座標。不過,使用預先構建好的變換,如TranslateTransform、RotateTransform、ScaleTransform以及SkewTransform,比使用MatrixTransform並嘗試爲但願執行的操做構造正確的矩陣更簡單的多。當使用TransformGroup執行一系列變換時,WPF將全部變換融合到單獨的MatrixTransform變換中以確保得到最佳性能。性能

  全部變換(經過Transform類)繼承自Freezable類,這意味着它們支持自動更改通知功能。若是改變了在形狀中使用的變換,形狀會當即從新繪製自身。動畫

  變換是那些在不一樣上下文中很是有用的古怪概念中的一個。下面例舉幾個例子:spa

  •   傾斜形狀。到目前爲止已經介紹了水平對齊的矩形、橢圓、直線以及多邊形。使用RotateTransform變換,可轉動座標系統,使建立特定的形狀更容易。
  •   重複形狀。許多圖畫是在不一樣的位置使用相似的形狀構建的。使用變換,可先繪製一個形狀,而後移動、旋轉、縮放該形狀,以及執行其餘操做。
  •   動畫。經過變換,可建立大量精緻的效果。例如,旋轉形狀、將形狀從一個地方移到另外一個地方,以及動態扭曲形狀。

1、變換形狀3d

  爲變換形狀,將RenderTransform屬性指定爲但願使用的變換隊形。根據使用的變換隊形,須要填充不一樣的屬性以配置變換隊形。code

  例如,若是旋轉形狀,須要使用RotateTransform變換,並以度爲單位提供旋轉角度。下面的示例將舉行旋轉25°:orm

 <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°的效果。xml

<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>
RotateShape

 

   使用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屬性更有用,儘管根據須要可使用二者中的一個,或者同時使用二者。

2、變換元素

  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可以保證流失佈局以及外邊距繼續以相同的方式工做的部分原理,即便應用了一個或多個變換也一樣如此。

相關文章
相關標籤/搜索