Как нормализовать функции перехода CSS3 в разных браузерах?
Событие окончания перехода Webkit называется webkitTransitionEnd, Firefox - это transitionEnd, опера - это oTransitionEnd. Что является хорошим способом решения всех из них в чистом JS? Должен ли я делать анализ браузера? или реализовать каждый по отдельности? Какой-то другой способ, который не произошел со мной?
то есть:
//doing browser sniffing
var transitionend = (isSafari) ? "webkitTransitionEnd" : (isFirefox) ? "transitionEnd" : (isOpera) ? "oTransitionEnd";
element.addEventListener(transitionend, function(){
//do whatever
},false);
или же
//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
}
10 ответов
В Modernizr используется улучшенная техника:
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';
}
Затем вы можете просто вызывать эту функцию всякий раз, когда вам нужно событие окончания перехода:
var transitionEnd = transitionEndEventName();
element.addEventListener(transitionEnd, theFunctionToInvoke, false);
Согласно комментарию Матейса, самый простой способ обнаружить события перехода - использовать библиотеку, в данном случае jquery:
$("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')
});
В javascript без библиотек он становится немного многословным:
element.addEventListener('webkitTransitionEnd', callfunction, false);
element.addEventListener('oTransitionEnd', callfunction, false);
element.addEventListener('transitionend', callfunction, false);
element.addEventListener('msTransitionEnd', callfunction, false);
function callfunction() {
//do whatever
}
Обновить
Следующее является более чистым способом сделать это, и не требует модерниз
$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
//do something
});
альтернативно
var transEndEventNames = {
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition': 'transitionend',
'OTransition': 'oTransitionEnd otransitionend',
'msTransition': 'MSTransitionEnd',
'transition': 'transitionend'
}, transitionEnd = transEndEventNames[Modernizr.prefixed('transition')];
Это основано на коде, предложенном Modernizr, но с дополнительным событием для более новых версий Opera.
Если вы используете jQuery и Bootstrap $.support.transition.end
вернет правильное событие для текущего браузера.
Он определен в Bootstrap и используется в его обратных вызовах анимации, хотя в документах jQuery сказано не полагаться на эти свойства:
Хотя некоторые из этих свойств описаны ниже, они не подвержены длительному циклу устаревания / удаления и могут быть удалены, когда внутренний код jQuery больше не нуждается в них.
Начиная с 2015 года этот однострочник должен заключить сделку (IE 10+, Chrome 1+, Safari 3.2+, FF 4+ и Opera 12+):-
var transEndEventName = ('WebkitTransition' in document.documentElement.style) ? 'webkitTransitionEnd' : 'transitionend'
Присоединить слушателя события просто: -
element.addEventListener(transEndEventName , theFunctionToInvoke);
Второй способ идти. Только одно из этих событий будет срабатывать в каждом браузере, поэтому вы можете установить все из них, и оно будет работать.
Вот более чистый способ
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";
}
Принятый ответ верен, но вам не нужно заново создавать этот элемент снова и снова и...
Создайте глобальную переменную и добавьте функцию (ы):
(function(myLib, $, window, document, undefined){
/**
* @summary
* Returns the browser's supported animation end event type.
* @desc
* @see {@link https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript/}
* @function myLib.getAnimationEndType
* @return {string} The animation end event type
*/
(function(){
var type;
myLib.getAnimationEndType = function(){
if(!type)
type = callback();
return type;
function callback(){
var t,
el = document.createElement("fakeelement");
var animations = {
"animation" : "animationend",
"OAnimation" : "oAnimationEnd",
"MozAnimation" : "animationend",
"WebkitAnimation": "webkitAnimationEnd"
}
for (t in animations){
if (el.style[t] !== undefined){
return animations[t];
}
}
}
}
}());
/**
* @summary
* Returns the browser's supported transition end event type.
* @desc
* @see {@link https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript/}
* @function myLib.getTransitionEndType
* @return {string} The transition end event type
*/
(function(){
var type;
myLib.getTransitionEndType = function(){
if(!type)
type = callback();
return type;
function callback(){
var t,
el = document.createElement("fakeelement");
var transitions = {
"transition" : "transitionend",
"OTransition" : "oTransitionEnd",
"MozTransition" : "transitionend",
"WebkitTransition": "webkitTransitionEnd"
}
for (t in transitions){
if (el.style[t] !== undefined){
return transitions[t];
}
}
}
}
}());
}(window.myLib = window.myLib || {}, jQuery, window, document));
Я использую такой код (с 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
}
Это позволяет мне использовать JS для добавления вещей, указав vP, связанный со свойством, и если он не попал в браузер, он просто использует стандарт. События позволяют мне легко связать так:
object.bind(transitionEnd,function(){
callback();
});
Закрытие Google гарантирует, что вам не нужно делать это. Если у вас есть элемент:
goog.events.listen(element, goog.events.EventType.TRANSITIONEND, function(event) {
// ... your code here
});
Смотря на источник goog.events.eventtype.js, TRANSITIONEND рассчитывается с помощью userragent:
// 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'),
Переопределение jquery:
(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);
и использование как:
$('myDiv').on('transitionend', function() { ... });