clip-rule

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2020 年 1 月⁩ 起,所有主流瀏覽器均已支援。

clip-rule CSS 屬性用於確定,當路徑的某些部分重疊其他部分時,遮罩框中哪些畫素位於由 剪裁路徑(clip path)定義的剪裁形狀內部,哪些畫素位於外部。

clip-rule 屬性僅適用於包含在 <clipPath> 元素內的 SVG 元素,如果存在,它會覆蓋該元素的 clip-rule 屬性值。clip-rule 屬性的工作方式與 fill-rule 屬性基本相同,只是它應用於 <clipPath> 定義。它對 CSS <basic-shape> 沒有任何影響。

語法

css
/* Keywords */
clip-rule: nonzero;
clip-rule: evenodd;

/* Global values */
clip-rule: inherit;
clip-rule: initial;
clip-rule: revert;
clip-rule: revert-layer;
clip-rule: unset;

nonzero

對於剪裁遮罩框中的每個點,都會向隨機方向繪製一條射線。每當射線與剪裁路徑的任何部分相交時,如果剪裁路徑的部分從左向右穿過射線,計數會增加一;如果路徑部分從右向左穿過射線,計數會減少一。如果最終計數總和為零,則該點位於路徑形狀之外。否則,它位於路徑形狀之內。

even-odd

對於剪裁遮罩框中的每個點,都會向隨機方向繪製一條射線。每當射線與剪裁路徑的任何部分相交時,計數會增加一。如果最終計數總和為偶數,則該點位於路徑形狀之外;否則,它位於路徑形狀之內。零被視為偶數。

正式語法

clip-rule = 
nonzero |
evenodd

示例

值比較

在此示例中,我們將不同的 CSS clip-rule 值應用於類似的 SVG <path> 元素,以演示 evenoddnon-zero 之間的區別。

HTML

標記包含多個 <svg> 容器,每個容器都包含一個定義星形輪廓的 <clipPath> 元素,以及一個用於在其中繪製星形的 <rect> 元素。星形由重疊的線條建立。除了 id 之外,前兩個 SVG 元素的標記是相同的。第三個 SVG 只包含 <path> 元素,顯示了建立星形的路徑線條如何重疊。

html
<svg>
  <clipPath id="star1">
    <path d="M50,0 21,90 98,35 2,35 79,90z" />
  </clipPath>
  <rect clip-path="url(#star1)" width="95" height="95" />
</svg>

<svg>
  <clipPath id="star2">
    <path d="M50,0 21,90 98,35 2,35 79,90z" />
  </clipPath>
  <rect clip-path="url(#star2)" width="95" height="95" />
</svg>

<svg id="star3">
  <path d="M50,0 21,90 98,35 2,35 79,90z" />
</svg>

CSS

第一個 SVG 中 <path>clip-rule 設定為 evenodd;第二個 SVG 中設定為 nonzero。對於僅包含路徑的 SVG,我們移除了預設的 fill,並定義了 stroke 顏色和 stroke-width,以使重疊的路徑線條可見。

css
#star1 path {
  clip-rule: evenodd;
}

#star2 path {
  clip-rule: nonzero;
}

#star3 path {
  fill: none;
  stroke: black;
  stroke-width: 1;
}

結果

在基本形狀定義中

此示例演示了,儘管 clip-rule 對 CSS <basic-shape> 沒有影響,但它會影響用作形狀來源的 <clipPath>

HTML

我們包含一個 SVG,其中包含兩個定義星形的 <clipPath> 元素,它們除了 id 屬性值外,其他都相同。我們還包含兩個將包含星形形狀的 <div> 元素。

html
<svg height="0" width="0">
  <defs>
    <clipPath id="star1">
      <path d="M100,0 42,180 196,70 4,70 158,180z" />
    </clipPath>
    <clipPath id="star2">
      <path d="M100,0 42,180 196,70 4,70 158,180z" />
    </clipPath>
  </defs>
</svg>

<div></div>
<div></div>

CSS

我們為 <div> 元素設定了 widthheight,並添加了 conic-gradient() 作為它們的 background-image 值。

css
div {
  height: 200px;
  width: 200px;
  background-image: conic-gradient(
    at center,
    rebeccapurple,
    green,
    lightblue,
    rebeccapurple
  );
}

我們使用 clip-path 屬性將不同的 <clipPath> 元素設定為每個 <div> 的剪裁路徑。

css
div:first-of-type {
  clip-path: url("#star1");
}
div:last-of-type {
  clip-path: url("#star2");
}

最後,我們為每個 <clipPath> 元素的 <path> 設定了不同的 clip-rule 值。

css
#star1 path {
  clip-rule: evenodd;
}
#star2 path {
  clip-rule: nonzero;
}

結果

選擇所有順時針路徑的路徑規則

