フーノページ



SVG feTurbulence

SVG、feDisplacementMap〜波形を要素にマッピング。










SVGフィルター、使い方。

〽️ SVGフィルターのまとめ記事はコチラ。


syntax。


<filter id = "「「5filtername」」">

    <feDisplacementMap
        in = "マップされる側のソース" 
        in2 = "マップに使うソース" 
        scale = "ずらし量"
        
        「「3<!--水平方向に使用するRGBA成分-->」」
        xChannelSelector = "A|R|G|B" 
        「「3<!--垂直方向に使用するRGBA成分-->」」
        yChannelSelector = "A|R|G|B"
        />
        
</filter>


RGBAの変化をマッピング。


こんにちは、「ふ」です。
SVGのフィルターシリーズ、今回は<feDisplacementMap>について紹介します。
<feDisplacementMap>は、要素に対して外部ソースのR/G/B/A チャンネルの変位を反映させる効果があります。


⬆︎は黒→青のグラデーション。これを外部ソースとし、RGBAのうち、Bチャンネル(青成分)の変位を反映させている様子です。
青成分の変位に応じるように、画像のピクセルに「ずれ」が発生しています。

SVGのような2Dグラフィックにおけるディスプレイスメントマップとは、要素のピクセルを「ずらす」ことによって、オブジェクトの歪みや波形効果を表現する手法のことを指します。その「ずらし形状」は、与えられる外部ソースのR/G/B/Aの変位がもととなります。

<feDisplacemantMap>を使えば、グラフィックソフトを使ったような特殊効果を、コーディングによって実装することができます。
使い方には少し複雑な部分もありますが、挑戦してみてください。


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





基本セット。


<feDisplacementMap
    in = "source"
    in2 = "source"
    scale = "num"
    xChannelSelector = "A|R|G|B"
    yChannelSelector = "A|R|G|B"
/>

<feDisplacementMap>のプロパティには次のものがあります。

・ in :マップされる側のソース、in2 :ずらし形状として使う外部ソース
in属性にずらしたい画像、in2属性にずらしの元となるグラデーションやノイズなどを指定します。

・ scale :ピクセルのずらし具合
scale属性はピクセルのずらしの大きさを数値で指定します。数値が大きいほど、マップされる側のソースの変形も大きくなります。
scaleの初期値は0となっており、指定なしだと要素はまったく変化しません

・ x/yChannelSelector
feDisplacementMapでは、in2のソースにあるR/G/B/A成分のいづれかを選んでin1にマップさせます。x/y方向において、それぞれどの成分を選択するかを指定するのが、このプロパティです。
初期値はいづれも「A(不透明度)」に指定されています。



ノイズをマップする。

<feDisplacementMap>、定番のつかいどころは <feTurbulence> で作ったノイズをマップさせる というものです。

<svg viewBox = "0 0 100 100">
    <circle cx = "50%" cy = "50%" r = "25" 
    fill = "palevioletred"
    filter = "url(「「5#filter01」」)"
    />    
</svg>

こちらの円オブジェクトに、ノイズをマップしてみましょう。
要素には、これから作っていく「filter01」を予め参照させています。

<svg viewBox = "0 0 100 100">
    <circle cx = "50%" cy = "50%" r = "25" 
    fill = "palevioletred"
    filter = "url(「「5#filter01」」)"
    /> 
    
    <filter id = "「「5filter01」」">
        <feTurbulence type = "fractalNoise" 
        baseFrequency = "0.1" result = "「「4noise」」"/>
    </filter> 
</svg>

<feTurbulence>でノイズを掛けた状態です。<feDisplacementMap>に結果を渡せるよう、result属性に「noise」と名前をつけておきました。

<feTurblence>フィルターに関しては、⬇︎の記事を参考にしてください。

SVG、feTurbulenceでノイズ発生。

〽️ SVGフィルターの大ボス。


<svg viewBox = "0 0 100 100">
    <circle cx = "50%" cy = "50%" r = "25" 
    fill = "palevioletred"
    filter = "url(#filter01)"
    /> 
    
    <filter id = "filter01">
        <feTurbulence type = "fractalNoise" 
        baseFrequency = "0.1" result = "「「4noise」」"/>
        
        <「「1feDisplacementMap」」 
            in = "SourceGraphic" 
            in2 = "「「4noise」」" 
            scale = "5"
        />
    </filter> 
</svg>

<filter>コンテナの中に、<feDisplacementMap>を追加します。

・in属性には元オブジェクトを指す「SourceGraphic」を指定。
・<feTurbulence>のresult名「noise」をin2に指定することで、ノイズの結果を渡しています。
・scale(ずらし量)を「5」としました。scale属性の初期値は「0(ずらしなし)」となっているので、必ず指定するようにしましょう。
・なお、x/yのchannelSelectorは初期値のままにしておきました。

結果⬆︎。円オブジェクトにノイズがマップされ、歪みました。

