ダメ。ゼッタイ。
スクロールの
スピード違反
時間を懸けたコンテンツ。
読まずにスクロールは
即逮捕!

image: ダメ。ゼッタイ。スクロールのスピード違反
Speeding Enforcement

スクロールスピードを検知し、速すぎるときは警告!をjavascriptで実装。

 | 2025/05/29

経緯

まじめなWEB技術の研究以外にも、ちょっとした遊びを
  • スクロールのスピード率を計測

    サイトの向上のため、ページ単位でも、ユーザーがどの位滞在しているのか?どのくらいスクロールしているのか?など詳細なデータを記録しています。そんな時、ちょっとがっかりするのが、どうみても、スクロール早すぎだろ、これじゃ記事読めないよね。ってデータですね。
    そんなわけで、あんまり早いスクロールはちょっと文句いってやるかって感じで開発してみました。

方法

スピード違反の定義
  • クロールの時間と移動距離の比率で判定

    道交法では瞬間的にでも、定められた制限速度を超過した時点で違反となります。が、
    今回の趣旨はコンテンツを明らかに読まずにすっ飛ばしているのはスピード違反と判定したいので、ある距離を移動する時間が制限時間より早い場合をスピード違反と判定します。
    方法はいろいろあるんですが…。setTimeout、requestAnimationFrameなどを使って一定時間内の距離と時間の割合。スクロールの開始から終了までを判定しその時間内の距離との比率。ある一定の距離を一回のスクロールで移動したら違反(たとえば、ブラウザの高さの1.2倍を一度に移動)。などなど。これらを組み合わせたりして定義します。

コード

コーディング
  • 新しい時間計測関連の関数performance.now()

    date,now()が過去のある時を基点とする絶対時刻なのに対して、performance.now()はページ読み込み後を基点とした相対的時刻を計測します。リロードするとまた、ゼロに戻り再計測します。そのため、計測が簡単で非常に使いやすいです。
    下記はスクロールの開始から終了までの距離と時間を計測し、その比率を計算するコードです。
    今回のスクロールの状態監視はスクロールイベントをチェックする方法ではなく
    スクロールの開始と終了の座標を比較し距離と時間を測定しています。
    詳細はonsole.logで確認してください。
    もう少し説明するとrequestAnimationFrameは16ms後にイベントが発生するので
    https://studio-happyvalley.com/labo/generate_events_at_regular_intervals/参照
    プログラム起動時の座標と16ms後の座標を比較し同じでなければスクロール中、同じであればスクロール停止と判断します。
    もっとも、16msをもっと長くすることも可能ですが重要なのは時間よりスクロール距離なので変更してません。

    llet startTime = null;
    let startScrollY = null;
    let lastScrollY = window.scrollY;
    let isScrolling = false;
    
    function trackScroll() {
        const currentScrollY = window.scrollY;
    
        if (currentScrollY !== lastScrollY) {
            // スクロール中
            if (!isScrolling) {
                startTime = performance.now();
                startScrollY = currentScrollY;
                isScrolling = true;
            }
    console.log(`スクロール中
    lastScrollY: ${lastScrollY}
    currentScrollY: ${currentScrollY}
    `);
            lastScrollY = currentScrollY;
            requestAnimationFrame(trackScroll);
        } else if (isScrolling) {
           // スクロールが停止したと判断 currentScrollY と lastScrollYが同じ
    console.log(`スクロール停止
    lastScrollY: ${lastScrollY}
    currentScrollY: ${currentScrollY}
    `);
            const endTime = performance.now();
            const elapsed = endTime - startTime;
            const distance = Math.abs(lastScrollY - startScrollY);
    
            console.log(`スクロール時間: ${elapsed.toFixed(2)}ms`);
            console.log(`スクロール距離: ${distance}px`);
    
            // 状態リセット
            startTime = null;
            startScrollY = null;
            isScrolling = false;
        } else {
            // スクロールが再開されるまで監視
            requestAnimationFrame(trackScroll);
        }
    }
    
    // 監視を開始
    trackScroll();
  • performance.now()を使ったスクロール中の時間と距離を測定するJS

    performance.now()を使ったスクロール中の時間と距離を測定するJS:https://labo.studio-happyvalley.com/speedWarning/trackScroll/

完成品

完成品にいろいろおまけを追加してみました。
  • スクロールのスピード違反を単純に『ピリピリー!スピード違反!』と言うだけではつまらない

    道交法でも違反者には免停、再度講習を受けないといけないのと同じように、ここでも違反するとスクロール禁止、テストの受講、という遊びを入れてみました。
    このテスト問題の解答の照合方法がかなり面白かったので、機会をみてご紹介したいと思います。
    また、テーマがスクロールなので左上に現在全体のどのあたりをスクロール中か一目でわかるナビゲーションも追加しました。
    これも意外と面白かったので後ほどご紹介したいと思います。
    下記にその完成品のサンプルを参照しました。
    免停解除の問題は3種類あります。ランダムで表示されます。
    スクロールのスピード違反を取り締まるJS:https://labo.studio-happyvalley.com/speedWarning/

『ダメ。ゼッタイ。.スクロールのスピード違反』関連のお薦め

このページで紹介しているプログラムやビジュアルなどご依頼いただければ実装を賜ります。
お問い合わせはこちら