【JavaScript】最後までスクロールが必要な利用規約と同意・登録機能を実装する

Scroll-All

こんにちはフロントエンドエンジニアのまさにょんです!

今回は、JavaScriptで最後までスクロールが必要な利用規約と同意・登録機能を実装する方法について解説します。

最後までスクロールが必要な利用規約と同意・登録機能の要件と実装ロジック

最後までスクロールが必要な利用規約と同意するのチェックボックスは、よく見ますね。

今回は、それを実装していきます。

要件定義と実装ロジックは次のとおりです。

要件定義

  1. 最後までスクロールをしたら同意するにCheckができるようになる。
  2. 同意するにCheckがついていないと登録ボタンは押せない。

実装ロジック

  1. 最後までスクロールをしたら「同意するCheckBox」のdisabledをfalseにする。
  2. 「同意するCheckBox」にCheckedになったら「登録するボタン」のdisabledをfalseにする。
  3. スクロールBoxを最後までScrollしたかの判定は、scrollHeight, clientHeight, scrollTopの計算で実施する。

スクロールBoxを最後までScrollしたかの判定は、scrollHeight, clientHeight, scrollTopの計算で実施する。

に関しては、別途、解説します。

SampleCode全文とHTML実行イメージ

【 最後までスクロールが必要な利用規約と同意・登録機能を実装する 】
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll-Box-Test🔥</title>
    <style>
        #privacy-policy {
            height: 300px;
            border: 1px solid;
            overflow-y: scroll;
        }
        #policy-checkbox {
            margin: 20px 20px 20px 40px;
            transform: scale(2);
        }
        .policy-accept{
            font-size: 20px;
        }
        #register{
            margin: 10px;
            width: 300px;
            padding: 10px;
            box-sizing: border-box;
            border: 1px solid #68779a;
            background: white;
            cursor: pointer;
        }
        #register:hover{
            background: #136bca;
        }
    </style>
</head>
<body>
    <h1>Scroll-Box の Testをするロボ玉🔥</h1>

    <h2>最後までスクロールが必要な利用規約と同意するを実装する</h2>

    <h2>最後までスクロールされたかを判定する</h2>

    <p>判定方法</p>

    <p>clientHeight + scrollTop = scrollHeight</p>

    <p>onscroll でスクロールした時のイベント情報を取得できます</p>

    <div id="privacy-policy">
        <h2><b>プライバシーポリシー</b></h2>

        <h3><b>1. 個人情報の利用目的</b></h3>
        <p>当ブログでは、お問い合わせや記事へのコメントの際、名前やメールアドレス等の個人情報を入力いただく場合がございます。</p>
        <p>取得した個人情報は、お問い合わせに対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、これらの目的以外では利用いたしません。</p>

        <h3><b>2. アクセス解析ツールについて</b></h3>
        <p>当ブログでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。</p>
        <p>このGoogleアナリティクスはトラフィックデータの収集のためにクッキー(Cookie)を使用しております。</p>
        <p>トラフィックデータは匿名で収集されており、個人を特定するものではありません。</p>

        <h3><b>3. 免責事項</b></h3>
        <p>当ブログからのリンクやバナーなどで移動したサイトで提供される情報、サービス等について一切の責任を負いません。</p>
        <p>また当ブログのコンテンツ・情報について、できる限り正確な情報を提供するように努めておりますが、正確性や安全性を保証するものではありません。情報が古くなっていることもございます。</p>
        <p>当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。</p>

        <h3><b>4. 著作権について</b></h3>
        <p>当ブログで掲載している文章や画像などにつきましては、無断転載することを禁止します。</p>
        <p>当ブログは著作権や肖像権の侵害を目的としたものではありません。</p>
        <p>著作権や肖像権に関して問題がございましたら、お問い合わせフォームよりご連絡ください。迅速に対応いたします。</p>
        
        <h3><b>5. リンクについて</b></h3>
        <p>当ブログは基本的にリンクフリーです。リンクを行う場合の許可や連絡は不要です。</p>
        <p>ただし、インラインフレームの使用や画像の直リンクはご遠慮ください。</p>
    </div>

    <div>
        <label for="policy-checkbox">
            <input type="checkbox" id="policy-checkbox" disabled>
            <span class="policy-accept">同意する</span>
        </label>
    </div>

    <div>
        <button id="register" type="button" onclick="RegisterProcess()" disabled>登録する</button>
    </div>

    <h3>参考・引用</h3>
    <ol>
        <li>
            <a href="https://qiita.com/buntafujikawa/items/fcf48a25146808e0542f" target="_blank">JavaScriptで最後までスクロールしないとチェックできない規約を作る</a>
        </li>
        <li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll_event" target="_blank">MDN: Element: scroll event</a>
        </li>
        <li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight" target="_blank">MDN: Element.clientHeight</a>
        </li>
        <li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop" target="_blank">MDN: Element.scrollTop</a>
        </li>
        <li>
            <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight" target="_blank">MDN: Element.scrollHeight</a>
        </li>
    </ol>

    <script>

        // 1. 同意するCheckBox
        const policyCheckBox = document.getElementById('policy-checkbox');
        console.log({policyCheckBox});

        // 2. 登録するボタン
        const registerButton = document.getElementById('register');
        console.log({registerButton});

        // 3. CheckBoxのChangeイベントで発火するDisabled-Switch
        function RegisterOK (){
            // 4. 同意するCheckが入ったら、登録するボタンが押せるようになる
            if (policyCheckBox.checked) {
                registerButton.disabled = false;
            } else {
                registerButton.disabled = true;
            }
            console.log({RegisterDisabled: registerButton.disabled});
        }

        // 5. 登録するボタンを押したときの実行処理-Function
        function RegisterProcess() {

            console.log('プライバシーポリシーに同意!登録ボタンが押されたロボ玉🔥');

            // 本来は、ここに通信処理などを記述する
        }

        // 6. CheckBoxにEventを追加する => CheckBoxのON/OFFイベントを検知する
        policyCheckBox.addEventListener('change', RegisterOK);

        const privacyPolicy = document.getElementById('privacy-policy');

        console.log({privacyPolicy});

        // [ 7. スクロールイベントの際の処理 ]

        // 1. onscroll => スクロール時のEventを取得する
        privacyPolicy.onscroll = (event) => {

            console.log({event});

            // 2. Scrollが発生した要素
            const target = event.target;
            console.log({target});

            // 3. element.scrollHeight
            // => overflow-y によって画面に描画されていないコンテンツも含むheightを測定する
            console.log({scrollHeight: target.scrollHeight});

            // 4. element.clientHeight
            // => 指定したElementのheightを測定する
            console.log({clientHeight: target.clientHeight});

            // 5. element.scrollTop
            // => 指定したElementを垂直にScrollしたピクセル数を取得する
            console.log({scrollTop: target.scrollTop});

            console.log(`scrollHeight = clientHeight + scrollTop`);
            console.log(`${target.scrollHeight} = ${target.clientHeight} + ${target.scrollTop}`);

            // 6. プライバシーポリシーのScrollBoxが最後までScrollされたら「同意ボタン」が押せるようになる!
            if (Math.abs(target.scrollHeight - target.clientHeight - target.scrollTop) < 1) {
                policyCheckBox.disabled = false;
            } 

        };

    </script>
