web-dev-qa-db-ja.com

jQueryを使用して複数の要素を順次アニメーション化するにはどうすればよいですか?

簡単だと思ったのですが、それでも動作しません。ボタンを1つクリックするだけで、いくつかのアニメーションが発生します-次々-しかし、すべてのアニメーションが同時に発生します。これが私のコードです-私が間違っているところを誰かに教えてもらえますか?:

$(".button").click(function(){
  $("#header").animate({top: "-50"}, "slow")
  $("#something").animate({height: "hide"}, "slow")
  $("ul#menu").animate({top: "20", left: "0"}, "slow")
  $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");
});
32
lnvrt

たくさんのコールバックを行うことができます。

$(".button").click(function(){
    $("#header").animate({top: "-50"}, "slow", function() {
        $("#something").animate({height: "hide"}, "slow", function() {
            $("ul#menu").animate({top: "20", left: "0"}, "slow", function() {
                $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");        
            });
        });
    });
});
24
jammus

キューは、同じ要素をアニメーション化している場合にのみ機能します。主は、上記が投票された理由を知っていますが、機能しません。

アニメーションコールバックを使用する必要があります。関数を最後のパラメーターとしてanimate関数に渡すことができ、アニメーションが完了した後に呼び出されます。ただし、コールバックを含むネストされたアニメーションが複数ある場合、スクリプトはかなり読みにくくなります。

following プラグインをお勧めします。これは、ネイティブのjQueryアニメーション関数を書き換え、キュー名を指定できるようにします。同じキュー名で追加したすべてのアニメーションは、-- ここ のように順次実行されます。

