jQuery取消以前排队的事件处理程序以重新启动CSS动画

时间:2014-07-25 15:21:30

标签: javascript jquery css3 event-handling css-animations

我正在创建幻灯片,该幻灯片将在计时器上运行(由进度条显示),但允许用户单击箭头以强制下一个。我尝试使用尽可能多的CSS3,所以对于我的循环计时器,我使用进度条的CSS3动画。

它的工作方式是我在width:0开始我的进度条,并将其设置为width:100%;。它的CSS transition5s。然后我观察动画的结束,并使用它来调用我的resetprogresschangeimage函数,之后我再次开始进度。它无限循环。

我已经创建了一个简化的jsFiddle,以显示我正在谈论的内容: http://jsfiddle.net/a3H9L/

简化版的代码如下。如你所见,我调用startProgress,我通过改变宽度来启动CSS3动画,然后为所述动画的结束设置一个观察者,此时我重置然后重新开始。

startProgress();

function startProgress() {
    $('div').width('100%');
    $('div').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',function(e){
        resetProgress();
        startProgress();
    });
}

function resetProgress (){
    $('div').addClass('notransition'); // Disable transitions
    $('div').width('0');
    $('div')[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
    $('div').removeClass('notransition'); // Re-enable transitions
}

$('button').click(function(event){
    resetProgress();
    startProgress();
});

我的问题是,如果用户点击重置(最终将是Next和Previous),如何在重置和开始新循环之前打破原始循环?现在,我认为我在没有结束原始循环的情况下开始一个新的循环,这让我同时运行了两个循环。

编辑:我认为有问题的原因是,当我点击重置几次时,除了重置进度之外,循环中的事情在其他时间开始发生。

1 个答案:

答案 0 :(得分:2)

<强> TL; DR:

在链接.off()

之前,只需致电.one()即可

让我们用你的小提琴进行实验。

实验1:

每次调用.one()函数时,使用控制台记录一条简单消息:

$('div').one('...', function(e) {
    console.log('one called!');
    resetProgress();
    startProgress();
});

<强>观察:

是的,你是对的,他们堆叠了!如果单击该按钮,则会添加更多.one()个函数,并且一旦条形图到达动画结束,它们将同时闪烁。一旦动画完成以下及随后的时间,它们中的所有部分仍会触发!

即:运行小提琴,单击您的按钮五次。完成第一个动画后,控制台会记录六条消息(5 + 1)。该栏重置自己并再生成六条消息。这个数字是六的倍数。


实验2:

现在,让我们尝试在功能开始时自行关闭:

$('div').one('...', function(e) {
    $(this).off(e);
    console.log('one called!');
    resetProgress();
    startProgress();
});

<强>观察:

这并没有产生我们期待的取消效果。与第一个实验的结果相同。


实验3:

让我们尝试关闭所有处理程序(省略“e”):

$('div').one('...', function(e) {
    $(this).off();
    console.log('one called!');
    resetProgress();
    startProgress();
});

<强>观察:

所有排队的.one()处理程序在动画结束时执行,但它们在运行一次后自行终止,并且在下次动画完成时不会触发。


实验4:

您实际想要做的是在设置新处理程序之前取消所有先前排队的处理程序。让我们这样做:

$('div').off().one('...', function(e) {
    console.log('one called!');
    resetProgress();
    startProgress();
});

<强>观察:

有你的答案!此功能现在运行一次,因为之前的处理程序在放置新的处理程序之前未设置。在链接.off()

之前,只需致电.one()即可

声明:

这些实验假设这些是您元素上唯一的事件处理程序。如果您有.on().one()或类似设置的其他处理程序,而不是使用.off()清除所有内容,则必须指定要清除的处理程序,如下所示:

.off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend')