0

我正在制作一个使用setTimeout和的简单淡入/淡出循环动画clearTimeout。到目前为止,这是我的代码:

HTML:

<p><span>loading...</span></p>
<a href="#" id="btn">STOP</a>

Javascript(jQuery1.9.1):

var _timer;
var _timerArr = [];

var loaderBlink = function() {
    $('p').find('span').fadeTo(200,.4).fadeTo(200,1,function() {
        _timer = setTimeout(function() { loaderBlink() }, 200);
        _timerArr.push(_timer);
        //console.log('loading...');
    });
};

var clearTimer = function() {
    $.each(_timerArr, function(i,val) {
        clearTimeout(val);
        console.log(val);
    });

    $('#btn').remove();
    $('p').fadeOut('fast');

    return false;
};

$('#btn').on('click', function() {
    clearTimer();
});

loaderBlink();

演示:http: //jsfiddle.net/nori2tae/MW9E8/

问题是,即使我将所有计时器推入一个数组以便之后通过单击停止按钮将它们全部清除,有时计时器也不会停止,只会继续运行。

可能我不完全理解setTimeoutand的概念clearTimeout。我需要一些解决方案并帮助理解这两个功能。

4

4 回答 4

2

这是一个 setIntevall 版本:

编辑:它运作良好,但你必须用你的函数 loaderBlink(); 包装计时器;又一次,误删了,咖啡还不够。

var _timer;

_timer = setInterval(function () {
            $('p').find('span').fadeTo(200,.4).fadeTo(200,1);
            console.log('loading...');
        }, 400);


var clearTimer = function() {
    clearInterval(_timer);

    $('#btn').remove();
    $('p').fadeOut('fast');

    return false;
};

$('#btn').on('click', function() {
    clearTimer();
});

http://jsfiddle.net/XHUTV/2/

于 2013-03-24T10:32:35.057 回答
1

保存对数组中所有计时器的引用没有多大意义——计时器不会连续运行,因此仅将最近的计时器存储在单个数组中就足够了。你只需要停止最后一个,其他的都已经停止了。

我怀疑当您在动画运行时单击某个时间点时计时器不会停止,因此该按钮会停止所有计时器,但尚未启动的计时器除外,因为动画队列仅在动画停止时才启动它。

无论如何,如果没有计时器,这实际上会更容易、更可靠。

var blink = true;

var loaderBlink = function() {
    if( blink ) {
        $('p').find('span').delay( 200 ).fadeTo(200,.4).fadeTo(200,1,function() {
            loaderBlink();
            console.log('loading...');
        });
    }
};

$('#btn').on('click', function() {    
    blink = false;
    $(this).remove();
    $('p').stop().fadeOut('fast');

    return false;
});

loaderBlink();

该操作与原始代码略有不同:200 ms 延迟是在动画循环的开始而不是之后,但我认为这不是问题。.stop()确保循环不会再次开始。

演示:http: //jsfiddle.net/WAprd/17/

于 2013-03-24T10:28:39.947 回答
1

您解决此问题的方法有点错误-正如您所见,您将时间定义为 200 毫秒-这次时间很短,在代码做出反应之前,您的单击下一个计时器将继续进行,因此有时它有时会起作用不是。同样将所有 interval_ids 保存在一个数组中没有任何意义,因为 setTimeout 只发生一次(与 setInterval 相反)。您需要做的是使用标志并关闭单个计时器 ID:http: //jsfiddle.net/MW9E8/2/

var _timer;
var _timerArr = [];
var fading;

var loaderBlink = function() {
    if(fading){
        $('p').find('span').fadeTo(200,.4).fadeTo(200,1,function() {
            interval_id = setTimeout(function() { loaderBlink() }, 200);
           // _timerArr.push(_timer);
            console.log('loading...');
        });
    }
};

var clearTimer = function() {
    /*
    $.each(_timerArr, function(i,val) {

        console.log(val);
    });
    */    
    clearTimeout(interval_id);
    fading = false;

   // $('#btn').remove();
   // $('p').fadeOut('fast');

    return false;
};

$('#btn').on('click', function() {
    clearTimer();
});

fading = true;
loaderBlink();
于 2013-03-24T10:33:58.783 回答
1

如果您在动画中使用 jQuery,那么您最好继续使用 jQuery 来处理其他所有内容……无需混入setIntervalsand setTimeouts

小提琴

http://jsfiddle.net/QNMkp/

标记

<span id="loading">Loading...</span>

<button id="stop">Stop!</button>

js

$(function(){

    var fadeLoading;

    (fadeLoading = function(){
        $('#loading:not(.stopped)')
            .fadeTo(200,0.4)
            .fadeTo(200,1, fadeLoading) /// you can just loop this
        ;
    })();

    $('#stop').click(function(){
        $('#loading')
            .addClass('stopped') /// add a class to stop new fade starting
            .stop() /// stop existing animations
            .fadeTo(200,1) /// fade loading up to 100%
        ;
    });

});
于 2013-03-24T10:48:23.740 回答