Événements de transition CSS3

Réponses:

210

Brouillon des transitions CSS du W3C

L'achèvement d'une transition CSS génère un événement DOM correspondant. Un événement est déclenché pour chaque propriété qui subit une transition. Cela permet à un développeur de contenu d'effectuer des actions qui se synchronisent avec l'achèvement d'une transition.


Webkit

Pour déterminer quand une transition se termine, définissez une fonction d'écoute d'événement JavaScript pour l'événement DOM qui est envoyé à la fin d'une transition. L'événement est une instance de WebKitTransitionEvent et son type est webkitTransitionEnd.

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

Mozilla

Un seul événement est déclenché lorsque les transitions sont terminées. Dans Firefox, l'événement est transitionend, dans Opera oTransitionEnd, et dans WebKit il l'est webkitTransitionEnd.

Opéra

Il existe un type d'événement de transition disponible. L' oTransitionEndévénement se produit à la fin de la transition.

Internet Explorer

L' transitionendévénement se produit à la fin de la transition. Si la transition est supprimée avant la fin, l'événement ne se déclenchera pas.


Stack Overflow: Comment normaliser les fonctions de transition CSS3 dans les navigateurs?

Davor Lucic
la source
3
Notez que l'événement s'appelle "transitionend" dans Firefox et "oTransitionEnd" dans Opera
Andreas Köberle
8
Personne n'a mentionné quoi que ce soit au sujet de la partie transition-début de la question. N'existe-t-il aucun moyen d'enregistrer un gestionnaire d'événements à déclencher avant le début de la transition?
tyler
Existe-t-il désormais un moyen standard d'y parvenir? Semble 2 ans, c'est long! Les choses ont probablement changé.
Mild Fuzz
@tyler je ne sais pas comment contourner le manque de transitions-start.
Davor Lucic
La question de stackoverflow liée à @Mild Fuzz a une solution intéressante.
Davor Lucic
73

Mettre à jour

Tous les navigateurs modernes prennent désormais en charge l'événement sans préfixe:

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

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


J'utilisais l'approche donnée par Pete, mais j'ai maintenant commencé à utiliser ce qui suit

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

Alternativement, si vous utilisez bootstrap, vous pouvez simplement faire

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

C'est parce qu'ils incluent les éléments suivants dans 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);

Notez qu'ils incluent également une fonction emulateTransitionEnd qui peut être nécessaire pour garantir qu'un rappel se produit toujours.

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

Sachez que parfois cet événement ne se déclenche pas, généralement dans le cas où les propriétés ne changent pas ou une peinture n'est pas déclenchée. Pour nous assurer que nous recevons toujours un rappel, définissons un délai d'expiration qui déclenchera l'événement manuellement.

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

À M
la source
3
Vous ne pouvez pas faire quelque chose comme ça. Dans certains cas, le callbaack sera déclenché plus d'une fois.
sebastian
11
Dans les navigateurs qui conservent à la fois les noms d'événements préfixés et réguliers Vous pouvez contourner le problème en utilisant .one au lieu de .on
AlexG
61

Tous les navigateurs modernes prennent désormais en charge l'événement sans préfixe:

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

Fonctionne dans les dernières versions de Chrome, Firefox et Safari. Même IE10 +.

neave
la source
16

Dans Opera 12, lorsque vous liez en utilisant le JavaScript brut, 'oTransitionEnd' fonctionnera:

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

cependant si vous liez via jQuery, vous devez utiliser 'otransitionend'

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

Si vous utilisez Modernizr ou bootstrap-transition.js, vous pouvez simplement faire un changement:

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

Vous pouvez également trouver des informations ici http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/

Peter
la source
6

Juste pour le plaisir, ne fais pas ça!

$.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
la source
3

Si vous souhaitez simplement détecter une seule fin de transition, sans utiliser de framework JS, voici une petite fonction utilitaire pratique:

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

Usage:

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

puis si vous souhaitez annuler à un moment donné, vous pouvez toujours le faire avec

handler.cancel();

C'est également bon pour d'autres usages événementiels :)

OpherV
la source