<filter id = "filter01">
    <feTurbulence type = "fractalNoise" 
    baseFrequency = "0.1" result = "noise"/>
        
    <feDisplacementMap 
        in = "SourceGraphic" 
        in2 = "noise" 
        scale = "「「150」」"
    />
</filter> 

scaleを「50」と、大幅に上げてみます。

激しくノイズが掛かりました。




HTML要素にマップ。


HTML内部にインラインで記述したSVGフィルターは、テキストや画像などの通常要素にも施すことができます。

<img>にマップ。


<body>
    <img src = "neko.jpeg">
</body>

🔸 neko.jpeg
「neko.jpeg」を用意しました。
今日のご飯をあげるその前に、<feDisplacementMap>の実験台になってもらいます。

<body>
<svg style = "position:fixed;">
    <filter id = "「「5filter02」」">
    <feTurbulence type = "fractalNoise" baseFrequency = "0.1" result = "noise"/>
    <feDisplacementMap in = "SourceGraphic" in2 = "noise" scale = "50"/>
    </filter>
</svg>

<img src = "neko.jpeg" style = "filter:url(「「5#filter02」」)">

</body>

インラインで記述した「ノイズ→マップ」のフィルターを、<img>のCSSで呼び出します。



<img>要素にもノイズをマップすることができました。



テキストにマップ。


<p style = "font-size:300%;font-weight:bold;">
限界    
</p>

限界

今度はテキスト⬆︎にもマップしてみましょう。

