在CSS转换中启用供应商前缀会使回调触发两次

Hec*_*nzo 2 javascript jquery callback css-transitions transitionend

我正在实现一个很好的解决方案(在这里找到),在使用CSS转换时使用回调函数和jQuery.

问题是,如果我使用供应商前缀,Chrome至少会绑定两个事件:一个用于webkitTransitionEnd,第二个用于transitionend,当然,它会触发两次回调.这是我的一段代码:

jQuery("#main").one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
  console.log("POUM!");
});
Run Code Online (Sandbox Code Playgroud)

难道我做错了什么?

kal*_*ley 6

你没有做错任何事.Chrome只使用前缀和非前缀版本.

有几种选择:

  1. 使用外部变量.

    var fired = false;
    jQuery("#main").one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
        if ( ! fired ) {
            fired = true;
            console.log("POUM!");
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用某种检测来获得transitionend的单个变量(下面使用Modernizr,并从他们的文档中获取):

    var transitionend = (function(transition) {
         var transEndEventNames = {
             'WebkitTransition' : 'webkitTransitionEnd',// Saf 6, Android Browser
             'MozTransition'    : 'transitionend',      // only for FF < 15
             'transition'       : 'transitionend'       // IE10, Opera, Chrome, FF 15+, Saf 7+
        };
    
        return transEndEventNames[transition];
    })(Modernizr.prefixed('transition'));
    
    // then
    jQuery("#main").one(transitionend, function(e) {
        console.log("POUM!");
    });
    
    Run Code Online (Sandbox Code Playgroud)

注意:

Safari 6似乎触发onload了CSS中设置的任何内容.所以,如果你有(假设所有前缀)

#main {
    width: 40px;
    height: 40px;
    transition: all 200ms;
}
Run Code Online (Sandbox Code Playgroud)

Safari将触发transitionendwith widthheighton load.有几种方法可以解决这个问题:

  • 使用更具体的transition-property(但是如果你在CSS中设置它,它仍然会触发)
  • 在javascript中执行以下操作(这不是最漂亮的事情,但它应该照顾那个边缘情况,它仍然适用于Chrome)小提琴

    var transitionProperty = 'background-color',
        startColor = jQuery("#main").on(transitionend, function(e) {
            var el = $(this);
            if ( transitionProperty === e.originalEvent.propertyName && el.css(transitionProperty) !== startColor ) {
                console.log("POUM!");
                // This is to make it only happen once.
                $(this).off(transitionend);
            }
        }).css(transitionProperty);
    
    Run Code Online (Sandbox Code Playgroud)

  • @INT看来Safari已经完成了Chrome所做的工作,并从属性中删除了前缀,但将事件名称更改为`transitionend`(no camelcase).我正在根据[Modernizr的文档]更新脚本(http://modernizr.com/docs/#prefixed) (2认同)