</body>
</html>

【実装ポイント】スクロールイベントの際の処理

今回の実装のポイントである「スクロールイベント」の際の処理について解説していきます。

まず要点をピックアップすると次のとおりです。

  1. Element.onscroll は、スクロール要素がスクロールされるとEventが発生します。
  2. id名「privacy-policy」は「overflow-y: scroll;」でスクロール要素になっています。
  3. element.scrollHeight は、画面に描画されていないコンテンツも含むheightを測定します。
  4. element.clientHeight は、指定したElementのheightを測定します。
  5. element.scrollTop は、指定したElementを垂直にScrollしたピクセル数を取得します。

混乱しやすいのは、次の3つでしょう。

scrollHeight(見えてない部分も含むスクロールBox全体の高さ)

clientHeight(画面に見えている高さ)

scrollTop(スクロールしたpx・Scrollした高さ)

これは「 scrollHeight = clientHeight + scrollTop 」と言う関係性です。

画面に見えている高さとScrollした高さをプラスすると、見えてない部分も含むスクロールBox全体の高さになります。

ただし、厳密性を求めて計算式は次のものを適用します。

要素が完全にスクロールされたかどうかを判断する

scrollTopは丸められていない数値ですが、scrollHeightclientHeightは丸められます。

したがって、スクロール領域が一番下までスクロールされているかどうかを判断する唯一の方法は、スクロール量がしきい値に十分近いかどうかを確認することです (この例では1)。

Math.abs(element.scrollHeight – element.clientHeight – element.scrollTop) < 1

以下は、小数を含む可能性があるため、常に機能するとは限りません。scrollTop

element.scrollHeight – Math.abs(element.scrollTop) === element.clientHeight

引用元: MDN: Element.scrollHeight
// [ 7. スクロールイベントの際の処理 ]

// 1. onscroll => スクロール時のEventを取得する
privacyPolicy.onscroll = (event) => {

    console.log({event});

    // 2. Scrollが発生した要素
    const target = event.target;
    console.log({target});

    // 3. element.scrollHeight
    // => overflow-y によって画面に描画されていないコンテンツも含むheightを測定する
    console.log({scrollHeight: target.scrollHeight});

    // 4. element.clientHeight
    // => 指定したElementのheightを測定する
    console.log({clientHeight: target.clientHeight});

    // 5. element.scrollTop
    // => 指定したElementを垂直にScrollしたピクセル数を取得する
    console.log({scrollTop: target.scrollTop});

    console.log(`scrollHeight = clientHeight + scrollTop`);
    console.log(`${target.scrollHeight} = ${target.clientHeight} + ${target.scrollTop}`);

    // 6. プライバシーポリシーのScrollBoxが最後までScrollされたら「同意ボタン」が押せるようになる!
    if (Math.abs(target.scrollHeight - target.clientHeight - target.scrollTop) < 1) {
        policyCheckBox.disabled = false;
    } 

};

JavaScript書籍 Ver. 中級-上級者向け

JavaScript書籍 Ver. 初級者向け

Twitterやってます!Follow Me!

神聖グンマー帝国の逆襲🔥

神聖グンマー帝国の科学は、世界一ぃぃぃぃぃぃ!!!!!

参考・引用

  1. JavaScriptで最後までスクロールしないとチェックできない規約を作る
  2. MDN: Element: scroll event
  3. MDN: Element.clientHeight
  4. MDN: Element.scrollTop
  5. MDN: Element.scrollHeight

【おすすめ関連記事】

【 指定した画面の位置まで自動スクロール 】
【 Cookieの利用同意と拒否のバナーを作る 】
【 Cookieの取得・追加・更新・削除・有効期限の設定 】

最近の投稿