Come faccio a normalizzare le funzioni di transizione CSS3 tra i browser?

L’evento finale di transizione di Webkit si chiama webkitTransitionEnd, Firefox è transitionEnd, opera è oTransitionEnd. Qual è un buon modo per affrontarli tutti in puro JS? Dovrei fare lo sniffing del browser? o implementare ciascuno separatamente? Qualche altro modo che non mi è successo?

vale a dire:

//doing browser sniffing var transitionend = (isSafari) ? "webkitTransitionEnd" : (isFirefox) ? "transitionEnd" : (isOpera) ? "oTransitionEnd"; element.addEventListener(transitionend, function(){ //do whatever },false); 

o

 //asigning an event listener per browser element.addEventListener(webkitTransitionEnd, function(){callfunction()},false); element.addEventListener(oTransitionEnd, function(){callfunction()},false); element.addEventListener(transitionEnd, function(){callfunction()},false); function callfunction() { //do whatever } 

C’è una tecnica usata in Modernizr, migliorata:

 function transitionEndEventName () { var i, undefined, el = document.createElement('div'), transitions = { 'transition':'transitionend', 'OTransition':'otransitionend', // oTransitionEnd in very old Opera 'MozTransition':'transitionend', 'WebkitTransition':'webkitTransitionEnd' }; for (i in transitions) { if (transitions.hasOwnProperty(i) && el.style[i] !== undefined) { return transitions[i]; } } //TODO: throw 'TransitionEnd event is not supported in this browser'; } 

Quindi puoi chiamare questa funzione ogni volta che ti serve l’evento di fine transizione:

 var transitionEnd = transitionEndEventName(); element.addEventListener(transitionEnd, theFunctionToInvoke, false); 

Come per il commento di Matijs, il modo più semplice per rilevare gli eventi di transizione è con una libreria, jquery in questo caso:

 $("div").bind("webkitTransitionEnd.done oTransitionEnd.done otransitionend.done transitionend.done msTransitionEnd.done", function(){ // Unlisten called events by namespace, // to prevent multiple event calls. (See comment) // By the way, .done can be anything you like ;) $(this).off('.done') }); 

In javascript senza libreria diventa un po ‘prolisso:

 element.addEventListener('webkitTransitionEnd', callfunction, false); element.addEventListener('oTransitionEnd', callfunction, false); element.addEventListener('transitionend', callfunction, false); element.addEventListener('msTransitionEnd', callfunction, false); function callfunction() { //do whatever } 

Se usi jQuery e Bootstrap $.support.transition.end restituirà l’evento giusto per il browser corrente.

È definito in Bootstrap e utilizzato nei suoi richiami di animazione , anche se i documenti di jQuery dicono di non fare affidamento su queste proprietà:

Sebbene alcune di queste proprietà siano documentate di seguito, non sono soggette a un lungo ciclo di rimozione / rimozione e possono essere rimosse una volta che il codice jQuery interno non ne ha più bisogno.

http://api.jquery.com/jQuery.support/

Aggiornare

Quello che segue è un modo più pulito di farlo, e non richiede modernizzazione

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

In alternativa

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

Questo è basato sul codice suggerito da Modernizr, ma con l’evento extra per le versioni più recenti di Opera.

http://modernizr.com/docs/#prefixed

A partire dal 2015, questo one-liner dovrebbe fare il deal (IE 10+, Chrome 1+, Safari 3.2+, FF 4+ e Opera 12 +): –

 var transEndEventName = ('WebkitTransition' in document.documentElement.style) ? 'webkitTransitionEnd' : 'transitionend' 

Albind il listener di eventi è semplice: –

 element.addEventListener(transEndEventName , theFunctionToInvoke); 

Ecco un modo più pulito

  function transitionEvent() { // Create a fake element var el = document.createElement("div"); if(el.style.OTransition) return "oTransitionEnd"; if(el.style.WebkitTransition) return "webkitTransitionEnd"; return "transitionend"; } 

Il secondo è la strada da percorrere. Solo uno di quegli eventi verrà triggersto in tutti i browser, quindi puoi impostarli tutti e funzionerà.

la chiusura di google ti assicura che non devi farlo. Se hai un elemento:

 goog.events.listen(element, goog.events.EventType.TRANSITIONEND, function(event) { // ... your code here }); 

guardando la sorgente di goog.events.eventtype.js, TRANSIZIONE è calcasting osservando l’useragent:

 // CSS transition events. Based on the browser support described at: // https://developer.mozilla.org/en/css/css_transitions#Browser_compatibility TRANSITIONEND: goog.userAgent.WEBKIT ? 'webkitTransitionEnd' : (goog.userAgent.OPERA ? 'oTransitionEnd' : 'transitionend'), 

Io uso un codice come questo (con jQuery)

 var vP = ""; var transitionEnd = "transitionend"; if ($.browser.webkit) { vP = "-webkit-"; transitionEnd = "webkitTransitionEnd"; } else if ($.browser.msie) { vP = "-ms-"; } else if ($.browser.mozilla) { vP = "-moz-"; } else if ($.browser.opera) { vP = "-o-"; transitionEnd = "otransitionend"; //oTransitionEnd for very old Opera } 

Ciò mi consente di usare JS per aggiungere cose specificando vP concatenato con la proprietà e, se non ha colpito un browser, utilizza solo lo standard. Gli eventi mi permettono di bind facilmente in questo modo:

 object.bind(transitionEnd,function(){ callback(); }); 

jquery override:

 (function ($) { var oldOn = $.fn.on; $.fn.on = function (types, selector, data, fn, /*INTERNAL*/ one) { if (types === 'transitionend') { types = 'transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd'; } return oldOn.call(this, types, selector, data, fn, one); }; })(jQuery); 

e utilizzo come:

 $('myDiv').on('transitionend', function() { ... });