2017-05-03 185 views
0

我想做一个功能,每次用户滚动“进入”一些容器div,网页顺利滚动到该div(我不知道我是否清楚,你可以更好地管理它看着我的JSFiddlejquery动画滚动问题

当用户滚动缓慢或使用箭头键时,它可以正常工作,但如果用户做出突然滚动,则动画滚动根本不流畅。它有时也会在动画中间的相反方向上跳跃。

我不确定这是导致动量滚动还是滚动速度增加,当用户快速旋转滚轮时。或者可能是我没有想到的其他原因。

这里是最少的代码重现错误(同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) 
}); 

我也是h另外两个功能,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

你的代码非常复杂,所以我的修改可能仍然有问题,但可能可以帮助你或提供一些新的想法。

Check out my modified fiddle here

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

随着你的事件侦听器只有:

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

我还使用了isElementInViewport绝招here

对于检查顶部的视能见度/我已经添加as-topas-bottom标记元素的div的底部到HTML这样的:

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

那现在一切都从我这里,希望你可以使用它...

+0

这仍然会导致一些问题,如果用户滚动真的很快,但它比我有更多的顺利。我遇到的问题是我的'.autoscroll'容器有填充和/或边距。我必须将这些填充物移动到标记元素。无论如何,这指出我在正确的方向,帮助功能实际上帮助很大。非常感谢你的时间 –

+0

我有一段时间所以提出了另一个答案,检查出来! – ARS81

1

这里有一个不同的方法:

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

的代码完全重写。它使用超时并且仅使用scroll事件,因此即使在触摸设备上它也应该可以工作。

允许快速滚动并修复您的容器填充问题,因为在每个容器之前只需要一个标记<div class="as-marker"></div>。不需要鼠标滚轮插件。

它可以很容易地重构为可以在多个可滚动元素上重用的jQuery插件。