質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

resizeするとスクロールイベントの挙動がおかしくなる

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,027
退会済みユーザー

退会済みユーザー

やりたい事

#next_aをクリックしたら#section_aまでスクロールし、
0.8秒後に.contentまで自動でスクロールする。(bとcは省略)
という事をしたいのですが、以下のコードで一応できました。

しかし、画面の向きを変えresize後に上記の事をするとスクロールの挙動がおかしくなります。
コンソールで確認すると、どうやらresizeする前のスクロール位置とresize後のスクロール位置が交互に読み込まれているみたいです。

多分、resizeする度にoffset().topを取得すれば解決すると思うのですが、やり方が分かりません。
どのようにしたら良いでしょうか?

また、上記のほかに解決策があればそちらも教えて頂きたいです。

宜しくお願いします。

  var resizeTimer = null;
  $(window).on('load resize', function () {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(function () {

    var hSize = $(this).height();
        $('.content').height(hSize);

    var $a = $('#section_a'),
        $b = $('#section_b'),
        $c = $('#section_c'),
        aTop = $a.offset().top,
        a_contentTop = $a.find('.content').offset().top,
        bTop = $b.offset().top,
        b_contentTop = $b.find('.content').offset().top,
        cTop = $c.offset().top,
        c_contentTop = $c.find('.content').offset().top;

        $('#next_a').on('click', function () {
            $('body,html').animate({
                scrollTop: $a
            }, 800, autoscroll_a);
        });

        $('#next_b').on('click', function () {
            $('body,html').animate({
                scrollTop: $b
            }, 800, autoscroll_b);
        });

        $('#next_c').on('click', function () {
            $('body,html').animate({
                scrollTop: $c
            }, 800, autoscroll_c);
        });

       function autoscroll_a() {
            setTimeout(function () {
                $('body,html').animate({
                    scrollTop: $a_contentTop
                }, 300);
            }, 800)
        }

        function autoscroll_b() {
            setTimeout(function () {
                $('body,html').animate({
                    scrollTop: $b_contentTop
                }, 300);
            }, 800)
        }

        function autoscroll_c() {
            setTimeout(function () {
                $('body,html').animate({
                    scrollTop: $c_contentTop
                }, 300);
            }, 800)
        }

    }, 200);
コード

※追記

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <title>TEST</title>

    <style>
        body {
            margin: 0;
        }

        .btn,
        .first_btn {
            position: relative;
        }

        #next_a,
        #next_b,
        #next_c,
        #top {
            font-size: 25px;
            cursor: pointer;
            position: absolute;
            bottom: 50px;
            left: 50%;
            margin-left: -25px;
        }

        .title,
        .content {
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .title {
            font-size: 25px;
            background: #000;
            color: #fff;
        }

        .content {
            font-size: 20px;
            background: #eee;
        }
    </style>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

</head>

<body>

    <div class="first_btn">
        <div id="next_a">次へ</div>
    </div>
    <section id="section_a">
        <div class="title">
            <h2>a</h2>
        </div>
        <div class="content">
            <h3>ここに内容</h3>
        </div>
        <div class="btn">
            <div id="next_b">次へ</div>
        </div>
    </section>
    <section id="section_b">
        <div class=title>
            <h2>b</h2>
        </div>
        <div class="content">
            <h2>ここに内容</h2>
        </div>
        <div class="btn">
            <div id="next_c">次へ</div>
        </div>
    </section>
    <section id="section_c">
        <div class="title">
            <h2>c</h2>
        </div>
        <div class="content">
            <h2>ここに内容</h2>
        </div>
        <div class="btn">
            <div id="top">戻る</div>
        </div>
    </section>

    <script>
        var resizeTimer = null;
        $(window).on('load resize', function() {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(function() {

                var hSize = $(this).height();
                $('.first_btn,.title,.content').height(hSize);


                var $a = $('#section_a'),
                    $b = $('#section_b'),
                    $c = $('#section_c'),
                    aTop = $a.offset().top,
                    a_contentTop = $a.find('.content').offset().top,
                    bTop = $b.offset().top,
                    b_contentTop = $b.find('.content').offset().top,
                    cTop = $c.offset().top,
                    c_contentTop = $c.find('.content').offset().top;

                $('#next_a').on('click', function() {
                    $('body,html').animate({
                        scrollTop: aTop
                    }, 800, autoscroll_a);
                });

                $('#next_b').on('click', function() {
                    $('body,html').animate({
                        scrollTop: bTop
                    }, 800, autoscroll_b);
                });

                $('#next_c').on('click', function() {
                    $('body,html').animate({
                        scrollTop: cTop
                    }, 800, autoscroll_c);
                });

                $('#top').on('click', function() {
                    $('body,html').animate({
                        scrollTop: 0
                    }, 800);
                });

                function autoscroll_a() {
                    setTimeout(function() {
                        $('body,html').animate({
                            scrollTop: a_contentTop
                        }, 300);
                    }, 800);
                }

                function autoscroll_b() {
                    setTimeout(function() {
                        $('body,html').animate({
                            scrollTop: b_contentTop
                        }, 300);
                    }, 800);
                }

                function autoscroll_c() {
                    setTimeout(function() {
                        $('body,html').animate({
                            scrollTop: c_contentTop
                        }, 300);
                    }, 800);
                }

            }, 200);
        });
    </script>
</body></html>
コード

※最初のjQueryのコードを少し書き変えました。(基本的なところは変えていません)
上記のコードを見て頂けると分るかと思うのですが、
質問の内容の通り、resizeするとスクロールの挙動がおかしくなります。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • hatena19

    2019/09/21 09:26

    htmlも提示してもらえると、回答者が検証しやすくなります。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2019/09/21 14:09

    申し訳ございません。
    追記しておきます。

    キャンセル

回答 2

checkベストアンサー

+2

HTMLの提示がないので検証はしてませんが、下記のような感じになるのでは。
HTMLの提示があったので、検証してみました。
元のコードをコピペして移動させただけでしたが、よく読んだらコード間違いが散見されたので修正しました。
これで、こちらの検証ではエラーなく動いてますが、これがご希望の動作かどうかは判断しかねます。

$(function () {
    var resizeTimer = null,
        $a = $('#section_a'),
        $b = $('#section_b'),
        $c = $('#section_c'),
        aTop, a_contentTop, bTop, b_contentTop, cTop, c_contentTop;

    $('#next_a').on('click', function () {
        $('body,html').animate({
            scrollTop: aTop
        }, 800, autoscroll_a);
    });

    $('#next_b').on('click', function () {
        $('body,html').animate({
            scrollTop: bTop
        }, 800, autoscroll_b);
    });

    $('#next_c').on('click', function () {
        $('body,html').animate({
            scrollTop: cTop
        }, 800, autoscroll_c);
    });

    function autoscroll_a() {
        setTimeout(function () {
            $('body,html').animate({
                scrollTop: a_contentTop
            }, 300);
        }, 800)
    }

    function autoscroll_b() {
        setTimeout(function () {
            $('body,html').animate({
                scrollTop: b_contentTop
            }, 300);
        }, 800)
    }

    function autoscroll_c() {
        setTimeout(function () {
            $('body,html').animate({
                scrollTop: c_contentTop
            }, 300);
        }, 800)
    }

    //位置取得
    $(window).on('load resize', function () {
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function () {

            var hSize = $(this).height();
            $('.content').height(hSize);
            aTop = $a.offset().top;
            a_contentTop = $a.find('.content').offset().top;
            bTop = $b.offset().top;
            b_contentTop = $b.find('.content').offset().top;
            cTop = $c.offset().top;
            c_contentTop = $c.find('.content').offset().top;

        }, 200);
    });
});

load resize イベントでは位置取得のみにするようにすればいいかと。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/21 16:32

    ご回答ありがとうございます。
    上記のコードを参考に、追記したコードを書き換えてみたのですがエラーが出ました。
    エラー個所の記述を消していっても次から次にエラーが出てきていて、エラーの特定には至りませんでした。

    キャンセル

  • 2019/09/21 17:07

    ご回答ありがとうございます!
    上記のコードで無事 動作確認が取れました。
    ありがとうございます!
    最後に一つお聞きしたいことがあるのですが、
    $(function)の中の上部にあるこちらの変数
    「aTop, a_contentTop, bTop, b_contentTop, cTop, c_contentTop;」
    ですが、これは空の変数を先に作っておき、
    $(window).on('load resize', function)で値を代入することで、
    resize後の変数を$(function)と$(window).on('load resize', function)の両方で使えるようにするという事を行っているのでしょうか?

    キャンセル

  • 2019/09/21 17:33

    はい、そういう理解であっています。

    キャンセル

  • 2019/09/21 17:35

    ありがとうございます!

    キャンセル

+1

HTMLコードがないため確認できませんが、おそらく resize イベントのたびに click イベントのリスナを設定しているからだと思います。これは上書きされずに複数登録されますから、上手く動作しなくなるだろうと思います。

解決方法は、$('#next_a').onなどの部分を resize イベントリスナの外に出すことです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/21 14:20

    ご回答ありがとうございます。
    $('#next_a').onの部分を一式resizeイベントリスナ外に出しましたが、今度はresize時にoffset().topの値が変わらないという問題と、そもそものoffset().topの値がおかしくなるという問題がしまいました。
    詳しくは追記の方で書かせえて頂きますので、もしよろしければ一度頂けれると助かります。

    キャンセル

  • 2019/09/21 17:13

    解決することができました。
    ご回答いただきありがとうございます!

    キャンセル

  • 2019/09/21 17:15

    ご解決されて何よりです。

    キャンセル

  • 2019/09/21 17:36

    ありがとうございます^^

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る