HTML
JavaScript
jQuery

スクロールイベントの負荷を軽減しつつpagetopへスムーススクロールさせる(イベント発火回数比較)

少しスクロールするとふわっと表示されてクリックするとページ上部にひゅ〜んとスムーススクロールするボタンを実装する機会結構ありますよね?

で、jQueryで$(window).on('scroll', function〜でスクロール量が○○以上になったらfadeInして〜とかやると思うのですが、何もしないとスクロールのたびにものすごい数処理が走ってしまいます。

なので、何らかの方法でスクロールイベントの負荷軽減をしつつ実装するかと思うのですが、その方法を少し比較しつつ実際に使えるコードとして残しておきたいと思います。

スクロールイベント比較DEMO

デモの右下に表示されているボタンがそれぞれ

(1) 負荷軽減なし
(2) setTimeout使う
(3) _.throttle関数使う

になっています。

setTimeoutを使う

  var timer = null;
  $(window).on('scroll',function() {
    clearTimeout( timer );
    timer = setTimeout(function() {
      if ($(this).scrollTop() > 300) {
        $('.pagetop2').fadeIn(200);
      } else {
        $('.pagetop2').fadeOut(200);
      }
    }, 200);
  });

デモの(2)の動きです。setTimeoutで予約したミリ秒内経つまでは、clearTimeoutで予約取り消し続けて、指定ミリ秒立ったら中の処理が実行されるみたいな感じで負荷軽減するパターン。
今回の処理で使うとちょっと表示されるまでの時間がもっさりしすぎてる気がする。

lodash(プラグイン)の_.throttle関数使う

https://lodash.com/docs/4.17.4#throttle
scrollイベント中に一定間隔で処理を実行してくれるやつ
デモ(3)の動きです。

https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js

ヘッダーでlodash.min.jsを読み込んで配布先のDocumentationを参考に以下のように設定しました。

$(window).on('scroll', _.throttle(updatePosition, 250));

function updatePosition() {
  if ($(this).scrollTop() > 300) {
    $('.pagetop3').fadeIn(200);
  } else {
    $('.pagetop3').fadeOut(200);
  }
}

アニメーションの動きはスムーズですね。

イベント発火回数を比較してみる

ウィンドウサイズを780px×588pxぐらいにして、一番下までスクロールしてまた上に戻るという動作で、
$(window).on('scroll', 〜の中の「ボタン表示/非表示をスクロール量で判定する」イベントが何回呼ばれたかを、console.count();で比較してみました。

comparison.png

スクロールするスピード等で多少前後するとは思いますが、やはり何もしないとすごい回数呼ばれますね。

_.throttle関数を使ってスムーススクロールするボタンを実装してみる

比べてみた結果、lodashの_.throttle関数使う方法が負荷を軽減しつつストレスなく表示できそうなので、こちらを使ってページ上部にスムーススクロールするボタンを作りたいと思います。

DEMO

<a class="pagetop" href="#" style="display:none;"></a>

こちらのaタグにイベントを当てます。
CSSのposition: fixed;で画面の右下に配置して最初は非表示にしておきます。

<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js'></script>

必要なjsを読み込みます。2つめのjquery.easing.min.jsはイージングのアニメーションに'easeOutExpo'使いたかったので読み込んでますが、jQueryにもともと入ってるlinearswingを使うのであれば読み込む必要ありません。

jsのコードは以下の様な感じです。

$(function() {
 // 300px下にスクロールしたらボタンを表示する
  function updatePosition() {
    if ($(this).scrollTop() > 300) {
      $('.pagetop').fadeIn(200);
    } else {
      $('.pagetop').fadeOut(200);
    }
  }
  // スクロール中250ミリ秒ごとにupdatePosition実行
  $(window).on('scroll', _.throttle(updatePosition, 250));
  // .pagetpoを押すと上にスムーススクロールさせる
  $('.pagetop').on('click', function(e){
    e.preventDefault();
    $('html, body').animate({
      scrollTop: 0
    }, 800, 'easeOutExpo');
  });
});

lodashほかにも色々あるので勉強してみようと思います。