【问题标题】:jQuery - Disable Click until all chained animations are completejQuery - 禁用单击,直到所有链接的动画都完成
【发布时间】:2009-08-13 13:03:30
【问题描述】:

问题

下面的解决方案旨在将显示 div1groupDiv 向下滑动,并为 提供足够的空间div2 滑入。这一切都是通过在 #Link.Click() 元素上链接动画来实现的。

不过,当快速点击链接时,它似乎出错了。有没有办法防止这种情况?通过禁用 Click 功能直到 链接 动画完成?我目前有检查,但他们似乎没有做这项工作:(

这是我正在使用的代码:

自定义动画函数。


//Slide up or down and fade in or out
jQuery.fn.fadeThenSlideToggle = function(speed, easing, callback) {
    if (this.is(":hidden")) {
        visibilityCheck("show", counter--);
        return this.slideDown({duration: 500, easing: "easeInOutCirc"}).animate({opacity: 1},700, "easeInOutCirc", callback);
    } else {
        visibilityCheck("hide", counter++);
        return this.fadeTo(450, 0, "easeInOutCirc").slideUp({duration: 500, easing: "easeInOutCirc", complete: callback});
    }
};

//Slide off page, or into overflow so it appears hidden.
jQuery.fn.slideLeftToggle = function(speed, easing, callback) {
    if (this.css('marginLeft') == "-595px") {
        return this.animate({marginLeft: "0"}, speed, easing, callback);
    } else {
        return this.animate({marginLeft: "-595px"}, speed, easing, callback);
    }
};

在dom准备好了,我有这个:


$('#Link').toggle(
    function() {
        if (!$("#div2 .tab").is(':animated')) {
            $("#GroupDiv").fadeThenSlideToggle(700, "easeInOutCirc", function() {$('#div2 .tab').slideLeftToggle();});
        }
    },
    function(){
        if (!$("#groupDiv").is(':animated')) {
            $('#div2 .tab').slideLeftToggle(function() {$("#groupDiv").fadeThenSlideToggle(700, "easeInOutCirc", callback);} );
        }
    }
);

HTML 结构是这样的:


<div id="groupDiv">
     <div id="div1">
          <div class="tab"></div>
     </div>
     <div id="div2">
          <div class="tab"></div>
     </div>
</div>

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    问题是您第一次为 div#GroupDiv 设置动画,因此在 groupDiv 完成动画并触发回调之前,您的初始检查 if (!$("#div2 .tab").is(':animated')) 将为 false。

    你可以试试

    if (!$("#div2 .tab").is(':animated') && !$("#GroupDiv").is(':animated')) 
    

    但是我怀疑这将涵盖真正的快速点击。最安全的是使用解除绑定事件

    $(this).unbind('toggle').unbind('click');

    作为 if 内的第一行,然后您可以取消动画检查。这样做的缺点是您必须使用传递给自定义动画函数的回调重新绑定。

    【讨论】:

    • 嗯,可以。这有什么严重的缺点吗?我现在就试一试,然后回复你。
    • 除了取消绑定/绑定事件的性能开销之外,其他的不多。
    • 我从切换函数中删除了 if 语句,并添加到 $(this).unbind('toggle');但是,它似乎并没有取消绑定切换。 :S
    • 试试 $(this).unbind('toggle').unbind('click');
    • 实现梦想!这是已排序的解绑部分。虽然,在回调中再次绑定会带来另一个问题。 $("groupDiv").fadeThenSlideToggle(700, "easeInOutCirc", function() {$('#div2 .tab').slideLeftToggle(700, "easeInOutCirc", function() { $(this).bind('toggle ').bind('click');} );});抛出一个源自 jquery.js 文件的疯狂错误:TypeError: Result of expression 'H' [undefined] is not an object。所以我假设某些东西没有通过回调正确传递?
    【解决方案2】:

    您可以在动画运行时轻松禁用链接

    $('a').click(function () {
        if ($(':animated').length) {
            return false;
        }
    });
    

    您当然可以替换 $('a') 选择器以仅匹配部分链接。

    【讨论】:

    • 这就是他本质上在做的事情
    • 我更喜欢$('a').click(function () { if ($(this).is(':animated')) { return false; } });
    • @GFoley83 您的代码只有在链接动画时才有效。我的版本会检查 DOM 中是否有动画。
    • @RaYell 是的,没错。根据您要完成的工作,在当前范围内检查应该是所需要的全部例如停止多次点击以显示和隐藏移动导航。 ":animated" 不是 css 规范的一部分,它是一个 jQuery 扩展。所以在没有过滤器的情况下运行它,尤其是在整个 DOM 上(这是你推荐的)是非常低效的。
    【解决方案3】:

    动画可以重复点击的东西是需要注意的,因为它容易出错。我认为您的问题是即使您停止单击,动画也会排队并执行。我解决它的方法是在元素上使用 stop() 函数。

    语法:jQuery(selector).stop(clearQueue,gotoEnd) //两个参数都是布尔值
    More Info

    当我单击一个按钮时,我首先停止动画并清除队列,然后我继续在其上定义新动画。 gotoEnd 可以保持为 false(默认值),但如果需要,您可以尝试将其更改为 true,您可能会喜欢这样的结果。

    使用示例:jQuery('button#clickMe').stop(true).animate({left:+=10})。

    【讨论】:

    • 这不是他们排队的事实,我通过 :animated 检查来防止这种情况。事实上,它们彼此不同步的方式不止一种。
    【解决方案4】:

    你可以把这第一件事放在点击事件中

    $(element).css({ "pointer-events":"none"}); ,以及动画的回调函数中的this $(element).css({ "pointer-events":"auto"});

    【讨论】:

    • 迄今为止最简单的方法。我发现它也值得将其应用于整个容器,以限制动画运行时的任何其他冲突。
    【解决方案5】:

    您可以解除绑定...但这也应该可以:

    if (!$("#div2 .tab").is(':animated') && !$("#GroupDiv").is(':animated')) return;
    

    【讨论】:

      【解决方案6】:

      我最近制作了一个 AJAX jQuery 插件,其中包含大量动画。我发现的AJAX动画bug的解决方法如下。

          $(options.linkSelector).click(function(e){
          if ($("#yourNav").hasClass("disabled")) {
            return false;
          } else {
            e.preventDefault();
            $("#yourNav").addClass("disabled")
            // Prepare DOM for new content
            $(content).attr('id', 'content-old');
            $('<div/>', {id: 'ajMultiLeft'}).css({'top': '100%'}).insertAfter('#content-old');
      
            // Load new content
            $(content).load(linkSrc+ ' ' +options.content+ ' > *', function() {
      
            // Remove old content
      
            $(content).animate({top: '100%'}, 1000, function(){
              $(content-old).remove(); 
              $("#yourNav").removeClass("disabled")
            });
      
            setBase();
          }
      

      这样做是使每个链接的点击事件不响应,而父 div 有一个禁用类。禁用的类由函数在初始点击时设置,并通过最终动画的回调删除。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        • 2015-06-10
        相关资源
        最近更新 更多