2010-01-18 16 views
91

È possibile ricevere una notifica (come il callback) quando una transizione CSS è stata completata?Richiamata sulla transizione CSS

+0

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

risposta

77

So che Safari implementa un callback webkitTransitionEnd che è possibile allegare direttamente all'elemento con la transizione.

Il loro esempio (riformattato a più linee):

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

Grazie Doug, l'ha fatto. – Pompair

+0

c'è la stessa cosa per gli altri browser e il webkit? – meo

+6

sì, 'transitionend' per Mozilla e 'oTransitionEnd' in Opera. – qqryq

98

Sì, se queste cose sono supportate dal browser, quindi viene attivato un evento quando la transizione completa. L'evento reale però, si differenzia tra i browser:

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

Tuttavia si dovrebbe essere consapevole che webkitTransitionEnd non si attiva sempre! Questo mi ha catturato fuori un certo numero di volte, e sembra accadere se l'animazione non avrebbe alcun effetto sull'elemento. Per ovviare a questo, ha senso utilizzare un timeout per attivare il gestore di eventi nel caso in cui non sia stato attivato come previsto. Un post sul blog su questo problema è disponibile qui: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/<-500 Internal Server Error

Con questo in mente, ho tendono ad usare questo evento in un pezzo di codice che sembra un po 'come questo:

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: per ottenere il nome finale dell'evento di transizione è possibile utilizzare il metodo inviato come risposta in: How do I normalize CSS3 Transition functions across browsers?.

Nota: questa domanda è anche legato a: - CSS3 transition events

+2

Questa è una risposta molto più completa di quello accettato. Perché non è questo più upvoted. – Wes

+0

Ricordarsi di chiamare 'transitionEndedHandler' in' transitionEnded' (o modificare 'transitionEnded' di' transitionEndedHandler' in 'addEventListener' e' removeEventListener' e chiamare 'transitionEnded' in' transitionEndedHandler') – Miquel

+0

Grazie a @Miquel; penso che abbia usato 'transitionEnded 'quando intendevo' transitionEndedHandler'. –

6

Il jQuery.transit plugin, un plugin per le trasformazioni e transizioni CSS3, può chiamare le animazioni CSS dallo script e vi darò un callback.

42

Sto usando il seguente codice, è molto più semplice di cercare di individuare quale specifico evento finale viene utilizzato da un browser.

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

In alternativa, se si utilizza bootstrap allora si può semplicemente fare

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

Questo è becuase essi includono quanto segue in 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

Questo è più lento perché deve cercare nell'intero elenco ogni volta che accade l'evento per vedere se è quello corretto. – phreakhead

+3

@phreakhead Le prestazioni di questi approcci saranno molto simili – Tom

Problemi correlati