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

标签 javascript jquery css event-handling css-animations

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

它的工作方式是,我从 width:0 开始我的进度条,并将其设置为 width:100%;。它具有 5s 的 CSS3 transition。然后我观察动画的结束,并用它来调用我的 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();
});

我的问题是,如果用户单击重置(最终将是下一个和上一个),我该如何在重置和开始新循环之前打破原来的循环?现在,我认为我正在开始一个新循环而不结束原始循环,这让我同时运行两个循环。

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

最佳答案

长话短说:

在链接你的 .one() 之前简单地调用一个 .off()


让我们使用您的 fiddle 进行实验。

实验 1:

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

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

观察:

是的,你是对的,它们是叠加的!如果您单击该按钮,则会添加更多 .one() 函数,并且会在条到达动画末尾时同时触发。一旦动画完成以下和后续时间,所有这些仍会触发!

即:运行 fiddle,点击你的按钮五次。第一个动画完成后,控制台记录 6 条消息 (5 + 1)。条形图会自行重置并产生另外 6 条消息。这是六的倍数。


实验 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();
});

观察:

这就是你的答案!该函数现在运行一次,因为在放置新的处理程序之前取消设置以前的处理程序。在链接您的 .one()

之前,只需调用 .off()

免责声明:

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

.off('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend')

关于javascript - jQuery 取消先前排队的事件处理程序以重新启动 CSS 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24959123/

相关文章:

html - 调整窗口大小时保持圆的纵横比

javascript - jstree 使用 html 将按钮添加到节点并使用上下文菜单重命名

JavaScript 简单的 "error-handling"通过用条件替换 NaN

javascript - 如何捕获jquery异常?

html - 表不收缩

html - 在保持宽高比的同时将标题定位在图像边框内

javascript - 如何在固定导航栏下显示图片?

javascript - 如何在身份验证后从静态 Express 页面提供整个 angularJS SPA?

jquery - 如果 $(window).load() 被弃用,我应该使用什么?

javascript - 最小最大价格范围验证不适用于 jquery.validate.js