CSSのぼかしフィルターを利用した、フォーカスによる遠近表現
CSS3のfilterプロパテッィを利用すると、ぼかしの効果を
難しい記述をすることなく簡単に実装することができます。
このぼかしを日常で見る機会はというと、
肉眼やカメラである1点にピント(焦点)を合わせたとき、
ピントの合っていないところはぼやけて見えますが、
このピンぼけの状態がぼかしと同じ見え方になると思います。
ピントを合わせている対象物の距離を中心に、ピントはどんどんずれてぼかし効果も大きくなっていますの。
そのため、このぼかし効果を利用すれば、遠近の表現ができるのではないかと考えました。
そこで、それをCSS3のfliter効果を利用して作ってみましたので、
ご紹介いたします。
↓こちらが作ってみたもの(Chrome, FireFox, Safari, Operaで動作します)
概要と方法
概要
- 今回作るものは、仮想の焦点位置を設定した画像をいくつか配置し、
その焦点位置を基準にぼかし効果の強さを変更します。 - 焦点の合っている位置を変更できるハンドルを配置し、
その値を変更すると、焦点の合っている場所が変更され、ぼかし効果が変更されます。 - 画像をクリックすると、その画像に焦点の合っている位置を変更します。
手順
- HTMLで画像(<img>)を配置して、仮想の焦点位置をdata属性として設定する
- 焦点の合っている位置を変更するハンドルを、
HTML5のINPUTタグの新しいタイプであるrangeをつかって配置します。 - jQueryのcssプロパティを使って、ぼかし効果を変化させる
1. HTMLで画像(<img>)を配置して、仮想の焦点位置をdata属性として設定する
1 2 3 4 5 6 7 8 | <div id="viewArea"> <ul class="image"> <li><img src="images/spring4.jpg" data-focus="0"></li> <li><img src="images/summer2.jpg" data-focus="33"></li> <li><img src="images/autumn4.jpg" data-focus="67"></li> <li><img src="images/winter4.jpg" data-focus="100"></li> </ul> </div> |
HTML上で画像をimgで配置し、そこにdata属性で仮想の焦点位置を設定します。
今回は焦点位置の属性名をdata-focusとして、最も近くの画像を0、最も遠くの画像を100として設定しました。
2.焦点の合っている位置を変更するハンドルを、HTML5のINPUTタグの新しいタイプであるrangeをつかって配置
1 2 3 4 5 6 7 8 9 | <div id="viewArea"> <ul class="image"> <li><img src="images/spring4.jpg" data-focus="0"></li> <li><img src="images/summer2.jpg" data-focus="33"></li> <li><img src="images/autumn4.jpg" data-focus="67"></li> <li><img src="images/winter4.jpg" data-focus="100"></li> </ul> </div> <p id="controler">Focus<br><input type="range" id="changeFocus" min="0" max="100" step="1" value="0"></p> |
先ほどの画像の下にHTML5で新たに追加されたINPUTタイプの”range”を配置します。
最小値をmin属性、最大値をmax属性、値のステップ値をstep属性で設定します。
今回は値の範囲を0から100までとし、ステップ値は1にしました。
jQueryのcssプロパティを使って、ぼかし効果を変化させる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | $(function(){ //userAgent var userAgent = window.navigator.userAgent.toLowerCase(), ua = ""; if(userAgent.indexOf('chrome') != -1 || userAgent.indexOf('safari') != -1 || userAgent.indexOf('Opera') != -1){ ua = "webkit"; } /*-- 初期設定 --*/ var focusData = [], imgCnt = 0; $("#viewArea>ul>li>img").each(function(){ focusData[imgCnt] = Number($(this).attr("data-focus")); //画像のdata-focus属性の値を取得 imgCnt++; }); for(var i = 0; i < imgCnt; i++){ //対象画像の数だけ繰り返し var focusNum = Math.abs(Math.round((focusData[i] - $(this).val()) / 10)); //ぼかし(Blur)の値を変更 if(ua == "webkit"){ //chrome safariのときはfilterを利用 $("#viewArea>ul>li>img").eq(i).css({ "-webkit-filter": "blur(" + focusNum + "px)" }); }else{ //それ以外のときはSVG Filterを利用 $("#viewArea>ul>li>img").eq(i).css({ "filter": "url(\"data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><defs><filter id=\'blur\'><feGaussianBlur in=\'SourceGraphic\' stdDeviation=\'" + focusNum + "\' /></filter></defs></svg>#blur\")" }); } } //Focusハンドル(input[type='range'])を操作したときの動作 $("#changeFocus").on("mousemove change", function(){ for(var i = 0; i < imgCnt; i++){ var focusNum = Math.abs(Math.round((focusData[i] - $(this).val()) / 10)); //ぼかし(Blur)の値を変更 if(ua == "webkit"){ //chrome safariのとき $("#viewArea>ul>li>img").eq(i).css({ "-webkit-filter": "blur(" + focusNum + "px)" }); }else{ //それ以外 $("#viewArea>ul>li>img").eq(i).css({ "filter": "url(\"data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><defs><filter id=\'blur\'><feGaussianBlur in=\'SourceGraphic\' stdDeviation=\'" + focusNum + "\' /></filter></defs></svg>#blur\")" }); } } }); //画像をクリックしたときの動作 $("#viewArea>ul>li>img").click(function(){ var nowVal = Number($("#changeFocus").val()), //変更前のFocusハンドルの値を取得 tgVal = Number($(this).attr("data-focus")), //画像のdata-focus属性の値を取得 cnt = 0; //カウンターをリセット //画像のdata-focusの値になるまで、Focusハンドルの値を1ずつ変更 var changeFocus = setInterval(function(){ if(nowVal + cnt != tgVal){ if(nowVal < tgVal){ cnt++; }else{ cnt--; } $("#changeFocus").val(nowVal + cnt).change(); //Focusハンドルの値を変更 }else{ clearInterval(changeFocus); //Focusハンドルが画像のdata-focusの値になったら繰り返しを停止 } }, 0); }); }); |
jQueryの大まかな流れとしては、
- imgのdata-focusの値を取得
- 一番遠いときのぼかしの値(100)を10として、ピントが合っている位置からimgまでの値の差をぼかしの値に変換(10で割って四捨五入)
- jQueryのcssプロパティを使って、ブラウザに合わせたぼかし効果を適用
- Focusハンドルを操作したり、画像をクリックしたら、ピントが合っている位置を変更して、
ぼかしを再計算して適用
といった感じになります。
ChromeやSafariなどのwebkit系ブラウザでは-webkit-filterプロパティを使い、
それ以外のFireFoxなどではSVG Filterを使うように振り分けています。
IEもチャレンジしてみましたが、今回は時間切れとなってしまったため、対応していません。
画像をクリックしたときには、変化している様子がわかりやすいように、
setInterval()を使ってアニメーションさせています(ぼかしの効果は複雑なためブラウザ上での処理が大変で時間がかかるようなので、intervalの時間は0にしています)。
遠近を表現するだけでなく、注目させたいところを強調したりするのにも使えるのではないかと思います。
参考にさせていただいたサイト
CSS と SVG で曇りガラスのような効果を作る | Unformed Building
Author Profile
NINOMIYA
Webデザイナー兼コーダー出身のフロントエンド開発者です。 UXデザインやチーム開発の効率化など、勉強中です。
SHARE