フーノページ



SVG feBlend

SVG、feBlendで色をブレンドする。








syntax。


<filter id = "「「5filtername」」">
    <feBlend in = "" in2 = ""
    mode = "「「1normal|multiply|screen|darken|lighten」」"
    />   
</filter> 


ブレンドとは。


こんにちは、「ふ」です。
SVGのフィルターシリーズ、今回はブレンドモードを指定する<feBlend>について紹介します。

CGにおける「ブレンド」とは、2つの要素が重なり合った部分の色を、指定した法則でブレンドさせて、特殊な表現を生み出す手法です。
SVGのフィルターにもこの機能が用意されており、今回とりあげる<feBlend>を使うことで実現します。

当記事では2つの色がどのようにブレンドされているのか、その仕組みとともに解説していきます。SVGのみならずコンピュータグラフィック全般においても、役立つ知識が得られます🎵


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





要素を配置。


<feBlend>の様子を観察するための、要素を準備しましょう。

<svg viewBox="0 0 400 300">

    <circle cx="250" cy="150" r="85"
        fill = "rgb(150,100,240)"/>

    <circle cx="150" cy="150" r="85" 
        fill = "fill:rgb(200,240,80)"/>

</svg>


重なり合った円を配置しました。
両方の円をフィルターコンテナに取り込むため、背面の紫をフィルターを掛ける元ソースとし、前面の黄緑を<defs>要素にして定義化、<feImage>として取り込むようにします。

<svg viewBox="0 0 400 300">

    <circle cx="250" cy="150" r="85"
        fill = "rgb(150,100,240)" filter = "url(「「5#blend01」」)"/>
    <defs>
        <circle id = "「「2yellowgreen」」" cx="150" cy="150" r="85" 
            fill = "fill:rgb(200,240,80)"/>
    </defs>
    
    <filter id = "「「5blend01」」" filterUnits = "userSpaceOnUse" 
        width = "100%" height = "100%" x = "0" y = "0">
        <feImage href = "#「「2yellwgreen」」" result = "「「5yellowgreen」」"/>
    </filter>

</svg>

フィルターコンテナの中で紫の円を「SourceGraphic」、黄緑の円を「yellowgreen」として取り込めるようにしています。
<feImage>フィルターについては、⬇︎の記事を参考にしてください。

SVGのfeImageフィルター。

〽️ 外部画像をフィルターで合成。




normal。


<feBlend in = "" in2 = ""
    mode = "「「1normal|multiply|screen|darken|lighten」」"/>    

準備ができたので、<feBlend>を試しましょう。
feBlendではin、in2属性で2つのソースを呼び出し、mode属性でブレンドの種類を指定します。

mode属性の値は5種類あります。ひとまづは「normal」から。このモードでは色のブレンドを起こすことなく、そのまま表示されます。

<filter id = "blend01" filterUnits = "userSpaceOnUse" 
        width = "100%" height = "100%" x = "0" y = "0">
        
        <feImage href = "#yellwgreen" result = "「「1yellowgreen」」"/>
        
        <feBlend in = "「「5yellowgreen」」" in2 = "SourceGraphic" 
        mode = "「「1normal」」"/>
</filter>

<feBlend>でin属性に黄緑の円、in2属性に元ソースである紫の円を呼び出します。
そしてmode属性に「normal」を指定。

結果⬆︎です。
モードを「normal」としているので、2つの円はフツーに重なっているだけです。このあと、ほかのモード値も試していきます。




lighten/darken。



lighten/darkenは、要素2つのRGBのうち、値が大きい/小さいほうを採用して重なり部分の色とします。



lighten。


lightenは双方の値の大きいほうを重なり部分に採用します。
RGB値が大きくなるので、交差部分は明るくなります。

 <feBlend in = "yellowgreen" in2 = "SourceGraphic" 
        mode = "「「1lighten」」"/>

交差部分が明るくなりました。



darken。


darkenは逆に値の小さいほうを採用。
重なり部分は暗くなります。

 <feBlend in = "yellowgreen" in2 = "SourceGraphic" 
        mode = "「「1darken」」"/>

暗くなりましたね。




multiply/screen。


multiply/screenでは2つのRGB値から特定の式によって算出されたものを、重なり部分のRGB値として採用します。

RGBは通常、0〜255の範囲で表現されますが、計算を行う際にはこれを0〜1の範囲に直して(正規化して)計算します。


方法は簡単です。各RGB値を255で割るだけです。たとえばR = 200なら、200/255でおよそ0.78となります。



multiply。


result = A*B

multiplyは「乗算」という意味です。
双方のRGB値を掛け合わせたものが、結果色として採用されます。



multiplyは正規化したそれぞれのRGBを掛け合わせて、結果色のRGB値を算出します。これを0〜255の範囲に戻すとおよそR:115 G:93 B:80となります。
1以下の数値を掛け合わせているので結果は元の数値より小さくなる、つまり暗い色になります。

 <feBlend in = "yellowgreen" in2 = "SourceGraphic" 
        mode = "「「1multiply」」"/>

