

お世話になっております。  
表題の件ですが、ウェブサイトにてページトップボタンがフッター位置まで来た時にslideUpで消えるようにしたいのですが、何回も消えたり現れたりを繰り返してしまいます。

最初の記述に、スクロールを始めた時にslideを設定しているのが引っかかっておかしくなっているのかなと思うのですが、直し方がわかりません。

当方javascript全くの初心者です。  
何卒ご教授の方よろしくお願いいたします。

<https://jsfiddle.net/aq8j1rLL/>

[code]

    $(function() {
    
      var topBtn = $('.pagetop');
    
      // ページトップボタンを非表示にする
      topBtn.hide();
    
      $(window).scroll(function() {
    
        if ($(this).scrollTop() > 0) {
          topBtn.slideDown();
        } else {
          topBtn.slideUp();
        }
    
        // フッターに到達したら非表示
    
        // ドキュメントの高さ
        scrollHeight = $(document).height();
    
        //　ウィンドウの高さ+スクロールした高さ→　現在のトップからの位置
        scrollPosition = $(window).height() + $(window).scrollTop();
    
        // フッターの高さ
        footHeight = $("footer").innerHeight();
    
        // 現在の下から位置が、フッターの高さの位置にはいったら
        if (scrollHeight - scrollPosition <= footHeight) {
    
          //  ".pagetop"のpositionをabsoluteに変更し、フッターの高さの位置にする        
          topBtn.css({
            "position": "absolute", //フッターの
          });
          topBtn.slideUp();
    
        } else {
          topBtn.css({
            "position": "fixed",
          });
          topBtn.slideDown();
        }
    
      });
    
      // トップへスムーススクロール
      $('.pagetop a').click(function() {
        $('body,html').animate({
          scrollTop: 0
        }, 'slow');
        return false;
      });
    
    });
[/code]

[code]

    html,
    body {
      width: 100%;
      height: 100%;
    }
    body {
      margin: 0;
      padding: 0;
    }
    body article {
      min-height: 100%;
      position: relative;
      height: auto !important;
      height: 100%;
    }
    #maincontent {
      width: 100%;
      height: 800px;
      padding-bottom: 48px;
    }
    /*---- フッター ----*/
    
    footer {
      width: 100%;
      height: 48px;
      background-color: black;
      position: absolute;
      bottom: 0;
    }
    /*---- ページトップボタン ----*/
    
    #pagetop-wrap {
      position: relative;
    }
    .pagetop {
      position: fixed;
      right: 20px;
      bottom: 20px;
      width: 100px;
      height: 100px;
    }
    .pagetop > a {
      width: 100px;
      height: 100px;
      font-size: 20px;
      line-height: 102px;
      background-color: #ffdd3f;
      color: white;
      text-align: center;
      border-radius: 50px;
      display: block;
      transition: all 0.6s ease-in-out 0s;
    }
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <article>
    
      <section id="maincontent"></section>
    
      <footer>
        <div id="pagetop-wrap">
          <p class="pagetop">
            <a href="#"><i class="fa fa-chevron-up"></i></a>
          </p>
        </div>
      </footer>
    
    </article>
[/code]


CC BY-SA 3.0
2017-01-07T10:25:27.330
31690
2017-02-21T00:40:36.437
2017-01-10T12:22:23.727
3054
20135
question
javascript jquery
jQuery の scroll イベントが何回も繰り返される


※だいぶコードが長いので、今回の質問と関係なさそうなところや改行を削っています

ご質問のコードでスクロール位置とslide方向の関係を見てみると...

[code]

    // ここでは this === window なので、$(window).scrollTop() と同じ
    // スクロール位置がページ上端なら slideUp()、でなければ slideDown()
    if ($(this).scrollTop() > 0) {
      topBtn.slideDown();
    } else {
      topBtn.slideUp();
    }
    
    // (略)
    
    // フッターが画面内に入るところまでスクロールしたら slideUp()
    if (scrollHeight - scrollPosition <= footHeight) {
      topBtn.css({ "position": "absolute" });
      topBtn.slideUp();
    } else {
      topBtn.css({ "position": "fixed" });
      topBtn.slideDown();
    }
    
[/code]

フッターが画面内に入るところまでスクロールした場合、 **前半のifで`slideDown()` が実行されたのちに、後半のifで `slideUp()`
が実行される**ことになります。これが原因で、出たり消えたりする動きになっています。

また scroll
イベントはスクロール位置が変わるたびに頻繁に呼び出されます。その度にこの上下運動のアニメーションが予約されるので、スクロールを止めてもしばらく動き続けます。

試しに、アニメーションの待ち数を左上に表示するようにしてみました。これを実行して、スクロールすると待ち数がどう変化するか、見てみてください。

[code]

    $(function() {
      var topBtn = $('.pagetop');
      topBtn.hide();
    
      // アニメーションの待ち数を表示
      setInterval(function(){
        $('#counter').text("queue: " + topBtn.queue().length);
      }, 200);
    
      $(window).scroll(function() {
        if ($(this).scrollTop() > 0) {
          topBtn.slideDown();
        } else {
          topBtn.slideUp();
        }
    
        scrollHeight = $(document).height();
        scrollPosition = $(window).height() + $(window).scrollTop();
        footHeight = $("footer").innerHeight();
    
        if (scrollHeight - scrollPosition <= footHeight) {
          topBtn.css({ "position": "absolute" });
          topBtn.slideUp();
        } else {
          topBtn.css({ "position": "fixed" });
          topBtn.slideDown();
        }
      });
    });
[/code]

[code]

    #counter { position: fixed; width: 10em; background: #ddf;}
    html, body { margin: 0; height: 100%; }
    article { position: relative; height: auto; }
    #maincontent { height: 800px; }
    footer { width: 100%; height: 48px; background-color: black; position: absolute; bottom: 0; }
    .pagetop { position: fixed; right: 20px; bottom: 20px; width: 100px; height: 100px; }
    .pagetop > a { width: 100px; height: 100px; background-color: #ffdd3f; border-radius: 50px; display: block; }
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="counter"></div>
    <article>
      <section id="maincontent"></section>
      <footer>
        <div id="pagetop-wrap">
          <!-- pだとマージンがついてややこしいのでdivに変更 -->
          <div class="pagetop">
            <a href="#"></a>
          </div>
        </div>
      </footer>
    </article>
[/code]

解決策は `if($(this).scrollTop() > 0)`
の方を消すことです。もしページ上端でも別の処理を実行したいなら、「ページ上端」「ページ下端」「それ以外」で分岐するなどして、
**一回のscrollイベントで slideUp/Down を複数回呼ばない** ようにしましょう。

これで「何回も消えたり現れたり」ということはなくなります。


CC BY-SA 3.0
2017-01-10T14:21:00.043
31756
2017-01-10T14:21:00.043
8000
31690
answer