web-dev-qa-db-ja.com

JQueryを使用してカスタム関数をチェーンまたはキューに入れるにはどうすればよいですか?

HTMLの異なる部分に異なるアニメーションを実行する複数の機能があります。これらの関数をチェーンまたはキューに入れて、アニメーションが同時にではなく順次実行されるようにしたいと考えています。

ユーザーがさまざまなボタンやリンクをクリックしているように見えるように、複数のイベントを順番に自動化しようとしています。

おそらくコールバック関数を使用してこれを行うことができますが、その後、さまざまな関数からすべてのアニメーションを引き出して、正しいパターンに再グループ化する必要があります。

Jqueryの「キュー」は役に立ちますか?キューの documentation を理解できませんでした。

例、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>

ありがとう。

編集: timers で試しましたが、もっと良い方法があると思いました。

編集#2:

より具体的にさせてください。ページのさまざまな要素のクリック&ホバーイベントにバインドされた複数の関数があります。通常、これらの関数は互いに何の関係もありません(互いに参照しません)。既存の関数のコードを変更せずに、これらのイベントを通過するユーザーをシミュレートしたいと思います。

24
orandov

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」、1秒の休止、コンソールに「Second」、1秒の休止が表示され、最後にコンソールに「Third」が表示されます。

基本的な考え方は、要素にバインドされた名前付きキューをいくつでも持つことができるということです。 dequeueを呼び出して、キューから要素を削除します。これは手動で何度でも手動で実行できますが、キューを自動的に実行する場合は、キューに入れられた関数内でdequeueを呼び出すだけです。

JQueryのアニメーションはすべて、fxというキュー内で実行されます。要素をアニメーション化すると、新しいアニメーションが自動的にキューに追加され、アニメーションが実行されていない場合はデキューが呼び出されます。必要に応じて、独自のコールバックをfxキューに挿入できます。最後に手動でdequeueを呼び出す必要があります(他のキューの使用と同様)。

37
Yehuda Katz

関数の配列を作成し、キューに入れたいすべての関数を追加します。

次に、配列をループし、jQueryを介して各関数をイベントに呼び出す関数呼び出しを追加します。

おそらく、これも内部で処理できるjQuery用の非常に単純なプラグインを作成できます。

3
Spencer Ruport

そのようなものはどうですか?

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);
2
Skaumo

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);
2
marcc

2番目をコールバック関数として実行します。

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

最初のアニメーションが終了したときにtwo()を実行します。そのような場合のために時限キューにさらにアニメーションがある場合、代わりに jquery timer plugin を使用します。代わりにsetTimeout()を使用します。これは、場合によって非常に便利です。

2
Sinan

Webプロジェクトの1つで、発生したイベントに応じて、さまざまな一連のアクションを実行する必要がありました。私はこれをコールバック(Visitorパターンのようなもの)を使用して行いました。関数やアクションのグループをラップするオブジェクトを作成しました。次に、それらのラッパーをキューに入れます。配列は正常に機能します。イベントが発生すると、配列を反復処理して、コールバックを受け取るオブジェクトの特殊なメソッドを呼び出します。そのコールバックにより、反復が続行されました。

関数をラップするには、 適用関数 の知識が必要です。 apply関数は、スコープのオブジェクトと引数の配列を取ります。そうすれば、ラップしている関数について何も知る必要がなくなります。

2
geowa4

より安全で完全に機能する方法は、変数とif分岐を使用することです。次の例では、1秒かかる4つのジョブを実行します。ジョブの後に、関数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>
1
gamadrillen

本当に簡単な修正。

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();
1
DigitalDesignDj

@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);
}
0
twenjamin
$('div#animateTest1').animate({left: '+=200'},2000, 
function(){
   $('div#animateTest2').animate({ width: '+=200' }, 2000);
}
);
0
Florin Daniel

コピーして貼り付け............ 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>
0
Jacques

イェフダ・カッツの答えは技術的には正しいですが、大きく複雑なアニメーションでは非常に速く膨らみます。

私はあなたのような状況のためのキューイング機能を可能にするプラグインを作りました(必要なら一時停止と再開で)。

デモ: https://jessengatai.github.io/okaynowthis.js/

Okaynowthis.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

    });

});
0
Jesse

アニメーション間隔が2000ミリ秒で既に定義されている限り、2000ミリ秒の遅延で2番目の呼び出しを実行できます。

One();
SetTimeout(function(){
  Two();
}, 2000);
0
Alex Pavlov

以下は機能し、コールバックがnullの場合はエラーになりません。

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);
0
TrippRitter