Retorno de chamada na transição CSS

Respostas:

82

Eu sei que o Safari implementa um retorno de chamada webkitTransitionEnd que você pode anexar diretamente ao elemento com a transição.

Seu exemplo (reformatado para várias linhas):

box.addEventListener( 
     'webkitTransitionEnd', 
     function( event ) { 
         alert( "Finished transition!" ); 
     }, false );
Doug Neiner
fonte
existe a mesma coisa para outro navegador além do webkit?
meo
6
sim, 'transactionend' para Mozilla e 'oTransitionEnd' no Opera.
qqryq
2
o que o falso no final faz?
meo
@meo Tem algo a ver com o thiselemento dentro do callback. Mas é um parâmetro obrigatório, portanto, neste caso, está apenas cumprindo o requisito.
Doug Neiner
8
@DougNeiner O falso no final é para useCaptureMode. Quando ocorre um evento, existem duas fases - a primeira fase é o modo de captura, a segunda é o modo de bolha. No modo de captura, o evento desce do elemento do corpo para o elemento especificado. Em seguida, ele entra no modo de bolha, onde faz o inverso. Esse parâmetro falso final especifica que você deseja que o ouvinte de evento ocorra no modo de bolha. Um uso disso é anexar manipuladores de eventos imediatamente antes de serem necessários no modo de bolha. =) 37signals.com/svn/posts/…
rybosome
103

Sim, se essas coisas forem suportadas pelo navegador, um evento será disparado quando a transição for concluída. O evento real, entretanto, difere entre os navegadores:

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

No entanto, você deve estar ciente de que webkitTransitionEndnem sempre dispara! Isso me surpreendeu várias vezes e parece ocorrer se a animação não tiver efeito sobre o elemento. Para contornar isso, faz sentido usar um tempo limite para disparar o manipulador de eventos no caso de não ter sido disparado conforme o esperado. Uma postagem do blog sobre esse problema está disponível aqui: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/ <- 500 Internal Server Error

Com isso em mente, eu tendo a usar este evento em um pedaço de código que se parece um pouco com isto:

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 obter o nome do final do evento de transição, você pode usar o método postado como a resposta em: Como normalizo funções de transição CSS3 entre navegadores? .

Observação: esta questão também está relacionada a: - eventos de transição CSS3

Mark Rhodes
fonte
2
Esta é uma resposta muito mais completa do que a aceita. Por que isso não é mais votado.
Wes
Lembre-se de chamar transitionEndedHandlerem transitionEnded(ou mudança transitionEndedpor transitionEndedHandlerem addEventListenere removeEventListenere chamada transitionEndedem transitionEndedHandler)
Miquel
Obrigado @Miquel; acho que acabei de usar transitionEndedquando quis dizer transitionEndedHandler.
Mark Rhodes
Acredito que o problema do Chromium para isso pode ser encontrado aqui: code.google.com/p/chromium/issues/detail?id=388082 Embora, o último comentário pareça (incorretamente na minha opinião) descartá- lo como um bug e, portanto, está atualmente marcado como "não corrige".
Willster
Não há necessidade de nomes diferentes hoje em dia caniuse.com/#feat=css-transitions
Juan Mendes
43

Estou usando o código a seguir, é muito mais simples do que tentar detectar qual evento final específico um navegador usa.

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

Alternativamente, se você usar bootstrap, você pode simplesmente fazer

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

Isso ocorre porque eles incluem o seguinte em 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
fonte
2
Isso é mais lento porque tem que pesquisar em toda a lista cada vez que o evento acontece para ver se é o correto.
phreakhead
3
@phreakhead O desempenho de qualquer uma dessas abordagens será muito semelhante
Tom
6

O plugin jQuery.transit , um plugin para transformações e transições CSS3, pode chamar suas animações CSS a partir de um script e fornecer um retorno de chamada.

Brian
fonte
5

Isso pode ser facilmente alcançado com o transitionendevento, consulte a documentação aqui. Um exemplo simples:

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
fonte
1
Esta é a resposta correta hoje em dia, não há necessidade de mais prefixos. caniuse.com/#feat=css-transitions
Juan Mendes