我观察到这种情况发生在Chrome和Firefox中,并且表现出一些不同。看起来当一个标签不在焦点上时,setTimeout仍然会执行,但它应该对执行操作的给定dom元素没有它应该采用的一些属性帐户。
例如,check out this page。面板5和6上有两个幻灯片。为这个幻灯片提供动力的功能会影响元素的可见性和位置(使它们在没有摆动的情况下通过正确的反弹缓和到中心缩小,我将步进功能一起攻击) 。如果您正在查看它们,它们可以正常工作,但是如果您将其切换到另一个地方,然后再切换回幻灯片,您会看到setTimeout已经提前了很多次,但是图像都被打包了,应该弹出的古代没有(好像它们在标签失焦时没有被隐藏或可见),或者它们将奇迹般地转移到舞台的最右侧(就好像它们的坐标不存在一样)或者在浏览器窗口未对焦时出错。
阻止这种情况发生的最佳方法是什么?除非/直到浏览器窗口具有焦点,否则不会触发setTimeout?
一种解决方案是使用css3变换而不是高度和宽度,这至少可以让我不必在屏幕外处理元素的坐标,但它不会改变这样的事实: setTimeout变得一团糟,很奇怪。
以下是实际功能:
// dom element goes out
function popOut(cssFilter, dur){
var aPop = this;
aPop.duration = dur;
$(cssFilter+':visible').stop(false,true).each(function(){
var my = this;
my.X = $(this).position().left;
my.Y = $(this).position().top;
$(this).animate({'height': 0, 'width': 0}, {'duration': aPop.duration, 'easing': 'easeOutElastic', step: function(now, fx){
if(fx.prop == 'height') $(this).css('top', ((fx.start - now)/2) + my.Y);
else if(fx.prop == 'width') $(this).css('left', ((fx.start - now)/2) + my.X);
}, queue: true, complete: function(){
$(this).css({'top': my.Y,'left': my.X, 'display': 'none'});
} });
});
}
// dom element comes in
function popIn(cssFilter, dur){
var aPop = this;
aPop.duration = dur;
$(cssFilter+':hidden').stop(false,true).each(function(){
var my = this;
my.H = this.height,
my.W = this.width;
$(this).css({ 'height': 0, 'width': 0, 'display': 'block'});
my.X = $(this).position().left,
my.Y = $(this).position().top;
$(this).css({ 'left' :(my.X + my.W/2), 'top' : (my.Y + my.H/2)}).animate({'height': my.H, 'width': my.W}, { 'duration': aPop.duration, 'easing': 'easeOutElastic', step: function(now, fx){
if(fx.prop == 'height') $(this).css('top', ((fx.end - now)/2) + my.Y);
else if(fx.prop == 'width') $(this).css('left', ((fx.end - now)/2) + my.X);
}, queue: true, complete: function(){
$(this).css({'top': my.Y, 'left': my.X, 'display': 'block'});
} });
})
}
// dom element slideshow
function popSlideshower(classToCycle, pauseButtonPanelId){
var thisPop = this;
// the items that have the classToCycle class need to also have classes ploink1, ploink2, ploink3... ploinkn - to specify order of displaywhatchamacallit
$('.'+classToCycle+":not(.ploink1)").hide();
this.totCount = $('.'+classToCycle+':not(.also)').length; // the also class allows there to be multiple images with the same ploink number; the also ploinks will not go toward the total count
this.currentIndex = 1;
this.classOfCycler = classToCycle;
this.currentlyPlaying = true;
// prepend button to the given narrative block id
$('#c_'+pauseButtonPanelId+' .narrative').prepend('<p style="text-align: center;"><a href="#" id="'+classToCycle+'-pauseButt" class="inlineButton"><span>Pause Slideshow</span></a></p>');
$('#'+classToCycle+'-pauseButt').click(function(aClick){
aClick.preventDefault();
$(this).blur(); // removes the weird dotted outline in FF
if(thisPop.currentlyPlaying) {
$(this).html('<span>Continue</span>');
thisPop.currentlyPlaying = false;
}
else {
$(this).html('<span>Pause</span>');
thisPop.currentlyPlaying = true;
}
});
this.popPloink = function(){
if(this.currentlyPlaying){ // this method allows multiple slideshows to stay synchronized; the timeout never stops firing, even though the slideshow stops advancing
var nextIndex = this.currentIndex == this.totCount ? 1 : this.currentIndex + 1;
popOut("."+this.classOfCycler+".ploink"+this.currentIndex, 700);
popIn("."+this.classOfCycler+".ploink"+nextIndex, 700);
this.currentIndex = nextIndex;
}
setTimeout(function() { thisPop.popPloink(); }, 4000);
}
setTimeout(function() { thisPop.popPloink(); }, 4000);
}