2017-05-03 184 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插件。