マテリアルリップル効果のためのCSSテクニック

CSSとJavaScriptを使用したリップル効果のさまざまなテクニックのガイド

最近、マテリアルデザインからWebアプリケーションにリップル効果を実装する必要がありました。そして、それがどのように実装されているのかわからないことに気付きました。これは、私が既存の実装を研究する旅へと私を導き、あなたに役立つかもしれない真新しい技術を思いつきさえしました。

この波及効果とは何ですか?

Googleのマテリアルデザインの波及効果がわからないのですか?洞窟に何年住んでいますか?

ボタンを押すと、波及効果が使用されます。マウスまたはタッチ操作でも同じように機能します。

ボタンをクリックまたはタッチする位置を接点と呼びます。そこから、波紋が外側に移動して送信され、ボタン全体がいっぱいになるまで大きくなるにつれて不透明度が失われます。その後、完全に消えます。

この波紋効果のダイナミクスは、液体の表面に触れたときや、岩を湖に落としたときに得られる波紋に似ています。

Webで見られる波紋

いくつかの調査を行った後、Webアプリケーションに波及効果を実装するために使用される2つの主な手法を見つけることができました。

:: after擬似要素の使用

この手法を使用すると、ボタンの:: after疑似要素は半透明の円としてスタイル設定され、成長およびフェードするようにアニメーション化されます。コンテナボタンにはオーバーフローが必要です:ボタンの表面の外側に円がオーバーフローしないように非表示にし、位置:ボタン内に円を簡単に配置できるようにします。この手法の詳細については、Ionuț Colceriuによるこの記事をご覧ください。

この手法の優れた点の1つは、リップル効果に対する純粋なCSSソリューションであることです。ただし、波及効果は常に接点ではなくボタンの中心から始まります。それは最も自然なフィードバックではありません。

JavaScriptを使用して連絡先を保存し、それを使用してリップルを配置することで改善できます。それがまさに、material.ioがWebリップルコンポーネントに対して行ったことです。 CSS変数を使用して連絡先を保存し、:: after疑似要素はこれらの変数を使用して配置します。

子要素を使用する

本質的に、この手法は以前と同じ戦略を使用します。ただし、擬似要素の代わりに、ボタン内にspan要素を追加し、JavaScriptで配置できます。この手法は、Jhey Tompkinsによるこの記事で説明されています。

最も単純な実装では、ボタンをクリックするたびにスパンを作成し、クリックイベントでマウスの位置を使用してスパンの位置を変更します。 CSSアニメーションは、完全に透明になるまでスパンを拡大およびフェードさせます。アニメーションが終了したら、DOMからスパンを削除するか、カーペットの下にそのまま残すかを選択できます。透明なスパンがぶら下がっているのに気付かないでしょう。

私はこれの別のバリエーションを見つけました。子要素はスパンではなくsvgであり、svgはJavaScriptによってアニメーション化されます。このバリエーションはデニスゲーベルによって説明されていますが、本質的には同じであり、おそらく複雑なSVGの形状と効果を使用できるようです。

入力の送信に関する問題

上記の両方の手法は素晴らしいようです。しかし、これはtype = submitで入力要素にそれらを適用しようとしたときに起こることです:

なぜ機能しないのですか?

入力要素は置換された要素です。つまり、DOMとCSSに関して、これらの要素を使用してできることはほとんどありません。具体的には、子要素を持つことはできず、擬似要素も持つことはできません。これらの手法が失敗する理由は明らかです。

したがって、マテリアルデザインを使用している場合は、input [type = submit]から離れて、ボタン要素に固執することをお勧めします。またはそのまま読み続けてください。

入力を送信するためのリップルの追加

私が取り組んでいたWebアプリケーションでは、すでに多くの送信ボタンがありました。それらをすべて別の要素に変更するには、多くの作業が必要になり、スタイルシートとJavaScriptロジックが破損するリスクが高くなります。そのため、既存の送信ボタンに波紋を追加する方法を理解する必要がありました。

ラッピングコンテナを使用する

インラインブロック要素内に送信ボタンをラップし、インラインブロック要素をリップルサーフェスとして使用できることにすぐに気付きました。以下に簡単なデモを示します。

私はこのソリューションがシンプルであることを気に入っていますが、それでも多くの場所でマークアップを変更する必要がありました。そして、私はそれが脆弱なソリューションであることを知っていました。新しい開発者がプロ​​ジェクトに参加し、さざ波に適切にラップすることなく送信ボタンを作成します。そこで、DOMを変更する必要のない他のソリューションを探し続けました。

放射状グラデーション

放射状グラデーション構文により、グラデーションの中心とサイズの両方を制御できます。もちろん、半透明色を含むグラデーションの色を制御することもできます。そして、それが適用される要素をオーバーフローさせることはありません。だから、それはすでに私が必要とするすべてをしているようです!

それほど速くはありません... 1つ欠けている点があります。background-imageプロパティはアニメートできません。 CSSアニメーションを使用して、グラデーションを透明にしたりフェードしたりできませんでした。 background-sizeプロパティをアニメーション化することでなんとか成長させることができましたが、それが私にできるすべてでした。

フェードサークルをアニメーション画像として(apng形式を使用して)作成し、それを背景画像として適用するなど、他のいくつかのことを試しました。しかし、その後、イメージループの開始と終了を制御できませんでした。

最後に、JavaScriptを使用したソリューション

CSSでできないことは、JavaScriptでできます。 CSSアニメーションを使用してこの効果を働かせることを認めるよりも多くの時間を費やした後、あきらめて、アニメーションをJavaScriptで記述することにしました。

上記の放射状グラデーションソリューションから始め、window.requestAnimationFrameを使用して、放射状グラデーション、成長、フェードの流動的なアニメーションを作成しました。最終的な解決策は次のとおりです。

結論

したがって、CSSだけではなく、送信ボタンに波及効果を与えることができます。

このテクニックはウェブのどこにも文書化されていないので、自分で呼び出しています。 LeonardoのリップルテクニックはDOMの変更を必要とせず、擬似要素や子要素に依存しないため、どの要素にも機能します。ただし、完璧なソリューションではありません。

まず、パフォーマンスがあります。 JavaScriptを使用してグラデーションをアニメーション化すると、ブラウザーの最適化の多くが失われます。ただし、変更されるプロパティは背景画像だけなので、ブラウザはリフローする必要がなく、スタイルを再適用して要素を再描画するだけでよいと思われます。実際には、それがまさに起こることであり、パフォーマンスは本当に良いです。その声明の例外はFirefox Mobileであり、何らかの理由でアニメーションに追いついていません。 (編集:最新のFirefox Mobileバージョンではアニメーションはスムーズです)

第二に、この手法はボタンのbackground-imageプロパティを使用します。デザインでボタンの背景に画像を適用する必要がある場合、リップル効果がそれを上書きします。デザインでその画像が本当に必要な場合は、JavaScriptを変更して、既存の背景画像の上に放射状のグラデーションを描画できます。

第三に、これはInternet Explorerでは機能しないようです。ただし、IE10以降では動作しない理由はわかりません。 IEが放射状グラデーションに異なる構文を使用しているためかもしれません。しかし、IEを最近気にしているのは誰ですか? (編集:この方法はInternet Explorer 11では問題なく動作します)