在此 SVG 影像中,我們有兩個被剪裁的矩形,每個矩形都使用一種剪裁規則。有兩個 <clipPath> 元素,這樣可以一個設定為使用非零剪裁規則,另一個設定為使用奇偶規則。兩個路徑的內部和外部部分都以順時針方向繪製。

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 50">
  <g stroke="#112233" fill="#bbccdd">
    <!-- basic rectangle and clipping path visualization follow -->
    <rect x="10" y="10" width="30" height="30" />
    <path
      d="M 65,5 l 20,20 -20,20 -20,-20 20,-20 m 0,10 l 10,10 -10,10 -10,-10 10,-10 z"
      fill="none"
      stroke-width="0.5" />
    <!-- rectangles to be clipped follow -->
    <rect x="110" y="10" width="30" height="30" clip-path="url(#clipper1)" />
    <rect x="160" y="10" width="30" height="30" clip-path="url(#clipper2)" />
  </g>
  <!-- clipping paths follow -->
  <clipPath id="clipper1" clipPathUnits="objectBoundingBox">
    <path
      d="M 0.5 -0.15 l 0.65 0.65 -0.65,0.65 -0.65,-0.65 0.65,-0.65 m 0,0.33 l 0.33,0.33 -0.33,0.33 -0.33,-0.33 0.33,-0.33 z"
      clip-rule="evenodd" />
  </clipPath>
  <clipPath id="clipper2" clipPathUnits="objectBoundingBox">
    <path
      d="M 0.5 -0.15 l 0.65 0.65 -0.65,0.65 -0.65,-0.65 0.65,-0.65 m 0,0.33 l 0.33,0.33 -0.33,0.33 -0.33,-0.33 0.33,-0.33 z"
      clip-rule="nonzero" />
  </clipPath>
</svg>

對於應用於剪裁矩形的剪裁路徑,使用 CSS clip-rule 屬性將一個路徑設定為使用 nonzero 規則,另一個設定為使用 evenodd 規則。這些規則覆蓋了 SVG 中 clip-path 屬性的值,這些值已被有意設定為與 CSS 施加的值相反。

css
#clipper1 {
  clip-rule: nonzero;
}
#clipper2 {
  clip-rule: evenodd;
}

由於路徑的內部和外部部分都以順時針(從左到右)方向移動,因此兩種剪裁規則產生的剪裁形狀將不同。對於 nonzero,形狀外部部分內的任何射線都將計數為大於零的值,因為它將遇到一個或多個從左到右的路徑片段。對於 even-odd,路徑兩部分之間的點將具有奇數計數,而內部路徑內部或外部部分外部的任何點將具有偶數計數。

為具有不同纏繞路徑的路徑選擇規則

此示例使用與上一個示例相同的 SVG,不同之處在於剪裁路徑的內部部分以逆時針方向纏繞。

html
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 50">
  <g stroke="#112233" fill="#bbccdd">
    <!-- basic rectangle and clipping path visualization follow -->
    <rect x="10" y="10" width="30" height="30" />
    <path
      d="M 65,5 l 20,20 -20,20 -20,-20 20,-20 m 0,10 l 10,10 -10,10 -10,-10 10,-10 z"
      fill="none"
      stroke-width="0.5" />
    <!-- rectangles to be clipped follow -->
    <rect x="110" y="10" width="30" height="30" clip-path="url(#clipper1)" />
    <rect x="160" y="10" width="30" height="30" clip-path="url(#clipper2)" />
  </g>
  <!-- clipping paths follow -->
  <clipPath id="clipper1" clipPathUnits="objectBoundingBox">
    <path
      d="M 0.5 -0.15 l 0.65 0.65 -0.65,0.65 -0.65,-0.65 0.65,-0.65 m 0,0.33 l -0.33,0.33 0.33,0.33 0.33,-0.33 -0.33,-0.33 z" />
  </clipPath>
  <clipPath id="clipper2" clipPathUnits="objectBoundingBox">
    <path
      d="M 0.5 -0.15 l 0.65 0.65 -0.65,0.65 -0.65,-0.65 0.65,-0.65 m 0,0.33 l 0.33,0.33 -0.33,0.33 -0.33,-0.33 0.33,-0.33 z" />
  </clipPath>
</svg>

我們應用與之前相同的 CSS。

css
#clipper1 {
  clip-rule: nonzero;
}
#clipper2 {
  clip-rule: evenodd;
}

在這種情況下,由於路徑的外部部分以順時針(從左到右)方向移動,而路徑的內部部分以逆時針(從右到左)方向移動,因此無論使用哪種剪裁規則,產生的剪裁形狀都將相同。

規範

規範
CSS 蒙版模組 Level 1
# the-clip-rule

瀏覽器相容性

另見