先日、WordPressのeコマーステーマをリリースしたところ、バナー画像に使っている「ぼかしで覆うエフェクト」に関する質問がたくさん寄せられました。ぼかしで覆うエフェクトはどんな画像にでも動的に適用できる注目のエフェクトで、優れた画像処理方法だと考えています。さらに重要なことは、汎用的なテクニックなのでデザイナーにとって使い勝手がいいということです。この記事では私が学んだことを手短に紹介しましょう。
上のバナーの「ぼかしで覆うエフェクト」について簡単に説明します。
- 単一の画像として使用
- 非破壊的(non-destructive)である(オリジナルのJPEG・PNG画像に直接変更を加えていない)
- 画像にテキストを追加でき、テキストによって画像が隠されてもよい
- ほとんどあらゆる形状のマスクを適用できる
- モダンブラウザーの対応状況は比較的良いものの、マスクの位置決定に工夫が必要な場合もある
このテクニックでカギとなるのはSVGです。SVGがその名のとおりベクター形式であることは知っていると思いますが、実はSVGにはPNGとJPEG画像にだけ使える、ピクセルベースのトリックもあるのです。
SVG1.1のフィルター効果
最初はもっともシンプルなフィルターからです。基本的なSVGフィルターは、一連のフィルタータグを作成し、参照用のIDでフィルターに名前を付けるだけで簡単に設定できます。例ではフィルターのIDを「myblurlayer」としました。
次のSVGスニペットをページに追加すると、画面にはなにも表示されませんが新しいフィルターが作成され、任意のページ要素(画像、テキスト、パネルなど)に適用できます。stdDeviationの値を大きくするとぼかしが強くなります。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="0">
<filter id="myblurfilter" width="110%" height="100%">
<feGaussianBlur stdDeviation="2" result="blur" />
</filter>
</svg>
コードではシンプルなSVGのぼかしエフェクト(feGaussianBlur)を使いましたが、使えるフィルターエフェクトはほかにも十数個あります。フィルターはCSSを使って適用するのがもっとも一般的です。
.blurme {
-webkikt-filter: url('#myblurfilter');
filter: url('#myblurfilter'); }
<img class='blurme' src='myimage.png' />
(注:お気づきの通り、ぼかしだけでいいならもっとシンプルな方法があります)
さてこのようにCSSでクラス名を使えば、シンプルなフィルターエフェクトは大半のブラウザーでうまく動きます。残念なことに、Safariにはバグがあり、もっと高機能のフィルターをで使おうとすると不安定になります。
HTMLのimgタグを使うよりも、SVG要素内部にベースとなるJPEGかPNG画像を配置したほうが結果にばらつきが出ないことが分かりました。画像を次のようにマークアップできます。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" width="100%" height="100%" xlink:href="https://www.sitepoint.com/themes/ecommerce/wp-content/uploads/sites/4/ecom-banner-2-1_1020x304_acf_cropped-1.jpg"/>
</svg>
この手法を使っても、ブラウザーではごく普通のimgタグを使った場合となにも変わらないように見えるでしょう。この<image>要素にフィルターを直接適用します。
フィルターにマスクをかける
SVGでは、画像をSVG要素内で操作できるオブジェクトに変換する<feImage>という便利なフィルター効果を使えます。例ではこの機能をマスクとして使います。マークアップは次のようになります。
<feImage id="feimage" xlink:href="our-mask-will-go-here" x="0" y="0" height="300px" result="mask" preserveAspectRatio="none"/>
技術的にはxlink:hrefの部分に外部ファイル(たとえば、mask.svg)へのリンクを記述できますが、ブラウザーによってはうまく動作しない場合もありました。代わりに、フィルターに直接SVGマスクのコードを記述します。
マスク形状の作成
SVGについてさらに話を進める前に、マスクの作成が必要です。例ではシンプルな長方形の「レターボックス」エフェクトを作成しますが、好みの形で構いません。とはいえ、比較的シンプルなマスクがおすすめです。
優れた軽量オンラインSVGエディター「Method-Draw」を使ってSVGを作成します。Method-Drawは扱いやすい無料のSVGエディターなので、シンプルなマスクを作成するのに便利です。もちろん、Illustratorを使ってもうまくいきます。
シンプルな黒と白のシェイプを作成したのち、「View」→「Source」とクリックしてクリップボードにSVGのマークアップをコピーします。
このマスクをフィルター内に記述するにはマークアップを「data URI」に変換しなければなりません。data URIとは基本的にSVGのマークアップをそのまま符号化したもので、ブラウザーは扱いやすくなりますが、人間には文字化けしているようにしか見えません。
新しいタブでData URI Converterを開き、「Provide text」を選択してテキストフィールドにSVGのマークアップをペーストします。
Data URI ConverterにSVG用に使うことを伝えなければならないので、「Enter Mime Type」のフィールドにimage/svg+xmlと入力します。「Generate Data URI」をクリックすると、大部分が意味不明の長い文字列が取得されます。これが変換後のマスクです。
返還後のマスクをクリップボードにコピーし、SVGフィルターのコードに戻って<feImage>のxlink:href=にペーストします。
フィルターのコードは以下のようになります。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="blurlayer" width="110%" height="100%">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feImage id="feimage" xlink:href="data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIzMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQogPGc+DQogIDx0aXRsZT5iYWNrZ3JvdW5kPC90aXRsZT4NCiAgPHJlY3QgZmlsbD0ibm9uZSIgaWQ9ImNhbnZhc19iYWNrZ3JvdW5kIiBoZWlnaHQ9IjMwMiIgd2lkdGg9IjEwMjYiIHk9Ii0xIiB4PSItMSIvPg0KIDwvZz4NCg0KIDxnPg0KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+DQogIDxyZWN0IGlkPSJzdmdfMSIgaGVpZ2h0PSIxMzMiIHdpZHRoPSIxMDI0IiB5PSI4NC41IiB4PSIwIiBmaWxsLW9wYWNpdHk9Im51bGwiIHN0cm9rZS1vcGFjaXR5PSJudWxsIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlPSJudWxsIiBmaWxsPSIjMDAwMDAwIi8+DQogPC9nPg0KPC9zdmc+" x="0" y="0" height="300px" result="mask" />
... <!--more to come here -->
</filter>
</defs>
</svg>
SVGの「サンドイッチ」機能
複数のエフェクトを「サンドイッチ(挟み込み)」して単一の画像として扱えるのはSVGのもっともすごい機能の1つです。最初に必要なのは、マスクとぼかしフィルターを組み合わせて一体化することです。これはテレビにビデオやゲーム機など複数の機器を接続するのに少し似ています。<feComposite>を使って実装します。
<feComposite in2="mask" in="blur" operator="in" result="comp" />
見てのとおり、マスクからの出力(result="mask")とぼかしフィルターからの出力(result="blur")を取得し、(in2="mask")と(in="blur")を使って合成し、resultとして「comp」を呼び出します。
フィルターとソース画像を組み合わせる
あとはぼかしエフェクトを任意の指定した画像に適用するように、フィルターに指示すれば大丈夫です。<feMerge>を使って覆われたぼかしエフェクトと任意の指定した画像をマージすればよいのです。幸いSVGには「SourceGraphic」のコンセプトが通用できるので、フィルターに「SourceGraphic」と「comp」をマージすると指示するだけでOKです。
コードは次のようになります。
<feMerge result="merge">
<feMergeNode in="SourceGraphic" />
<feMergeNode in="comp" />
</feMerge>
フィルターの準備はできました。あとは画像に適用するだけです。
デモ用に、JPGのソース画像を独立したSVG要素に埋め込みfilter="url(#blurlayer)"でフィルターを適用しました。
<image filter="url(#blurlayer)" x="0" y="0" width="100%" height="300px" xlink:href="https://www.sitepoint.com/themes/ecommerce/wp-content/uploads/sites/4/ecom-banner-2-1_1020x304_acf_cropped-1.jpg"/>
</svg>
全体をまとめたデモは次のようになります。
さらにもう1つ
これまで説明してきたように、SVGフィルターを使えばエフェクトを互いに重ね合わせられます。マスクされた領域の色をフィルター効果の<feColormatrix>で調整すればさらに凝ったことができます。
以下のコードをフィルターのコードの冒頭部分に追加するとフィルターで赤・緑・青のきめ細かいチャンネルコントロールが可能になり、マスクされた領域を暗くしてテキストとのコントラストを鮮明にできます。例で「0.7」とした部分はデフォルトの行列では「1」に設定されています。RGBチャンネルの値をそれぞれ小さくしただけです。
<feColorMatrix
type="matrix"
values=".7 0 0 0 0
0 .7 0 0 0
0 0 .7 0 0
0 0 0 1 0 " />
「feColorMatrix」について詳しい説明はしませんが、分かりやすく説明したUna Kravetsの記事をぜひ参考にしてください。
ボタンクリックで操作できる優れたツールで、行列をいろいろ変えると画像の色にどのように影響するかを確認できます。ライブデモを頻繁に試すことが習得へのいちばんの近道です。
色を微調整した最終的なデモはこちらです。
ステップアップ
ここまでのデモは分かりやすくするために、もっともシンプルな長方形のぼかしで覆いました。もっとおもしろい形のマスクを使ってもよいでしょう。
この例では複雑な幾何学模様のマスクを作成し、よりはっきりとしたカラーエフェクトと組み合わせています。
最後に
Photoshopのような画像エディターなしでは考えられなかったような効果をいろいろ試したり、思い描いた視覚効果を実現したりできるのは楽しいことです。この記事はデザイナー向けに執筆したので、ぜひ気軽にコードを使ってみてください。
この記事のもっとも重要なコンセプトは、作成した複数の「SourceGraphic」に異なるエフェクトや透明度を適用できるというアイデアでしょう。ジッター効果、赤青の3Dホログラム効果、shattered glass(割れガラス)効果をはじめ無限のバリエーションを演出できます。
紹介したエフェクトは現在ほとんどのブラウザーでサポートされていますが、多少のばらつきはあります。Chrome、Firefox、Safari、IE10〜11では満足な結果が得られましたが、特定のエフェクトで期待した結果を出すために異なる手法を試す必要が何度かありました。なぜかSafariではフィルターを適用した領域がほかのブラウザーに比べて明るく表示されます。
さらに、フィルターに不具合があると画像がまったく表示されなくなってしまう、困った特性も覚えておいてください。だから徹底的なテストが必要なのです。とはいえ、複雑でしかも一時的な画像視覚処理をブラウザー上で実行でき、簡単に削除できることを考えると、SVGフィルターを使わない手はないはずです。
(原文:Design Tricks with SVG Filters: A Masked Blur Effect)
[翻訳:新岡祐佳子/編集:Livit]