10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Re: jQueryで要素を点滅させる

Last updated at Posted at 2015-06-04

jQueryで要素を点滅させる - Qiita / soeda_jp にてjQueryのfadeOut / fadeInをつかった要素の点滅方法が紹介されていました。
CSSアニメーションをつかったほうが負荷が小さいんじゃないだろうかと思い、色々調べてみました。
途中で飽きて、すごくふわふわした記事になっています。

#各実装での測定

以下の環境で検証しています。

  • jQuery 1.11.3
  • Google Chrome 43.0 (PC版・2015/06現在最新版)

setInterval+jQueryをつかった点滅

script1.js
$("div").on('click', function(){
  $self = $(this);
  setInterval(function(){
    $self.fadeOut(500).fadeIn(500);
  },1000)
});

測定しやすいよう、元記事のスクリプトを少し改変したスクリプトです。
要素がクリックされると、その要素を1秒間隔で消したり出したりするアニメをjQueryで実装してみました。

以下の図は、要素をクリックしてしばらく点滅させている間のメモリ消費を、Chromeのデベロッパーツールで測定したものです。

Screenshot_from_2015-06-04 20:25:05.png

なんかよくわからないですが、User JS Heapが増えたり減ったりしていますね。ヒープって言うからにはきっと、動的に確保しているメモリ容量とか何でしょう。知りませんが。
ときどきかっくんと落ちているのはGCが動いているのでしょう。一回目の山より、二回目の山が大きいのは、「大きく育ちそうなリストのGC頻度を減らす」とかなんかそんなjsの最適化があるのではないだろうか。
1分くらい放置していると、パソコンのファンが唸り始めたりしました。怖い。

CSSをつかった点滅

style.css
.pikapika{
  animation: pika2 1s infinite alternate;
}
@keyframes pika2{
  from{opacity: 1;} 
  to{opacity:0;}
}
script2.js
$("div").on('click', function(){
  $(this).addClass('pikapika');
});

細かい調整が面倒くさいので、厳密におなじアニメーションではありませんが、点滅アニメーションをCSSによって実装してみました。
javascriptではクリックした際にクラスを付与することしかしていません。

jQueryオンリーの場合と同様に、要素をクリックしてから点滅している間をしばらく、Chromeのデベロッパーツールで測定しました。

Screenshot_from_2015-06-04 20:53:40.png

User JS Heapはクリック時に一度だけ増加し、その後で要素が点滅している間もずっと一定です。パソコンのファンも静かで、お隣さんに怒られる心配をしなくて良い。
演出周りは極力CSSを利用したほうが良さそうです。ただし、animationプロパティはIE9以下では利用できません。レガシーなIEを使う場合は<marquee>などを使うといいのではないでしょうか。

jQueryのfadeOut / fadeInについて

もう一度、javascriptの方を見てみます。

script1.js
$("div").on('click', function(){
  $self = $(this);
  setInterval(function(){
    $self.fadeOut(500).fadeIn(500);
  },1000)
});

fadeIn / fadeOutがどのような実装になっているかは、以下が参考になります

  1. jquery/jquery 1.11-stable/src/effects.js#L592-L593- GitHub ... fadeOut / fadeInの定義
  2. jquery/jquery 1.11-stable/src/effects.js#L470-L487- GitHub ... fadeOut / fadeInが呼ぶjQuery#animationメソッドの実装。GitHub上ではインデントが崩れているかもしれないので、気合いで読む。
  3. jquery/jquery 1.11-stable/src/effects.js#L429-L459- GitHub .. jQuery#animationから呼ばれるjQuery.speedの定義。アニメーション速度・Easing(描画モード)、アニメーション終了時のコールバック関数の定義などから、アニメーション全体の定義を作って、アニメーションキューにいれる

上記を踏まえると、script1.jsでは

  1. アニメーションキューに「500msかけて消える」のイベントが格納
  2. アニメーションキューに「500msかけて出る」のイベントが格納
  3. 1のアニメが終わったら、キューが空か判定する。→2がまだあるので実行
  4. 2のアニメがおわったら、キューが空か判定する。→もう無いので終了
  5. 1〜2のキュー登録が1000ms毎に行われる→実は常にアニメーションキューが空にならない→ヒープが積み重なっていく?

試しに元記事のようにsetIntervalを3000msにしたら、パソコンの唸りがなくなったり、Heapの青い線の増加のしかたが上記よりも顕著ではなくなりました。なるほど。

んでは、CSSのアニメーションはどんな実装になっているのか…というのをfirefoxのソースコードでも参考に読み解いてみようと思ったのですが、挫折しました。たぶんGPUが処理しているから速い(小学生並みの理解)

10年くらい前だと、CSSを多用したページはかくかくした動きをしていた気がするのですが、いろいろ進化しているようです。

補遺

ちなみにscript1.jsですが、おなじ要素を何度もクリックしたり、別の<div>要素をクリックした場合、点滅の仕方がおかしくなります。(元ネタの記事のスクリプトは、おそらく画面描画時に一度だけ呼ばれる事を前提にしているため問題ありません)
当記事のスクリプトは検証用なので気にしませんが、あえて実用に修正するなら以下のような二度押し防止策が必要でしょう。

  • setInterval()の戻り値を変数に持ち、その変数がnullの時だけsetInterval()する
  • Unserscore#onceなどをつかって、一度しか動かさない

参考

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?