0

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

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

我的困境是:在某些时候,用户可能想要暂停一切并在闲暇时再次恢复。我似乎无法添加此功能!

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

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

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

任何有关实现暂停和恢复功能的指导将不胜感激。

下面的代码非常简化,每个函数都包含更多元素和动画。

小提琴在这里

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 promise 系统使用了许多函数,因为每个函数都由许多动画组成。建议的答案将如何实现?

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

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

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

所以简而言之,我仍在研究所有答案,但与 charlietfls's 接近/接近。将 Alnitak 的数组添加到他的数组或将 charlietfl 的嵌套添加到 Alnitak 的数组。

这比我想象的更加激烈;我感谢您的贡献和代码学习....非常翔实!

4

2 回答 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 。

于 2012-11-16T22:38:03.123 回答
1

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

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

样本数据:

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;
}

演示:http: //jsfiddle.net/SWHTx/5/

于 2012-11-16T23:04:19.460 回答