setTimeout使用多个选项卡加速

时间:2011-05-24 15:10:18

标签: javascript jquery timer settimeout

我遇到类似于this one的setTimeout问题。但是这个解决方案对我没用,因为我不能在我的文件中使用php。

我的网站有一个滑块,其中包含每8秒钟移动一次的图像列表。但是,当我在浏览器中打开几个标签然后再切换回来时,它就变得疯狂了。 滑块继续一个接一个地移动图像而没有8秒的时间延迟。

我只在Chrome和最新的Firefox中看到它。

**编辑:我检查了console.log(),并且setTimeout在clearTimeout之前和之后返回相同的数字。不知道为什么。也许这也与它有关? **

编辑2:我添加了一个小提琴:http://jsfiddle.net/Rembrand/qHGAq/8/

代码类似于:

spotlight: {
    i: 0,
   timeOutSpotlight: null,

   init: function()
   {
       $('#spotlight .controls a').click(function(e) {

           // do stuff here to count and move images

           // Don't follow the link
           e.preventDefault();

           // Clear timeout
           clearTimeout(spotlight.timeOutSpotlight);

           // Some stuff here to calculate next item

           // Call next spotlight in 8 seconds
           spotlight.timeOutSpotlight = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);
       });

       // Select first item
       $('#spotlight .controls a.next:first').trigger('click');
   },

   animate: function(i)
   {
       $('#spotlight .controls li:eq(' + (spotlight.i) + ') a.next').trigger('click');
   }
}

7 个答案:

答案 0 :(得分:13)

来自jQuery documentation

  

由于requestAnimationFrame()的性质,你永远不应该   使用setInterval或setTimeout循环排队动画。为了   保留CPU资源,支持requestAnimationFrame的浏览器   不显示窗口/选项卡时,不会更新动画。如果   您继续通过setInterval或setTimeout对动画进行排队   动画暂停,所有排队的动画将开始播放   当窗口/标签重新获得焦点时。为了避免这个潜在的问题,   在循环中使用上一个动画的回调,或追加a   函数.queue()设置超时以启动下一个   动画。

答案 1 :(得分:11)

我终于找到了答案,而这完全不是我所期待的。 似乎罪魁祸首是jQuery的.animate(),我用它来移动滑块中的图像。

我计算并移动我的图像位置:

$('.spotlight-inner')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
 ;

现在问题似乎是在某些浏览器中,在切换到新选项卡并返回后,jQuery的.animate()会保存动画并立即将它们全部触发。所以我添加了一个过滤器以防止排队。该解决方案来自CSS-Tricks.com

$('.spotlight-inner')
    .filter(':not(:animated)')
    .animate(
        { left: scrollToVal },
        {duration: 'slow'}
    )
;

你回去时看到的第一张幻灯片可能会有点跳跃,但它比以前的超高速旋转木马要好。

完整代码here

答案 2 :(得分:1)

使用jquery动画队列属性有一种更简单的方法:

$(this).animate({
    left: '+=100'
}, {duration:500, queue:false});

答案 3 :(得分:1)

我不知道这是否会对你有所帮助,但它帮助了我的幻灯片。我所做的是每次我调用一个应该以设定的间隔发生的动画,因为setTimeout,我调用了clearQueue(),它将摆脱已经设置发生的任何其他动画。然后我会调用动画。这样,当你回到那个标签时,你没有把所有这些动画排队,而且它变得疯狂。在最大值你只会有一个设置。

这样的事情:

       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.clearQueue(); // get rid of other instances of the animation
            spotlight.animate(spotlight.i);
        }, 8000);

它可能在所有情况下都不起作用(取决于时间),但我希望能帮助某人!

答案 4 :(得分:0)

您还必须考虑使用clearTimeout。

当您调用setTimeout函数时,它会返回一个ID,您可以将此ID保存在像

这样的变量中
timeoutID = setTimeout(function () {
                spotlight.animate(spotlight.i);
            }, 8000);

在设置新超时之前,您可以调用类似

的功能
clearTimeout(timeoutID)

答案 5 :(得分:0)

我怀疑浏览器会对输入事件进行排队,例如“点击”,但只有当事件发生的标签实际上具有焦点时才会触发它们。

也许您应该尝试直接调用点击回调,而不是使用trigger('click')

这样的事情:

spotlight: {
    i: 0,
   timeOutSpotlight: null,
   clickFunc: function(element) {

       // do stuff here to count and move images

       // Clear timeout
       clearTimeout(spotlight.timeOutSpotlight);

       // Some stuff here to calculate next item

       // Call next spotlight in 8 seconds
       spotlight.timeOutSpotlight = setTimeout(function () {
            spotlight.animate(spotlight.i);
       }, 8000);
   },

   init: function()
   {

       $('#spotlight .controls a').click(function (e) {

           // Don't follow the link
           e.preventDefault();

           spotlight.clickFunc(this);
       });

       // Select first item
       spotlight.clickFunc($('#spotlight .controls a.next:first'));
   },

   animate: function(i)
   {
       var element = $('#spotlight .controls li:eq('+spotlight.i+') a.next');
       spotlight.clickFunc(element);
   }
}

答案 6 :(得分:0)

你在运行什么版本的jQuery?显然这个问题在1.6.3版本中已“修复” - 它们还原了导致这种情况发生的变化。讨论herehere

虽然将来可能不得不解决这个问题,但现在好像我们已经摆脱困境。