iOS6 でもサポートされた CSS フィルタの使い方
とってもお茶目なマップアプリで話題沸騰中の iOS6 、皆さん既にアップデートしましたでしょうか。この素晴らしすぎるマップアプリの前にすべてが霞んでいますが、もちろん他にも多数の改良点があります。その中のひとつとして Safari (WebKit) に追加されたのが本日のお題である CSS フィルタで、名前のとおり Web ページ上の任意の要素に各種フィルタエフェクトをかけるというものです。実際に以前執筆した@IT さんの記事のサンプルも iOS6 な iPad でバッチリ動作しました。
CSS フィルタはデスクトップでも WebKit 系の最新ブラウザでしか使えないという状況で(Firefox は後述の SVG フィルタのみサポート)、この段階で Mobile Safari が対応してきたのには驚きました。 Android の Chrome はまだ未対応ですが、近いうちにサポートするのは間違いないでしょう。こうした高度なビジュアル表現の活用も、モバイル Web がどんどん先行していきそうな勢いですね。
というわけで、本日は活用範囲が大きく広がった CSS フィルタの使い方をご紹介します。
CSS フィルタの基礎
前述のとおり、 CSS フィルタは CSS の指定で任意の要素にぼかしや色相変換などのフィルタをかける機能です。 CSS プロパティの基本的な書式は以下になります。
filter: <フィルタ名>(<パラメータ>) <フィルタ名>(<パラメータ>) ... ;
<フィルタ名> は適用するフィルタを指定する文字列で、現在のところ 12 のフィルタが定義されています。 <パラメータ> はフィルタのパラメータで、意味や記述方法はフィルタごとに異なります。このフィルタ名とパラメータのセットを複数並べることで、複数のフィルタを重ねることも可能です。
なお、上記では規格に従って CSS プロパティ名は「filter」としましたが、現在は Web ブラウザごとのプレフィクスを付けないと機能しません。現在はサポートブラウザが限定されていますが、将来への希望も含めて webkit, moz, ms, o およびプレフィクスなしの記述を含めておくとよいでしょう。
使えるフィルタは、大別して以下の 3 種類に分類できます。
- プリセットフィルタ
- SVG フィルタ
- カスタムフィルタ (CSS Shaders)
これらのうち、今回 iOS6 でサポートされたのは最初のプリセットフィルタです。ぼかしや色相変換などの代表的なフィルタを CSS 指定のみで適用するもので、効果は限定されますが、使い方はとても簡単です。本日は主にこのプリセットフィルタについてご紹介します。
SVG フィルタは SVG の filter タグで定義されたフィルタを HTML に適用するものです。こちらは iOS6 では未サポートですが、デスクトップでは Google Chrome と Firefox でサポートされているので、最後に基本的な使い方のみ触れています。最後のカスタムフィルタは先日の記事で CSS Shaders として取り上げたので、興味のある方はそちらをご覧ください。
プリセットフィルタを使う
プリセットフィルタでは、以下の 10 種類のフィルタが利用できます。
フィルタの書式 | 説明 |
---|---|
grayscale(強度) | モノクロ化 |
sepia(強度) | モノクロ化し、セピア色に近づける |
saturate(強度) | 彩度の調整 |
hue-rotate(角度) | 色相変換 |
invert(強度) | 反転 |
opacity(強度) | 透明度の調整 |
brightness(強度) | 明度の調整 |
contrast(強度) | コントラストの調整 |
blur(半径) | ぼかし |
drop-shadow(影パラメータ) | 影の描画 |
上記のパラメータのうち、「強度」は効果の強さをパーセントで指定します(100% 以上の値が指定できるものもある)。角度は色相の回転角(90deg など)、半径は長さの単位(2px など)、影パラメータは box-shadow と同じ書式です。例として、色相を 90 度変更して影を描画する例を示します。
filter: hue-rotate(90deg) drop-shadow(8px 8px 4px #888); -webkit-filter: hue-rotate(90deg) drop-shadow(8px 8px 4px #888); -moz-filter: hue-rotate(90deg) drop-shadow(8px 8px 4px #888); -o-filter: hue-rotate(90deg) drop-shadow(8px 8px 4px #888); -ms-filter: hue-rotate(90deg) drop-shadow(8px 8px 4px #888);
ここでは画像に対してフィルタをかけていますが、 video や canvas などを含む任意の要素に効果を適用できます。
また、上のサンプルで画像の形に沿った影が描画されていることにも注目してください。 box-shadow はボックス型の影しか描画できませんでしたが、 CSS フィルタの drop-shadow は最終的なアルファ値を正しく考慮した影を生成してくれます。
これらのプリセットフィルタの効果をインタラクティブに調整できるページも公開されています。 WebKit 専用のようなので、 Chrome か Safari 6 で試してみてください。
http://html5-demos.appspot.com/static/css/filters/...
アニメーションを適用する
CSS フィルタにはもちろんアニメーションも適用できます。 CSS transition を使えば、マウスホバーでエフェクトがスウッっと解除されていくような効果も簡単に実現できます。
img { filter: grayscale(100%) blur(2px); -webkit-filter: grayscale(100%) blur(2px); -moz-filter: grayscale(100%) blur(2px); -o-filter: grayscale(100%) blur(2px); -ms-filter: grayscale(100%) blur(2px); transition: -webkit-filter 0.3s; -webkit-transition: -webkit-filter 0.3s; -moz-transition: -webkit-filter 0.3s; -o-transition: -webkit-filter 0.3s; -ms-transition: -webkit-filter 0.3s; } img:hover { filter: grayscale(0%) blur(0px); -webkit-filter: grayscale(0%) blur(0px); -moz-filter: grayscale(0%) blur(0px); -o-filter: grayscale(0%) blur(0px); -ms-filter: grayscale(0%) blur(0px); }
従来なら 2 枚の画像のクロスフェードなどをしていたところですが、 CSS フィルタならば CSS の指定のみで簡単に、しかもより自然な形で表現できます。うまく使えば、少ない手間でよりインパクトのある効果的な UI が実現できるでしょう。
SVG フィルタ
最後に、 SVG フィルタについても少し触れておきます。 前述のとおり、 SVG フィルタは従来から SVG で使われてきたフィルタ機能を HTML に適用するものです。 SVG のフィルタ機能については @IT さんの連載の SVGの回(後編)で解説しているので、詳細はそちらを参照してください。
SVG フィルタを使うと、プリセットフィルタだけでは実現できない多彩な効果を適用できます。以下はそのひとつであるライティング効果を利用して、文字に浮き彫りのような表現を与えたものです。 Chrome ではスクロール時にフィルタがおかしくなるというバグがあるようなので、もし効果がおかしいときはこの位置でページをリロードしてみてください。
<svg height="0"> <filter id="page_lighting"> <feGaussianBlur stdDeviation="4" in="SourceAlpha" result="h" /> <feDiffuseLighting surfaceScale="20" diffuseConstant="1" lighting-color="white" in="h" result="d"> <feDistantLight azimuth="-45" elevation="45" /> </feDiffuseLighting> <feSpecularLighting surfaceScale="20" specularConstant="1" specularExponent="8" lighting-color="white" in="h" result="s"> <fePointLight x="250" y="-50" z="100" /> </feSpecularLighting> <feComposite operator="arithmetic" in="d" in2="SourceGraphic" k1="1" k2="0" k3="0.5" k4="0" result="dd"/> <feComposite operator="arithmetic" in="dd" in2="s" k1="0" k2="1" k3="1" k4="0" result="ss" /> <feComposite operator="in" in="ss" in2="SourceAlpha" /> </filter> </svg> <div style=" font-size:96px; font-weight:bold; color:#c44; filter:url(#page_lighting); -webkit-filter:url(#page_lighting); -moz-filter:url(#page_lighting); -ms-filter:url(#page_lighting); -o-filter:url(#page_lighting); ">CSS Filter</div>
やっていることを簡単に説明すると、まずあらかじめ高さ 0 の svg タグを使って SVG フィルタを定義しておきます。 filter タグ、及びその内部がそれです。そして、効果を適用したいタグのスタイルで以下のようにして filter タグの id を指定します。もちろん、さらに他のフィルタを重ねることも可能です。
filter: url(#<filterタグのID>);
問題は filter タグ内の記述をどうするかですが、これが少々厄介です。 SVG のフィルタ機能は畳み込み演算などのローレベルなモジュールを組み合わせて効果を実現するように設計されており、多彩な表現を柔軟に作り出せる代わりに、フィルタの構築には専門的な知識とノウハウが必要になります。
前述の @IT さんの記事では Inkscape で作ったフィルタをそのまま利用する方法を紹介していて、 SVG フィルタが安定動作するようになれば、それが最もお勧めできる方法です。しかし、現在は Chrome でも一部のフィルタモジュールが(たぶん)正しく動作しておらず、少し複雑なフィルタを使うと途端になにも表示されなくなります。残念ながらまだ実用段階には達していないという印象です。
将来的には、 CSS Shaders と同様にとても有望な機能だと思うので、 Chrome 以外のブラウザも含めて、ぜひサポートに力を入れてほしいところです。
詳しくはこちらの記事をどうぞ!
この記事にコメントする