确定'onscroll'事件的来源

时间:2017-10-12 08:54:11

标签: javascript events browser onscroll

我有一个窗口'onscroll'事件的监听器。在那个处理程序中,我需要以某种方式弄清楚触发事件的原因,例如:我正在运行一个触发window.scrollTo(x,y)的动画,如果事件是由动画触发的,则侦听器应该有不同的行为。更准确地说,如果用户在动画运行时滚动,我必须停止动画。甚至可以在触发window.scrollTo(x,y)时将上下文传递给事件处理程序,还是有一些hacky解决方法来实现这个目的?

以下是我想要实现的一些伪代码:

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处理程序。

1 个答案:

答案 0 :(得分: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