我已经使用javascript创建了一种效果,以显示项目中的顶级类别。
如上图所示,它工作得很好。但是跑了一段时间后如果用户离开此页面并切换到另一个选项卡,并在一段时间后返回到该选项卡,则它开始变得很奇怪。
下面是我用来实现这种效果的代码。
var curCat = 0;
var cats = [
"<a href='/search/?cat=1'>Animals</a>",
"<a href='/search/?cat=2'>Graffiti</a>",
"<a href='/search/?cat=3'>Figures</a>",
"<a href='/search/?cat=6'>Landscape</a>",
"<a href='/search/?cat=7'>Portrait</a>",
"<a href='/search/?cat=9'>Other</a>"
];
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setInterval(function() {
$(catDisplay).fadeOut();
setTimeout(function() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
}, 400);
}, 3000);
}
$(document).ready(function() {
catSlider();
});
是什么导致此问题?我想念什么?
答案 0 :(得分:6)
当选项卡没有焦点时(以及许多其他奇数游戏,例如焦点返回时加速),计时器会受到限制,因此您的setInterval
和setTimeout
可能会不同步
相反,只需使用setTimeout
,其中每个动作(淡入和淡入)都会触发下一个动作:
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
function fadeOut() {
$(catDisplay).fadeOut();
setTimeout(fadeIn, 400);
}
function fadeIn() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setTimeout(fadeOut, 3000);
}
setTimeout(fadeOut, 3000);
}
和/或您可能会考虑fadeOut
和fadeIn
可以触发的回调,尤其是在fadeOut
上:
function catSlider() {
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
function fadeOut() {
$(catDisplay).fadeOut(fadeIn); // ***
}
function fadeIn() {
if (++curCat >= cats.length) {
curCat = 0;
}
$(catDisplay).html(cats[curCat]);
$(catDisplay).fadeIn();
setTimeout(fadeOut, 3000);
}
setTimeout(fadeOut, 3000);
}
旁注:如果您愿意,可以替换
if (++curCat >= cats.length) {
curCat = 0;
}
使用
curCat = (curCat + 1) % cats.length;
答案 1 :(得分:0)
3000ms间隔的运行时间可能比400ms超时快,因为在您返回到标签页后,浏览器会尝试使间隔同步。要解决此问题,您可以使用延迟循环,例如:
const timer = ms => new Promise(res => setTimeout(res, ms));
(async function() {
while(true) {
hideCurrent();
await timer(400);
showNext();
await timer(2600);
}
})()