jQuery delay() - 如何停止它?

22

我已经尝试过stop(true,true)、stop(true)和clearQueue();但这些方法都没有起作用。

我遇到了幻灯片快速切换的问题,我已经写了一些函数来重置一切,但它并没有起到作用。

function reset(){
   $('div').clearQueue();
   $('#img').html('').css({'left':0,'right':0,'opacity':1,'z-index':1});
   $('#img2').html('').css({'left':0,'right':0,'opacity':1,'z-index':1});
   $('#place').html('');$('#place').html('<div id="img"></div><div id="img2"></div>');
}

但我认为这并不会停止(或删除)动画中的delay()函数。所以我不知道是否不必使用setTimeout函数。

这是一段动画脚本的代码:

reset();
actual_slide=2;
  $('#img').html('<img src="'+image[4]+'" alt="Obrázek">').css({'opacity':0,'z-index':2}).delay(time_delay/5).fadeTo(time_fast,1).delay(time_delay*2).fadeTo(time_fast,0);
  $('#img2').html('<img src="'+image[3]+'" alt="Obrázek">').css({'opacity':'0','top':0}).fadeTo(time_fast,1).animate({'top':'-495'},time_delay*3,function(){
    if(actual_slide==2){$('#img2').css({'top':0}).fadeTo(time_fast*2,0).html('');}else{reset();}
    if(actual_slide==2){$('#img').html('<img src="'+image[3]+'" id="1" alt="Obrázek">').fadeTo(time_fast*2,'1').css({'left':-300,'top':-700}).animate({'left':-900,'top':-700},time_delay*2);}else{reset();}
    if(actual_slide==2){$('#1').css({'width':1365,'height':1200}).animate({'width':1665,'height':1400},time_delay*2);}else{reset();}
  });                          

在重复执行该函数之前,实际幻灯片必须进行保护,但这也行不通。问题是当我快速切换幻灯片时,因为该重置并未停止所有动作,它会开始执行我不想要的操作(例如将图片更改为其他内容等)。


1
http://bugs.jquery.com/ticket/6150 -- 看起来他们已经在jQuery 1.7版本中修复了这个问题。下载该版本并查看是否解决了您的问题,或者阅读错误报告以获取一些可能的解决方法。 - Blazemonger
也许是重复的问题:jQuery:使用stop()的delay()或timeout()? - Blazemonger
我刚试过了,它可以在jQuery 1.8.3上运行。 - jmcollin92
4个回答

23
您可以通过使用.dequeue()函数来打破.delay()
以下是一个示例:
//this is only for make sure that we skip 'delay', not other function
var inDelay = false;

function start()
{
    $('.gfx').animate
    ({
        width: 100
    }, function(){inDelay = true}).delay(3000).animate
    ({
        width: 0
    }, function(){inDelay = false})
}

function breakTheDelay()
{
    if(inDelay)
    {
        $('.gfx').dequeue();
    }
}

http://jsfiddle.net/wasikuss/5288z/

//编辑:提供了更复杂的示例,包括日志时间戳和清理(没有清理,多次点击 Start 是不可预测的),以证明它可以工作。

http://jsfiddle.net/q0058whc/

或者下面:

//this is only for make sure that we skip 'delay', not other function
var inDelay = false;
var ltime = 0;

// console log will aways show 'end' values: 2000, 1000 an 400
// values may be different due to time wasted on calling functions
// sometimes delay is shorten by 0-200ms, it can be caused by js engine probably  

function start()
{
    cleanup();
    ltime = (1*new Date());
    $('.gfx').queue('fx', function(next)
    {
      logtime( 'animate1_start' );
     $('.gfx').animate
      ({
          width: 100
      }, 2000, function(){logtime('animate1_end');inDelay = true;})
      next();
    })
    .queue('fx', function(next)
    {
     logtime('delay_start');
     next()
    })
    .delay(1000)
    .queue('fx', function(next)
    {
     logtime('delay_end');
     next()
    })
    .queue('fx', function(next)
    {
     logtime('animate0_start');
     $('.gfx').animate
      ({
          width: 0
      }, function(){logtime('animate0_end');inDelay = false;})
      next()
    });
}

function cleanup()
{
  // remove current queue
    $('.gfx').clearQueue()
    // first animate runned interval. stop it 
    .stop()
    // reset width of element
    .css('width',0)
}

