吉本集の個人ブログ
Web制作の技術について書いています。たまに日記も書きます。

【SVG】マスク要素(コンテナ要素)

2015年2月24日 / category : svg

マスク要素は、通常のマスク処理ではなく、色チャンネルとアルファチャンネルの値を計算し、オブジェクトと背景を合成する処理です。
例えば、下記のようなマスキング処理を見てみます。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m0" maskUnits="userSpaceOnUse" x="0" y="0" width="150" height="150">
   <rect x="0" y="0" width="150" height="150" fill="#fff">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#009ce5" />
 <circle cx="150" cy="150" r="150" fill="#e5000d" mask="url(#m0)" />
</svg>

これは、赤いオブジェクトを白いマスクを通して、青い背景と合成したサンプルです。
ただ、白い(#fff)マスクの場合、マスキング処理では赤いオブジェクトがそのまま合成されています。

次のサンプルを見てみます。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m1" maskUnits="userSpaceOnUse" x="0" y="0" width="150" height="150">
   <rect x="0" y="0" width="150" height="150" fill="#999">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#009ce5" />
 <circle cx="150" cy="150" r="150" fill="#e5000d" mask="url(#m1)" />
</svg>

このサンプルでは、灰色(#999)のマスクを使用しています。そのため、マスキング処理により合成箇所の色が変化しています。
白い(#fff)マスクの場合は、オブジェクトの色がそのまま合成されました。

それでは黒い(#000)マスクの場合は、どうなるでしょうか。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m2" maskUnits="userSpaceOnUse" x="0" y="0" width="150" height="150">
   <rect x="0" y="0" width="150" height="150" fill="#000">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#009ce5" />
 <circle cx="150" cy="150" r="150" fill="#e5000d" mask="url(#m2)" />
</svg>

黒い(#000)マスクの場合は、赤いオブジェクトが消えてしまいました。
このように、マスク要素は通常のマスク処理ではなく、マスキング処理を行い、オブジェクトと背景を合成することです。

続いて、マスクにグラデーションをかけてみます。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <linearGradient id="gr" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="300" y2="0">
   <stop offset="0" stop-color="#fff" stop-opacity="0" />
   <stop offset="0.5" stop-color="#fff" stop-opacity="1" />
   <stop offset="1" stop-color="#fff" stop-opacity="0" />
  </linearGradient>
  <mask id="m3" maskUnits="userSpaceOnUse" x="0" y="0" width="300" height="300">
   <rect x="0" y="0" width="300" height="300" fill="url(#gr)">
  </mask>
 </defs>
 <rect width="300" height="300" fill="#74baf5" />
 <rect width="300" height="300" fill="#f59674" mask="url(#m3)" />
</svg>

次に、このグラデーションのマスクをテキストにかけてみます。

TSUDOI
HTML
<svg width="300" height="300"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 <defs>
  <linearGradient id="gr2" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="300" y2="0">
   <stop offset="0" stop-color="#fff" stop-opacity="0" />
   <stop offset="0.5" stop-color="#fff" stop-opacity="1" />
   <stop offset="1" stop-color="#fff" stop-opacity="0" />
  </linearGradient>
  <mask id="m4" maskUnits="userSpaceOnUse" x="0" y="0" width="300" height="300">
   <rect x="0" y="0" width="300" height="300" fill="url(#gr2)">
  </mask>
  <text id="txt" x="0" y="176" font-family="Verdana" font-size="72">TSUDOI </text>
 </defs>
 <rect width="300" height="300" fill="#74baf5" />
 <use xlink:href="#txt" fill="#f59674" mask="url(#m4)" />
</svg>

面白そうなことができそうですね、、、とりあえず今回はmask要素の使い方ということで、次は使用できる属性についてまとめていきます。

maskUnits=”userSpaceOnUse”

marker要素でも出てきた座標系の定義についてです。
maskUnits属性は、mask要素に対して定義されます。
“userSpaceOnUse”を指定した場合は、mask要素を使用している要素に対する座標が基準となります。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m5" maskUnits="userSpaceOnUse" x="0" y="0" width="150" height="150">
   <circle cx="150" cy="150" r="140" fill="#fff">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#f59674" />
 <circle cx="150" cy="150" r="150" fill="#74baf5" mask="url(#m5)" />
</svg>

maskUnits=”objectBoundingBox”

maskUnits属性に、”objectBoundingBox”を指定した場合は、マスク要素を使用している要素の比率で設定します。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m6" maskUnits="objectBoundingBox" x="0" y="0" width="0.5" height="0.5">
   <circle cx="150" cy="150" r="140" fill="#fff">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#f59674" />
 <circle cx="150" cy="150" r="150" fill="#74baf5" mask="url(#m6)" />
</svg>

比率で設定するため、mask要素のwidth属性、height属性には”0.5″が設定されています。
これは、mask要素が使用されている要素であるcircle要素に対し、mask要素のサイズを半分にするためです。

maskContentUnits=”userSpaceOnUse”

maskContentUnits属性は、mask要素の内容に対して設定する属性です。
属性の値は、maskUnits属性と同様”userSpaceOnUse”と”objectBoundingBox”で、意味も同様です。

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m7" maskContentUnits="userSpaceOnUse" x="0" y="0" width="300" height="300">
   <circle cx="150" cy="150" r="70" fill="#fff">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#f59674" />
 <circle cx="150" cy="150" r="150" fill="#74baf5" mask="url(#m7)" />
</svg>

maskContentUnits=”objectBoundingBox”

HTML
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <defs>
  <mask id="m8" maskContentUnits="objectBoundingBox" x="0" y="0" width="300" height="300">
   <circle cx="0.5" cy="0.5" r="0.24" fill="#fff">
  </mask>
 </defs>
 <circle cx="150" cy="150" r="150" fill="#f59674" />
 <circle cx="150" cy="150" r="150" fill="#74baf5" mask="url(#m8)" />
</svg>