2017-10-12 116 views
2

我有一個窗口'onscroll'事件的偵聽器。在那個處理程序中,我需要以某種方式找出觸發事件的原因,例如如果事件是由動畫觸發的,我正在運行一個觸發window.scrollTo(x,y)的動畫,並且偵聽器應該具有不同的行爲。更確切地說,如果用戶在動畫運行時滾動,我必須停止動畫。當我觸發window.scrollTo(x,y)還是有一些hacky的解決方法來實現這一點時,甚至可以傳遞一個上下文到事件處理程序?確定'onscroll'事件的來源

這裏是什麼,我想實現一些僞代碼:

let isAnimationRunning = false 

function onScrollHandler(e) { 
    const isTriggeredByOnAnimationTick = // how to figure that one out??? 

    if (isAnimationRunning && !isTriggeredByOnAnimationTick) { 
    stopAnimation() 
    } 
    // do something else 
} 

// called every key frame (requestAnimationFrame) 
function onAnimationTick(scrollY) { 
    // will trigger onscroll handler at some point in time 
    window.scrollTo(0, scrollY) 
} 

window.addEventListener('scroll', onScrollHandler) 

runAnimation(onAnimationTick) 

我已經想過使用不同的處理器在移動鼠標滾輪和觸控事件。然而,這種做法我遇到了兩個問題:

  1. 一個人拿出另一黑客弄清楚,無論是觸摸手勢結束後,通過滾動條
  2. 用戶滾動在移動設備上滾動減速,從而我不知道滾動事件何時停止,而不使用onscoll處理程序。

回答

0

而不是檢測用戶滾動,我們可以寧可檢查位置,我們想要着陸的位置。如果改變用戶可能已經滾動:

function scroll(x,y,end,interrupt,requireX, requireY){ 
    //the movement applied after each loop 
    const speedX = 1, speedY = 1; 

    //check if the scrolled amount is not what we expect 
    if(requireX && requireX !== scrollX || 
     requireY && requireY !== scrollY) return interrupt(); 

    //check if we reached our position 
    if(Math.abs(x - scrollX) < speedX && 
     Math.abs(y - scrollY) < speedY 
    ) return end(); 

    //now finally scroll using window.scrollBy 
    scrollBy(
     x > scrollX ? speedX : -speedX, 
     y > scrollY ? speedY : -speedY 
    ); 

    //next iteration in 10ms 
    setTimeout(scroll, 10, x, y, end, interrupt,scrollX, scrollY) ; 
} 

整個事情是那麼可用作:

scroll(
    1000, //x to scroll to 
    0, //y to scroll to 
    _=>alert("finish"), //end handler 
    _=>alert("interrupt") //user interrupted handler 
); 

Try it