PerfectVector
著者: Irene Kim2 分で読める

SVGのclipPath単位:独自の形を対象に合わせる

SVGのclipPath単位を選び、輪郭を正規化して比率を保ちます。穴と元の形状を保持しながら、横長と縦長の対象で検証します。

目次

クリッピング形状を対象の境界に合わせて伸縮させる場合は、clipPathUnits="objectBoundingBox"を使います。先に形状の座標を正規化してください。配置を明示したい場合や、形の比率を保持する等倍率の拡大縮小が必要な場合は、userSpaceOnUseを使います。

属性を変えるだけでは、数百単位で描いたパスがゼロから1の間の形状に変換されません。クリップのほぼ全体が対象の外側へ移動することがあります。このガイドでは独自のしおりの輪郭を使い、座標の変更、その結果の変形、ひし形の開口部を正方形に保つ中央配置を示します。

クリッピングは見える範囲を制御します。元のパスを切り取り、新しい編集可能な形状にする操作ではありません。きれいなSVGの輪郭がすでにあれば直接使ってください。トレースが必要なのは、ラスター画像からその輪郭を復元する場合だけです。

リサイズする前に座標系を選ぶ

既定値はuserSpaceOnUseです。クリップの座標は、そのクリップを参照する要素のユーザー座標系に属します。objectBoundingBoxでは、対象の境界の左上が(0, 0)、右下が(1, 1)に対応します。clipPathUnitsリファレンスを参照してください。

要件座標系の選択必要な作業
既知のローカル座標にクリップを保つuserSpaceOnUse対象に対してパスを配置します
各対象に合わせて輪郭を伸縮させるobjectBoundingBox元のパスを正規化し、軸ごとの異なる倍率を許容します
変形せずに輪郭を収めるuserSpaceOnUse等倍率の拡大縮小と中央配置の移動量を計算します

対象の境界ボックスは、外側SVGのviewBoxと同じとは限りません。グループのクリッピングでは、そのグループの境界が使われ、内部の矩形とは異なる場合があります。最初のテストを予測しやすくするには、寸法が既知の矩形に直接クリップを適用します。

横長と縦長の対象を比較する

しおりの外側の境界はx=20、y=10、width=100、height=100です。ひし形は、同じパス内の2つ目のサブパスです。テストでは、ローカルSVG単位で200 × 120と120 × 200の矩形に適用しています。

横長と縦長の矩形にしおり形のクリップを適用したブラウザー比較:固定座標、境界ボックス座標による伸縮、比率を保つ配置と透明なひし形の穴
以下の独自SVGのブラウザー描画です。固定座標は100 × 100の形を保持し、境界ボックスの対応付けは対象ごとに伸縮し、等倍率の配置は比率を保ちます。市松模様は表示用の背景です。

中央列は各対象の境界を満たしますが、ひし形は横長や縦長になります。右列はひし形と下部の切り欠きを保持し、対象の長い軸方向に余白が残ります。6つの開口部はすべて透明のままです。

次の完全な例をclippath-comparison.svgとして保存し、ブラウザーで開きます。列は画像と同じ順番です。上段は横長、下段は縦長の矩形です。表示用の移動変換はサンプルを並べるもので、対象のローカル寸法は変えません。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 470">
  <defs>
    <path id="silhouette" d="M20 10H120V110L70 85L20 110Z M70 30L85 45L70 60L55 45Z"/>
    <clipPath id="fixed" clipPathUnits="userSpaceOnUse">
      <use href="#silhouette" clip-rule="evenodd"/>
    </clipPath>
    <clipPath id="box" clipPathUnits="objectBoundingBox">
      <use href="#silhouette" clip-rule="evenodd"
        transform="matrix(.01 0 0 .01 -.2 -.1)"/>
    </clipPath>
    <clipPath id="wide-fit" clipPathUnits="userSpaceOnUse">
      <use href="#silhouette" clip-rule="evenodd"
        transform="matrix(1.2 0 0 1.2 16 -12)"/>
    </clipPath>
    <clipPath id="tall-fit" clipPathUnits="userSpaceOnUse">
      <use href="#silhouette" clip-rule="evenodd"
        transform="matrix(1.2 0 0 1.2 -24 28)"/>
    </clipPath>
  </defs>
  <g fill="#107c86">
    <rect x="0" y="0" width="200" height="120"
      transform="translate(20 30)" clip-path="url(#fixed)"/>
    <rect x="0" y="0" width="200" height="120"
      transform="translate(260 30)" clip-path="url(#box)"/>
    <rect x="0" y="0" width="200" height="120"
      transform="translate(500 30)" clip-path="url(#wide-fit)"/>
    <rect x="0" y="0" width="120" height="200"
      transform="translate(60 230)" clip-path="url(#fixed)"/>
    <rect x="0" y="0" width="120" height="200"
      transform="translate(300 230)" clip-path="url(#box)"/>
    <rect x="0" y="0" width="120" height="200"
      transform="translate(540 230)" clip-path="url(#tall-fit)"/>
  </g>