結果⬆︎です。darkenのときと近いものになりました。



screen。


result = A+B-AB

screenの計算式は少し複雑。AとBの和からAとBの積を引いたものが結果となります。



詳しい証明は省きますが、結果は常に元のAやBより大きい値となります。つまり明るい色になります。

 <feBlend in = "yellowgreen" in2 = "SourceGraphic" 
        mode = "「「1screen」」"/>

交差部分がかなり明るくなりました。




画像と重ねてみる。


4種類のモードをみてきました。明るい/暗いで分けると、

明るくなる系: lighten、screen
暗くなる系: darken、multiply

となりますが、lighten/darkenはややマイルドな色の変化、それに比べてscreen/multiplyは変化が大きいように見えますね。実際の場面ではどのように使い分ければいいのか?

これまでは単色の要素同士を重ねて試してきましたが、風景画像と掛け合わせてみましょう。


<svg viewBox="0 0 841.89 595.28" >
<style type="text/css">
	.st1{fill:#DEDB47;}
</style>
    
<filter id = "img_back" filterUnits = "userSpaceOnUse">
    <feImage href = "yama.png" result = "yama"></feImage> 
    <feBlend in2 = "yama" in = "SourceGraphic" mode = "normal"/>
</filter>
    
<g filter = "url(#img_back)">
	<path class="st1" d="M305.59,255.19v0.79c-0.31,17.28-5.81,30.78-16.02,40.99c-15.86,14.92-42.09,22.46-78.68,21.67h-0.47v-16.96
		h0.47c11.31,0.79,46.01,2.83,65.17-14.45c8.32-7.7,12.72-18.22,12.72-31.72c0.31-18.37-15.39-32.98-15.39-32.98l-3.61-3.14
		l0.79-4.71c3.14-18.06,1.26-31.09-4.71-38.16c-6.6-7.85-18.06-7.38-23.87-7.38h-20.1v41.15h33.45v16.65h-33.45v67.69h-16.96V152.49
		l36.59-0.31c7.54,0,25.13-0.31,37.06,13.35c7.07,7.85,10.21,18.85,10.21,33.45c0,3.93,0,8.64-0.79,14.13
		C294.6,220.64,305.59,235.56,305.59,255.19z"/>
	<path class="st1" d="M341.71,152.33v141.65h-16.8V152.33H341.71z"/>
	<path class="st1" d="M420.71,200.7c11.31,3.14,21.2,10.99,27.01,21.99c5.5,9.74,5.5,19.63,5.5,23.87l-0.31,8.32h-57.79v-16.96
		h40.52c-0.47-2.67-1.26-5.03-2.36-7.38c-3.93-7.07-9.89-11.78-16.96-13.82c-7.85-1.88-16.8-0.31-24.66,4.4
		c-13.82,8.95-17.75,27.8-8.64,41.93c7.07,11.78,18.06,16.02,34.86,14.13c0,0,11.78-2.04,21.99-11.78l11.78,11.78v0.31
		c-14.13,13.82-30.94,16.17-31.72,16.17c-23.24,2.67-40.52-4.4-51.51-21.67c-13.66-21.83-7.38-51.35,14.13-65.02
		C394.32,199.91,408.14,197.56,420.71,200.7z"/>
	<path class="st1" d="M543.36,237.92v56.06H526.4v-56.06c0-8.95-1.88-14.92-6.6-18.06c-9.11-5.81-26.38-1.1-32.19,1.57h-0.47v72.55
		h-16.8v-93.75h16.8v3.61c9.89-3.14,28.27-7.07,42.09,1.88C538.65,212,543.36,223,543.36,237.92z"/>
	<path class="st1" d="M636.96,152.33v141.65H609.8c-16.02,0-46.64-9.42-48.68-45.86c-1.1-19.94,6.75-44.29,49.47-47.9v16.96
		c-29.84,2.36-33.29,16.02-32.51,30.15c1.57,29.05,28.58,29.84,31.72,29.84H620V152.33H636.96z"/>
</g>
</svg>


◾️ normal

山の写真に「Blend」のロゴを配置しました。
現在modeはnormalで、そのまま重なっている状態です。

◾️ lighten

lightenを使ってみました。
テキストロゴの上半分が背景に溶け込み、ほとんど見えなくなっています。

◾️ screen

screenです。
交差部分が明るくなっていますが、lighenのときよりもロゴの輪郭がはっきりしています。

◾️ darken

今度は暗くなる系の2つを比べてみましょう。darkenが⬆︎です。

◾️ multiply

multiply⬆︎です。
darkenのときよりもテキストロゴの輪郭がはっきりしています。

ここまでみてくると、

lighten/darken :背景に溶け込みやすい
screen/multiply :ブレンドしても輪郭がはっきりとする

といった感じでしょうか。
みなさんも色々と実験してみてください。

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




「ふ」です。

ふ

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