Rückruf nach Abschluss des CSS3-Übergangs

202

Ich möchte ein Element ausblenden (seine Deckkraft auf 0 umstellen) und dann, wenn Sie fertig sind, das Element aus dem DOM entfernen.

In jQuery ist dies unkompliziert, da Sie das "Entfernen" angeben können, das nach Abschluss einer Animation erfolgen soll. Aber wenn ich mit CSS3-Übergängen animieren möchte, muss ich trotzdem wissen, wann der Übergang / die Animation abgeschlossen ist?

CJ
quelle

Antworten:

334

Für Übergänge können Sie Folgendes verwenden, um das Ende eines Übergangs über jQuery zu erkennen:

$("#someSelector").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

Mozilla hat eine ausgezeichnete Referenz:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#Detecting_the_start_and_completion_of_a_transition

Für Animationen ist es sehr ähnlich:

$("#someSelector").bind("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function(){ ... });

Beachten Sie, dass Sie alle Ereigniszeichenfolgen mit Browserpräfix gleichzeitig an die bind () -Methode übergeben können, um das Auslösen des Ereignisses in allen Browsern zu unterstützen, die dies unterstützen.

Aktualisieren:

Gemäß dem Kommentar von Duck: Sie verwenden die .one()Methode von jQuery, um sicherzustellen, dass der Handler nur einmal ausgelöst wird. Beispielsweise:

$("#someSelector").one("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

$("#someSelector").one("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function(){ ... });

Update 2:

Die jQuery- bind()Methode ist veraltet, und die on()Methode wird ab sofort bevorzugt jQuery 1.7.bind()

Sie können auch die off()Methode für die Rückruffunktion verwenden, um sicherzustellen, dass sie nur einmal ausgelöst wird. Hier ist ein Beispiel, das der Verwendung der one()Methode entspricht:

$("#someSelector")
.on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
 function(e){
    // do something here
    $(this).off(e);
 });

Verweise:

Jim Jeffers
quelle
13
Es ist erwähnenswert, dass der Rückruf für jedes untergeordnete Element ausgelöst wird, das ebenfalls übertragen wird . Dies ist sehr wichtig, wenn Sie sich fragen, warum Ihr Rückruf öfter ausgelöst wird, als Sie erwartet hatten. Mir ist derzeit keine Umgehung bekannt.
Lev
22
@Lev Sie können dies leicht abmildern, indem Sie das aktuelle Ziel des Ereignisses mit seinem Ziel vergleichen. Also so etwas wie: function (event) {if (event.target === event.currentTarget) {/ * Mach Sachen * /}}
Jim Jeffers
5
Ja, das habe ich kurz nach dem Schreiben des Kommentars herausgefunden. > _ <Danke, dass du es gepostet hast; Ich bin sicher, es wird anderen helfen! :)
Lev
9
Wir verwenden .on()eher als .bind()für jQuery v1.7 + api.jquery.com/bind
olo
4
Alle modernen Browser unterstützen jetzt das nicht festgelegte Ereignis. caniuse.com/#feat=css-transitions Beachten Sie außerdem, dass "Transitionend WebkitTransitionEnd" in Chrome zweimal ausgelöst wird.
Michael S.
17

Eine weitere Option wäre die Verwendung des jQuery Transit Framework zu verwenden, um Ihre CSS3-Übergänge zu verarbeiten. Die Übergänge / Effekte funktionieren auf Mobilgeräten gut und Sie müssen Ihrer CSS-Datei keine einzige Zeile unordentlicher CSS3-Übergänge hinzufügen, um die Animationseffekte auszuführen.

Hier ist ein Beispiel, das die Deckkraft eines Elements beim Klicken auf 0 ändert und nach Abschluss des Übergangs entfernt wird:

$("#element").click( function () {
    $('#element').transition({ opacity: 0 }, function () { $(this).remove(); });
});

JS Fiddle Demo

ROFLwTIME
quelle
Der Rückruf funktioniert nicht - vielleicht liegt es an einer Änderung der API des Transits, die ich nicht kenne, aber das Geigenbeispiel funktioniert nicht. Es löst die Hide-Methode aus, bevor die Animation ausgeführt wird (in Chrom versucht)
Jonathan Liuti
@ JonathanLiuti getestet mit FireFox 25, IE11, Chrome 31. Funktioniert einwandfrei.
ROFLwTIME
Ja @ROFLwTIME du hast vollkommen recht - es scheint, dass mein Chrom einfach verrückt geworden ist. Habe die Geige heute nach einem sauberen Neustart von Chrom erneut getestet und sie funktioniert wie erwartet. Mein Fehler ! Tut mir leid wegen diesem.
Jonathan Liuti
14

Es ist ein animationendEreignis , das siehe Dokumentation beobachtet werden kann hier , auch für CSS - transitionAnimationen Sie nutzen könnten transitionendEreignis

Es sind keine zusätzlichen Bibliotheken erforderlich, die alle mit Vanilla JS funktionieren

document.getElementById("myDIV").addEventListener("transitionend", myEndFunction);
function myEndFunction() {
	this.innerHTML = "transition event ended";
}
#myDIV {transition: top 2s; position: relative; top: 0;}
div {background: #ede;cursor: pointer;padding: 20px;}
<div id="myDIV" onclick="this.style.top = '55px';">Click me to start animation.</div>

Yehuda Schwartz
quelle
2
Dies ist eine Borderline- Link-Antwort . Sie sollten Ihre Antwort erweitern, um möglichst viele Informationen hier aufzunehmen, und den Link nur als Referenz verwenden.
Auf Wiedersehen StackExchange
4
Stimmen Sie dieses ab, da es das erste ist, das sich nicht auf jQuery verlässt. Es macht keinen Sinn, einen ganzen Baum für einen Ast zu fällen.
Aaron Mason
7

Für alle, für die dies nützlich sein könnte, ist hier eine jQuery-abhängige Funktion, mit der ich erfolgreich eine CSS-Animation über eine CSS-Klasse angewendet und anschließend einen Rückruf erhalten habe. Es funktioniert möglicherweise nicht perfekt, da ich es in einer Backbone.js-App verwendet habe, aber vielleicht nützlich.

var cssAnimate = function(cssClass, callback) {
    var self = this;

    // Checks if correct animation has ended
    var setAnimationListener = function() {
        self.one(
            "webkitAnimationEnd oanimationend msAnimationEnd animationend",
            function(e) {
                if(
                    e.originalEvent.animationName == cssClass &&
                    e.target === e.currentTarget
                ) {
                    callback();
                } else {
                    setAnimationListener();
                }
            }
        );
    }

    self.addClass(cssClass);
    setAnimationListener();
}

Ich habe es irgendwie so benutzt

cssAnimate.call($("#something"), "fadeIn", function() {
    console.log("Animation is complete");
    // Remove animation class name?
});

Ursprüngliche Idee von http://mikefowler.me/2013/11/18/page-transitions-in-backbone/

Und das scheint praktisch: http://api.jqueryui.com/addClass/


Aktualisieren

Nachdem ich mit dem obigen Code und anderen Optionen zu kämpfen habe, würde ich vorschlagen, sehr vorsichtig zu sein, wenn man auf CSS-Animationen hört. Wenn mehrere Animationen ausgeführt werden, kann dies beim Abhören von Ereignissen sehr schnell chaotisch werden. Ich würde dringend empfehlen, für jede Animation eine Animationsbibliothek wie GSAP zu verwenden, auch für die kleinen.

David Sinclair
quelle
Vielen Dank für das Teilen, ich habe es verwendet und das Hinzufügen bearbeitet e.stopImmediatePropagation(); self.trigger(this.whichAnimationEvent()); //for purge existing event callback.apply(self);
BomAle
5

Die akzeptierte Antwort wird derzeit zweimal für Animationen in Chrome ausgelöst. Vermutlich liegt das daran, dass es webkitAnimationEndebenso gut erkennt wie animationEnd. Folgendes wird definitiv nur einmal ausgelöst:

/* From Modernizr */
function whichTransitionEvent(){

    var el = document.createElement('fakeelement');
    var transitions = {
        'animation':'animationend',
        'OAnimation':'oAnimationEnd',
        'MSAnimation':'MSAnimationEnd',
        'WebkitAnimation':'webkitAnimationEnd'
    };

    for(var t in transitions){
        if( transitions.hasOwnProperty(t) && el.style[t] !== undefined ){
            return transitions[t];
        }
    }
}

$("#elementToListenTo")
    .on(whichTransitionEvent(),
        function(e){
            console.log('Transition complete!  This is the callback!');
            $(this).off(e);
        });
Chuck Le Butt
quelle
3
Ich würde vorschlagen, stattdessen die Funktion whichAnimationEvent () aufzurufen, da sie sich mit Animationsereignissen befasst.
Jakob Løkke Madsen