Eventos de transición CSS3

Respuestas:

210

Borrador de transiciones CSS W3C

La finalización de una transición CSS genera un evento DOM correspondiente. Se dispara un evento por cada propiedad que sufre una transición. Esto permite a un desarrollador de contenido realizar acciones que se sincronizan con la finalización de una transición.


Webkit

Para determinar cuándo se completa una transición, configure una función de escucha de eventos JavaScript para el evento DOM que se envía al final de una transición. El evento es una instancia de WebKitTransitionEvent, y su tipo es webkitTransitionEnd.

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

Mozilla

Hay un solo evento que se dispara cuando se completan las transiciones. En Firefox, el evento es transitionend, en Opera oTransitionEnd, y en WebKit webkitTransitionEnd.

Ópera

Hay un tipo de evento de transición disponible. El oTransitionEndevento se produce al finalizar la transición.

explorador de Internet

El transitionendevento se produce al finalizar la transición. Si la transición se elimina antes de completarse, el evento no se activará.


Desbordamiento de pila: ¿Cómo normalizo las funciones de transición CSS3 en los navegadores?

Davor Lucic
fuente
3
Tenga en cuenta que el evento se llama "transitionend" en firefox y "oTransitionEnd" en Opera
Andreas Köberle
8
Nadie ha mencionado nada sobre la parte de inicio de transición de la pregunta. ¿No hay forma de registrar un controlador de eventos para que se active antes de que comience la transición?
tyler
¿Existe ahora una forma estándar de lograr esto? Parece que 2 años es mucho tiempo! Las cosas probablemente han cambiado.
Mild Fuzz
@tyler no sé cómo solucionar la falta de transiciones-comienzo.
Davor Lucic
La pregunta de stackoverflow enlazado @Mild Fuzz tiene una solución interesante.
Davor Lucic
73

Actualizar

Todos los navegadores modernos ahora admiten el evento no prefijado:

element.addEventListener('transitionend', callback, false);

https://caniuse.com/#feat=css-transitions


Estaba usando el enfoque dado por Pete, sin embargo, ahora he comenzado a usar lo siguiente

$(".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 es porque 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 (  ._.)
  }


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

}(jQuery);

Tenga en cuenta que también incluyen una función emulateTransitionEnd que puede ser necesaria para garantizar que siempre se produzca una devolución de llamada.

  // 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
  }

Tenga en cuenta que a veces este evento no se dispara, generalmente en el caso en que las propiedades no cambian o no se activa una pintura. Para garantizar que siempre recibamos una devolución de llamada, establezcamos un tiempo de espera que active el evento manualmente.

http://blog.alexmaccaw.com/css-transitions

Tom
fuente
3
No puedes hacer algo así. En algunos casos, la devolución de llamada se disparará más de una vez.
sebastian
11
En navegadores que mantienen los nombres de eventos prefijados y regulares. Puede solucionarlo usando .one en lugar de .on
AlexG
61

Todos los navegadores modernos ahora admiten el evento no prefijado:

element.addEventListener('transitionend', callback, false);

Funciona en las últimas versiones de Chrome, Firefox y Safari. Incluso IE10 +.

neave
fuente
16

En Opera 12 cuando se enlaza usando el JavaScript simple, 'oTransitionEnd' funcionará:

document.addEventListener("oTransitionEnd", function(){
    alert("Transition Ended");
});

sin embargo, si vincula jQuery, debe usar 'otransitionend'

$(document).bind("otransitionend", function(){
    alert("Transition Ended");
});

En caso de que esté utilizando Modernizr o bootstrap-transition.js, simplemente puede hacer un cambio:

var transEndEventNames = {
    'WebkitTransition' : 'webkitTransitionEnd',
    'MozTransition'    : 'transitionend',
    'OTransition'      : 'oTransitionEnd otransitionend',
    'msTransition'     : 'MSTransitionEnd',
    'transition'       : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];

Puede encontrar información aquí también http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/

Peter
fuente
6

¡Solo por diversión, no hagas esto!

$.fn.transitiondone = function () {
  return this.each(function () {
    var $this = $(this);
    setTimeout(function () {
      $this.trigger('transitiondone');
    }, (parseFloat($this.css('transitionDelay')) + parseFloat($this.css('transitionDuration'))) * 1000);
  });
};


$('div').on('mousedown', function (e) {
  $(this).addClass('bounce').transitiondone();
});

$('div').on('transitiondone', function () {
  $(this).removeClass('bounce');
});
yckart
fuente
3

Si simplemente desea detectar un solo final de transición, sin usar ningún marco JS, aquí hay una pequeña y conveniente función de utilidad:

function once = function(object,event,callback){
    var handle={};

    var eventNames=event.split(" ");

    var cbWrapper=function(){
        eventNames.forEach(function(e){
            object.removeEventListener(e,cbWrapper, false );
        });
        callback.apply(this,arguments);
    };

    eventNames.forEach(function(e){
        object.addEventListener(e,cbWrapper,false);
    });

    handle.cancel=function(){
        eventNames.forEach(function(e){
            object.removeEventListener(e,cbWrapper, false );
        });
    };

    return handle;
};

Uso:

var handler = once(document.querySelector('#myElement'), 'transitionend', function(){
   //do something
});

entonces, si desea cancelar en algún momento, aún puede hacerlo con

handler.cancel();

También es bueno para otros usos de eventos :)

OpherV
fuente