9

问题是当我尝试制作多个动画时,它们都会同时发生。
有没有办法让动画一个接一个地进行而不使用回调?

这是我想要做的:

$('#a1').click(function() { $('#div1').hide(3000); });
$('#a2').click(function() { $('#div2').hide(3000); });
$('#a3').click(function() { $('#div3').show(3000); });

如果您在第一个动画完成之前#a1单击然后单击#a2then #a3,则它不应立即开始,而是等到动画队列为空后再开始下一个。

以这个演示为例

我希望能够一个接一个地单击,a1然后首先让它完全隐藏第一个 div,然后完全隐藏第二个,然后显示第三个。a2a3

我的例子过于简单,虽然这可以通过回调来完成,但我真正的问题不能,所以回调不是一个选项。

本质上,如果您单击所有三个动画应该在 9 秒内完成。

此演示应提醒 ('took around 9 seconds to complete')

4

7 回答 7

9

.queue()在一个常见的 jQuery 对象上使用:

var q = $({}); // this could also be a common parent, e.g. $('body')
$('#a1').click(function() {
    q.queue(function(next) {
        $('#div1').hide(3000, next);
    });
    return false;
});
$('#a2').click(function() {
    q.queue(function(next) {
        $('#div2').hide(3000, next);
    });
    return false;
});
$('#a3').click(function() {
    q.queue(function(next) {
        $('#div3').show(3000, next);
    });
    return false;
});​

演示

于 2012-06-12T18:14:00.303 回答
3

使用.promise()show回避和上的回调hide

.promise() 方法返回一个动态生成的 Promise,一旦绑定到集合的特定类型的所有操作(无论是否排队)都结束,该 Promise 就会被解析。

默认情况下,type为“fx”,这意味着当被选元素的所有动画都完成时,返回的Promise被解析

使用.queue()限制每个 promise 解析的动画数量(另见jsFiddle):

var promises = $({});

$('#a1').click(function() {
    promises.queue(function(next) {
        $('div').promise().done(function() {
            $('#div1').hide(3000);
            next();
        });
    });
    return false;
});
$('#a2').click(function() {
    promises.queue(function(next) {
        $('div').promise().done(function() {
            $('#div2').hide(3000);
            next();
        });
    });
    return false;
});
$('#a3').click(function() {
    promises.queue(function(next) {
        $('div').promise().done(function() {
            $('#div3').show(3000);
            next();
        });
    });
    return false;
});
于 2012-06-14T08:54:54.837 回答
2

尝试用队列创建一些数组,并检查其中是否有东西,作为动画的回调,如果有,则再次运行它。我已经玩过你的例子了。

看看这个:

http://jsfiddle.net/acrashik/nqh6x/6/

var queue = {
    q: [],
    run: function(elem, type, time, recall) {
        if (queue.isRunning && !recall) {
            console.log('pushed: ' + elem + type + time);            
            queue.q.push({elem:elem, type:type, time:time});
        } else {
            console.log('running:' + elem);
            queue.isRunning = true;
            if (type=='hide') {
                $(elem).hide(time, function(){
                    queue.recall();
                })
            } else {
                $(elem).show(time, function(){
                    queue.recall();
                })             
            }
        }                    
    },
    recall: function(){
        console.log(queue.q.length);                    
        if (queue.q.length > 0) {
            queue.run(queue.q[0].elem, queue.q[0].type, queue.q[0].time, true);
            queue.q = queue.q.splice(1,queue.q.length);
        } else {
            queue.isRunning = false;
            queue.q = [];
        }
    },            
    isRunning: false
}
$('#a1').click(function() { queue.run('#div1','hide',2200) });
$('#a2').click(function() { queue.run('#div2','hide',2200) });
$('#a3').click(function() { queue.run('#div3','show',2200) });
于 2012-06-12T13:18:50.827 回答
1

我会使用该animate()函数,因为它带有一个完整的函数,当动画完成时调用它http://api.jquery.com/animate/

所以要使用 jQuery 文档示例:

$('#clickme').click(function() {
  $('#book').animate({
   opacity: 0.25,
   left: '+=50',
   height: 'toggle'
}, 5000, function() {
// Animation complete this is where you call the next animation...
  });
});

function another_animation () {
  $('xyz').animate({
   opacity: 0.25,
   left: '+=50',
}5000, function() {
// Animation complete this is where you call the next animation

我认为这是最干净的方法...

于 2012-06-18T22:38:47.197 回答
0

你可以这样做:

(function(){
    var col=(function(){
        var i=1;
        return function(n){alert("you clicked link nr " + n + ", total clicks: "+i++)};
    })();
    $('#a1').click(function(){col(1)});
    $('#a2').click(function(){col(2)});
    $('#a3').click(function(){col(3)});
})();

我不会为你编写整个代码,但这应该让你很好地了解如何去做。此外,任何变量或函数都不能从全局范围或任何其他范围内访问。

于 2012-06-12T12:39:55.027 回答
-1

在动画前添加 stop():

$('#a1').click(function() { $('#div1').stop().hide(3000); });
$('#a2').click(function() { $('#div2').stop().hide(3000); });
$('#a3').click(function() { $('#div3').stop().show(3000); });
于 2012-06-03T18:25:34.727 回答
-2

用这个 $(element).promise().done(function () {...})

在你的情况下

$('#a1').click(function () {
    $('#div1').hide(3000);
});
$('#a2').click(function () {
    $("#div1").promise().done(function () {
        $('#div2').hide(3000);
    });
});
$('#a3').click(function () {
    $("#div2").promise().done(function () {
        $('#div3').hide(3000);
    });
});

仅当所选元素上的上一个动画完成时,才会执行下一个动画。

于 2012-06-03T19:01:29.870 回答