jquery stop()所有动画都没有让延迟$ .when,.promise(),. done()返回完成?

时间:2012-11-16 22:28:18

标签: jquery animation deferred promise flow-control

似乎每50-100个jsfiddle更新引导我到stackoverflow社区来帮助解决我创建的新问题!谢谢!

背景:我有几个包含动画的函数,函数将在前一个函数完成后触发。通过一些帮助和研究,我开始使用$ .when和.promise()来控制这些东西超过我最初的非常丑陋的回调字符串&每个函数的setTimeouts。

我的困境是这样的:在某些时候,用户可能想要暂停所有内容并在闲暇时重新恢复。我似乎无法添加此功能!

我能用$('div:animated')暂停所有动画。停止()但这是暂时的,因为.promise()仍然可以解决!有没有办法覆盖这种行为?任何可能有助于暂停和恢复更容易实施的重组?

明天我计划沿着将所有动画添加到代理对象队列的路径,但不确定在新对象上创建全局队列将如何与现有结构一起使用。我还打算在添加一些布尔值来检查值是否关闭然后不调用函数或动画否则执行。我不确定这些解决方案中的任何一个是否应该采取适当的方向?

预览这篇文章后,我也倾向于学习如何重构我的嵌套启动按钮功能!

非常感谢实施暂停和恢复功能的任何方向。

以下代码大大简化,每个功能都包含更多元素和动画。

a fiddle here

JS:

    $('#start').click( function() {
    // run a and wait one second, when done run b and wait 1 second...
    a().delay(100).promise().done( function(){
        b().delay(100).promise().done( function(){
            c().delay(100).promise().done( function(){
                d().delay(100).promise().done( function(){
                    e().delay(100).promise().done( function(){
                        f().delay(100).promise().done( function(){
                            alert('all done!');
                        });
                    });
                });
            });
        });
    });


    });

    $('#reset').click( function() {
        $('.box').css({
            top: '0px'
        });
    });
    $('#pause').click( function() {
        $('div:animated').stop();
    });
   function a() {
        return $('.box1').animate({top: '100px'}, 1000, function(){
            $('.box1').animate({top: '50px'}, 1000);        
        });
        return $('.box6').animate({top: '200px'}, 4000);
    }
    function b(){
        return $('.box2').animate({top: '100px'}, 1000);
    }
    function c(){
        return $('.box3').animate({top: '100px'}, 1000, function(){
            $('.box3').animate({top: '50px'}, 1000);        
        });
    }
    function d(){
        return $('.box4').animate({top: '100px'}, 1000);
    }
    function e(){
        return $('.box5').animate({top: '100px'}, 1000, function(){
            $('.box5').animate({top: '50px'}, 1000);        
        });
    }
    function f(){
        return $('.box6').animate({top: '100px'}, 1000);
    }

html& CSS

<button id='start'>animate</button>
<button id='reset'>Reset</button>
<button id='pause'>pause</button>
<div class='boxes'>
    <div class='box box1'></div>
    <div class='box box2'></div>
    <div class='box box3'></div>
    <div class='box box4'></div>
    <div class='box box5'></div>
    <div class='box box6'></div>
</div>​
.boxes{position: relative}
.box{width: 40px; height: 40px; background-color: green; position:absolute;}
.box1{left: 0px;}
.box2{left: 60px;}
.box3{left: 120px;}
.box4{left: 180px;}
.box5{left: 240px;}
.box6{left: 300px;}
​

修改  你的答案提供了我所寻求的学习经历;我真的很感激心灵的分享!我设法的例子可能无法充分展示现实世界的问题,因为所提出的答案不允许多个动画同时发射?我至少不这么想?例如,box1和box2可以同时移动,或者当box3触发时,box6也是如此。我实现的最初的VERY UGLY承诺系统使用了许多函数,因为每个函数都由许多动画组成。如何通过提出的答案实现这一目标?

EDIT2 两个答案,charlietfl's让我轻松添加同时触发的辅助功能;很重要。 Alnitak有一种优雅的方法来构建一个数组并将其应用到动画中,这些动画很容易改变动画类型(fadeOut(),fadeIn())。

