Javascript 如何跨浏览器规范化 CSS3 过渡功能?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5023514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I normalize CSS3 Transition functions across browsers?
提问by methodofaction
Webkit's transition end event is called webkitTransitionEnd, Firefox is transitionEnd, opera is oTransitionEnd. What is a good way of tackling all of them in pure JS? Should I do browser sniffing? or implement each one separately? Some other way that hasn't occurred to me?
webkit的transition结束事件叫做webkitTransitionEnd,Firefox是transitionEnd,opera是oTransitionEnd。在纯 JS 中处理所有这些问题的好方法是什么?我应该做浏览器嗅探吗?还是分别实施每一项?其他一些我没有想到的方式?
i.e.:
IE:
//doing browser sniffing
var transitionend = (isSafari) ? "webkitTransitionEnd" : (isFirefox) ? "transitionEnd" : (isOpera) ? "oTransitionEnd";
element.addEventListener(transitionend, function(){
//do whatever
},false);
or
或者
// Assigning an event listener per browser
element.addEventListener("webkitTransitionEnd", fn);
element.addEventListener("oTransitionEnd", fn);
element.addEventListener("transitionEnd", fn);
function fn() {
//do whatever
}
回答by webinista
There's a technique used in Modernizr, improved:
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';
}
Then you can just call this function whenever you need the transition end event:
然后,您可以在需要转换结束事件时调用此函数:
var transitionEnd = transitionEndEventName();
element.addEventListener(transitionEnd, theFunctionToInvoke, false);
回答by methodofaction
As per Matijs comment, the easiest way to detect transition events is with a library, jquery in this case:
根据 Matijs 评论,检测转换事件的最简单方法是使用库,在本例中为 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')
});
In library-less javascript it gets a bit verbose:
在无库的 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
}
回答by Tom
Update
更新
The following is a cleaner way of doing it, and doesn't require modernizr
以下是一种更简洁的方法,不需要modernizr
$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
//do something
});
Alternatively
或者
var transEndEventNames = {
'WebkitTransition': 'webkitTransitionEnd',
'MozTransition': 'transitionend',
'OTransition': 'oTransitionEnd otransitionend',
'msTransition': 'MSTransitionEnd',
'transition': 'transitionend'
}, transitionEnd = transEndEventNames[Modernizr.prefixed('transition')];
This is based on the code suggested by Modernizr, but with the extra event for newer versions of Opera.
这是基于 Modernizr 建议的代码,但对于较新版本的 Opera 有额外的事件。
回答by meleyal
If you use jQuery and Bootstrap $.support.transition.end
will return the right event for the current browser.
如果您使用 jQuery,Bootstrap$.support.transition.end
将为当前浏览器返回正确的事件。
It is defined in Bootstrapand used in its animation callbacks, though the jQuery docs say not to rely on these properties:
它在 Bootstrap中定义并在其动画回调中使用,尽管 jQuery 文档说不要依赖这些属性:
Although some of these properties are documented below, they are not subject to a long deprecation/removal cycle and may be removed once internal jQuery code no longer needs them.
尽管下面记录了其中一些属性,但它们不会受到长时间的弃用/删除周期的影响,并且可能会在内部 jQuery 代码不再需要它们时被删除。
回答by Salman von Abbas
As of 2015, this one-liner should do the deal (IE 10+, Chrome 1+, Safari 3.2+, FF 4+ and Opera 12+):-
截至 2015 年,这款单线应该可以完成交易(IE 10+、Chrome 1+、Safari 3.2+、FF 4+ 和 Opera 12+):-
var transEndEventName = ('WebkitTransition' in document.documentElement.style) ? 'webkitTransitionEnd' : 'transitionend'
Attaching the event listener is simple:-
附加事件侦听器很简单:-
element.addEventListener(transEndEventName , theFunctionToInvoke);
回答by Nicholas
Here is a more cleaner way
这是一种更清洁的方法
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";
}
回答by centurian
Accepted answer is correct but you don't have to re-create that element again-and-again-and...
接受的答案是正确的,但您不必一次又一次地重新创建该元素......
Build a global variable and add the function(s):
构建一个全局变量并添加函数:
(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));
回答by Are Butuv
jquery override:
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);
and usage like:
和用法如:
$('myDiv').on('transitionend', function() { ... });
回答by Lea Verou
The second is the way to go. Only one of those events will fire in every browser, so you can set all of them and it'll work.
二是要走的路。在每个浏览器中只会触发这些事件中的一个,因此您可以设置所有这些事件并且它会起作用。
回答by Rich Bradshaw
I use code like this (with jQuery)
我使用这样的代码(使用 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
}
That lets me use JS to add things by specifying vP concatentated with the property, and if it didn't hit a browser it just uses the standard. The events lets me easily bind like so:
这让我可以使用 JS 通过指定与属性连接的 vP 添加东西,如果它没有访问浏览器,它就使用标准。这些事件让我可以像这样轻松地绑定:
object.bind(transitionEnd,function(){
callback();
});