24

我有多个函数可以对 HTML 的不同部分执行不同的动画。我想链接或排队这些函数,以便它们按顺序而不是同时运行动画。

我正在尝试按顺序自动执行多个事件,以使用户看起来像是在单击不同的按钮或链接。

我可能可以使用回调函数来做到这一点,但是我必须从不同的函数中提取所有动画并以正确的模式重新组合。

jquery“队列”有帮助吗?我无法理解队列的文档

例如,jQuery:

 function One() {
        $('div#animateTest1').animate({ left: '+=200' }, 2000);
    }
    function Two() {
        $('div#animateTest2').animate({ width: '+=200' }, 2000);
    }

// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
    One();
    Two();

HTML:

    <div id="animatetest" style="width:50px;height:50px;background-color:Aqua;position:absolute;"></div>
    <div id="animatetest2" style="width:50px;height:50px;background-color:red;position:absolute;top:100px;"></div>

谢谢。

编辑:我用计时器尝试过,但我认为有更好的方法。

编辑#2:

让我更具体一点。我有多个功能绑定到页面不同元素上的单击和悬停事件。通常这些函数彼此无关(它们不相互引用)。我想在不更改现有函数代码的情况下模拟用户经历这些事件。

4

15 回答 15

38

jQuery Queue 代码没有得到充分的记录,但基本思想是这样的:

$("#some_element").queue("namedQueue", function() {
  console.log("First");
  var self = this;
  setTimeout(function() {
    $(self).dequeue("namedQueue");
  }, 1000);
});

$("#some_element").queue("namedQueue", function() {
  console.log("Second");
  var self = this;
  setTimeout(function() {
    $(self).dequeue("namedQueue");
  }, 1000);
});

$("#some_element").queue("namedQueue", function() {
  console.log("Third");
});

$("#some_element").dequeue("namedQueue");

如果你运行这段代码,你会在控制台看到“First”,停顿1s,在控制台看到“Second”,再停顿1s,最后在控制台看到“Third”。

基本思想是您可以将任意数量的命名队列绑定到一个元素。您可以通过调用从队列中删除一个元素dequeue。您可以根据需要手动多次执行此操作,但如果您希望队列自动运行,您只需dequeue在 queued up 函数内部调用即可。

jQuery 中的动画都在一个名为fx. 当您为元素设置动画时,它会自动将新动画添加到队列中,如果当前没有动画正在运行,则调用 dequeue。如果您愿意,您可以将自己的回调插入fx队列;您只需要dequeue在最后手动调用(与任何其他队列使用一样)。

于 2009-07-08T01:26:30.183 回答
3

我会创建一个函数数组并添加你想要排队的每个函数。

然后我会附加一个函数调用,它循环遍历数组并通过 jQuery 将每个函数调用到事件中。

您可能可以为 jQuery 创建一个非常简单的插件,它也可以在内部处理这个问题。

于 2009-07-07T23:36:27.977 回答
2

假设您想保留OneTwo作为单独的功能,您可以执行以下操作:

