<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のフィルターシリーズ、今回は重なった要素の好きな部分を切り取ることのできる、feCompositeを紹介します。
feCompositeは、重ね合った要素において交差している部分/していない部分、それぞれの領域の表示/非表示を自在にコントロールすることができるフィルターです。
ベクターグラフィックソフトのパスファインダーのようなことがSVGでできてしまうんです。
このたびSVGの書籍を出版しました。
しっかりとしたSVGスキルが身に付く内容となっています。参考にしてください。
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>
<feComposite in = "" in2 = ""
operator = "「「1over|in|out|atop|xor|lighter|arithmetic」」"/>
重なり合った要素は、3つの領域に分類することができます。
@1@ inのみの部分
@2@ in2のみの部分
@3@ inとin2が重なり合っている部分(&&)
feCompositeのoperator属性は、これら3つの領域に対しての操作を行います。
「over」はinとin2両方を表示させますが、重なり部分(&&)においてはinのほうを表示させます。
<feComposite in = "SourceGraphic" in2 = "nami"
「「1operator = "over"」」/>
重なり領域には、inである文字部分が表示されています。
inとin2に読み込ませるソースを入れ替えてみましょう。
<feComposite 「「2in2」」 = "SourceGraphic" 「「2in」」 = "nami"
operator = "over"/>
重なり領域にはinに指定した、波型部分が表示されました。
結果的に、overは単なる「重なりの順序」を操作していることになりますね。
operator属性の「in」は、重なり合った部分(&&)のみを表示させます。色に関してはinのものが採用されます。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "「「1in」」"/>
inをSourceGraphic、in2を元に戻しています。
交差部分のみが表示されました。
「out」は、inの重なっていない部分のみを表示させます。in2の領域でinを切り取った形になります。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "「「1out」」"/>
文字部分が波型部分の領域で切り取られました。
「atop」はin2の領域内でのみ、inを表示させます。in2に含まれない部分は非表示となります。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "「「1atop」」"/>
inである文字部分のうち、in2と重なっている部分のみが表示されました。
ここで「over」のときのように、inとin2のソースを入れ替えてみましょう。
<feComposite 「「2in2」」 = "SourceGraphic" 「「2in」」 = "nami"
operator = "atop"/>
文字部分の中でのみ波型が表示され、ちょっとロゴのようになってきましたね。
「xor」は、交差部分をくりぬきます。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "「「1xor」」"/>
交差部分が切り取られました。
背景画像を付けたくなりますね。
「lighter」は、双方のRGBそれぞれから大きいほうの値を採用し、交差部分に新たな色を作り出します。
いま、inのRGB値は(0,160,233)で、in2は(228,0,127)となっています。Rが大きいのはin2のほう。GとBも比較して、大きかったほうが交差部分のRGB値に採用されます。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "「「1lighter」」"/>
交差部分の色が生成されました。
RGBではその値が大きくなるほど、明るい色となります。「lighter」という名の意味がわかりましたね。
<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」としておきます。
初期状態はこんな感じ。lighterのときと同じ状態になっています。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "arithmetic"
k1 = "0" k2 = "1" k3 = "「「10.5」」" k4 = "0"
/>
波型部分in2を弱めてみます。
該当するのはk3、これを「0.5」としました。
波型部分が弱まり、文字部分の色味が強くなりました。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "arithmetic"
k1 = "0" k2 = "1" k3 = "1" k4 = "「「10.5」」"
/>
全体を司るk4は、「1」に近づくにつれ完全不透明な白に向かっていきます。「0」から「0.5」に増やしてみましょう。
全体が薄く〜 つまり、白に近づきました。
<feComposite in = "SourceGraphic" in2 = "nami"
operator = "arithmetic"
k1 = "「「14」」" k2 = "1" k3 = "1" k4 = "「「1-0.5」」"
/>
交差部分を担当するk1をいじってみます。
k1の値を「4」として、また効果を観察しやすいようk4を「-0.5」とし、全体のRGB値を下げています。
全体は暗い色になりましたが、交差部分はくっきり明るく表示されています。
さまざまな変化が楽しめるので、みなさんも色々と試してみてください。
最後までお読みくださり、ありがとうございました。
今回はSVGのフィルター、feCompositeについて紹介してきました。面白い効果を得ることができますが、実装手順がやや複雑というのが難点でもあります。それゆえ簡単な切り抜きであれば、SVGの<mask>や<clipPath>を利用したほうが良いでしょう。
逆にマニアックな切り取りや変化を楽しみたいのであれば、今回のfeCompositeを極めてみてください(笑)
ではまた〜 🎵
ベクターグラフィック、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。