如何在浏览器中规范化CSS3 Transition功能?

met*_*ion 89 javascript css dom-events css-transitions

Webkit的转换结束事件称为webkitTransitionEnd,Firefox是transitionEnd,opera是oTransitionEnd.在纯JS中处理所有这些问题的好方法是什么?我应该做浏览器嗅探吗?或分别实施每一个?还有其他一些方法没有发生在我身上?

即:

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

element.addEventListener(transitionend, function(){
  //do whatever
},false);
Run Code Online (Sandbox Code Playgroud)

要么

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

function fn() {
   //do whatever
}
Run Code Online (Sandbox Code Playgroud)

web*_*sta 165

在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'; 
}
Run Code Online (Sandbox Code Playgroud)

然后,只要需要转换结束事件,您就可以调用此函数:

var transitionEnd = transitionEndEventName();
element.addEventListener(transitionEnd, theFunctionToInvoke, false);
Run Code Online (Sandbox Code Playgroud)

  • 为什么需要重新定义`undefined`? (4认同)
  • oTransitionEnd在Opera中被降级为otransitionend.请参阅http://www.opera.com/docs/specs/presto2.10/#m274 (3认同)

met*_*ion 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')
});
Run Code Online (Sandbox Code Playgroud)

在无库的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
}
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,我来到这里是因为我的同事刚刚发现他们的代码中抛出了多个事件,看起来就像这个答案 (7认同)

Tom*_*Tom 8

更新

以下是一种更简洁的方法,并不需要现代化

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

另外

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

这是基于Modernizr建议的代码,但是对于较新版本的Opera有额外的事件.

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

  • jQuery版本在基于Webkit的浏览器中触发两个事件(至少). (2认同)
  • @Dan我用一个而不是on所以它只会触发一次 (2认同)

mel*_*yal 8

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

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

虽然下面记录了其中一些属性,但它们不需要很长的弃用/删除周期,并且一旦内部jQuery代码不再需要它们就可以删除它们.

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

  • 作为这里最简单的解决方案,这是一个真正的耻辱,这有一个警告. (2认同)
  • 我认为只有在使用bootstrap时才有效 (2认同)

Sal*_*bas 6

截至2015年,这个单行应该做的交易(IE 10 +,Chrome 1 +,Safari 3.2 +,FF 4+和Opera 12 +): -

var transEndEventName = ('WebkitTransition' in document.documentElement.style) ? 'webkitTransitionEnd' : 'transitionend'
Run Code Online (Sandbox Code Playgroud)

附加事件监听器很简单: -

element.addEventListener(transEndEventName , theFunctionToInvoke);
Run Code Online (Sandbox Code Playgroud)