如何跨浏览器规范化 CSS3 过渡功能?

IT技术 javascript css css-transitions dom-events
2021-02-02 18:47:31

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
}
6个回答

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);
它现在也是全小写的 transitionend。dev.w3.org/csswg/css3-transitions/#transition-events
2021-03-12 18:47:31
我删除了 MsTransition 位,但会保留答案的其余部分。所有主要非 WebKit 浏览器的当前版本都不需要供应商前缀。transition并且transitionend足够了。请参阅:caniuse.com/#search=transitions
2021-03-26 18:47:31
为什么需要重新定义undefined
2021-03-30 18:47:31
@ Atav32,我也想知道。我唯一能想到的就是它在那里,以防其他人已经将它重新定义为某些东西。
2021-04-04 18:47:31
oTransitionEnd 在 Opera 中被小写为 otransitionend。opera.com/docs/specs/presto2.10/#m274
2021-04-09 18:47:31

根据 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
}
如果您转换了多个属性,它将触发多个事件。参见:stackoverflow.com/a/18689069/740836
2021-03-12 18:47:31
有趣的是,我来到这里是因为我的同事刚刚发现在他们的代码中抛出了多个事件,这些事件看起来与这个答案完全一样
2021-03-20 18:47:31
@Duopixel 请测试您的答案并考虑更改它,因为它会在 Chrome 和 Safari 中引发两个事件(以及至少所有其他 Webkit 浏览器以及旧的 Firefox 和 Opera)。msTransitionend这里不需要。
2021-03-21 18:47:31
倒数第二个不应该是驼峰式的。
2021-03-25 18:47:31

更新

以下是一种更简洁的方法,不需要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

jQuery 版本在基于 Webkit 的浏览器中触发两个事件(至少)。
2021-03-15 18:47:31
@Dan 我使用一个而不是 on 所以它只会触发一次
2021-03-19 18:47:31
这是一个很好的方法,但它需要 Modernizr。这可以简单地编写但没有 Modernizr 吗?
2021-04-07 18:47:31
抱歉,我没有注意到你有one而不是on太明显了!
2021-04-09 18:47:31

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

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

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

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

它被添加到他们的代码中github.com/twbs/bootstrap/blob/...
2021-03-23 18:47:31
作为这里最简单的解决方案,有这样一个警告真是太可惜了。
2021-03-27 18:47:31

截至 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);
可爱的解决方案。不幸的是,它不会告诉您是否transitionend根本不支持: var transEndEventName = ('WebkitTransition' in document.documentElement.style) ? 'webkitTransitionEnd' : ('transitionend' in document.documentElement.style) ? 'transitionend' : false; 然后做一个简单的检查: if(transEndEventName) element.addEventlistener(transEndEventName, theFunctionToInvoke)
2021-03-12 18:47:31
刚刚在 IE 11 中测试它并返回 false
2021-03-17 18:47:31
我认为应该单独检查:stackoverflow.com/a/29591030/362006
2021-03-20 18:47:31
这个答案也适用于现在吗?(2016 年 1 月)
2021-04-10 18:47:31