</svg>

青緑の塗りは矩形のものです。クリッピングパスが、見える輪郭を提供します。スクリーンショットは同じSVGの周囲にラベルと市松模様を追加しています。単独のファイル自体は背景が透明です。

原点も含めて元の境界を正規化する

境界が(minX, minY, width, height)の元データの点(x, y)について、次のように計算します。

normalizedX = (x - minX) / width
normalizedY = (y - minY) / height

ここでは(x - 20) / 100と(y - 10) / 100です。box定義の行列は、パスデータを書き換えずに両方の操作を行います。

matrix(0.01 0 0 0.01 -0.2 -0.1)

(20, 10)を(0, 0)へ、(120, 110)を(1, 1)へ対応させます。原点を引かずに100で割るだけでは、対象内で形がずれたままになります。次に境界ボックスの対応付けが、正規化した結果を対象の幅と高さに独立して拡大縮小します。

正規化したい形状の実際の境界を使います。viewBoxには意図した余白がある場合があり、その寸法が輪郭の境界と等しいとは限りません。その余白を保持したい場合は、2つの測定値を誤って混ぜず、意図してviewBoxの矩形を使います。

入れ子の変換がある読み込み画像では、一貫した1つの座標系で測定と正規化を行います。変換を確実に考慮できない場合は、生のパスデータをコピーする前にエディターで変換を整理してください。SVGの編集手順では、納品前のパスとグループの確認を説明しています。

1つの倍率で比率を保持する

ローカルの(0, 0)にある幅W、高さHの対象矩形には、次を使います。

s  = min(W / width, H / height)
tx = (W - s * width) / 2 - s * minX
ty = (H - s * height) / 2 - s * minY
matrix(s 0 0 s tx ty)

横長の対象では、s=1.2、tx=16、ty=-12です。クリップはx=40..160、y=0..120を占めます。縦長の対象では、s=1.2、tx=-24、ty=28となり、クリップをx=0..120、y=40..160に配置します。

これらはuserSpaceOnUse内の明示的な行列なので、対象のローカル寸法が変わったら再計算します。SVG全体を別のCSSサイズで表示するだけなら、構図がまとめて拡大縮小されます。内部の矩形を横長から縦長へ変えるのは、別の操作です。

この計算は、元の幅と高さがゼロでなく、未考慮の回転や傾斜がないことを前提にしています。内側へ収める操作なので、余白が残るのは想定どおりです。モチーフの比率よりも対象全体を満たすことが重要なら、境界ボックス単位による伸縮が適しています。

クリッピング形状に開口部を保持する

この例は、各clipPath内のuseにclip-rule="evenodd"を設定しています。参照するパスには、外側のしおりとひし形のサブパスの両方が含まれます。この規則が、複合形状のどの領域をクリップ内とするか決めます。

青緑の矩形へclip-ruleを置いても、クリッピング形状の規則は設定されません。同様に、元データの描画に使うfill-ruleは、クリッピングの規則の代わりにはなりません。MDNのclip-ruleリファレンスでは、clipPath内での適用範囲を説明しています。

