共用方式為


HOW TO:控制複合圖案的填色

更新:2007 年 11 月

GeometryGroupPathGeometryFillRule 屬性會指定供複合圖案使用的「規則」,以判斷指定點是否屬於幾何的一部分。FillRule 有兩個可能值:EvenOddNonzero。下列小節將描述如何使用這兩個規則。

EvenOdd:這個規則會判斷某個點是否在填滿區域內,方法是從該點往任何方向畫一條無限長的射線,然後計算這條射線穿越指定圖案內的路徑區段數。如果這個數目是奇數,則這個點在圖形內,如果是偶數,則這個點在圖形外。

舉例來說,下列 XAML 會建立由一系列同心環 (目標) 組成的複合圖案,其 FillRule 會設為 EvenOdd

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>
    <GeometryGroup FillRule="EvenOdd">
      <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
      <EllipseGeometry RadiusX="70" RadiusY="70" Center="75,75" />
      <EllipseGeometry RadiusX="100" RadiusY="100" Center="75,75" />
      <EllipseGeometry RadiusX="120" RadiusY="120" Center="75,75" />
    </GeometryGroup>
  </Path.Data>
</Path>

下圖顯示在上述範例中建立的圖案。

螢幕擷取畫面:FillRule 屬性為 EvenOdd

在上面的圖例中,請注意中央和第三個環並沒有填滿。這是因為在這兩個環內任何點繪製出的射線,都會穿越過偶數的區段數。請參閱下圖:

圖表:FillRule 屬性值為 EvenOdd

NonZero:這個規則會判斷某個點是否在路徑的填滿區域內,方法是從該點往任何方向畫一條無限長的射線,然後檢視圖案的區段與這條射線交叉的位置。從零開始算起,每當有區段由左至右穿過這條射線時就加一,而每當有路徑區段由右至左穿過這條射線時就減一。如果在計算交叉後得到的結果是零,則這個點是在路徑外。否則會在內部。

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>
    <GeometryGroup FillRule="NonZero">
      <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
      <EllipseGeometry RadiusX="70" RadiusY="70" Center="75,75" />
      <EllipseGeometry RadiusX="100" RadiusY="100" Center="75,75" />
      <EllipseGeometry RadiusX="120" RadiusY="120" Center="75,75" />
    </GeometryGroup>
  </Path.Data>
</Path>

使用上述範例,FillRuleNonzero 值會產生下圖這樣的結果:

螢幕擷取畫面:FillRule 值為 NonZero

如您所見,所有的環都已填滿。這是因為所有區段都是朝同一個方向,所以從任何點繪製出的射線,都會穿越過一個或多個區段,而這些交叉總合不會等於零。舉例來說,在下圖中,紅色箭號代表區段繪製的方向,而白色箭號代表從最裡面環的某點出發的任意射線。從零開始算起,每當射線穿過區段時值就加一,因為區段是由左至右穿越射線。

圖表:FillRule 屬性值等於 NonZero

為了要為 Nonzero 規則行為提供更佳的示範,需要有一個較為複雜的圖案,而區段要從不同方向出發。下列 XAML 程式碼會建立類似上述範例的圖案,不同的是這是以 PathGeometry 建立的四個同心弧狀,而非 EllipseGeometry 建立的完全封閉同心圓。

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>
    <GeometryGroup FillRule="NonZero">
      <PathGeometry>
        <PathGeometry.Figures>

          <!-- Inner Ring -->
          <PathFigure StartPoint="10,120">
            <PathFigure.Segments>
              <PathSegmentCollection>
                <ArcSegment Size="50,50" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,120" />
              </PathSegmentCollection>
            </PathFigure.Segments>
          </PathFigure>

          <!-- Second Ring -->
          <PathFigure StartPoint="10,100">
            <PathFigure.Segments>
              <PathSegmentCollection>
                <ArcSegment Size="70,70" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,100" />
              </PathSegmentCollection>
            </PathFigure.Segments>
          </PathFigure>

          <!-- Third Ring (Not part of path) -->
          <PathFigure StartPoint="10,70">
            <PathFigure.Segments>
              <PathSegmentCollection>
                <ArcSegment Size="100,100" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,70" />
              </PathSegmentCollection>
            </PathFigure.Segments>
          </PathFigure>

          <!-- Outer Ring -->
          <PathFigure StartPoint="10,300">
            <PathFigure.Segments>
              <ArcSegment Size="130,130" IsLargeArc="True" SweepDirection="Clockwise" Point="25,300" />
            </PathFigure.Segments>
          </PathFigure>
        </PathGeometry.Figures>
      </PathGeometry>
    </GeometryGroup>
  </Path.Data>
</Path>

下圖顯示在上述範例中建立的圖案。

螢幕擷取畫面:FillRule 屬性值為 NonZero

請注意,第三個從中央出發的弧並沒有填滿。下圖顯示為什麼會這樣。圖中的紅色箭號代表區段繪製的方向。而兩個白色箭號代表從「未填滿」區域的某點出發的兩條任意射線。如圖所示,指定射線在路徑上穿越的區段值總合為零。依據以上定義,總合為零代表該點不是幾何的一部分 (不屬於填滿部分),而總合「不」為零 (包含負值) 則為幾何的一部分。

圖表:FillRule 屬性值為 NonZero

**注意:**基於 FillRule 的目的,所有圖案都視為封閉的。如果區段中有缺口,請繪製虛構的線來封閉區段。在上述範例中,環當中有小型的缺口。基於這個樣子,有人可能會認為穿過缺口的射線,可能會跟另一個方向的射線產生不同的結果。以下是其中一個缺口的放大圖,以及封閉該缺口的「虛構區段」(繪製區段的目的在於套用 FillRule)。

圖表:如果是 FillRule,線段一定都會關閉

請參閱

工作

HOW TO:建立複合圖案

概念

幾何概觀