所以我试图做的是将两者合并,这样我就可以为使用Alnitaks数组格式的辅助动画创建一个嵌套数组:

['.box1', 'animate', { top:  '50px'}, 1000],
总而言之,我仍在研究所有答案,但与charlietfls的关系近似/差不多。将Alnitak的阵列添加到他的或添加charlietfl的嵌套到Alnitak的。

这比我想要的更激烈;感谢您的贡献和代码来学习....非常有用!

2 个答案:

答案 0 :(得分:3)

允许多个同步动画的jQuery方法非常好,但是当你的动画全部是顺序的时候就太过分了。

我建议创建一个动画描述数组,然后在一个简单的循环中一次调用一个。

每个描述都需要知道要设置动画的元素,调用哪个函数以及函数参数是什么。

暂停动画只是一个不循环的问题:

function next() {
    if (!animating) return;

    var a = list.shift();
    if (a) {
        var el = a[0];
        var fn = a[1];
        var args = a.slice(2);
        $.fn[fn].apply($(el), args).promise().done(next);
    } else {
        alert('all done!');
    }
};

请参阅http://jsfiddle.net/alnitak/ANRa3了解演示。

答案 1 :(得分:1)

而不是使用animate的回调来调用辅助动画,如果你链接animate().delay().animate(),你可以返回辅助动画的承诺。

我的解决方案使用嵌套的对象数组,因此您可以根据需要轻松地在一个序列中添加任意数量的动画。诀窍是创建一个包含组内所有promise的数组,并使用该数组确定完整的动画组何时完成。

示例数据:

var animations = [
   /* first group array */
    [ {  "sel": ".box1","main": {"css": {"top": "100px"},"dur": 1000},
         "secondary": {"delay": 100,"css": {"top": "50px"},"dur": 1000    }
        },
        {"sel": ".box2","main": {"css": {"top": "100px"},"dur": 1000}},
       {"sel": ".box4","main": {"css": {"top": "100px"},"dur": 1000}},
      {    "sel": ".box5","main": {"css": {"top": "100px"},"dur": 1000},
            "secondary": {"delay": 100,"css": {"top": "50px"},"dur": 1000    }
        }      
    ],
     /* second group array */
    [ { "sel": ".box3","main": {"css": {"top": "100px"},"dur": 1000},
            "secondary": {"delay": 100,"css": {"top": "50px"},"dur": 1000    }
        },
       {"sel": ".box4","main": {"css": {"top": "100px"},"dur": 1000}}
    ]
];

JS:

var curr = -1;
var paused = false;

function animateBoxes() {
    if (paused) {
        return;
    }
    //curr = (curr + 1 < animations.length) ? curr + 1 : 0;
    curr=curr+1;

    if( !animations[curr]){
        alert('DONE!!');
        return;
    }
    /* array of animation deffereds*/
    var anims = [];

    $.each(animations[curr], function(i, currAnim) {
        var anim = boxAnimate(currAnim);
        anims.push(anim)
    });

    $.when.apply(null, anims).done(function() {
        animateBoxes();
    });
}


$('#start').click(function() {
    paused = false;
    animateBoxes();
});

$('#reset').click(function() {
    curr = -1;
    stopanimation();
    $('.box').css({
        top: '0px'
    });
});
$('#pause').click(function() {
    stopanimation();
});


function stopanimation() {
    paused = true;
    $('div:animated').stop(true, true);

}

function boxAnimate(obj) {

    var $el = $(obj.sel),
        anim;
    if (obj.secondary) {
        /* chain animate & delay to get promise for last effect */
        anim = $el.animate(obj.main.css, obj.main.dur)
                  .delay(obj.secondary.delay)
                  .animate(obj.secondary.css, obj.secondary.dur)
    } else {
        anim = $el.animate(obj.main.css, obj.main.dur)
    }
    return anim;
}

DEMO:http://jsfiddle.net/SWHTx/5/