白いひし形を別に追加すればクリップから差し引ける、と考えないでください。クリッピングパス内の子の輪郭は、見える領域として結合されます。塗り色は、白黒のマスク値としては機能しません。このような穴には、複合パスと意図した巻き数の規則を使います。SVGの穴が埋まる問題のガイドは、元になるパス構造を説明しています。

半透明の端や輝度に基づく表示が必要なデザインでは、同じ画像でclipPathとSVGマスクを比較してください。クリップは幾何学的な境界に役立ち、マスクは別の表示モデルを提供します。CSSで色を付ける単色アイコンには、SVGのCSSマスクガイドを参照してください。

境界と書き出し結果を確認する

水平線や垂直線は、ストロークが見えていても、形状の境界ボックスの高さや幅がゼロになる場合があります。そのような対象にはobjectBoundingBoxを避け、正規化時にゼロの元寸法で割らないでください。SVGの座標仕様では、この境界ボックスの計算からストローク幅を除外し、これらの退化したケースについて注意しています。

納品前に、次を確認します。

  1. 参照するクリップIDが存在し、文書内で一意であることを確認します。
  2. 最小の開口部も含め、横長と縦長の対象を比較します。
  3. 元データと対象の境界を、それぞれ意図した座標系で確認します。
  4. 書き出したSVGを保存し、使用するアプリで開き直します。
  5. クリップを編集可能に保つ必要がある場合は、元の形状を保持します。

CSS Masking仕様は、クリッピングが描画を変えるだけで、要素固有の形状は変えないとしています。そのため、カッターや形状処理アプリでは、実際のパスの交差処理など、エディターの操作が必要な場合があります。そのアプリで結果のパスを確認してください。ブラウザーのプレビューが正しいだけでは、カット可能なファイルとは判断できません。

必要な場合にラスターの輪郭を復元する

独自のモチーフがPNGやJPGでしか残っておらず、クリップ用の編集可能な輪郭が必要な場合に、PerfectVectorが役立ちます。画像をSVGへ変換し、外側の端、内側の開口部、不要な背景形状を確認してから、輪郭を取り出します。クリップに含める輪郭を選んでください。元データの色は、別々のクリッピング強度を定義しません。

既存のベクターマスターがあれば保持します。この例のような単純な幾何学的なしおりは、直接描けます。ベクター化はクリップの単位を選んだり、境界を正規化したり、恒久的なブーリアン切り取りを行ったりはしません。元データの選択について詳しくは、画像のベクター化の概要を参照してください。

よくある質問

objectBoundingBoxは形の比率を保ちますか? いいえ。正規化したクリップを、対象の幅と高さに独立して対応させます。輪郭の比率を保つ必要がある場合は、userSpaceOnUseで等倍率の拡大縮小を使ってください。

clipPathUnitsを変えると形が隠れるのはなぜですか? パス座標が元データの単位のままかもしれません。元の原点も含めて対象に対する座標系へ正規化するか、userSpaceOnUseを保持して明示的に配置します。

クリッピングでSVGの隠れた部分は削除されますか? いいえ。元の形状を保持したまま、描画される範囲を変えます。納品ファイルに永久に切り取った輪郭が必要なら、適切なパス編集操作を使います。

参考資料

  1. MDN — clipPathUnits — 座標系の選択と、既定のユーザー空間の解釈。
  2. MDN — clip-rule — クリッピングパス内での巻き数規則の配置。
  3. W3C — SVGの座標系 — 境界ボックスの対応付け、ストロークの除外、ゼロ寸法の制限。
  4. W3C — CSS Masking — クリッピング形状、輪郭の結合、変わらない元のパス。

クリップがラスターのモチーフから始まる場合は、PerfectVectorでSVGを準備し、輪郭と開口部を確認してから、伸縮か等倍率の配置を選ぶ前に、両方の対象比率でテストしてください。

ブログのその他の記事

編集しやすい
よりきれいなSVGから始めましょう