文章出處

在WPF的DrawingContext對象中,提供了基本的繪制橢圓和矩形的API:DrawEllipse和DrawRectangle。但是,這些是遠遠不夠用的,我們在日常應用中,更多的是使用DrawGeometry函數,它可以繪制更多復雜的幾何圖形,并且提供了許多強大而易用的函數,在大多數場景下,甚至可以取代DrawEllipse和DrawRectangle函數。

在WPF圖形體系中,Geometry類表示幾何圖形的基類,使用的時候是實例化它的一些子類,具體的有:

基本幾何圖形

  

 

幾何圖形集合

路徑集合圖形PathGeometry里可以包含一系列幾何圖形集合,常見的有:

貝塞爾曲線:貝塞爾曲線系列還比較多,具體有如下幾種:

  1. BezierSegment:在兩個點之間創建一條三次方貝塞爾曲線。
  2. PolyBezierSegment:創建一系列三次方貝塞爾曲線。
  3. PolyQuadraticBezierSegment:創建一系列二次貝塞爾曲線。
  4. QuadraticBezierSegment:創建一條二次貝塞爾曲線。

除了這種組合的方式之外,系統還提供了一個通過一系列API來繪制的StreamGeometry。它不支持綁定,動畫,相應也更加靈活而高效。

    StreamGeometry geometry = new StreamGeometry;

    using (StreamGeometryContext ctx = geometry.Open())
    {
        ctx.BeginFigure(new Point(10, 100), true , true);
        ctx.LineTo(new Point(100, 100), true , false);
        ctx.LineTo(new Point(100, 50), true, false);
    }

 

復合幾何圖形

使用 GeometryGroupCombinedGeometry 或者通過調用靜態的 Geometry 方法 Combine,可以創建復合幾何圖形對象。它們主要的區別是:

  • CombinedGeometry 對子圖形進行疊加操作,沒有面積的子圖形將被丟棄。只能組合兩個子圖形(但是這兩個子圖形也可以是復合幾何圖形)。
  • GeometryGroup 只進行組合,而不進行面積疊加。可以添加多個子圖形。有關示例,請參見如何:創建復合形狀

CombinedGeometry的疊加方式有四種:UnionIntersectExclude 和 Xor,它們的效果為:

 

 

這些在我們的日常應用中是非常有用的,具體示例請參看MSDN文章: 如何:創建復合形狀如何:創建組合的幾何圖形

 

常用方法

Geometry對象中本身還包含了一系列非常有用的方法,如:

這些都是非常常用的方法,例如FillContains,StrokeContains用于鼠標命中測試是非常方便的。

 

呈現方式

Geometry對象并不能作為圖像獨立呈現出來,它一般有如下幾種呈現方式:

在Path中呈現:

可以作為GeometryDrawing.Geometry的參數呈現為Path對象

    <Path Stroke="Black" StrokeThickness="1" >
        <Path.Data>
            <LineGeometry StartPoint="10,20" EndPoint="100,130" />
        </Path.Data>
    </Path>

這種方式下寫一些簡單的幾何圖形還行,但對于PathGeometry來說有些冗繁,因此XAML采用了一種簡單的路徑標記語法來簡化這一過程,

    <Path Stroke="Black" Fill="Gray">
        <Path.Data>
            <PathGeometry Figures="M 10,100 C 10,300 300,-200 300,100" />
        </Path.Data>
    </Path>

甚至可以直接簡化為:

    <Path Stroke="Black" Fill="Gray" Data="M 10,100 C 10,300 300,-200 300,100" />

這種語法在一些第三方矢量圖轉換過來的文件中非常常見,如果能熟練掌握的話,寫一些簡單的幾何圖形也是非常方便的。

在DrawingContext中呈現

可以作為DrawingContext. DrawGeometry的參數呈現,這種方式后面的文章中做會更多的說明,這里就不多介紹了。

在GeometryDrawing中呈現

可以作為GeometryDrawing.Geometry的參數呈現為Drawing對象

復制代碼
    <GeometryDrawing Brush="MediumBlue">
        <GeometryDrawing.Geometry>
            <GeometryGroup>
                <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
                <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
            </GeometryGroup>
        </GeometryDrawing.Geometry>
    </GeometryDrawing>
復制代碼

 當然,Drawing對象也不能獨立呈現,一般是作為DrawingBrush或作為DrawingContext.DrawDrawing的參數來使用的

 

其它用途:

作為UIElement.Clip參數裁剪控件

    <Image Source="sampleImages\Waterlilies.jpg" Width="200" Height="150" HorizontalAlignment="Left">
        <Image.Clip>
            <EllipseGeometry RadiusX="100" RadiusY="75" Center="100,75"/>
        </Image.Clip>
    </Image>

  

