setTimeout使用多个选项卡加速

我有一个与此类似的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'); } } 

从jQuery文档 :

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

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

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

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

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

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

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

在这里摆弄完整的代码

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

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

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

所以这样的事情:

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

它可能不适用于所有情况(取决于时间),但我希望这有助于某人!

您还必须认为使用clearTimeout。

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

 timeoutID = setTimeout(function () { spotlight.animate(spotlight.i); }, 8000); 

在设置新超时之前,您可以调用函数

 clearTimeout(timeoutID) 

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

也许你应该尝试直接调用你的点击回调而不是使用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); } } 

你在运行什么版本的jQuery? 显然这个问题对于版本1.6.3来说是“固定的” – 它们恢复了导致这种情况发生的变化。 在这里和这里讨论。

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