簡體   English   中英

jQuery動畫滾動問題

[英]Jquery animated scrolling issue

我正在嘗試創建一個函數,每次用戶將其“滾動”到某個容器div時,網絡都會平滑滾動至該div(我不知道我是否清楚,您可以更好地了解我的JSFiddle

當用戶緩慢滾動或使用箭頭鍵時,它可以正常工作,但是如果用戶進行突然滾動,則動畫滾動根本不流暢。 有時它還會在動畫的中間朝相反的方向跳躍。

我不確定這是動量滾動的原因還是用戶快速旋轉滾輪時滾動速度增加的原因。 也許還有其他我沒想到的原因。

這是重現該錯誤的最少代碼(與JSFiddle相同)

HTML:

<body>
  <div style="background-color:red;" class="autoscroll">
    <p style="line-height:3;color:white;">
    Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem
    </p>
  </div>
  <div style="background-color:blue;" class="autoscroll">
    <p style="line-height:3;color:white;">
    Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>
    </p>
  </div>
  <div style="background-color:green;" class="autoscroll">
    <p style="line-height:3;color:white;">
    Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem
    </p>
  </div>
  <div style="background-color:brown;" class="autoscroll">
    <p style="line-height:3;color:white;">
    Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>Ipsum Lorem<br><br>
    </p>
  </div>
</body>

CSS:

.autoscroll{
  min-height:100%;
}
html, body, p{
  margin:0;
  padding:0;
}

JS:

$(function() {

  var scrollFlag = true;
  window.setTimeout(function(){

    $(window).on('wheel keydown scroll',function(event){

      var validate_scroll = false;
      var scroll_direction = '';
      if(event.type=="wheel"){
        if(event.originalEvent.deltaY < 0){
          scroll_direction = 'up';
          validate_scroll = true;
        }
        if(event.originalEvent.deltaY > 0){
          scroll_direction = 'down';
          validate_scroll = true;
        }
      }else{ //keydown
        if(event.which == 38){ //UP
          scroll_direction = 'up';
          validate_scroll = true;
        }
        if(event.which == 40){ //DOWN
          scroll_direction = 'down';
          validate_scroll = true;
        }
      }

      if(validate_scroll && scrollFlag){
        var windowHeight = $(window).height();
        var st = $(window).scrollTop();
        var st2 = windowHeight + st;

        if (scroll_direction == 'down'){ 
          //downscroll
          $('.autoscroll').each(function(){

            var ost = $(this).offset().top;
            if (ost < st2 && st < ost && scrollFlag){

              console.log('smooth scrolling down');
              disableScroll();
              scrollFlag = false;
              $('window,html,body').stop(true);

              $('html,body').animate({
                scrollTop: ost
              }, 1200, "linear", function(){
                enableScroll();
                scrollFlag = true;
              });

            }
          });
        }else if (scroll_direction == 'up'){
          //upscroll

          $('.autoscroll').each(function(){
            var ost = $(this).offset().top;
            var ost2 = ost + $(this).outerHeight(true);
            if (ost2 < st2 && st < ost2 && scrollFlag){
              console.log('smooth scrolling up');
              disableScroll();
              scrollFlag = false;
              $('window,html,body').stop(true);

              $('html,body').animate({
                scrollTop: ost2 - windowHeight
              }, 1200, "linear",  function(){
                enableScroll();
                scrollFlag = true;
              });


            }
          });
        }


      }//if validate_scroll && scrollFlag

    });

  }, 1000)
});

我還有另外兩個功能, disableScrollenableScroll 這些我沒有包含在我的JSFiddle中,因為無論如何該錯誤仍會重現,但這只是修復它的嘗試,但是我迷失了應該保留還是刪除這些功能。 我也很感謝對此的建議

var keys = {37: 1, 38: 1, 39: 1, 40: 1};

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
      e.preventDefault();
  e.returnValue = false;  
}
function preventDefaultForScrollKeys(e) {
    if (keys[e.keyCode]) {
        preventDefault(e);
        return false;
    }
}
function disableScroll() {
console.log('disabling scroll')
  if (window.addEventListener) // older FF
      window.addEventListener('DOMMouseScroll', preventDefault, false);
  window.onwheel = preventDefault; // modern standard
  window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
  window.ontouchmove  = preventDefault; // mobile
  document.onkeydown  = preventDefaultForScrollKeys;
}
function enableScroll() {
console.log('enabling scroll')
    if (window.removeEventListener)
        window.removeEventListener('DOMMouseScroll', preventDefault, false);
    window.onmousewheel = document.onmousewheel = null; 
    window.onwheel = null; 
    window.ontouchmove = null;  
    document.onkeydown = null;  
}

我對此事進行了一些研究,但無法解決。 很感謝任何形式的幫助。 謝謝。

您的代碼非常復雜,因此我的修改可能仍然有問題,但可能可以幫助您或提出一些新想法。

在這里查看我修改過的小提琴

首先,我建議您使用此跨瀏覽器的jQuery mousewheel插件: https : //github.com/jquery/jquery-mousewheel

這樣,您的事件監聽器僅是:

$(document).on('mousewheel keydown',function(event){ });

我也在這里使用isElementInViewport技巧

為了檢查div頂部/底部的視口可見性,我將as-topas-bottom標記元素添加到了html中,如下所示:

 <div class="autoscroll">
    <div class="as-top"></div>
    <p>Lipsum stuff...</p>
    <div class="as-bottom"></div>
  </div>

這就是我的全部,希望您可以使用它...

這是另一種方法:

https://jsfiddle.net/aq5a43kr/5/

該代碼被完全重寫。 它使用超時並且僅使用scroll事件,因此即使在觸摸設備上也應該可以使用。

允許快速滾動並解決您的容器填充問題,因為它在每個容器之前只需要一個標記<div class="as-marker"></div> 不需要mousewheel插件。

它可以很容易地重構為一個可以在多個可滾動元素上重復使用的jQuery插件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM