jquery stop()所有动画,不让$ .when,.promise(),.done()返回完整吗?

问题描述 投票:0回答:2

似乎每个50-100 jsfiddle更新都将我带到stackoverflow社区,以帮助解决我创建的新问题!所以谢谢!

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

我的难题是:在某个时候,用户可能想暂停所有内容,然后在闲暇时再次恢复。我似乎无法添加此功能!

我可以使用$('div:animated')。stop()暂停所有动画,但这是临时的,因为.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也会移动。我实现的最初的非常丑陋的承诺系统使用了许多功能,因为每个功能都由许多动画组成。建议的答案将如何实现?

EDIT2有两个答案,charlietfl允许我轻松添加同时触发的辅助函数;很重要。 Alnitak拥有一种构造数组并将其应用于动画的优雅方法,该方法非常容易更改动画类型(fadeOut(),fadeIn())。

因此,我试图将两者结合起来,以便可以为使用Alnitaks数组格式的辅助动画创建嵌套数组:

['.box1', 'animate', { top:  '50px'}, 1000],

总之,我仍在研究所有答案,但与charlietfls的答案接近/接近。向其添加Alnitak的数组,或向Alnitak的数组添加charlietfl的嵌套。

这比我以前打算的还要强烈;感谢您的贡献和可学习的代码。...非常有用!

jquery animation promise deferred control-flow
2个回答
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
投票

而不是使用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/

© www.soinside.com 2019 - 2024. All rights reserved.