我正在jQuery中创建一个内容旋转器.共5项.项目1淡入,暂停10秒,淡出,然后项目2淡入.重复.
很简单.使用setTimeout我可以调用一组创建循环的函数,并将无限期地重复该过程.
我现在想要通过单击导航元素来随时添加中断此旋转器的功能,以直接跳转到其中一个内容项.
我最初开始沿着不断地(例如每半秒)ping一个变量的路径,该路径将检查是否点击了导航元素,如果是,则放弃循环,然后根据单击的项重新启动循环.
我遇到的挑战是如何通过计时器实际ping一个变量.解决方案是深入研究JavaScript闭包......这有点超出我的想法,但绝对需要深入研究.
然而,在此过程中,我提出了一个替代选项,实际上似乎在性能上更好(理论上,至少).我在这里运行一个示例:
(它正在使用console.log,因此运行fireBug)
示例脚本:
$(document).ready(function(){
var loopCount = 0;
$('p#hello').click(function(){
loopCount++;
doThatThing(loopCount);
})
function doThatOtherThing(currentLoopCount) {
console.log('doThatOtherThing-'+currentLoopCount);
if(currentLoopCount==loopCount){
setTimeout(function(){doThatThing(currentLoopCount)},5000)
}
}
function doThatThing(currentLoopCount) {
console.log('doThatThing-'+currentLoopCount);
if(currentLoopCount==loopCount){
setTimeout(function(){doThatOtherThing(currentLoopCount)},5000);
}
}
})
Run Code Online (Sandbox Code Playgroud)
逻辑是每次点击触发元素都会启动循环,向自身传递一个等于全局变量当前值的变量.该变量在循环中的函数之间来回传递.
每次单击触发器也会增加全局变量,以便循环的后续调用具有唯一的局部变量.
然后,在循环内,在调用每个循环的下一步之前,它会检查它所具有的变量是否仍然与全局变量匹配.如果没有,它知道一个新的循环已经被激活,所以它只是结束现有的循环.
对此的想法?有效的方案?更好的选择?注意事项?危险?
更新:
我通过clearTimeout选项使用John的建议.
但是,我无法让它发挥作用.逻辑是这样的:
var slideNumber = 0;
var timeout = null;
function startLoop(slideNumber) {
//... code is here to do stuff here to set up the slide based on slideNumber...
slideFadeIn()
}
function continueCheck() {
if (timeout != null) {
// cancel the scheduled task.
clearTimeout(timeout);
timeout = null;
return false;
} else {
return true;
}
};
function slideFadeIn() {
if (continueCheck){
// a new loop hasn't been called yet so proceed...
$mySlide.fadeIn(fade, function() {
timeout = setTimeout(slideFadeOut,display);
});
}
};
function slideFadeOut() {
if (continueCheck){
// a new loop hasn't been called yet so proceed...
slideNumber=slideNumber+1;
$mySlide.fadeOut(fade, function() {
//... code is here to check if I'm on the last slide and reset to #1...
timeout = setTimeout(function(){startLoop(slideNumber)},100);
});
}
};
startLoop(slideNumber);
Run Code Online (Sandbox Code Playgroud)
循环的上述踢.
然后我有导航项,单击时,我希望上面的循环停止,然后重新启动一个新的开始幻灯片:
$(myNav).click(function(){
clearTimeout(timeout);
timeout = null;
startLoop(thisItem);
})
Run Code Online (Sandbox Code Playgroud)
如果我从click事件中注释掉'startLoop ...',它确实会停止初始循环.但是,如果我离开最后一行,它实际上并不会停止初始循环.为什么?会发生的是,两个循环似乎并行运行一段时间.
因此,当我单击我的导航时,会调用clearTimeout,这会清除它.
你应该做的是保存返回的句柄setTimeout并清除它clearTimeout以中断旋转器.
var timeout = null;
function doThatThing() {
/* Do that thing. */
// Schedule next call.
timeout = setTimeout(doThatOtherThing, 5000);
}
function doThatOtherThing() {
/* Do that other thing. */
// Schedule next call.
timeout = setTimeout(doThatThing, 5000);
}
function interruptThings() {
if (timeout != null) {
// Never mind, cancel the scheduled task.
clearTimeout(timeout);
timeout = null;
}
}
Run Code Online (Sandbox Code Playgroud)
单击导航元素时,只需调用即可interruptThings().好的部分是它会立即生效,你不需要做任何轮询或其他任何复杂的事情.