フーノページ



SVG feComposite

SVG、feCompositeで要素を切り抜き。








syntax。

<filter id = "「「5composite」」" filterUnits = "userSpaceOnUse">

    <feImage href = "〇〇.png" 
    width = "100%" x = "0" result = "「「5source2」」"/>
    
    <feComposite in = "SourceGraphic" in2 = "「「5source2」」" 
    operator = "「「1over|in|out|atop|xor|lighter|arithmetic」」"/>
    
</filter>
#element {
    filter:url(「「5#composite」」);
}


SVGでパスファインダー?


こんにちは、「ふ」です。
SVGのフィルターシリーズ、今回は重なった要素の好きな部分を切り取ることのできる、feCompositeを紹介します。

SVG要素同士の切り抜き
feCompositeは、重ね合った要素において交差している部分/していない部分、それぞれの領域の表示/非表示を自在にコントロールすることができるフィルターです。
ベクターグラフィックソフトのパスファインダーのようなことがSVGでできてしまうんです。



このたびSVGの書籍を出版しました。
しっかりとしたSVGスキルが身に付く内容となっています。参考にしてください。





feComposite内で要素を重ねる。


SVGで文字と、波型のパスを作りました。双方を重ねて色々切り取ってみたいと思います。がその前に。

feCompositeを試すためには、重ねる要素それぞれを「filterコンテナの中で扱えるソースにする」作業が必要です。

feImageフィルターを使えば、result属性でfilter部品として合成できるようになります。
文字と波型のうち、波型部分を読み込みイメージ、文字部分を元ソースとして扱えるようにしていきましょう。

<svg viewBox="0 0 841.89 595.28" >

    「「3<!-- 波型のパスデータ -->」」
    <path id="「「5nami」」" d="...."/>   
    
    「「3<!-- 文字のパスデータ -->」」
    <g id="「「5moji」」">
        <path d="...."/>
        <path d="...."/>
        <path d="...."/>
        <path d="...."/>
    </g>

</svg>

こちら⬆︎が現在のコード。波型部分のパスと文字部分のパスデータには、それぞれ「nami」「moji」とid名を付けて呼び出せるようにしています。

    「「3<!-- 波型のパスデータ -->」」
    「「1<defs>」」
    <path id="nami" d="...."/> 
    「「1</defs>」」
    
    「「3<!-- 文字のパスデータ -->」」
    <g id="moji">
        <path d="...."/>
        <path d="...."/>
        <path d="...."/>
        <path d="...."/>
    </g>

波型部分を<defs>〜<defs>で囲みます。
<defs>で囲まれた要素は、ただの「定義された要素」という扱いになり、呼び出すまでは実際に描画されることはありません。

filterコンテナを作成し、波型部分をfeImageで呼び出してみましょう。

<filter id = "「「1composite」」" filterUnits = "userSpaceOnUse">

    <feImage href = "「「5#nami」」" width = "100%" height = "100%"
    x = "0" y = "0" result = "「「4nami」」"/>
    
</filter>

filterコンテナを定義し、id名を「composite」としました。

feImage要素で波型部分のidを呼び出しています。そしてresult属性に「nami」と指定しました。このresultに指定した名前を使って、合成用フィルターでfeImageの結果を呼び出すことができます。
文字部分に、定義したfilterを掛けてみましょう。

#moji {
    filter:url(「「1#composite」」);
}

結果⬆︎です。
元のSVG要素はまだfilterコンテナに取り込んでいないので、貼り付けた波型部分だけが表示されている状態です。
ここからfeCompositeを使って、文字部分つまり元のソースも表示させましょう。

<filter id = "composite" filterUnits = "userSpaceOnUse">

    <feImage href = "#nami" width = "100%" height = "100%" 
    x = "0" y = "0" result = "「「4nami」」"/>
    
    <feComposite in = "「「1SourceGraphic」」" in2 = "「「4nami」」"/>
    
</filter>

feCompositeにはin属性、in2属性があります。重ねたい要素を、それぞれの属性値に指定します。

inには文字部分(フィルターを掛けられた元のソース)を呼び出したいので「SourceGraphic」と指定。
先ほどfeImageで取り込んだものにはresult属性で「nami」という名前を付けていました。これをin2に指定します。

元のSVG画像と見た目は変わりませんが、テキスト部分と波部分がfeComposite内で重ねられています。
このあとoperator属性で、色々な切り取りを試していきましょう。



コピぺ用。

