画廊动画期间的clearTimeout

时间:2011-08-10 17:03:02

标签: jquery animation settimeout setinterval

我创建了一个自动播放的画廊。

当画廊停止它的动画并且我们悬停在画廊时,一切都按预期工作。

但是我遇到了一个奇怪的问题:

虽然图库是动画 - >徘徊在画廊, clearTimeout似乎无法正常工作并且在mouseleave上画廊表现得很奇怪,或者发生了一个我无法理解和解决的奇怪冲突。我回到另一个画廊,我做了几天才有类似的功能,我遇到了同样的问题。

我在这里缺少一些关键的东西

问题中的画廊:jsFiddle

var myTimeOut;

/////// ANIMATION /////////////   
    function animation(cb){         
            $('#slider').animate({left: '-=600' },800, cb);
    }      
    /////// AUTO SLIDE ////////////
    function auto() {
        myTimeOut = setTimeout(function() {
            animation(function(){
                auto();                   
            });   
        }, 2000);
    }
    auto();

以及我如何暂停它:

    ///// MOUSE actions //////////   
    $('#galcontainer').mouseenter( function () {
      clearTimeout(myTimeOut);
    });
    $('#galcontainer').mouseleave( function () {
     auto();
    });

修改

添加'悬停标志'(如答案中所示)效果非常好,但是在动画期间'快速mouseenterenter / mouseleave'时,可以看到使用此解决方案的小错误。
修复该问题可能是在mouseleave添加$('#slider')。stop()。不是一个好的解决方案
我还能做什么?

7 个答案:

答案 0 :(得分:3)

当动画正在进行时,有时鼠标输出事件不会被触发,因此pause变量不会设置为false。当由于暂停不是false而触发下一个mouseoever事件时,它将再次设置超时。我确保在设置新的超时之前清除任何先前的超时。

看一下这个工作演示。

http://jsfiddle.net/8Lzxs/3/

答案 1 :(得分:1)

问题是在动画期间,没有超时停止。一个超时已经触发,并且在动画完成之前不会创建其他超时。因此,如果在动画进行过程中将鼠标悬停,则动画将继续。您可以使用标志来解决此问题,以判断是否应停止动画。如果设置了标志,则自动返回并且不设置另一个超时。

http://jsfiddle.net/PXVSW/6/

答案 2 :(得分:1)

如果在动画运行时鼠标进入,则无效。那是因为计时器已经触发,动画结束时它将在完成时开始一个新的。我能想到解决这个问题的最少重写就是当你徘徊时自动函数检查时设置一个全局标志,这样如果设置了全局标志就不会启动新的动画。

您可以在此处查看hoverFlag解决方案:http://jsfiddle.net/jfriend00/EaKnj/

一个有趣的测试案例是在动画运行时让鼠标进入。

答案 3 :(得分:1)

如果不深入研究代码,我会通过添加一些额外的检查来修复它。

首先,我做到了这一点,不用担心timeOut标识符被替换了。我使用一个数组,以防多个事件堆叠在一起,并清除该数组中的所有超时。

其次,我添加了一个stop()值,如果stopped为true,动画将不会运行。

这是我改变的小提琴:http://jsfiddle.net/6WhNw/

答案 4 :(得分:1)

我发现在iOS 6上滚动(也就是一种动画)似乎也会导致同样的问题:只要视图滚动,就不能可靠地清除超时。

我认为这是一个iOS Bug而且 - 在我的情况下 - 发现了一个不使用set和clearTimeout的解决方案。

同样的问题无法在(多个)Android Stock浏览器和Chrome中重现。

答案 5 :(得分:0)

您需要使用setInterval而不是setTimeout。由于动画正在调用回调,它会一遍又一遍地调用动画。

http://jsfiddle.net/PXVSW/7/

var galW =  $('#gallery').width() ,
    imgN =  $('#slider img').length ,
    direction,      // direction ( -=  or  0- ) // set initially to 'null','undefined'
    counter = 1,    // counter
    myTimeOut;       // global setTimeout

$('#slider').width(galW * imgN);

/////// ANIMATION /////////////   
function animation(){                 // cb : makes animation accept a callback
        $('#slider').animate({left: direction+''+galW},800);
}  

/////// AUTO SLIDE ////////////
function auto() {
    myTimeOut = setInterval(function() {
        if ( counter != imgN){           // if counter != '4' (N of Images)
            counter++                    // add '1' to counter
            direction = '-=';            // set direction to go 'left' 
        }
        else{
            counter = 1;
            direction = '0-';            // trick - to bring slider to '0px' left (start position)
        }
        animation();   
    }, 2000);
}
auto();

///// MOUSE STATE //////////   
$('#galcontainer').mouseenter( function () {
  clearInterval(myTimeOut);
});
$('#galcontainer').mouseleave( function () {
 auto();
});

答案 6 :(得分:0)

问题 :在动画期间mouseenter,jQuery .animate()回调cb已经在队列中(即使调用clearTimeout,将调用另一个auto(),这将触发后续运行等。)

使用setInterval并利用所有这些回调是关键:

<强> jsFiddle demo

$(function(){                 // DOM ready shorthand
    var $sli =  $("#slider"), // Cache elements you plan to reuse
        galW =  $('#gallery').width(),
        imgN =  $sli.find('img').length,
        counter = 0,          // set it to index 0!
        itv;                  // setInterval (scope var)
    
    $sli.width(galW * imgN);

    function anim() {
      ++counter; counter%=imgN;                       // Incr.counter; and wrap-around
      $sli.stop().animate({left: -galW*counter},900); // width*counter = px position
    }
    function autoSlide() {
        itv = setInterval(anim, 3000);
    }
    autoSlide();
    
    ///// MOUSE STATE //////////   
    $sli.hover(function(){ clearInterval(itv); }, autoSlide);
});
#galcontainer{
    position:relative;
    margin:20px auto;
    width:600px;
}
#gallery{
    position:relative;
    overflow:hidden;
    width:600px;
    height:240px;
}
#slider{
    position:absolute;
    top:0px;
    left:0px;
}
#slider img{
    float:left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="galcontainer">    
    <div id="gallery">    
        <div id="slider">
            <img src="http://dummyimage.com/600x240/479/fff"/>
            <img src="http://dummyimage.com/600x240/636/fff"/>
            <img src="http://dummyimage.com/600x240/587/fff"/>
            <img src="http://dummyimage.com/600x240/447/fff"/>
        </div>     
    </div>   
</div>

(关于原始(但已修改)代码的注释)

由于只有一个方向,direction变量"+=""0-"是不需要的,因此请使用counter = 0索引,并使用提醒进行环绕/重置{ {1}}运算符。此外,

%

可以写成:

        animation(function(){
            auto();                   
        }); 

因为 animation(auto); 已经是一个函数。

auto

可以与///// MOUSE STATE ////////// $('#galcontainer').mouseenter( function () { clearInterval(myTimeOut); }); $('#galcontainer').mouseleave( function () { auto(); }); 方法一起使用(如上例所示)