function logtime( name )
{
 var ntime = (1*new Date());
 console.log( name + ': ' + ( ntime - ltime ) );
  ltime = ntime;
}

function breakTheDelay()
{
    if(inDelay)
    {
        $('.gfx').dequeue();
    }
}

//
// version without 'inDelay' check only if you know what are you doing
// http://jsfiddle.net/wasikuss/hkw9H/
//
.gfx
{
    background: red;
    width: 0;
    height: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button onclick="start()">Start</button>
<button onclick="breakTheDelay()">Can't wait!</button>
<div class="gfx"></div>


2
如果你尝试操作这个程序,你会发现dequeue可以取消延迟的最终结果,但是无法取消延迟本身。在所示的例子中,你可以取消动画效果,但是如果你在3秒内再次点击,延迟仍然在运行,动画效果会再次被取消。 - paj
如果您在动画期间单击“无法等待!”然后单击“开始”,它将无法按预期工作。请等待动画完成,然后在延迟期间按下“无法等待!”和“开始”。它应该返回并再次将宽度动画化为100px。 - wasikuss
不行,这个并不能完全工作,只需快速点击那两个按钮多次,然后点击开始,动画将不会等待适当的时间,而会立即来回移动或出现一些奇怪的延迟。 - Max Yari
这个回答不正确... 延迟没有停止。演示。点击几次提示,然后继续点击停止。它没有停止延迟。撤销我的赞成票。 - lzl124631x
@MaxYari,是的,因为Start不关心当前队列。问题是“如何停止.delay()”,而不是“如何编写应用程序并保护免受多次点击”。如果您等待第一个动画结束,那么会有3秒的延迟。单击“Stop”以中断它。我将添加更多保护的修改示例... - wasikuss

13

从 jQuery delay 页面:

.delay() 方法最适合用于延迟排队的 jQuery 特效。由于其功能有限——例如,它没有提供取消延迟的方法——.delay() 不是 JavaScript 的原生 setTimeout 函数的替代品,后者在某些使用情况下可能更为适合。

可以查看一下 doTimeout 插件,它可能正是你所需要的。

希望这可以帮助到你!


谢谢您的回答,我尝试使用普通的setTimeout,现在它几乎可以工作了。但是现在我只需要以某种方式同步两个计时器。 - rojikada
2
我不明白为什么jQuery的stop方法不能停止延迟。虽然加1,但使用doTimeout插件解决了我的问题。 - net.uk.sweet
1
当尝试将setTimeout与队列和动画一起使用时,由于requestAnimationFrame的存在,两者可能会失去同步,从而导致问题。 - James Westgate

6

通过这篇文章,有一个非常简单的方法,就是使用.animate替换掉.delay


1
仅供参考,以防该页面消失,'arniarent'写道:我通过使用animate()替换delay()来解决了这个问题的方法:$('#element').stop(true,false).animate({opacity:1},200,'easeOutExpo').animate({opacity:1},2000).animate({opacity:0},1000,'easeInQuint');在这种情况下,animate({opacity:1},2000)作为delay(2000)工作,但是可以取消。 - Domenico De Felice
我使用了.fadeTo(delayMs, 1),这是.animate调用的缩写版本。我真的很想知道为什么延迟错误在4年前被标记为已修复,但它仍然存在问题,以及为什么.delay不能在幕后使用动画来解决这个问题。 - Roman Starkov
1
延迟错误已经修复 - 您只需要使用 stop(true),因为如果不这样做,您只会停止延迟,而队列的其余部分仍然会继续。如果您想跳过延迟,但接着执行队列中的其他动画,则可以使用 stop(false) - Simon_Weaver

1
我希望用户能够快速重复地重新启动动画链,有时甚至在动画中间进行。因此,我没有使用delay(),而是将动画应用于虚假的CSS属性{"null":1}。这里是一个简单的淡入淡出效果。对我来说似乎行得通!
//- fade in
$el.stop().animate({"opacity":1}, 200, "easeInSine", function(){
    //- delay for 2000ms
    $el.stop().animate({"null":1}, 2000, function(){
        //- fade out
        $el.stop().animate({"opacity":0}, 1000, "easeInOutSine", function(){
            //- final callback
        });
    });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接