另外,也常用在DrawingGroup.ClipGeometry和DrawingContext.PushClip中裁剪圖像。

作為DoubleAnimationUsingPath. PathGeometry屬性生成路徑動畫

 可以將PathGeometry 對象定義的幾何路徑旋轉(轉動)對象的路徑。

 

 PathGeometry用法

先看顯示效果:
Path標記語法
(圖1)

XAML(代碼A)
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <Canvas>

<!--這是使用PathFigureCollection的表示方法-->
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>
    <PathGeometry Figures="M 10,100 C 10,300 300,-160 300,100" />
  </Path.Data>

</Path>

<!--這是使用StreamGeometry的表示方法-->
<Path Stroke="Black" Data="M 100,240 C 510,300 80,100 300,160 H40 v80" />
</Canvas>
</Page>

 請留意上面加粗及紅色文字部分。

WPF提供兩個類來描述路徑數據:一個是StreamGeometry,另一個是PathFigureCollection。

類似:<Path Stroke="Black" Data="M 100,240 C 510,300 80,100 300,160 H40 v80" />的形式是StreamGeometry的XAML代碼表示形式,也是最簡潔的表示形式。
而類似:
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>
    <PathGeometry Figures="M 10,100 C 10,300 300,-160 300,100" />
  </Path.Data>
</Path>
這樣的方式是使用PathFigureCollection的XAML代碼表示方式。

這兩種方式都可以達至同一種顯示效果,那么,什么時候使用StreamGeometry,什么時候使用PathFigureCollection方式呢?
一般地,當你建立路徑后,不再需要修改時,可使用StreamGeometry方式,如果還需要對路徑數值進行修改,則使用PathFigureCollection方式(這里就是PathGeometry)。

Data屬性的表示語法:
(1)StreamGeometry方式: [填充規則] 外形描述[外形描述]*
(2)PathFigureCollection方式: 外形描述[外形描述]*

注:
(1)上面語法中,[...]表示可選,*代表任意個。
(2)“填充規則”中,有EvenOdd和Nonzero兩種。XAML中為了簡潔,使用“F0”表示EvenOdd,“F1”表示Nonzero。
(3)“外形描述”的語法:moveCommand drawCommands [closeCommand]
其中:移動指令(moveCommand),繪制指令(drawCommands),關閉指令(closeCommand)。
(4)moveCommand指定起始點,使用一個drawingCommand描述外形輪廓的內容描述,closeCommand用來關閉路徑。

如下圖:


Path Data Markup Syntax
(圖2)

下面來解釋一下“M 100,240 C510,300 80,100 300,160 H40 v80”這樣字符串的意義。
分為四種情況來解釋:
1. 移動指令:Move Command(M):M 起始點  或者:m 起始點
比如:M 100,240或m 100,240
使用大寫M時,表示絕對值; 使用小寫m時; 表示相對于前一點的值,如果前一點沒有指定,則使用(0,0)。

2. 繪制指令(Draw Command):
我們可以繪制以下形狀:
(1) 直線:Line(L)
(2) 水平直線: Horizontal line(H)
(3) 垂直直線: Vertical line(V)
(4) 三次方程式貝塞爾曲線: Cubic Bezier curve(C)
(5) 二次方程式貝塞爾曲線: Quadratic Bezier curve(Q)
(6) 平滑三次方程式貝塞爾曲線: Smooth cubic Bezier curve(S)
(7) 平滑二次方程式貝塞爾曲線: smooth quadratic Bezier curve(T)
(8) 橢圓圓弧: elliptical Arc(A) 

上面每種形狀后用括號括起的英文字母為命令簡寫的大寫形式,但你也可以使用小寫。使用大寫與小寫的區別是:大寫是絕對值,小寫是相對值。

比如:L 100, 200 L 300,400表示從絕對坐標點(100,200)到另一絕對坐標點(300,400)的一條直線。而l 100, 200 l 300,400則表示相對上一點(如果未指定,則默認為(0,0)坐標點)開始計算的坐標點(100,200)到坐標點為(300,400)的一條直線。

當我們重復使用同一種類型時,就可以省略前面的命令。比如:L 100, 200 L 300,400簡寫為:L 100, 200 300,400。

下圖是以下XAML代碼的繪制效果(為了方便你比較,我加了背景格子,每小格為10像素):
XAML(代碼B):
<Path Stroke="Black" StrokeThickness="1" Data="M 10,100 L 100,100 100,50 Z M 10,10 100,10 100,40 Z" />
使用兩種不同XAML代碼方式展示出同樣的效果圖
(圖3)