function One(callback) {
    $('div#animateTest1').animate({ left: '+=200' }, 2000, 
        function(e) { callback(); });
}
function Two() {
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
    One(Two);
于 2009-07-07T23:08:50.887 回答
2

我会将第二个作为回调函数运行:

$('div#animateTest1').animate({ left: '+=200' }, 2000, function(){
    two();
});

它将在第一个动画完成时运行 two(),如果您在这种情况下在定时队列上有更多动画,我使用jquery 计时器插件而不是 setTimeout(),这在某些情况下非常方便。

于 2009-07-07T23:10:09.467 回答
2

在我的一个 Web 项目中,我必须根据触发的事件执行各种操作序列。我使用回调(类似于访问者模式)来做到这一点。我创建了一个对象来包装任何功能或一组动作。然后我将这些包装器排队;数组工作正常。当事件触发时,我将遍历数组,调用我的对象的特殊方法,该方法接受回调。该回调触发了我的迭代继续。

要包装函数,您需要了解应用函数。apply 函数接受一个对象作为作用域和一个参数数组。这样你就不需要知道你要包装的函数的任何信息。

于 2009-07-07T23:37:16.587 回答
2

只是类似的东西怎么样?

var f1 = function() {return $(SELECTOR1).animate({ 'prop': 'value' }, 1000)};
var f2 = function() {return $(SELECTOR2).animate({ 'prop': 'value' }, 1000)};
var f3 = function() {return $(SELECTOR3).animate({ 'prop': 'value' }, 1000)};

$.when(f1).then(f2).then(f3);
于 2014-07-20T03:56:00.597 回答
1

一种更安全且 100% 的工作方式是使用变量和 if 分支。在下面的示例中,我们执行 4 个作业,需要 1 秒,在作业之后我们希望函数 f2 运行。

<html><body>
<div id="a" class="a" />
 <script type="text/javascript">
var jobs = 0;
function f1() {
job(); 
job();
job();
job();    
};

function f2() {
    if(jobs >3)
        l("f2");
};

<!------------------------- ->
function job() {
    setTimeout(function() {
        l("j");
        jobs+=1;
        f2();
    }, 1000);
}
function l(a) {
    document.getElementById('a').innerHTML+=a+"<br />";
};
f1();


</script></body></html>
于 2011-05-23T06:57:20.093 回答
1

真正简单的修复。

function One() {
        $('div#animateTest1').animate({ left: '+=200' }, 2000, Two);
    }
    function Two() {
        $('div#animateTest2').animate({ width: '+=200' }, 2000);
    }

// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
    One();
//We no longer need to call Two, as it will be called when 1 is completed.
    //Two();
于 2012-01-11T16:09:52.393 回答
0

至于已经在 2000 毫秒内定义的动画间隔,您可以在 2000 毫秒内进行第二次延迟调用:

One();
SetTimeout(function(){
  Two();
}, 2000);
于 2009-07-07T23:06:23.887 回答
0

复制和粘贴............7/9/2013

<!doctype html>
<html lang="en">
    enter code here<head>
  <meta charset="utf-8">
  <title>jQuery.queue demo</title>
  <style>
  div { margin:3px; width:40px; height:40px;
        position:absolute; left:0px; top:30px;
        background:green; display:none; }
  div.newcolor { background:blue; }
    </style>
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>

  <button id="start">Start</button>
  <button id="stop">Stop</button>
  <div></div>
<script>
   $("#start").click(function () {
      $("div").show("slow");
      $("div").animate({left:'+=200'},5000);
      jQuery.queue( $("div")[0], "fx", function () {
        $(this).addClass("newcolor");
        jQuery.dequeue( this );
      });
      $("div").animate({left:'-=200'},1500);
      jQuery.queue( $("div")[0], "fx", function () {
        $(this).removeClass("newcolor");
        jQuery.dequeue( this );
      });
      $("div").slideUp();
    });
    $("#stop").click(function () {
      jQuery.queue( $("div")[0], "fx", [] );
      $("div").stop();
    });
</script>

</body>
</html>
于 2013-09-06T22:39:31.727 回答
0
$('div#animateTest1').animate({left: '+=200'},2000, 
function(){
   $('div#animateTest2').animate({ width: '+=200' }, 2000);
}
);
于 2012-01-30T14:37:43.050 回答
0

@TrippRitter 必须将 .call 附加到回调

One = function(callback){
    $('div#animateTest1').animate({ left: '+=200' }, 2000, function(){
        if(typeof callback == 'function'){
            callback.call(this);
        }
    });
}

Two = function(){
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

One(function(){ 
    Two();
});

但它与执行以下操作相同

$('div#animateTest1')
    .animate({ left: '+=200' }, 2000, 
    function(){
       Two();
    });

Two = function(){
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}
于 2009-11-30T22:51:19.367 回答
0

如果回调为空,以下将起作用并且不会出错:

function One(callback)
{
    $('div#animateTest1').animate({ left: '+=200' }, 2000, 
       function()
       {
            if(callback != null)
            {
                 callback();
            }
       }
    );
}
function Two()
{
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

var callback = function(){ Two(); };
One(callback);
于 2009-11-27T19:36:14.323 回答
0

虽然 Yehuda Katz 的回答在技术上是正确的,但它会随着更大更复杂的动画而迅速膨胀。

我为像你这样的情况制作了一个插件,允许排队功能(如果需要,可以暂停和恢复)。

演示:https ://jessengatai.github.io/okaynowthis.js/

使用 Oknowthis.js 解决您的问题的方法如下所示:

$('window').load(function(){

    // keyframe 1
    $('body').okaynowthis('keyframe',0,function(){
        $('div#animateTest1').animate({ left: '+=200' }, 2000);
        // + anything else you want to do

    // keyframe 2 (with 2 seconds delay from keyframe 1)
    }).okaynowthis('keyframe',2000,function(){
        $('div#animateTest2').animate({ left: '+=200' }, 2000);
        // + anything else you want to do

    });

});
于 2016-10-14T05:21:10.330 回答
-1

而不是创建一个函数简单的方法是在这里:

$('#main').animate({ "top": "0px"}, 3000, function()
   {    $('#navigation').animate({ "left": "100px"},  3000, function() 
        {
            alert("Call after first and second animation is completed.");
        })
    }
);

因此,Jquery 默认提供一个一个执行函数的队列。

于 2010-11-26T07:08:18.147 回答