スクリプトの例

  $("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
29
redsquare

私はこれが古い質問であることを知っていますが、新しいjQueryバージョン(1.5以上)の回答で更新する必要があります。

$.when関数を使用すると、次のヘルパーを作成できます。

function queue(start) {
    var rest = [].splice.call(arguments, 1),
        promise = $.Deferred();

    if (start) {
        $.when(start()).then(function () {
            queue.apply(window, rest);
        });
    } else {
        promise.resolve();
    }
    return promise;
}

その後、次のように呼び出すことができます。

queue(function () {
    return $("#header").animate({top: "-50"}, "slow");
}, function () {
    return $("#something").animate({height: "hide"}, "slow");
}, function () {
    return $("ul#menu").animate({top: "20", left: "0"}, "slow");
}, function () {
    return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");        
});
26
Bill Barry

@schmunkの答えのわずかな改善は、他の無関係なアニメーションとの競合を避けるために、プレーンオブジェクトjQueryオブジェクトのキューを使用することです:

$({})
    .queue(function (next) {
        Elm1.fadeOut('fast', next);
    })
    .queue(function (next) {
        Elm2.fadeIn('fast', next);
    })
    // ...

the docs によると、これを実行する問題に遭遇したことはありませんが、プレーンオブジェクトラッパーでキューメソッドを使用することは公式にはサポートされていません。

プレーンオブジェクトの操作

現在、jQueryでラップされたプレーンJavaScriptオブジェクトでサポートされている操作は、.data()、. prop()、. bind()、. unbind()、. trigger()および.triggerHandler()のみです。

6
pgraham

複数のタグを順番にアニメーション化する

本文のようなタグを選択してグローバルキューイングを行うだけで、jQueryの組み込みアニメーションキューイングを活用できます。

_// Convenience object to ease global animation queueing
$.globalQueue = {
    queue: function(anim) {
        $('body')
        .queue(function(dequeue) {
            anim()
            .queue(function(innerDequeue) {
                dequeue();
                innerDequeue();
            });
        });

        return this;
    }
};

// Animation that coordinates multiple tags
$(".button").click(function() {
    $.globalQueue
    .queue(function() {
        return $("#header").animate({top: "-50"}, "slow");
    }).queue(function() {
      return $("#something").animate({height: "hide"}, "slow");
    }).queue(function() {
        return $("ul#menu").animate({top: "20", left: "0"}, "slow");
    }).queue(function() {
        return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");
    });
});
_

http://jsfiddle.net/b9chris/wjpL31o0/

これが機能する理由とその動作は次のとおりです。

  1. $.globalQueue.queue()の呼び出しは、タグのアニメーションへの呼び出しをキューに入れるだけですが、bodyタグのキューに入れます。

  2. JQueryがボディキューのタグアニメーションにヒットすると、タグのキューでタグのアニメーションが開始されます。ただし、jQueryアニメーションフレームワークが機能する方法では、カスタムアニメーションコールバックにより、タグのアニメーションキュー(この場合はボディ)が停止します。 、カスタムアニメーションが渡されたdequeue()関数を呼び出すまで。したがって、アニメーションタグと本文のキューが別々であっても、本文タグのキューはdequeue()が呼び出されるのを待機しています。 http://api.jquery.com/queue/#queue-queueName-callback

  3. タグのキューで最後にキューに入れられたアイテムを呼び出して、dequeue()関数を呼び出すことでグローバルキューを続行します。これにより、キューが結合されます。

  4. 便宜上、_globalQueue.queue_メソッドはチェーンを簡単にするためにthis参照を返します。

setInterval

完全を期すために、setIntervalの代わりを探すだけで簡単にここに着陸できます。つまり、個別のアニメーションを調整することはそれほど難しくありません。新しいブラウザーがアニメーションキューとタイマーを延期してCPUを節約する方法が原因で発生するアニメーション。

次のようにsetIntervalの呼び出しを置き換えることができます。

_setInterval(doAthing, 8000);
_

これとともに:

_/**
 * Alternative to window.setInterval(), that plays nicely with modern animation and CPU suspends
 */
$.setInterval = function (fn, interval) {
    var body = $('body');
    var queueInterval = function () {
        body
        .delay(interval)
        .queue(function(dequeue) {
            fn();
            queueInterval();
            dequeue();  // Required for the jQuery animation queue to work (tells it to continue animating)
        });
    };
    queueInterval();
};

$.setInterval(doAthing, 8000);
_

http://jsfiddle.net/b9chris/h156wgg6/

また、バックグラウンドタブのアニメーションがブラウザーで再度有効になっている場合は、これらのぎこちないアニメーションの爆発を避けてください。

2
Chris Moschini

ジャムスの答えを拡張すると、これはおそらく、アニメーションの長いシーケンスでは少し実用的です。リストを送信し、それぞれを順番にアニメーション化し、リストを削減してanimateを再帰的に呼び出します。すべて終了したら、コールバックを実行します。

ここのリストは選択された要素のリストですが、アニメーションごとに異なるアニメーションパラメータを保持するより複雑なオブジェクトのリストである場合もあります。

これはフィドルです

$(document).ready(function () {
    animate([$('#one'), $('#two'), $('#three')], finished);
});

function finished() {
    console.log('Finished');
}

function animate(list, callback) {
    if (list.length === 0) {
        callback();
        return;
    }
    $el = list.shift();
    $el.animate({left: '+=200'}, 1000, function () {
        animate(list, callback);
    });
}
2
Sean

エフェクトを同じキュー、つまりBODY要素のキューに入れることもできます。

$('.images IMG').ready(
   function(){
        $('BODY').queue(
            function(){
                $('.images').fadeTo('normal',1,function(){$('BODY').dequeue()});
            }
        );
    }
);

最後のエフェクトコールバック内で必ずdequeue()を呼び出してください。

1
schmunk

これは既に十分に回答されています(jammusの回答が最良だと思います)が、delay()関数を使用して、Webサイトでこれを行う方法に基づいて別のオプションを提供すると思いました...

  $(".button").click(function(){
     $("#header").animate({top: "-50"}, 1000)
     $("#something").delay(1000).animate({height: "hide"}, 1000)
     $("ul#menu").delay(2000).animate({top: "20", left: "0"}, 1000)
     $(".trigger").delay(3000).animate({height: "show", top: "110", left: "0"}, "slow");
});

(1000を目的のアニメーション速度に置き換えます。アイデアは、遅延関数がその量だけ遅延し、各要素のアニメーションの遅延を累積するため、アニメーションがそれぞれ500ミリ秒の場合、遅延値は500、1000、1500になります)

編集:FYI jqueryの「遅い」速度も600ミリ秒です。したがって、アニメーションで「低速」を使用したい場合は、遅延関数への後続の各呼び出しでこれらの値を使用してください-600、1200、1800

1
MrVimes

私はバックトラッキングソリューションについて考えていました。

たぶん、ここですべてのオブジェクトが同じクラスを持つように定義できます。たとえば、.transparent

次に、startShowingなどの関数を作成して、.transparentクラスを持つ最初の要素を検索し、それをアニメーション化し、.transparentを削除して、それ自体を呼び出すことができます。

順序は保証できませんが、通常はドキュメントが記述された順序に従います。

これは私が試してみた機能です

function startShowing(){
      $('.pattern-board.transparent:first').animate(
        { opacity: 1}, 
        1000,
        function(){
          $(this).removeClass('transparent');
          startShowing();
        }
      );
    }
0
Lomefin