SVGとclipPathで複雑な図形を切り抜く

実施したいこと

ファーストビューの動画や画像をCSSだけでは難しい複雑な図形で切り抜いて表現しているようなデザインがあります。
単純に四角形でborder-radiusなどで表現できない以下のような画像です。
非常に沼にハマったのですがSVGとclipPathを使って実装できます。

実装方針

  1. 画面には一切表示されないSVGを定義する
  2. clipPath(クリッピングマスク)で動画や画像を"切り抜く”ための型を作る。
  3. そのclipPathに動画や画像をCSSで適用する。

実際のコード例

body直下に非表示のSVGのエリアを作り切り抜く形状をclipPathで描きます。

■html

<body>
<svg width="0" height="0">
  <defs>
    <clipPath id="videoMask" clipPathUnits="objectBoundingBox">
      <path d="
        M0.078,1
        a0.026,0.04,0,0,1,-0.026,-0.04
        V0.164
        a0.026,0.04,0,0,1,0.026,-0.04
        H0.456
        V0.06
        a0.026,0.04,0,0,1,0.026,-0.04
        H0.96
        a0.026,0.04,0,0,1,0.026,0.04
        V0.89
        a0.026,0.04,0,0,1,-0.026,0.04
        H0.519
        V0.96
        a0.026,0.04,0,0,1,-0.026,0.04
        Z
      " />
    </clipPath>
  </defs>
</svg>

    

・svg width="0" height="0"で非表示のエリアを作ります。
・defs:再利用用の定義エリア。グラデーション、マスク、クリップパスなどを置く場所。ここにあるものは「描画されません」
・id="videoMask":cssと括り付けつるためにclipPathにidを付けます。
・clipPathUnits="objectBoundingBox":座標系が 0〜1 の割合指定で自動スケールされます。
・path d=" … ":「ペンの動き」を表す命令列です(drawかな?)。
・M0.078,1:Move(移動)左から7.8%、下端(100%)地点
・a0.026,0.04,0,0,1,-0.026,-0.04:a = 楕円弧(arc)横半径:2.6%、縦半径:4%、左下に丸みをつける、border-radius 的な処理です。
・右から三番目の値が1の時は描画方向が時計周り、0で反時計周りになります。
・右から2つの値(delta x , delta y)はその地点からの移動量を表して、角丸の終点(次の直線に乗る点)へどう移動したいかの値です。
 右に行きたい → +x
 左に行きたい → -x
 下に行きたい → +y
 上に行きたい → -y
・コード例だと現在地点からX軸が-2.6%、Y軸が-4%移動するので左下に丸みをつけることになります。
・ V0.164:V(vertical)垂直方向の上から16.4%の位置まで描画。
・H0.456:H(horizontal)水平方向に左から45.6%の位置まで描画。
Z:クローズ

■html
※動画を表示する位置に配置する。
<div class="fv__video-mask-wrapper">
    <div class="fv__video-mask">
        <video autoplay loop muted playsinline>
          <source src="./video/abcd.mp4" type="video/mp4">
        </video>
    </div>
</div> 

動画を表示する位置に要素を配置します。

■CSS
.fv__video-mask {
  max-width: 1000px;
  width: 100%;
  height: auto;
  aspect-ratio: 920/599;
  position: relative;
  overflow: hidden;
  right: -150px;
  -webkit-clip-path: url(#videoMask);
  clip-path: url(#videoMask);
}

clip-path: url(#videoMask);clip-pathのURLにclipPathのIDを指定します。

以上です。