使用requestAnimationFrame替换$(window).on(' scroll',function(){});是否安全?

时间:2014-12-04 12:25:24

标签: javascript ios performance requestanimationframe

当用户滚动时,我需要每隔±100ms 知道当前的滚动位置。该位置决定了页面的哪个部分被“照亮”。

使用$(window).on('scroll', function(){});一切正常。我使用_.debounce来去除事件并检查文档现在每100毫秒。

然而 - 在iPad上 - 滚动完全停止后才会触发'滚动',这在我的场景中很糟糕,所以我想找到一个更好的解决方案。 / p>

起初,我想使用setInterval并以每100毫秒的方式检查位置,但我读到它在移动设备上效率不高,即使标签未打开也会运行。所以我偶然发现了requestAnimationFrame,目前看起来我可以做到这一点:

saved_pos = -1;
rAF = window.requestAnimationFrame;
set_sticky_pos = function() {
  if (saved_pos === window.scrollY) {
    rAF(set_sticky_pos);
    return false;
  }
  saved_pos = window.scrollY;

  debounced_trigger_function(saved_pos);
  rAF(set_sticky_pos);
};

然后我的debounced_trigger_function将检查当前位置,并根据它在其父元素上添加一个类来阐明所需的内容。

通过这样做 - 有什么我应该知道的吗?这是一个很大的禁忌吗?

注意:您可能已经注意到我没有做任何真正的“动画”,这就是(我认为)实际上是为rAF设计的,但它似乎是对抗iPad on-scoll慢度的唯一方法。这正是我决定将问题发布在SO上的原因 - 即使我不是“动画”,也可以使用rAF吗?

TL; DR

可以使用rAF作为实时滚动位置检测的解决方法,而不是“动画”吗?

1 个答案:

答案 0 :(得分:2)

由于iOS设备使用的是webkit浏览器,您可以通过一行CSS实现平滑滚动:

-webkit-overflow-scrolling: touch;

如果这对您不起作用,那么您可以将rAF与自定义的polyfill一起使用和/或如果rAF不可用则回退滚动,但这很容易验证:

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            // defualt scrolling logic or setInterval
            window.setTimeout(callback, 1000 / 60);
          };
})();

此外,如果您不想在桌面浏览器上使用默认滚动,您可以使用Modernizr来检测运行代码的设备是否启用了触摸功能,而且(并且仅限于)您可以覆盖默认滚动行为。这就像

一样简单
if(Modernizr.touch) {
    // your custom scrolling logic here, rAF for example
}