<filter id = "「「5filter03」」">
<feTurbulence baseFrequency = "0.5" result = "noise"/>
<feDisplacementMap in = "SourceGraphic" in2 = "noise" 
scale = "20"/>
</filter>
<p style = "font-size:300%;font-weight:bold;
filter:url(「「5#filter03」」);">
限界    
</p>

限界

限界文字ができました。




グラデーションをマップ。


<feDisplacementMap>では、SVGで作ったグラデーションをマップさせることもできます。ただしグラデーション画像を<filter>コンテナへ取り込む際には、画像をdataURI化させるという作業が必要となります。

dataURI化?

datrURIとは、HTMLファイルに画像データを直接記述する手法です。外部urlを使って画像を呼び出す必要がないため、ページパフォーマンスの向上につながります。
SVGのバヤイはそのデータをHTML内に直接記述することができるので、dataURI化してもあまり意味はありません。が、<feDisplacementMap>にグラデーション画像を渡すときは、dataURI形式に変換しないと、Chromeをはじめとしたブラウザはレンダリングしてくれないのです。

⬆︎は、#000→#00f→#000→#00f...と、完全な黒からG成分maxを交互に繰り返す、円形グラデーションです。これをdataURI形式に変換し、マップさせてみましょう。

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink" 
viewBox="0 0 100 100">
    <radialGradient id = "grad01" spreadMethod = "reflect">
    <stop offset = "0" style = "stop-color:#000;"/>
    <stop offset = "0.5" style = "stop-color:#0f0;"/> 
    <stop offset = "0.75" style = "stop-color:#000;"/>
    <stop offset = "1" style = "stop-color:#0f0;"/> 
    </radialGradient>

    <rect width = "100%" height = "100%" fill = "url(#grad01)"/>
</svg>

円形グラデーション画像のコード⬆︎です。
<svg>の開始タグには「xmlns(名前空間)属性」を含めるようにしてください。

SVG→dataURI変換。

〽️ SVGをdataURIに変換。

dataURI変換ツール⬆︎を用意しました。こちらでコードを変換させます。

data:image/svg+xml;utf8,%0A%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20viewBox%3D%220%200%20100%20100%22%3E%0A%20%20%20%20%3CradialGradient%20id%20%3D%20%22grad01%22%20spreadMethod%20%3D%20%22reflect%22%3E%0A%20%20%20%20%3Cstop%20offset%20%3D%20%220%22%20style%20%3D%20%22stop-color%3A%23000%3B%22%2F%3E%0A%20%20%20%20%3Cstop%20offset%20%3D%20%220.5%22%20style%20%3D%20%22stop-color%3A%230f0%3B%22%2F%3E%20%0A%20%20%20%20%3Cstop%20offset%20%3D%20%220.75%22%20style%20%3D%20%22stop-color%3A%23000%3B%22%2F%3E%0A%20%20%20%20%3Cstop%20offset%20%3D%20%221%22%20style%20%3D%20%22stop-color%3A%230f0%3B%22%2F%3E%20%0A%20%20%20%20%3C%2FradialGradient%3E%0A%0A%20%20%20%20%3Crect%20width%20%3D%20%22100%25%22%20height%20%3D%20%22100%25%22%20fill%20%3D%20%22url(%23grad01)%22%2F%3E%0A%3C%2Fsvg%3E%0A

dataURIに変換したコードがこちら⬆︎。
<feImage>として、フィルターコンテナに取り入れます。

<svg style = "position:fixed">
<filter id = "filter04" >
<feImage href = '「「2data:image/svg+xml;utf8,%0A%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20viewBox%3D%220%200%20100%20100%22%3E%0A%3CradialGradient%20id%20%3D%20%22grad01%22%20spreadMethod%20%3D%20%22reflect%22%3E%0A%3Cstop%20offset%20%3D%20%220%22%20style%20%3D%20%22stop-color%3A%23000%3B%22%2F%3E%0A%3Cstop%20offset%20%3D%20%220.5%22%20style%20%3D%20%22stop-color%3A%230f0%3B%22%2F%3E%20%0A%3Cstop%20offset%20%3D%20%220.75%22%20style%20%3D%20%22stop-color%3A%23000%3B%22%2F%3E%0A%3Cstop%20offset%20%3D%20%221%22%20style%20%3D%20%22stop-color%3A%230f0%3B%22%2F%3E%20%0A%3C%2FradialGradient%3E%0A%0A%3Crect%20width%20%3D%20%22100%25%22%20height%20%3D%20%22100%25%22%20fill%20%3D%20%22url(%23grad01)%22%2F%3E%0A%0A%3C%2Fsvg%3E%0A」」' 
result = "「「5uzu」」"/>
<feDisplacementMap 
in = "SourceGraphic" in2 = "「「5uzu」」" scale = "40" 
xChannelSelector = "G" yChannelSelector = "G"/>    
</filter>    
</svg>

<feImage>のhref属性に、dataURIのコードを貼り付け。result名を「uzu」とし、<feDisplacementMap>に渡します。
グラデーションはG成分の変化なので、x/yのchannelSelectorを「G」に指定。

<svg class = "samp_svg" viewBox = "0 0 100 100">
    <image href = "neko.jpeg" 
    width = "100%" height = "100%" 
    preserveAspectRatio = "xMidYMid slice"/>
</svg>

<svg>の中で、<image>要素によって画像を取り込んだもの。
グラデーションマップのフィルターを掛けてみましょう。

<svg class = "samp_svg" viewBox = "0 0 100 100">
    <image href = "neko.jpeg" 
    width = "100%" height = "100%" 
    preserveAspectRatio = "xMidYMid slice"
    「「1filter = "url(#filter04)"」」/>
</svg>

渦巻きグラデーションがマップされました。




ChannelSelectorを試す。


先ほど使ったグラデーションは、G成分が0〜255を繰り返すものでしたので、効果が出やすいようにChannelSelectorをx/yともに「G(green)」としていました。

ちなみにこのグラデーションでは、R及びB成分はずっと0のままです。また不透明度であるA成分は「1(完全不透明)」のまま。
つまりG成分以外は終始、変位を起こしていません。

xChannelSelector = "A|R|G|B"
yChannelSelector = "A|R|G|B"

xおよびyのchannelSelectorは、マップさせる水平/垂直方向のチャンネルを指定するものです。
変位を起こしていないG成分以外のチャンネルを指定すると、どうなるのでしょうか?初期値の「A」を指定してみます。

<feDisplacementMap 
in = "SourceGraphic" in2 = "uzu" scale = "40" 
xChannelSelector = "「「1A」」" yChannelSelector = "「「1A」」"/>    
</filter>    

不透明度であるAチャンネルはグラデーションの中では常に一定です。そのため、画像はまったく歪んでいません。ただし全体がすこし「ずれ」を起こしました。
今度はRチャンネルを試してみましょう。

<feDisplacementMap 
in = "SourceGraphic" in2 = "uzu" scale = "40" 
xChannelSelector = "「「1R」」" yChannelSelector = "「「1R」」"/>    
</filter>    

Aチャンネルのときと対角方向にずれが発生しました。そして若干ではありますが、歪みを起こしています。

<feDisplacementMap 
in = "SourceGraphic" in2 = "uzu" scale = "40" 
xChannelSelector = "「「1A」」" yChannelSelector = "「「1G」」"/>    
</filter>    

x方向のチャンネルを「A」に、y方向のチャンネルを変位のはげしい「G」にしてみました。

その結果。 Aチャンネルを採用したx方向にだけ「ずれ」が発生し、y方向に指定したG成分によって渦巻いています。

以上のことから、「変位のないチャンネルを選択しても歪みはわずかだが、『ずれ』は発生する」ようです。




試行錯誤が必要。


最後までお読みくださり、 ありがとうございました。
今回は<feDisplacementMap>について紹介しました。トリッキーな効果が期待できる反面、思い通りの結果にするためには試行錯誤が必要になってくるでしょう。特にchannelSelectorによる「ずれ」の発生には気をつけたいものです。

各属性をいじって、少しずつ試していくようにしてくださいね。

ではまた〜 🎵




「ふ」です。

ふ

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