[SVG] filter 要素の基本的な使い方と filter 要素をつかったモノクロからカラーへ変化するマウスオーバー効果を作る方法
この記事は SVG Advent Calendar 2014 の2日目の記事です。前日の記事は、t_motooka さんの「clip と transform との組み合わせ – 職業プログラマの休日出勤」でした。
SVG の filter 要素を使うとどんなことができるのかという基本的なことと、filter 要素を使ったわりと簡単にできるマウスオーバー効果の作り方をご紹介します。
filter 要素でどんなことができるのか
filter 要素では SVG 内の画像をぼかしたり、色相を変えたりするようなフィルターを作ることができます。
ただ、filter 要素単独でフィルターを作る訳ではなく、原始フィルター(フィルターの効果を定義するようなもの?)と呼ばれる要素を子要素として記述しセットで使います。
原始フィルター要素は、feGaussianBlur(ぼかし)・feColorMatrix(明度の変更)・feBlend(画像を混ぜあわせる)など、ここでは紹介しきれないくらい沢山用意されています。またフィルターは重ねて使用し、複雑な効果をだすこともできます。
feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feFlood, feGaussianBlur, feImage, feMerge, feMorphology, feOffset, feSpecularLighting, feTile, feTurbulence
フィルターを適用したサンプルと適用方法
上段がフィルターを適用したサンプルです。
See the Pen VYvjya by Saomocari (@Saomocari) on CodePen.
左から、feGaussianBlur 要素でぼかし・feColorMatrix 要素で色相を変換・feColorMatrix 要素で彩度を変換するフィルターを適用しています。以下サンプルの fillter 要素部分のコードです。
<svg>
<defs>
<!-- ぼかし -->
<filter id="blur" x="20" y="20" width="200" height="200" filterUnits="userSpaceOnUse">
<feGaussianBlur stdDeviation="5" />
</filter>
<!-- 色相を変換 -->
<filter id="rotate">
<feColorMatrix type="hueRotate" values="90" />
</filter>
<!-- 彩度を変換 -->
<filter id="sepia">
<feColorMatrix type="saturate" values="0"/>
</filter>
</defs>
:
filter 要素は全体を defs 要素で囲み定義化します。filter 要素の中に出したい効果の原始フィルター要素と、効果に応じた値を記入します。filter 要素には id を付けておきます。
適用したい image 要素などに直接 filter 属性又は、CSS 側で filter プロパティを記入し、リンク先として fillter 要素につけた id を指定することで、フィルターが適用されます。
.photo1{
filter: url(#blur);
}
:
又は属性値で指定。
<image x="20" y="20" width="200" height="200" xlink:href="neko.jpg" filter="url(#blur)" />
モノクロからカラーへ変化するマウスオーバー効果の作り方
フィルターの実際の使いどころを考えてみた結果、マウスオーバーなどのアクションに使うのがよいかなと思ったので、マウスオーバーでモノクロ→カラーという動きを作ってみました。
CSS で実装したサンプル
See the Pen LEpRGx by Saomocari (@Saomocari) on CodePen.
CSS で実装するのはとても簡単です。SVG 内に filter 要素で彩度を 0 にするフィルターを作ります。
<svg width="100%" height="370">
<defs>
<filter id="gray">
<feColorMatrix type="saturate" values="0"/>
</filter>
</defs>
:
CSS で image 要素に作ったフィルター #gray を適用し、:hover 時にはフィルターを適用しないように、filter プロパティを none にすればOKです。
svg image{
filter: url(#gray);
}
svg image:hover{
filter: none;
}
JavaScript を使ってじんわりとカラーにするサンプル
サッと変わると少し味気ないので JavaScript を使ってじんわりとカラーに変更してみます。
See the Pen SVG fillter mouse over effect by Saomocari (@Saomocari) on CodePen.
CSS の時と同じく filter 要素で彩度を 0 にするフィルター #gray を作り、CSS で #gray のフィルターを適用します。JavaScript で値を取りやすいように、image 要素にも id を振っておきます。
<svg width="100%" height="370"> <defs> <filter id="gray"> <feColorMatrix type="saturate" values="0" /> </filter> </defs> <image id="sample_img" x="20" y="20" width="350" height="350" xlink:href="https://memocarilog.info/memocarilog-demo/ResponsiveSlideshow_jQuery/image/6.jpg" /> </svg>
JavaScript では、マウスオーバー時に feColorMatrix 要素の values の値を彩度 0(モノクロ)から彩度 1(カラー)まで setTimeout を使って徐々に数値をあげるということを行っています。(全てのコードはサンプルのタブをクリックで確認できます。)
:(略)
var setValue = 0 ;
var colorIn_timer;
// setValue 値を 0.05 ずつ足していって values に設定する
// というのを values が 1 になるまで繰り返し行う関数 ↓
function colorInTimer(){
if (setValue < 1){
setValue = setValue + 0.05;
fillterFe.setAttribute('values', setValue);
colorIn_timer = setTimeout(function(){colorInTimer(setValue);}, 10);
} else {
clearTimeout(colorIn_timer);
setValue = 0 ;
}
}
// image タグをマウスオーバー時上記の関数 colorInTimer() を実行
imageElm.onmouseover = function(){
colorInTimer();
}
// image タグをマウスアウト時 fillter の values を 0 へ戻す
imageElm.onmouseout = function(){
fillterFe.setAttribute('values', 0);
}
filter 要素は フィルターの種類も多く値の指定も複雑なものもあるので、全てを使いこなすのはかなり大変ですが、よく使われそうなモノクロやぼかしなどだけでも覚えておくと、表現の幅も広がりそうです。
ただ、悲しいことに現時点で IE9 以下・AndroidBrowser4.3 以下では、filter 要素がサポートされていません…(Can I use…)。モダンブラウザのみがターゲットの場合には、画像一枚でいろいろなエフェクトを実装できてよいのではないでしょうか。
記事内でご紹介した、参照先のサイトを見ながらいろいろなフィルターを作ってみるのも楽しいですよ。
明日の SVG Advent Calendar 2014 は、聴く耳を持たない(片方しか) の rikuo さん「SVG画像を書き出す際に重要な設定「小数点以下の桁数」とはなにか?」です。
3 Comments & Tracbacks