ここまでのフルコードを貼っておきます⬇︎。

<svg viewBox="0 0 841.89 595.28">

<style type="text/css">
	.st0{fill:#ED9E00;}
	.st1{fill:#00E0A1;}
</style>

<defs>
「「3<!-- 波型のパスデータ -->」」
<path id="nami" class="st1" d="M738.96,369.38c-76.06,0-117.23-21.06-147.3-36.43c-23.15-11.84-34.77-17.78-64.71-17.78
	c-29.95,0-41.57,5.94-64.71,17.78c-30.06,15.38-71.24,36.43-147.3,36.43s-117.23-21.06-147.3-36.43
	c-23.15-11.84-34.76-17.78-64.71-17.78V225.9c76.06,0,117.23,21.06,147.3,36.43c23.15,11.84,34.76,17.78,64.71,17.78
	c29.95,0,41.57-5.94,64.71-17.78c30.06-15.38,71.24-36.43,147.3-36.43s117.23,21.06,147.3,36.43
	c23.15,11.84,34.77,17.78,64.71,17.78V369.38z"/>     
</defs>

「「3<!-- 文字のパスデータ -->」」    
<g id="moji" filter = "url(#composite)">
	<path class="st0" d="M293.23,224.99c-5.57-3.54-17.72-8.86-33.92-8.86c-26.83,0-36.96,16.45-36.96,30.38
		c0,18.99,11.65,28.6,37.47,39.49c31.14,13.16,47.08,29.11,47.08,56.7c0,30.63-22.28,54.17-63.79,54.17
		c-17.47,0-36.45-5.32-46.07-12.15l5.82-17.47c10.38,6.83,25.82,11.9,41.52,11.9c25.82,0,41.01-13.92,41.01-34.68
		c0-18.99-10.38-30.63-35.44-40.76c-29.11-10.89-48.86-27.85-48.86-54.43c0-29.36,23.8-50.88,58.98-50.88
		c18.23,0,32.15,4.56,39.49,9.11L293.23,224.99z"/>
	<path class="st0" d="M469.93,201.19l-66.32,192.9h-22.28l-61.01-192.64h22.78l29.62,96.7c8.1,26.07,15.19,50.38,20.25,72.91h0.76
		c5.06-22.53,12.91-47.59,21.52-72.91l32.15-96.95L469.93,201.19L469.93,201.19z"/>
	<path class="st0" d="M628.39,386.24c-10.38,4.05-30.63,9.87-54.93,9.87c-75.69,0-93.66-56.45-93.66-97.21
		c0-58.73,38.22-99.49,98.73-99.49c18.48,0,34.93,3.54,44.55,8.1l-5.57,17.47c-9.37-4.3-21.52-7.85-39.49-7.85
		c-45.57,0-76.2,29.36-76.2,80.5c0,52.15,29.11,81.26,73.16,81.26c16.2,0,27.09-2.53,32.66-5.57v-61.77h-38.98V294.6h59.74
		L628.39,386.24L628.39,386.24z"/>
</g>

    
<filter id = "composite" filterUnits = "userSpaceOnUse">
<feImage href = "#nami" width = "100%" height = "100%" x = "0" y = "0" result = "nami"/> 
<feComposite in = "SourceGraphic" in2 = "nami"/>
</filter>

</svg>



operatorを指定して切り抜き。


<feComposite in = "" in2 = "" 
operator = "「「1over|in|out|atop|xor|lighter|arithmetic」」"/>

重なり合った要素は、3つの領域に分類することができます。

 @1@ inのみの部分
 @2@ in2のみの部分
 @3@ inとin2が重なり合っている部分(&&)

feCompositeのoperator属性は、これら3つの領域に対しての操作を行います。



over。

「over」はinとin2両方を表示させますが、重なり部分(&&)においてはinのほうを表示させます。

<feComposite in = "SourceGraphic" in2 = "nami" 
    「「1operator = "over"」」/>

feCompositeのover 重なり領域には、inである文字部分が表示されています。
inとin2に読み込ませるソースを入れ替えてみましょう。

<feComposite 「「2in2」」 = "SourceGraphic" 「「2in」」 = "nami" 
    operator = "over"/>

重なり領域にはinに指定した、波型部分が表示されました。
結果的に、overは単なる「重なりの順序」を操作していることになりますね。



in。

operator属性の「in」は、重なり合った部分(&&)のみを表示させます。色に関してはinのものが採用されます。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "「「1in」」"/>

inをSourceGraphic、in2を元に戻しています。

feCompositeのin(交差) 交差部分のみが表示されました。



out。

「out」は、inの重なっていない部分のみを表示させます。in2の領域でinを切り取った形になります。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "「「1out」」"/>

feCompositeのout 文字部分が波型部分の領域で切り取られました。



atop。

「atop」はin2の領域内でのみ、inを表示させます。in2に含まれない部分は非表示となります。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "「「1atop」」"/>

feCompositeのatop inである文字部分のうち、in2と重なっている部分のみが表示されました。
ここで「over」のときのように、inとin2のソースを入れ替えてみましょう。

<feComposite 「「2in2」」 = "SourceGraphic" 「「2in」」 = "nami" 
    operator = "atop"/>

文字部分の中でのみ波型が表示され、ちょっとロゴのようになってきましたね。



xor。

「xor」は、交差部分をくりぬきます。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "「「1xor」」"/>

feCompositeのxor 交差部分が切り取られました。
背景画像を付けたくなりますね。



lighter。


「lighter」は、双方のRGBそれぞれから大きいほうの値を採用し、交差部分に新たな色を作り出します。


いま、inのRGB値は(0,160,233)で、in2は(228,0,127)となっています。Rが大きいのはin2のほう。GとBも比較して、大きかったほうが交差部分のRGB値に採用されます。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "「「1lighter」」"/>

feCompositeのxor 交差部分の色が生成されました。
RGBではその値が大きくなるほど、明るい色となります。「lighter」という名の意味がわかりましたね。



arithmetic。


<feComposite operator = "arithmetic"
    k1 = "" k2 = "" k3 = "" k4 = "" /> 


最後に紹介する「arithmetic」という値は、各領域の強弱を個別に指定するものです。
operatorを「arithmetic」とし、k1〜k4のプロパティを使って各エリアの値をそれぞれ指定します。

k1 :重なり部分
k2 :in
k3 :in2
k4 :全体

いま各領域の「強弱」という表現を使いましたが、実際には

k1*in*in2 + k2*in + k3*in2 + k4

という、ちょっぴり複雑な計算式でRGBA値が算出されます。
ただこれについて深く語ると長くなるので、別記事で詳しくお伝えすることにします。とりあへづ「各領域の強弱」という解釈で、arithmeticを十分に使いこなすことは可能です。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "「「1arithmetic」」"
    k1 = "0" k2 = "「「11」」" k3 = "「「11」」" k4 = "0"
/>

まづはデフォルト的な設定。
inのk2とin2のk3は等倍の「1」に指定。 交差部分のk1、全体のk2は付加的な効果を及ぼすので、今は「0」としておきます。

feCompositeのover 初期状態はこんな感じ。lighterのときと同じ状態になっています。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "arithmetic"
    k1 = "0" k2 = "1" k3 = "「「10.5」」" k4 = "0"
/>

波型部分in2を弱めてみます。
該当するのはk3、これを「0.5」としました。

feCompositeのover 波型部分が弱まり、文字部分の色味が強くなりました。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "arithmetic"
    k1 = "0" k2 = "1" k3 = "1" k4 = "「「10.5」」"
/>

全体を司るk4は、「1」に近づくにつれ完全不透明な白に向かっていきます。「0」から「0.5」に増やしてみましょう。

feCompositeのover 全体が薄く〜 つまり、白に近づきました。

<feComposite in = "SourceGraphic" in2 = "nami" 
    operator = "arithmetic"
    k1 = "「「14」」" k2 = "1" k3 = "1" k4 = "「「1-0.5」」"
/>

交差部分を担当するk1をいじってみます。
k1の値を「4」として、また効果を観察しやすいようk4を「-0.5」とし、全体のRGB値を下げています。

feCompositeのover 全体は暗い色になりましたが、交差部分はくっきり明るく表示されています。

さまざまな変化が楽しめるので、みなさんも色々と試してみてください。




「切り取り師」は極めるべき。


最後までお読みくださり、ありがとうございました。

今回はSVGのフィルター、feCompositeについて紹介してきました。面白い効果を得ることができますが、実装手順がやや複雑というのが難点でもあります。それゆえ簡単な切り抜きであれば、SVGの<mask>や<clipPath>を利用したほうが良いでしょう。
逆にマニアックな切り取りや変化を楽しみたいのであれば、今回のfeCompositeを極めてみてください(笑)

ではまた〜 🎵




「ふ」です。

ふ

ベクターグラフィック、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。