ユーザが操作したことを視覚的に伝えるボタンを、Vue.jsを使ってコンポーネントとして作ります。
Ripple (波紋) エフェクト
クリックした箇所を中心に波紋が広がるようにかかるエフェクトです。マテリアルデザインで広く知られるようになりました。 マテリアルデザインガイドラインによれば、クリック箇所を特定せず、どこをクリックしても中心から広がるものは正確には Ripple エフェクトとは呼べないそうです。
コンポーネント化の恩恵
コンポーネント化することにより、複数の箇所で同じボタンを再利用できるわかりやすい利点の他に、ボタンを利用する側のコンポーネント上から、 Ripple エフェクトの実装を隠し、あたかもHTML標準の button 要素
かのように使うことができる利点があります。
Ripple エフェクトの実装は、シンプルな仕組みにしたとしてもそれなりにコード量があります。 クリック位置の特定や、 Ripple を表現するための要素、CSS Transition を含むボタン全体の CSS がそれです。 Vue.jsを使ってコンポーネントを分割することでこれらのコードを隠匿します。
Ripple エフェクトの再現
今回作成したRipple エフェクトは以下の手順で実現しました。
button 要素
のクリックした位置を取得・保持する- Ripple を形成する
span 要素
を挿入する - 保持していたクリック位置を使って
span 要素
の位置を変更する span 要素
のscale
をゼロに変更する- CSS Transition によって
span 要素
のscale
とopacity
を変化させる - Ripple を形成する
span 要素
を削除する
Tips
今回ボタンを作成する過程で発見した点や気を使った点を記します。
type 属性について
button
要素の type
属性のデフォルト値は type="submit"
ですが、経験上 type="button"
で指定することがほとんどなので、 コンポーネント内で type="button"
として初期値を変更しました。親要素からは特に指定せずとも、 type="button"
として振舞います。
pointer-events プロパティについて
あまり使ったことがなかった CSS プロパティ pointer-events
を使いました。このプロパティは値として none
を指定することにより、その要素が補足するマウスイベントを無視するようになります。1
ボタンを高速で連打したとき、表示されている span 要素
がクリックを補足してしまい、 Ripple エフェクトの出現位置が意図しないところに変わってしまう問題を解消しました。
このプロパティは CSS Level 4 ですが、モダンブラウザは対応しており、 IE はバージョン11から対応しています。
disable 属性について
Rippleエフェクト中にボタンを連続的にクリックできるかどうかは要件により異なると思われます。今回は、Ripple エフェクトが出ている間はボタンを非活性にして連打できないようにしました。
click イベントのハンドリングについて
今回作成したボタンはそれ単体では機能を持たず、単純に click イベントを vm.$emit
するだけです。 click イベントはボタンを使うコンポーネント側で定義したハンドラを @click
で補足して発火します。そのため、ボタンを再利用する箇所がどれだけ増えてもボタン側のコードを変更する必要がありません。
属性の上書きについて
ボタンを使う上で頻繁に制御すると思われる disabled
属性は、標準の button
要素に指定するのと同様に呼び出し側から制御できます。 今回作成したコンポーネントは props
を受け取らないようになっていますが、標準で指定可能な属性はそのまま記述すれば上書きされます。
このため、先述した type
属性も、type="submit"
として使用したい場合はそのように記述できます。