91

Webkit的transition结束事件叫做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);

或者

// Assigning an event listener per browser
element.addEventListener("webkitTransitionEnd", fn);
element.addEventListener("oTransitionEnd", fn);
element.addEventListener("transitionEnd", fn);

function fn() {
   //do whatever
}
4

11 回答 11

166

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);
于 2012-02-01T02:57:41.823 回答
22

根据 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')
});

在无库的 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
}
于 2011-10-13T10:08:51.487 回答
8

更新

以下是一种更清洁的方法,不需要modernizr

$(".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 有额外的事件。

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

于 2012-11-27T10:39:16.453 回答
8

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

在 Bootstrap 中定义并在其动画回调中使用,尽管 jQuery 文档说不要依赖这些属性:

尽管下面记录了其中一些属性,但它们不受长期弃用/删除周期的影响,并且一旦内部 jQuery 代码不再需要它们,它们可能会被删除。

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

于 2013-03-11T13:05:33.023 回答
6

截至 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);
于 2015-04-11T17:39:07.787 回答
1

第二个是要走的路。每个浏览器中只会触发其中一个事件,因此您可以设置所有这些事件并且它会起作用。

于 2011-02-17T11:23:40.850 回答
1

这是一种更清洁的方法

 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";
    }
于 2017-03-26T19:58:22.777 回答
0

我使用这样的代码(使用 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();
});
于 2011-03-31T14:10:42.843 回答
0

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

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

查看goog.events.eventtype.js的来源,TRANSITIONEND是通过查看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'),
于 2014-03-28T18:53:51.193 回答
0

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() { ... });
于 2016-08-12T15:44:57.360 回答
0

接受的答案是正确的,但您不必一次又一次地重新创建该元素......

构建一个全局变量并添加函数:

(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));
于 2019-11-28T09:34:41.980 回答