1. 程式人生 > >WPF學習第十二集-繪圖和動畫

WPF學習第十二集-繪圖和動畫

如今的軟體市場,競爭已經進入白熱化階段,功能強、運算快、介面友好、Bug少、價格低都已經成為了必備條件。這還不算完,隨著計算機的多媒體功能越來越強,軟體的介面是否色彩亮麗、是否能通過動畫、3D等效果是否吸引使用者的眼球也已經成為衡量軟體的標準。

軟體專案成功的三個要素是:資源、成本、時間。無論是為了在競爭中保持不敗還是為了激發起使用者對軟體的興趣,提高軟體介面的美化程度、恰當的將動畫和3D等效果引入應用程式都是一個必然趨勢。然而使用傳統的桌面應用程式開發工具和框架(如Winform、MFC、VB、Delphi等)進行開發時,為了使軟體介面變漂亮、加入動畫或者3D效果,邊際成本會非常的高。體現在:

資源消耗增大:需要招聘懂得動畫和3D程式設計的程式設計師,還需要更多的設計師、工薪和溝通成本隨著上升。

開發時間增加:介面美化、動畫和3D開發遠遠比業務邏輯開發困難、耗時。

成本增加:隨著資源消耗的增加和開發週期的拉長,成本必然增加。

之所以會出現這種情況,根本原因在於傳統開發工具和框架並沒有原生的支援美化使用者介面、嚮應用程式中新增動畫和3D效果等功能。舉個簡單的例子,當用戶提出需要把TextBox的外觀改成圓角時,Winform和Delphi程式設計師只能通過派生新類並在底層做修改的方法來實現。類似的使用者需求還有好多不得不實現,否則客戶會懷疑我們的開發能力;即使實現了也沒有什麼額外的經濟效益,因為這些東西在客戶的眼裡都是很簡單的東西。

WPF的推出可謂是對症下藥、專門解決上述問題。體現在:

XAML語言針對的是介面美化的問題,可以讓設計師直接加入開發團隊、降低溝通成本。

XAML的圖形繪製功能非常強大,可以輕易繪出複雜的圖示、圖畫。

WPF支援濾鏡功能,可以像PhotoShop一樣為物件新增各種效果。

WPF原生支援動畫開發,無論是設計師還是程式設計師,都能夠使用XAML或C#輕鬆開發製作絢麗的動畫效果。

WPF原生支援3D效果,甚至可以將其它3D建模工具建立的模型導進來、為我所用。

Blend作為專門的設計工具讓WPF如虎添翼,即能夠幫助不瞭解程式設計的設計師快速上手,又能夠幫助資深開發者快速建立圖形或者動畫的原型。

1.1   WPF繪圖

與傳統的.net開發使用GDI+進行繪圖不同,WPF擁有自己的一套繪圖API。使用這套API不但可以輕鬆繪製出精美的圖形,還可以為各種圖形新增類似與PhotoShop的“濾鏡效果”及“變形效果”。本節我們就一起研究WPF圖形API繪圖,效果和變形等功能。

先觀察下面一組圖片:


顯然,這組圖片是向量圖(Vector Image),無論怎樣放大縮小都不會出現鋸齒。你可能會想:“這是組PNG格式的圖片嗎?”答案是“NO”。這組圖是用XAML語言繪製的!XAML繪圖本身就是向量的,而且支援各式各樣的填充和效果,甚至還可以新增濾鏡,這些功能絲毫不亞於Photoshop。以前,使用PhotoShop製作出來的圖形需要程式設計師使用.net的繪圖介面進行二次轉換才能應用到程式裡,現在好了,直接把XAML程式碼拿來用就可以了。

繪圖並不是VisualStudio的強項,這些漂亮的XAML向量圖是怎麼畫出來的呢?答案是藉助Microsoft Expression Studio中的Blend和Design兩個工具。Blend我們已經介紹過了,用它可以直接繪製XAML圖形;Design可以像PhotoShop或者FireWorks那樣繪製圖形,再由設計者決定匯出xaml格式還是png格式。雖然“唯程式碼派”的程式設計師們在Visualstudio裡一行一行寫程式碼也能把複雜的圖形以非視覺化的形式創建出來,但在Blend和Design中畫出原型再在Visual Studio裡面進行細節的修飾才是提高效率之道。

積沙成塔,集腋成裘,別看前面那些圖片很複雜,但都是由幾個有限的基本圖形組成的。WPF的基本圖形包括以下幾個(它們都是Shap類的派生類):

Line:直線段,可以設定其筆觸(Stroke)。

Rectangle:矩形,既有筆觸,又有填充(Fill)。

Ellipse:橢圓,長寬相等的橢圓即為正圓,既有筆觸又有填充。

Polygon:多邊形,由多條直線線段圍成的閉合區域,既有筆觸又有填充。

PolyLine:折線(不閉合),由多條首尾相接的直線組成。

