如何在不同的浏览器中实现CSS3转换函数的规范化?

时间:2021-06-14 04:16:58

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 occured to me?

Webkit的转换结束事件称为webkitTransitionEnd, Firefox是transitionEnd, opera是oTransitionEnd。用纯JS处理所有问题的好方法是什么?我应该做浏览器嗅探吗?或者分别实现每一个?还有什么别的我没有想到的吗?

ie:

即:

//doing browser sniffing
var transitionend = (isSafari) ? "webkitTransitionEnd" : (isFirefox) ? "transitionEnd" : (isOpera) ? "oTransitionEnd";

element.addEventListener(transitionend, function(){
  //do whatever
},false);

or

//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 个解决方案

#1


159  

There's a technique used in Modernizr, improved:

现代科技中有一种改进的技术:

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);

#2


21  

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
}

#3


8  

If you use jQuery and Bootstrap $.support.transition.end will return the right event for the current browser.

如果您使用jQuery并引导$.support.transition。end将返回当前浏览器的正确事件。

It is defined in Bootstrap and 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代码不再需要它们时被删除。

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

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

#4


7  

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来说这是额外的事件。

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

http://modernizr.com/docs/前缀

#5


6  

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);

#6


1  

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";
    }

#7


0  

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.

第二点是要走的路。这些事件中只有一个会在每个浏览器中触发,所以您可以设置所有事件,它将会工作。

#8


0  

google closure makes sure you don't have to do this. If you have an element:

谷歌闭包确保您不需要这样做。如果你有一个元素:

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

looking at the source of goog.events.eventtype.js, TRANSITIONEND is calculated by looking at the useragent:

查看google .events.eventtype的源代码。通过查看useragent计算TRANSITIONEND:

// 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'),

#9


0  

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();
});

#10


0  

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() { ... });

#1


159  

There's a technique used in Modernizr, improved:

现代科技中有一种改进的技术:

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);

#2


21  

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
}

#3


8  

If you use jQuery and Bootstrap $.support.transition.end will return the right event for the current browser.

如果您使用jQuery并引导$.support.transition。end将返回当前浏览器的正确事件。

It is defined in Bootstrap and 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代码不再需要它们时被删除。

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

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

#4


7  

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来说这是额外的事件。

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

http://modernizr.com/docs/前缀

#5


6  

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);

#6


1  

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";
    }

#7


0  

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.

第二点是要走的路。这些事件中只有一个会在每个浏览器中触发,所以您可以设置所有事件,它将会工作。

#8


0  

google closure makes sure you don't have to do this. If you have an element:

谷歌闭包确保您不需要这样做。如果你有一个元素:

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

looking at the source of goog.events.eventtype.js, TRANSITIONEND is calculated by looking at the useragent:

查看google .events.eventtype的源代码。通过查看useragent计算TRANSITIONEND:

// 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'),

#9


0  

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();
});

#10


0  

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() { ... });