Existem eventos disparados por um elemento para verificar se uma transição do css3 foi iniciada ou finalizada?
Existem eventos disparados por um elemento para verificar se uma transição do css3 foi iniciada ou finalizada?
Respostas:
A conclusão de uma transição CSS gera um evento DOM correspondente. Um evento é disparado para cada propriedade que passa por uma transição. Isso permite que um desenvolvedor de conteúdo execute ações sincronizadas com a conclusão de uma transição.
Para determinar quando uma transição é concluída, defina uma função de ouvinte de evento JavaScript para o evento DOM que é enviado no final de uma transição. O evento é uma instância do WebKitTransitionEvent e seu tipo é
webkitTransitionEnd
.
box.addEventListener( 'webkitTransitionEnd',
function( event ) { alert( "Finished transition!" ); }, false );
Há um único evento que é acionado quando as transições são concluídas. No Firefox, o evento é
transitionend
no OperaoTransitionEnd
e no WebKitwebkitTransitionEnd
.
Existe um tipo de evento de transição disponível. O
oTransitionEnd
evento ocorre na conclusão da transição.
O
transitionend
evento ocorre na conclusão da transição. Se a transição for removida antes da conclusão, o evento não será acionado.
Estouro de pilha: Como normalizo as funções de transição CSS3 nos navegadores?
Atualizar
Todos os navegadores modernos agora suportam o evento não corrigido:
element.addEventListener('transitionend', callback, false);
https://caniuse.com/#feat=css-transitions
Eu estava usando a abordagem dada por Pete, mas agora comecei a usar o seguinte
$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
//do something
});
Como alternativa, se você usar o bootstrap, poderá simplesmente fazer
$(".myClass").one($.support.transition.end,
function() {
//do something
});
Isso acontece 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 ( ._.)
}
$(function () {
$.support.transition = transitionEnd()
})
}(jQuery);
Observe que eles também incluem uma função emulateTransitionEnd que pode ser necessária para garantir que sempre ocorra um retorno de chamada.
// 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
}
Esteja ciente de que, às vezes, esse evento não é acionado, geralmente no caso em que as propriedades não mudam ou uma pintura não é acionada. Para garantir que sempre recebamos um retorno de chamada, vamos definir um tempo limite que acionará o evento manualmente.
Todos os navegadores modernos agora suportam o evento não corrigido:
element.addEventListener('transitionend', callback, false);
Funciona nas versões mais recentes do Chrome, Firefox e Safari. Mesmo IE10 +.
No Opera 12, quando você liga usando o JavaScript simples, 'oTransitionEnd' funcionará:
document.addEventListener("oTransitionEnd", function(){
alert("Transition Ended");
});
no entanto, se você ligar através do jQuery, precisará usar 'otransitionend'
$(document).bind("otransitionend", function(){
alert("Transition Ended");
});
Caso esteja usando o Modernizr ou o bootstrap-transit.js, basta fazer uma alteração:
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
Você pode encontrar algumas informações aqui também http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/
Apenas por diversão, não faça isso!
$.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');
});
Se você simplesmente deseja detectar apenas um único final de transição, sem usar nenhuma estrutura JS, aqui está uma pequena função de utilitário:
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
});
se você deseja cancelar em algum momento, ainda pode fazê-lo com
handler.cancel();
Também é bom para outros usos do evento :)