我有一个setInterval,每秒运行一段代码30次。这工作得很好,但是当我选择另一个选项卡(使我的代码选项卡变得不活跃),setInterval由于某种原因被设置为空闲状态。
我制作了这个简化的测试用例(http://jsfiddle.net/7f6DX/3/):
var $div = $('div');
var a = 0;
setInterval(function() {
a++;
$div.css("left", a)
}, 1000 / 30);
如果您运行这段代码,然后切换到另一个选项卡,等待几秒钟并返回,动画将继续在切换到另一个选项卡时的位置。
因此,如果标签处于非活动状态,动画不会每秒运行30次。这可以通过计算每秒调用setInterval函数的次数来确认——如果选项卡处于非活动状态,这将不是30,而是1或2。
我想这样做是为了提高系统性能,但是有什么方法可以禁用这种行为吗?
这在我看来是劣势。
setInterval和requestAnimationFrame都不工作时,选项卡是不活跃的或工作,但不是在正确的时间。一种解决方案是使用另一个时间事件源。例如,web套接字或web工作者是两个事件源,当选项卡是非活动的时候工作得很好。所以不需要把你所有的代码都移动到一个web worker,只需要使用worker作为一个time事件源:
// worker.js
setInterval(function() {
postMessage('');
}, 1000 / 50);
.
var worker = new Worker('worker.js');
var t1 = 0;
worker.onmessage = function() {
var t2 = new Date().getTime();
console.log('fps =', 1000 / (t2 - t1) | 0);
t1 = t2;
}
这个示例的Jsfiddle链接。
我认为最好的理解这个问题的例子是:http://jsfiddle.net/TAHDb/
我在这里做了一件简单的事情:
间隔1秒,每次隐藏第一个跨度,并将其移动到最后,并显示第二个跨度。
如果你停留在页面上,它就像它所设想的那样工作。
但如果你把标签隐藏了几秒钟,当你回来的时候,你会看到一个奇怪的东西。
这就像所有在你现在不活跃的时候没有发生的事情都会在一次发生一样。所以在几秒钟内你会看到X个事件。它们是如此之快,以至于有可能同时看到所有6个跨度。
所以它接缝铬只延迟事件,所以当你回来所有的事件将发生,但所有的一次…
这是一个简单的幻灯片的实际应用。想象数字是图像,如果用户保持标签隐藏,当他回来的时候,他会看到所有的imgs浮动,完全混乱。
要解决这个问题,请像pimvdb告诉的那样使用stop(true,true)。
这将清除事件队列。
这是一个很老的问题,但我遇到了同样的问题。
如果你在chrome上运行你的网页,你可以阅读这篇文章在chrome 57的背景标签。
基本上间隔计时器可以运行,如果它没有耗尽定时器预算。
预算的消耗基于计时器内任务的CPU时间使用情况。
基于我的场景,我将视频绘制到画布上并传输到WebRTC。
webrtc视频连接将保持更新,即使标签是不活跃的。
然而,你必须使用setInterval而不是requestAnimationFrame,但是itt不推荐用于UI渲染。
最好是监听visibilityChange事件并相应地改变渲染机制。
此外,您可以尝试Kaan Soral建议的方法,它应该可以根据文档工作。
注意:这个解决方案不适合如果你喜欢你的间隔工作在背景上,例如,播放音频或其他东西。但如果你感到困惑,例如当你回到页面或选项卡时,你的动画不能正常工作,这是一个很好的解决方案。
有很多方法可以实现这个目标,也许“WebWorkers”是最标准的一个,但当然,它不是最简单和方便的一个,特别是如果你没有足够的时间,所以你可以试试这种方法:
基本概念:
为你的间隔(或动画)建立一个名字,并设置你的间隔(动画),所以它会运行时,用户第一次打开你的页面:var interval_id = setInterval(your_func, 3000);
通过$(window).focus(function() {});$(window).blur(function() {});你可以clearInterval(interval_id)每次浏览器(标签)是去激活和重新运行你的间隔(动画)每次浏览器(标签)将再次激活interval_id = setInterval();
示例代码:
var interval_id = setInterval(your_func, 3000);
$(window).focus(function() {
interval_id = setInterval(your_func, 3000);
});
$(window).blur(function() {
clearInterval(interval_id);
interval_id = 0;
});