我有一个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。
我想这样做是为了提高系统性能,但是有什么方法可以禁用这种行为吗?
这在我看来是劣势。
在大多数浏览器上,不活跃的选项卡执行优先级低,这可能会影响JavaScript计时器。
如果你的过渡值是使用帧间的实时时间间隔来计算的,而不是每个间隔上的固定增量,你不仅可以解决这个问题,而且还可以通过使用requestAnimationFrame来实现屏蔽动画,因为如果处理器不是很忙的话,它可以达到60fps。
下面是一个使用requestAnimationFrame实现动画属性转换的JavaScript示例:
var target = document.querySelector('div#target')
var startedAt, duration = 3000
var domain = [-100, window.innerWidth]
var range = domain[1] - domain[0]
function start() {
startedAt = Date.now()
updateTarget(0)
requestAnimationFrame(update)
}
function update() {
let elapsedTime = Date.now() - startedAt
// playback is a value between 0 and 1
// being 0 the start of the animation and 1 its end
let playback = elapsedTime / duration
updateTarget(playback)
if (playback > 0 && playback < 1) {
// Queue the next frame
requestAnimationFrame(update)
} else {
// Wait for a while and restart the animation
setTimeout(start, duration/10)
}
}
function updateTarget(playback) {
// Uncomment the line below to reverse the animation
// playback = 1 - playback
// Update the target properties based on the playback position
let position = domain[0] + (playback * range)
target.style.left = position + 'px'
target.style.top = position + 'px'
target.style.transform = 'scale(' + playback * 3 + ')'
}
start()
body {
overflow: hidden;
}
div {
position: absolute;
white-space: nowrap;
}
<div id="target">...HERE WE GO</div>
对于后台任务(与ui无关)
@UpTheCreek评论:
表现问题没问题,但还是
有些事情你需要继续做下去。
如果你有后台任务需要在给定的时间间隔内精确执行,你可以使用HTML5 Web Workers。看看下面Möhre的回答,了解更多细节…
CSS vs JS的“动画”
这个问题和其他许多问题都可以通过使用CSS转换/动画来避免,而不是基于JavaScript的动画,这会增加相当大的开销。我推荐这个jQuery插件,它可以让你像animate()方法一样从CSS过渡中受益。
只要这样做:
var $div = $('div');
var a = 0;
setInterval(function() {
a++;
$div.stop(true,true).css("left", a);
}, 1000 / 30);
不活跃的浏览器选项卡缓冲了一些setInterval或setTimeout函数。
Stop (true,true)将停止所有缓冲事件,并立即只执行最后一个动画。
window.setTimeout()方法现在限制在非活动选项卡中每秒发送不超过一个超时。此外,它现在将嵌套超时限制到HTML5规范允许的最小值:4毫秒(而不是以前的10毫秒)。
注意:这个解决方案不适合如果你喜欢你的间隔工作在背景上,例如,播放音频或其他东西。但如果你感到困惑,例如当你回到页面或选项卡时,你的动画不能正常工作,这是一个很好的解决方案。
有很多方法可以实现这个目标,也许“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;
});