2010-01-18 11 views
91

¿Es posible recibir una notificación (como devolución de llamada) cuando se ha completado una transición de CSS?Devolución de llamada en transición CSS

+0

http: // stackoverflow. com/questions/5023514/how-do-i-normalize-css3-transition-functions-across-browsers – zloctb

Respuesta

77

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

Su ejemplo (reordenada en varias líneas):

box.addEventListener( 
    'webkitTransitionEnd', 
    function(event) { 
     alert("Finished transition!"); 
    }, false); 
+1

Gracias Doug, eso fue todo. – Pompair

+0

¿hay lo mismo para otro navegador que para Webkit? – meo

+6

sí, 'transitionend' para Mozilla y 'oTransitionEnd' en Opera. – qqryq

98

Sí, si tales cosas son compatibles con el navegador, a continuación, se activa un evento cuando la transición se complete. El evento actual, sin embargo, se diferencia entre los navegadores:

  • navegadores Webkit (Chrome, Safari) utiliza webkitTransitionEnd
  • Firefox usa transitionend
  • IE9 + utiliza msTransitionEnd
  • Opera utiliza oTransitionEnd

Sin embargo, usted debe tener en cuenta que webkitTransitionEnd no siempre se activa! Esto me ha sorprendido varias veces, y parece ocurrir si la animación no tendría ningún efecto sobre 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 haya activado como se esperaba. Un blog acerca de este problema está disponible aquí: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/<-500 error interno del servidor

Con esto en mente, tienden a utilizar este evento en un trozo de código que se parece un poco como 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 utilizar el método publicado como la respuesta en: How do I normalize CSS3 Transition functions across browsers?.

Nota: esta pregunta también se relaciona con: - CSS3 transition events

+2

Esta es una respuesta mucho más completa que el aceptado. ¿Por qué no está esto más votado? – Wes

+0

Recuerde llamar a 'transitionEndedHandler' en' transitionEnded' (o cambie 'transitionEnded' por' transitionEndedHandler' en 'addEventListener' y' removeEventListener' y llame a 'transitionEnded' en' transitionEndedHandler') – Miquel

+0

Gracias @Miquel; Creo que acababa de usar 'transitionEnded' cuando quise decir' transitionEndedHandler'. –

6

El jQuery.transit plugin, un plugin para transformaciones CSS3 y transiciones, puede llamar a sus animaciones CSS desde el guión y le dará una devolución de llamada.

42

Estoy utilizando el siguiente código, es mucho más simple que tratar de detectar qué evento final específico utiliza un navegador.

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

Alternativamente, si se utiliza de arranque a continuación, sólo tiene que hacer

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

Ésta es becuase 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); 
+2

Esto es más lento porque tiene que buscar a través de esa lista completa cada vez que ocurre el evento para ver si es el correcto. – phreakhead

+3

@phreakhead El rendimiento de cualquiera de estos enfoques será muy similar – Tom

Cuestiones relacionadas