細心的讀者可能會發現,有點怪怪的感覺,因為我故意將下面的三角形的代碼放在前面了,這樣,似乎不太符合習慣。事實上,上面的代碼與這個結果完全一樣:
<Path Stroke="Black" StrokeThickness="1" Data="M 10,10 100,10 100,40 Z M 10,100 L 100,100 100,50 Z" />
這里有一個你暫時還沒見過的Z指令,它就是一個關閉指令(close Command),表示封閉指定形狀,即將首尾點連接起來形成封閉的區域。

繪制指令格式語法:

(1) 直線:Line(L)
格式:
L 結束點坐標 或: l 結束點坐標。
比如:L 100,100 或 l 100 100。坐標值可以使用x,y(中間用英文逗號隔開)或x y(中間用半角空格隔開)的形式。

(2) 水平直線  Horizontal line(H):繪制從當前點到指定x坐標的直線。
格式:H x值 或 h x值(x為System.Double類型的值)
比如:H 100或h 100,也可以是:H 100.00或h 100.00等形式。

(3) 垂直直線 Vertical line(V):繪制從當前點到指定y坐標的直線。
格式:V y值 或 v y值(y為System.Double類型的值)
比如:V 100或y 100,也可以是:V 100.00或v 100.00等形式。

(4) 三次方程式貝塞爾曲線 Cubic Bezier curve(C):通過指定兩個控制點來繪制由當前點到指定結束點間的三次方程貝塞爾曲線。
格式:C 第一控制點 第二控制點 結束點 或 c 第一控制點 第二控制點 結束點
比如:C 100,200 200,400 300,200 或 c 100,200 200,400 300,200
其中,點(100,200)為第一控制點,點(200,400)為第二控制點,點(300,200)為結束點。

(5) 二次方程式貝塞爾曲線 Quadratic Bezier curve(Q):通過指定的一個控制點來繪制由當前點到指定結束點間的二次方程貝塞爾曲線。
格式:Q 控制點 結束點 或 q 控制點 結束點
比如:q 100,200 300,200。其中,點(100,200)為控制點,點(300,200)為結束點。

(6) 平滑三次方程式貝塞爾曲線: Smooth cubic Bezier curve(S):通過一個指定點來“平滑地”控制當前點到指定點的貝塞爾曲線。
格式:S 控制點 結束點 或 s 控制點 結束點
比如:S 100,200 200,300

(7) 平滑二次方程式貝塞爾曲線 smooth quadratic Bezier curve(T):與平滑三次方程貝塞爾曲線類似。
格式:T 控制點 結束點 或 t 控制點 結束點
比如:T 100,200 200,300

關于第(6)種平滑三次方程式貝塞爾曲線與第(7)種平滑二次方程式貝塞爾曲線的比較:

如下圖:
平滑三次方程式貝塞爾曲線與平滑二次方程式貝塞爾曲線的比較
XAML代碼:
<!-- 這是左邊平滑三次方程式貝塞爾曲線的代碼 -->
<Path Stroke="Black" StrokeThickness="1"  Data="M 150,10 S 250,100 80,280" />

<!--這是關鍵點的連線示意-->
<Path Stroke="Black" StrokeThickness="1"  Data="M 150,10 L 250,100 80,280" />

<!-- 這是右邊平滑二次方程式貝塞爾曲線的代碼 -->
<Path Stroke="Red" StrokeThickness="2" StrokeDashArray="1,1,1"   Data="M 150,10 T 250,100 80,280" />
備注:為了方便比較,我使用了同一個控制點,坐標均為:(250,100),起始和結束點也一樣。另外,我使用了虛線(用了StrokeDashArray屬性)及不同顏色以示區分。

(8) 橢圓圓弧: elliptical Arc(A) : 在當前點與指定結束點間繪制圓弧。
A 尺寸 圓弧旋轉角度值 優勢弧的標記 正負角度標記 結束點
或:
a 尺寸 圓弧旋轉角度值 優勢弧的標記 正負角度標記 結束點
尺寸(Size): System.Windows.Size類型,指定橢圓圓弧X,Y方向上的半徑值。
旋轉角度(rotationAngle):System.Double類型。
圓弧旋轉角度值(rotationAngle):橢圓弧的旋轉角度值。 
優勢弧的標記(isLargeArcFlag):是否為優勢弧,如果弧的角度大于等于180度,則設為1,否則為0。 
正負角度標記(sweepDirectionFlag):當正角方向繪制時設為1,否則為0。 
結束點(endPoint):System.Windows.Point類型。

3. 關閉指令(close Command):用以將圖形的首、尾點用直線連接,以形成一個封閉的區域。
用Z或z表示。

如果你對SVG有所了解,你會發現它們是驚人的相似。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()