setInterval仅在第一次起作用

时间:2011-01-14 16:59:59

标签: javascript jquery

我正在尝试使用setTimer使用简单的jQuery为幻灯片放映动画。我向用户提供了一个按钮(带有按钮背景图像的“DIV”形式),他点击该按钮启动节目,然后变成暂停按钮。幻灯片应该每3秒更换一次。以下是相关代码:

    playLink  = $('<div id="lbPlayLink"  />').click(function(){
            $(playLink).hide();
            $(pauseLink).show();
            slideInterval = setInterval(function(){next()}, 3000)
    })[0];
    pauseLink = $('<div id="lbPauseLink" />').click(function(){
            $(playLink).show();
            $(pauseLink).hide();
            clearInterval(slideInterval);
    }).hide()[0];

next()函数调用执行将幻灯片替换为下一个幻灯片的工作。我已经检查了这个函数,如果我直接(同步)调用它就可以正常工作,但是,当它被setInterval异步调用时,它第一次工作正常(我点击按钮后3秒) ,但永远不会再被调用,即使它应该在3秒后调用。我知道它从未被调用,因为我在函数的开头和结尾都设置了“警报”调用。

如果我用next()替换setInterval中的alert('test')来电话,那么我可以看到setInterval正在按照预期进行操作。我不能为我的生活看到为什么alert()可以,但next()不是,除非它与函数的“范围”有关,但在这种情况下为什么它有效第一次?

我已尝试使用firebug调试代码,但它对这样的超时功能无法提供帮助。 Firefox和IE8都没有显示任何错误消息。

我已经查看了setInterval上此处和其他地方的各种帖子,但看不到任何我尚未尝试过的相关信息。我现在已经进行了大约3个小时的实验,而且它正在努力。有人可以建议我接下来可以尝试一下吗?

3 个答案:

答案 0 :(得分:1)

嗯,我不喜欢你编写代码的方式,它不是很易读,我宁愿建议类似下面的内容(尚未测试,不确定是否有效):

CSS:

#slides{
    /* So you can position your elements under the div#slides */
    position: relative;
}

.button {
    width: 50px;
    height: 10px;

    /* So you can position your button anywhere you like */
    position: absolute;
    bottom: 10px;
    right: 10px;
}

.play {
    background:url(..) no-repeat;
}

.pause {
    background:url(..) no-repeat;
}

HTML包含父级slides,其中包含与幻灯片相关的所有内容,而controller基本上包含您的按钮图片。

<div id="slides">
    <div id="controller" class="button play"></div>
</div>

代码:

(function() {

    //Let's wrap everything in an anonymous function, so to avoid variable confusion

    function next() {
        //Assume this is your code doing the sliding. I don't touch
    }

    var invt;

    function play() {
        //Always clear interval first before play
        if (invt) clearInterval(invt);
        invt = setInterval(function() {
            next();
        }, 3000);
    }

    function pause() {
        if (invt) clearInterval(invt);
    }

    $(document).ready(function() {
        $('#controller').click(function() {

            //It's not playing so it has the play class
            if ($(this).hasClass('play')) {
                $(this).removeClass('play').addClass('pause');
                pause();
            }else{
                $(this).removeClass('pause').addClass('play');
                play();
            }
        });
    });
})();

答案 1 :(得分:1)

在两者上更改此行:

$('<div id="lbPlayLink"  />').click(function(){

为:

$('<div id="lbPlayLink"  />').live("click", function(){

答案 2 :(得分:0)

澄清我是如何解决问题的:

我接受了Ivo的建议,只有一个按钮(虽然是“DIV”元素而不是“BUTTON”)并在“lbPlay”和“lbPause”之间更改此按钮的类以更改背景图像并触发正确的动作。

我的主要问题是我不知不觉地多次在此按钮上设置事件,我相信这是造成这种奇怪行为的原因。

我通过使用jQuery“data”方法将“setInterval”调用的返回码放入附加到DIV的变量(“ppHandler”)中来解决它。

新代码是:

if (typeof($(playPauseLink).data('ppHandler')) == 'undefined'){
    $(playPauseLink).click(function(){
        var $this = $(this);
        if ($this.hasClass('lbPlay')) {
            if ($this.data('ppHandler') != -1) clearInterval($this.data('ppHandler'));
            $this.data('ppHandler', setInterval(function(){next();}, slideInterval*1000));
            $this.removeClass('lbPlay').addClass('lbPause');
        } else {
            if ($this.data('ppHandler') != -1) clearInterval($this.data('ppHandler'));
            $this.data({ppHandler: -1});
            $this.removeClass('lbPause').addClass('lbPlay');
        }
    });

感谢所有回复的人。要查看最终结果,请访问“www.trips.elusien.co.uk”并单击“slimbox examples”链接,然后转到“示例9”。