Path:路徑(閉合區域),基本圖形中功能最強的一個,可由若干直線,圓弧,被塞爾曲線組成。

1   直線

直線是最簡單的圖形。使用X1,Y1兩個屬性值可以設定它的起點座標,X2,Y2兩個屬性值可以設定它的終點座標。控制終點/起點做標就可以實現平行,交錯等效果。Stroke(筆觸)屬性的資料型別是Brush(畫刷),凡是Brush的派生類均可以用於給這個屬性賦值。因為WPF提供多種漸變色畫刷,所以畫直線也可以畫出漸變效果。同時,Line的一些屬性還可以幫助我們畫出虛線以及控制線段終點的形狀。下面的例子綜合了這些屬性:

[html] view plaincopyprint?
  1. <Windowx:Class="WpfApplication1.Window45"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         Title="Window45"Height="293"Width="437">
  5.     <Grid>
  6.         <LineX1="10"Y1="20"X2="260"Y2="20"Stroke="Red"StrokeThickness="10"></Line>
  7.         <LineX1="10"Y1="40"X2="260"Y2="40"Stroke="Orange"StrokeThickness="6"></Line>
  8.         <LineX1="10"Y1="60"X2="260"Y2="60"Stroke="Green"StrokeThickness="3"></Line>
  9.         <LineX1="10"Y1="80"X2="260"Y2="80"Stroke="Purple"StrokeThickness="2"></Line>
  10.         <LineX1="10"Y1="100"X2="260"Y2="100"Stroke="Black"StrokeThickness="1"></Line>
  11.         <LineX1="10"Y1="120"X2="260"Y2="120"StrokeDashArray="3"Stroke="Black"StrokeThickness="1"></Line>
  12.         <LineX1="10"Y1="140"X2="260"Y2="140"StrokeDashArray="5"Stroke="Black"StrokeThickness="1"></Line>
  13.         <LineX1="10"X2="260"Y1="160"Y2="160"Stroke="Black"StrokeThickness="6"StrokeEndLineCap="Flat"></Line>
  14.         <LineX1="10"X2="260"Y1="180"Y2="180"Stroke="Black"StrokeThickness="8"StrokeEndLineCap="Triangle"></Line>
  15.         <LineX1="10"X2="260"Y1="200"Y2="200"StrokeEndLineCap="Round"StrokeThickness="10">
  16.             <Line.Stroke>
  17.                 <LinearGradientBrushEndPoint="0,0.5"StartPoint="1,0.5">
  18.                     <GradientStopColor="Blue"></GradientStop>
  19.                     <GradientStopOffset="1"Color="Red"></GradientStop>
  20.                 </LinearGradientBrush>
  21.             </Line.Stroke>
  22.         </Line>
  23.     </Grid>
  24. </Window>
程式執行效果如下:


有一點需要特別注意,初學者認為繪圖一定要在Canvas中完成(誰叫它的名字叫畫布呢),其實不然,繪圖可以在任何一種佈局控制元件中完成,WPF會自動根據容器的不同計算圖形的座標,日常生活中,常用的繪圖容器有Canvas和Grid。

2      矩形

矩形有筆觸(Stroke,即邊線)和填充(Fill)構成。Stroke屬性的設定和Line一樣,Fill屬性的資料型別是Brush。Brush是一個抽象類,所以我們不可能拿一個Brush類的例項為Fill屬性賦值而只能用Brush派生類來進行賦值。WPF繪圖系統中包含非常豐富的Brush型別,常用的有:

SolidColorBrush:實心畫刷。在XAML中可以使用顏色名稱字串直接賦值。

LinearGradientBrush:線性漸變畫刷。色彩沿設定的直線方向,按設定的變化點進行漸變。

RadialGradientBrush:徑向漸變畫刷。色彩沿半徑的方向、按設定的變化點進行漸變,形成圓形填充。

ImageBrsh:使用圖片作為填充類容。

DrawingBrush:使用向量圖(Vector)和點陣圖(BitMap)作為填充內容。

VisualBrush:WPF中的每個控制元件都是有FrameWrokElement派生而來的,而FrameWorkElment類又是由Visual類派生而來的。Visual意為“可視”之意,每個控制元件的視覺化形象就可以通過Visual類的方法獲得。獲得這個視覺化形象之後,我們可以用這個形象進行填充,這就是VisualBrush。比如我想把窗體上的某個控制元件拖到另外一個位置,當滑鼠鬆開之前需要在滑鼠指標下顯示一個幻影,這個幻影就是使用VisualBrush填充出來的一個矩形,並讓矩形捕捉滑鼠的位置、隨滑鼠移動。

下面是使用不同畫刷填充矩形的綜合例項:

[html] view plaincopyprint?
  1. <Windowx:Class="WpfApplication1.Window46"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         Title="Window46"Height="390"Width