Jquery动画滚动问题

时间:2017-05-03 21:01:20

标签: javascript jquery html css

我正在尝试创建一个每次用户滚动到"的功能。一些容器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中因为bug无论如何都会重现,它只是尝试修复它但是我不知道是否应该保留或删除这些功能。我也很感激你的建议

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;  
}

我已就此事做了几项研究,但我无法解决这个问题。很感谢任何形式的帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

您的代码非常复杂,因此我的修改可能仍然存在问题但可能会帮助您或提供一些新的想法。

Check out my modified fiddle here

首先,我建议你使用这个跨浏览器的jQuery mousewheel插件: https://github.com/jquery/jquery-mousewheel

只有你的事件监听器:

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

我还在使用here

中的isElementInViewport技巧

为了检查div的顶部/底部的视口可见性,我已将as-topas-bottom标记元素添加到html中,如下所示:

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

现在这一切都来自我,希望你能用它......