💧

jQueryとcssで作る波紋アニメーション

2022/06/13に公開

今回紹介する内容

マテリアルデザインなどではクリックしたときに波紋のようなアニメーションでクリック感を演出しています。今回はそのアニメーション効果を付け加える方法をご紹介します。

やりたいこと

波紋みたいなアニメーションをつけたい

あらすじ

  1. クリックしたときに波紋効果付きの要素を追加 mousedown
  2. アニメーションが終わったら削除 setTimeout

サンプル・ソース

全体のソースはGitHubに公開しています。

https://github.com/Harurow/zenn-sample-ripple

動作イメージは以下の通りです。クリックした分だけ波紋を表示します。

index.html

クラス ripple が指定されている要素がクリックされたときに波紋のアニメーションを追加するようにします。
jQueryを利用するのでCDNから追加。また波紋=rippleのアニメーションはripple.cssにて定義します。

index.html
  ... 略 ...
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <link rel="stylesheet" href="style.css" /> <!-- 全体のcss -->
  <link rel="stylesheet" href="ripple.css" /> <!-- 波紋のcss  -->
<body>
  <header>
    <div class="ripple"> <!-- この要素クリックすると波紋 -->
      <div class="title">
        リップルエフェクト サンプル
      </div>
    </div>
  </header>
  <main>
    <div class="ripple"> <!-- この要素クリックすると波紋 -->
      <div class="title">
        クリックしてみてください
      </div>
    </div>
  </main>
</body>
<script src="./ripple.js"></script>
<script src="./main.js"></script>
</html>

ripple.css

.ripple は波紋のアニメーション時に要素を一時的に絶対位置で追加します。そのため、position: relative を定義しています。
user-select は好みの問題です。🙂

ripple.css
.ripple {
  position: relative;   /* 波紋の要素を position:absoluteで指定するので */
  display: block;
  overflow: hidden;     /* 波紋効果がはみ出し防止 */

  -webkit-user-select: none;
  user-select: none;
}

... 略 ...

以下が波紋効果のアニメーションのCSSです。アニメーションは好みで変えることができます。

ripple.css
... 略 ...

.ripple-effect {
  position: absolute;       /* 親要素(ripple)からの絶対位置で設定する */
  display: inline-block;
  border-radius: 100%;      /* 真円にする */
  background: white;        /* お好みで */
  opacity: 0;
  transform: scale(0);
  animation: ripple-effect                  /* キーフレーム名  */
             750ms                          /* アニメーションの期間 */
             cubic-bezier(0, 0, 0, 1.0)     /* 最初早く後半はゆっくり */
             backwards;                     /* アニメーションの最後の状態をキープ */
  pointer-events: none;     /* この要素はマウスイベント無視 */
}

@keyframes ripple-effect {
  from {
    opacity: 1;             /* 最初は100%見える */
    transform: scale(0);    /* 最初は大きさ0% */
  }

  to {
    opacity: 0;             /* 最後は見えなくする  */
    transform: scale(1);    /* 最後は100%の大きさ */
  }
}

ripple.js

クリックしたイベントを処理するハンドラonRippleを定義。
要素を縦横300pxで生成。クリックした位置を中央に設定して作る。
アニメーションが終了したら要素を削除するためonanimaitonendのイベントを利用しています。

ripple.js
function onRipple (e) {
  const size = 300
  const x = e.offsetX
  const y = e.offsetY
  const w = size
  const h = size

  const effect = $('<span class="ripple-effect"></span>')
    .css({
      left: x - w / 2,
      top: y - h / 2,
      width: size,
      height: size
      })
    .appendTo(this)     // ripple クラスの要素の子供として追加
    .on('animationend', () => effect.remove())  // アニメーション終わったら消す
}

.rippleクラスを定義した要素に対してmousedownイベントハンドラを定義します。
jQueryで一括で設定します。

ripple.js
function initRipples () {
  $('.ripple')              // 全体から '.ripple' クラスが付いている要素を洗い出す
    .mousedown(onRipple)    // それぞれの 'mousedown' イベントに 'onRipple' を紐づける
}

main.js

ripple.jsで定義したinitRipplesを呼び出します。

main.js
$(() => {
  initRipples()
})

最後に

以上、波紋アニメーションのご紹介でした。いろいろな方々が同じ題材で記事を書かれているので公開しようか迷ったのですが、次回以降の記事でrippleが出てきそうなので前置きとして公開することにいたしました。ご参考になれば。

Discussion