¿Cómo usar jQuery para esperar el final de las transiciones CSS3?

Resuelto C.J. asked hace 12 años • 6 respuestas

Me gustaría desvanecer un elemento (cambiando su opacidad a 0) y luego, cuando termine, eliminar el elemento del DOM.

En jQuery, esto es sencillo ya que puede especificar que "Eliminar" se realice después de que se complete una animación. Pero si deseo animar usando transiciones CSS3, ¿hay alguna forma de saber cuándo se ha completado la transición/animación?

C.J. avatar Feb 13 '12 10:02 C.J.
Aceptado

Para las transiciones, puedes usar lo siguiente para detectar el final de una transición a través de jQuery:

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

Mozilla tiene una excelente referencia:

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

Para animaciones es muy similar:

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

Tenga en cuenta que puede pasar todas las cadenas de eventos con prefijo del navegador al método bind() simultáneamente para admitir la activación del evento en todos los navegadores que lo admitan.

Actualizar:

Según el comentario dejado por Duck: utiliza .one()el método de jQuery para garantizar que el controlador solo se active una vez. Por ejemplo:

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

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

Actualización 2:

El método jQuery bind()ha quedado obsoleto y on()se prefiere el método a partir de jQuery 1.7.bind()

También puede utilizar off()el método en la función de devolución de llamada para asegurarse de que se active solo una vez. A continuación se muestra un ejemplo que equivale a utilizar one()el método:

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

Referencias:

  • .off()

  • .one()

Jim Jeffers avatar Feb 13 '2012 04:02 Jim Jeffers

Hay un animationendevento que se puede observar, consulte la documentación aquí . También para transitionanimaciones CSS puede usar el transitionendevento.

No hay necesidad de bibliotecas adicionales, todas funcionan con Vanilla JS.

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>
Expandir fragmento

Yehuda Schwartz avatar Oct 31 '2018 20:10 Yehuda Schwartz

Para cualquiera a quien esto pueda resultarle útil, aquí hay una función dependiente de jQuery con la que tuve éxito para aplicar una animación CSS a través de una clase CSS y luego recibir una devolución de llamada. Puede que no funcione perfectamente ya que lo usé en una aplicación Backbone.js, pero tal vez sea útil.

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();
}

Lo usé un poco así

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

Idea original de http://mikefowler.me/2013/11/18/page-transitions-in-backbone/

Y esto parece útil: http://api.jqueryui.com/addClass/


Actualizar

Después de luchar con el código anterior y otras opciones, sugeriría ser muy cauteloso al escuchar los finales de la animación CSS. Con múltiples animaciones en marcha, esto puede complicarse muy rápidamente para la escucha de eventos. Recomiendo encarecidamente una biblioteca de animación como GSAP para cada animación, incluso las pequeñas.

David Sinclair avatar Apr 02 '2015 23:04 David Sinclair

La respuesta aceptada actualmente se activa dos veces para las animaciones en Chrome. Presumiblemente esto se debe a que webkitAnimationEndtambién lo reconoce animationEnd. Definitivamente lo siguiente solo se activará una vez:

/* 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 avatar Jul 13 '2016 16:07 Chuck Le Butt