Devolución de llamada en la transición CSS

Respuestas:

82

Sé que Safari implementa una devolución de llamada webkitTransitionEnd que puede adjuntar directamente al elemento con la transición.

Su ejemplo (reformateado a varias líneas):

box.addEventListener( 
     'webkitTransitionEnd', 
     function( event ) { 
         alert( "Finished transition!" ); 
     }, false );
Doug Neiner
fuente
¿Existe lo mismo para otro navegador que webkit?
meo
6
sí, 'transiciónend' para Mozilla y 'oTransitionEnd' en Opera.
qqryq
2
¿Qué hace lo falso al final?
meo
@meo Tiene algo que ver con el thiselemento dentro de la devolución de llamada. Pero es un parámetro obligatorio, por lo que en este caso solo cumple con el requisito.
Doug Neiner
8
@DougNeiner El falso al final es para useCaptureMode. Cuando ocurre un evento, hay dos fases: la primera fase es el modo de captura, la segunda es el modo de burbuja. En el modo de captura, el evento desciende del elemento del cuerpo al elemento especificado. Luego ingresa al modo burbuja, donde hace lo contrario. Ese parámetro falso final especifica que desea que el detector de eventos se produzca en modo burbuja. Un uso de esto es adjuntar controladores de eventos justo antes de que se necesiten en el modo de burbuja. =) 37signals.com/svn/posts/…
rybosome
103

Sí, si el navegador admite tales cosas, se activa un evento cuando se completa la transición. Sin embargo, el evento real difiere entre los navegadores:

  • Uso de navegadores Webkit (Chrome, Safari) webkitTransitionEnd
  • Usos de Firefox transitionend
  • Usos de IE9 + msTransitionEnd
  • Usos de Opera oTransitionEnd

Sin embargo, debe tener en cuenta que webkitTransitionEndno siempre se dispara. Esto me ha sorprendido varias veces y parece ocurrir si la animación no tuviera ningún efecto en el elemento. Para evitar esto, tiene sentido utilizar un tiempo de espera para activar el controlador de eventos en el caso de que no se active como se esperaba. Una publicación de blog sobre este problema está disponible aquí: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/ <- 500 Internal Server Error

Con esto en mente, tiendo a usar este evento en un fragmento de código que se parece un poco a esto:

var transitionEndEventName = "XXX"; //figure out, e.g. "webkitTransitionEnd".. 
var elemToAnimate = ... //the thing you want to animate..
var done = false;
var transitionEnded = function(){
     done = true;
     //do your transition finished stuff..
     elemToAnimate.removeEventListener(transitionEndEventName,
                                        transitionEnded, false);
};
elemToAnimate.addEventListener(transitionEndEventName,
                                transitionEnded, false);

//animation triggering code here..

//ensure tidy up if event doesn't fire..
setTimeout(function(){
    if(!done){
        console.log("timeout needed to call transition ended..");
        transitionEnded();
    }
}, XXX); //note: XXX should be the time required for the
        //animation to complete plus a grace period (e.g. 10ms) 

Nota: para obtener el nombre final del evento de transición, puede usar el método publicado como respuesta en: ¿Cómo normalizo las funciones de transición CSS3 en los navegadores? .

Nota: esta pregunta también está relacionada con: - Eventos de transición CSS3

Mark Rhodes
fuente
2
Esta es una respuesta mucho más completa que la aceptada. ¿Por qué esto no es más votado?
Wes
Recuerde llamar transitionEndedHandleren transitionEnded(o cambio transitionEndedpor transitionEndedHandleren addEventListenery removeEventListenery llamada transitionEndeden transitionEndedHandler)
Miquel
Gracias @Miquel; creo que acababa de usar transitionEndedcuando quise decir transitionEndedHandler.
Mark Rhodes
Creo que el problema de Chromium para esto se puede encontrar aquí: code.google.com/p/chromium/issues/detail?id=388082 Aunque, el último comentario parece (incorrectamente en mi opinión) descartarlo como un error y, por lo tanto, actualmente está marcado como "no se solucionará".
Willster
No hay necesidad de nombres diferentes hoy en día caniuse.com/#feat=css-transitions
Juan Mendes
43

Estoy usando el siguiente código, es mucho más simple que intentar detectar qué evento final específico usa un navegador.

$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', 
function() {
 //do something
});

Alternativamente, si usa bootstrap, simplemente puede hacer

$(".myClass").one($.support.transition.end,
function() {
 //do something
});

Esto se debe a que incluyen lo siguiente en bootstrap.js

+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================

  function transitionEnd() {
    var el = document.createElement('bootstrap')

    var transEndEventNames = {
      'WebkitTransition' : 'webkitTransitionEnd',
      'MozTransition'    : 'transitionend',
      'OTransition'      : 'oTransitionEnd otransitionend',
      'transition'       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }

    return false // explicit for ie8 (  ._.)
  }

  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false, $el = this
    $(this).one($.support.transition.end, function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

  $(function () {
    $.support.transition = transitionEnd()
  })

}(jQuery);
Tom
fuente
2
Esto es más lento porque tiene que buscar en toda la lista cada vez que ocurre el evento para ver si es el correcto.
phreakhead
3
@phreakhead Las actuaciones de cualquiera de estos enfoques serán muy similares
Tom
6

El complemento jQuery.transit , un complemento para transformaciones y transiciones CSS3, puede llamar a sus animaciones CSS desde el script y devolverle la llamada.

Brian
fuente
5

Esto se puede lograr fácilmente con el transitionendevento. Consulte la documentación aquí. Un ejemplo simple:

document.getElementById("button").addEventListener("transitionend", myEndFunction);

function myEndFunction() {
	this.innerHTML = "Transition event ended";
}
#button {transition: top 2s; position: relative; top: 0;}
<button id="button" onclick="this.style.top = '55px';">Click me to start animation</button>

Yehuda Schwartz
fuente
1
Esta es la respuesta correcta hoy en día, ya no es necesario tener prefijos. caniuse.com/#feat=css-transitions
Juan Mendes