JavaScriptスクロールイベント

概要: このチュートリアルでは、JavaScriptスクロールイベントとその適切な処理方法について学習します。

JavaScriptスクロールイベントの紹介

ドキュメントまたは要素をスクロールすると、ブラウザはスクロールイベントを発生させます。スクロールイベントは次の方法でトリガーできます。

  • スクロールバーの手動使用
  • マウスホイール
  • IDリンクのクリック
  • JavaScriptでの関数の呼び出し
  • など。

scrollイベントハンドラを登録するには、対象要素でaddEventListener()メソッドを呼び出します。

targetElement.addEventListener('scroll', (event) => {
    // handle the scroll event 
});Code language: PHP (php)

または、対象要素のonscrollプロパティにイベントハンドラを割り当てます。

targetElement.onscroll = (event) => {
    // handle the scroll event
};Code language: JavaScript (javascript)

ドキュメントのスクロール

通常、ページ全体のスクロールを処理するために、windowオブジェクトにscrollイベントのイベントハンドラを登録します。

たとえば、次の例は、ページのscrollイベントにイベントハンドラをアタッチする方法を示しています。

window.addEventListener('scroll',(event) => {
    console.log('Scrolling...');
});Code language: JavaScript (javascript)

あるいは、windowオブジェクトのonscrollプロパティを使用することもできます。

window.onscroll = function(event) {
    //
};Code language: JavaScript (javascript)

windowオブジェクトのonscrollプロパティはdocument.body.onscrollと同じであり、互換性があります。

document.body.onscroll = null;
console.log(window.onscroll); // nullCode language: JavaScript (javascript)

スクロールオフセット

windowオブジェクトには、スクロールイベントに関連する2つのプロパティがあります: scrollXscrollY

scrollXscrollYプロパティは、ドキュメントが現在水平方向と垂直方向にスクロールされたピクセル数を返します。scrollXscrollYは倍精度浮動小数点値なので、整数値が必要な場合は、Math.round()を使用して丸めることができます。

ドキュメントがまったくスクロールされていない場合、scrollXscrollYは0になります。

pageXOffsetpageYOffsetは、scrollXscrollYプロパティのエイリアスです。

要素のスクロール

windowオブジェクトと同様に、scrollイベントハンドラを任意のHTML要素にアタッチできます。ただし、スクロールオフセットを追跡するには、scrollXscrollYの代わりにscrollTopscrollLeftを使用します。

scrollTopプロパティは、要素のコンテンツが垂直方向にスクロールされたピクセル数を設定または取得します。scrollLeftプロパティは、要素のコンテンツが左端からスクロールされたピクセル数を取得および設定します。

次の例は、idがscrollDemodiv要素のscrollイベントを処理する方法を示しています。

<!DOCTYPE html>
<html>
<head>
    <title>JS Scroll Events</title>
    <style>
        #scrollDemo {
            height: 200px;
            width: 200px;
            overflow: auto;
            background-color: #f0db4f
        }

        #scrollDemo p {
            /* show the scrollbar */
            height: 300px;
            width: 300px;
        }
    </style>
</head>
<body>
    <div id="scrollDemo">
        <p>JS Scroll Event Demo</p>
    </div>

    <div id="control">
        <button id="btnScrollLeft">Scroll Left</button>
        <button id="btnScrollTop">Scroll Top</button>
    </div>

    <script>
        let control = document.querySelector('#control');

        control.addEventListener('click', function (e) {
            // get the scrollDemo
            let div = document.getElementById('scrollDemo');
            // get the target
            let target = e.target;
            // handle each button's click
            switch (target.id) {
                case 'btnScrollLeft':
                    div.scrollLeft += 20;
                    break;

                case 'btnScrollTop':
                    div.scrollTop += 20;
                    break;
            }
        });
    </script>
</body>
</html>
Code language: HTML, XML (xml)

スクロールイベントを処理するより良い方法

ページまたは要素をスクロールしている間、多くのscrollイベントが発生します。scrollイベントにイベントリスナーをアタッチすると、イベントハンドラのコードの実行に時間がかかります。

これは、スクロールジャンクとして知られる問題を引き起こします。スクロールジャンク効果は遅延を引き起こし、ページが指に固定されていないように感じさせます。

イベントスロットリング

タイマーを使用して、scrollイベントハンドラを軽量に保ち、Nミリ秒ごとに実行する方がはるかに優れています。そのため、次のコード(決して使用しないでください)を使用する代わりに

window.scroll = () => {
    // place the scroll handling logic here
};
Code language: JavaScript (javascript)

次のコードを使用する必要があります。

let scrolling = false;

window.scroll = () => {
    scrolling = true;
};

setInterval(() => {
    if (scrolling) {
        scrolling = false;
        // place the scroll handling logic here
    }
},300);
Code language: JavaScript (javascript)

動作方法

  • まず、scrollingフラグをfalseに設定します。scrollイベントが発生した場合、scrollイベントハンドラ内でscrollingフラグをtrueに設定します。
  • 次に、scrollイベントが発生した場合は、300ミリ秒ごとにsetInterval()を使用してscrollイベントハンドラを実行します。

このscrollイベントの処理方法は、イベントスロットリングと呼ばれ、onscrollの基本的な操作を300ミリ秒ごとにスロットルします。スロットリングは、スクロールイベントハンドラの速度を低下させます。

パッシブイベント

最近、最新のWebブラウザは、scrolltouchstartwheelなどの入力イベントでパッシブイベントをサポートするようになりました。これにより、UIスレッドは、カスタムイベントハンドラに制御を渡す前に、イベントをすぐに処理できます。

パッシブイベントをサポートするWebブラウザでは、preventDefault()を呼び出さないイベントリスナーにpassiveフラグを追加する必要があります。

document.addEventListener(
    'scroll',
    (event) => {
        // handle scroll event
    }, 
    { passive: true }
);
Code language: JavaScript (javascript)

passiveオプションがない場合、イベントハンドラのコードは、UIスレッドがスクロールを実行する前に常に呼び出されます。

パッシブイベントをサポートしているブラウザについては、こちらをご覧ください。

まとめ

  • scrollイベントは、ウェブページまたは要素をスクロールしたときに発生します。
  • ページの場合、scrollXscrollYプロパティは、ドキュメントが現在水平方向と垂直方向にスクロールされたピクセル数を返します。
  • 要素の場合、scrollTopscrollLeftプロパティは、要素のコンテンツが垂直方向にスクロールされたピクセル数と、左端からスクロールされたピクセル数を設定または取得します。
  • スクロールイベントをより適切に処理するには、イベントスロットリングテクニックを使用します。最新のWebブラウザでは、パッシブイベントリスナーを使用できます。
このチュートリアルは役に立ちましたか?