KEPRATE(ケプレイト)|大阪府枚方市・交野市・寝屋川市を中心に活動しているフリーランスWeb制作事務所 WordPress・レスポンシブ対応ならおまかせ!

マウスホイール時に余韻を与えなめらかに画面スクロールさせる

2018/05/02
Category :
  1. JavaScript
Tags :
  1. 自作

マウスホイールのスクロールの余韻がええ感じのサイトをたまに見かけるけどJavaScriptのソースを解析しづらかったので自作。
メモとして気になった箇所など残しておく。

JavaScript

ソースの中身。

$(function() {

    function KepMouseWheelSmooth() {

        var t = this;
        t.scrollTargetPos = 0;
        t.scrollPos = 0;
        t.delta;
        t.timeoutId;
        t.decelerationBase = 0.1;//この値が小さいほど減速率がゆるやかに

        t.wheelFlag = false;

        t.mouseWheelEvent = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';

        t.bodyH = $('body').innerHeight();
        t.winH = $(window).height();

        $(document).on(t.mouseWheelEvent, function(e) {

            //safariだとテキスト選択中おかしい
            if(!t.wheelFlag){
                var selection = getSelection();
                if(selection.rangeCount > 0){
                  var range = selection.getRangeAt(0);
                  selection.removeAllRanges();
                }
            }

            e.preventDefault();
            clearTimeout(t.timeoutId);
            t.wheelFlag = true;

            t.delta = e.originalEvent.deltaY ? -(e.originalEvent.deltaY) : e.originalEvent.wheelDelta ? e.originalEvent.wheelDelta : -(e.originalEvent.detail);

            //Firefoxだけdeltaの値が10分の1
            if (uaObj.browserName == 'firefox') t.delta = t.delta * 15;

            t.scrollPos -= t.delta;//ターゲットY値 リミット値を設ける
            if (t.scrollPos < 0) t.scrollPos = 0;
            if (t.scrollPos > t.bodyH - t.winH) t.scrollPos = t.bodyH - t.winH;

            t.timeoutId = setTimeout(function() {t.wheelFlag = false; }, 1000);//ホイール完了後は処理軽減

            return false;

        });

        // ブラウザから出た時 処理軽減
        $('body').on('mouseleave', function(e) {

            clearTimeout(t.timeoutId);
            t.wheelFlag = false;
            t.deceleration = 0;//スクロールバーのノブを動作させた時のガクるのを抑えるため
            return false;

        });

        $('body').on('mouseenter', function(e) {

            t.deceleration = t.decelerationBase;
            return false;

        });

        //スクロールバーで動作させたあとの値取得
        t.scrollFunc = function() {
            //スクロールバーの処理
            if (!t.wheelFlag) {
                t.scrollPos = $(document).scrollTop();
                t.scrollTargetPos = $(document).scrollTop();
            }
        }

        //初期値を取得
        t.scrollPos = $(document).scrollTop();
        t.scrollTargetPos = $(document).scrollTop();

        $(window).on('scroll', function() { t.scrollFunc() });

        t.smoothScrollfunc = function() {

            if (t.wheelFlag) {
                var ty = (t.scrollPos - $(document).scrollTop()) * t.deceleration;//(ターゲットY値-現在Y値)*減速率
                t.scrollTargetPos += Math.floor(ty);
                $(document).scrollTop((t.scrollTargetPos));
            }

            requestAnimationFrame(t.smoothScrollfunc);//requestAnimationFrame これは革命です

        }

        t.deceleration = t.decelerationBase;
        t.smoothScrollfunc();

    }

    //PCのみ発動
    if (uaObj.deviceName == "PC") var kepMouseWheelSmooth = new KepMouseWheelSmooth();

});

実装するにあたりハックした点

  1. Firefoxだとdelta(マウスホイールの移動量)の値が約10分の1になるのでFirefoxだけ15倍にした。
  2. 実装したスムーススクロールだとSafariだとテキスト選択中だとスクロールがなぜか重たくなったのでマウスホイール時はテキスト選択解除した。
  3. マウスホイールイベントとスクロールバーのノブを動かす動作がバッティングするのでブラウザ範囲から出た時を感知してごにょごにょした。
  4. スマホはもとからスムースな動作で余計な処理は入れたくなかったのでPCのみ対応。

勉強になった点

  1. テキスト選択の解除の仕方が分かった。まぁなかなか扱いどころがなさそうですが・・・
  2. requestAnimationFrameが便利。今まで使用しているライブラリに内部的に使用されてはいたですが自作してみてsetintervalでアニメーションさせた場合との違いにたまげました。
  3. Flashではよく使用していた減速率の公式を何年ぶりかに使用。
    プロパティ+=(ターゲット値-現在値)*減速率

隣の席でもっさりしたスクロールに悩んでいる可愛いWeb女子に教えて 君もモテモテだ!

  1. ソースの流用、改変は自由ですが自己責任とさせていただきます。
トラックバック URL
https://keprate.com/web/javascript/mouse-wheel-smooth/trackback/
奇跡的に興味を持たれた方は
是非お問い合わせください。
  • 電話番号の掛け間違いにお気をつけください。
  • 女性は業務に一切関係ございません。
PAGE TOP