Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/456.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript A「;“过渡”;始终激发且仅一次的事件_Javascript_Jquery_Css Transitions_Jquery Events - Fatal编程技术网

Javascript A「;“过渡”;始终激发且仅一次的事件

Javascript A「;“过渡”;始终激发且仅一次的事件,javascript,jquery,css-transitions,jquery-events,Javascript,Jquery,Css Transitions,Jquery Events,我需要一个特殊的transitionend类事件,在所有转换完成后触发一次,或者在CSS中没有定义转换时立即触发 到目前为止,我得出的结论是: (function($){ $.event.special.transitionsComplete = { setup: function(data, namespaces, eventHandle){ var queue = [], style = window.getComputedStyle(

我需要一个特殊的
transitionend
类事件,在所有转换完成后触发一次,或者在CSS中没有定义转换时立即触发

到目前为止,我得出的结论是:

(function($){

  $.event.special.transitionsComplete = {

    setup: function(data, namespaces, eventHandle){    
      var queue = [],
          style = window.getComputedStyle(this, null),
          computedProps = style.getPropertyValue('transition-property').split(', '),
          computedDurations = style.getPropertyValue('transition-duration').split(', '),
          $node = $(this);          

      // only count properties with duration higher than 0s
      for(var i = 0; i < computedDurations.length; i++)
        if(computedDurations[i] !== '0s')
          queue.push(computedProps[i]);           

      // there are transitions
      if(queue.length > 0){
        $node.on('webkitTransitionEnd.x transitionend.x', function(e){          
          queue.splice(queue.indexOf(e.originalEvent.propertyName));          
          if(queue.length < 1)
            $node.trigger('transitionsComplete');
        });

      // no transitions, fire (almost) immediately
      }else{
        setTimeout(function(){
          $node.trigger('transitionsComplete');
        }, 5);

      }

    },

    teardown: function(namespaces){
      $(this).off('.x');
    }

  };
})(jQuery);
(函数($){
$.event.special.transitionsComplete={
设置:函数(数据、名称空间、事件句柄){
变量队列=[],
style=window.getComputedStyle(这个,null),
computedProps=style.getPropertyValue('transition-property').split(','),
computedDurations=style.getPropertyValue('transition-duration').split(','),
$node=$(这个);
//仅统计持续时间大于0秒的属性
对于(var i=0;i0){
$node.on('WebKittTransitionEnd.x transitionend.x',函数(e){
拼接(queue.indexOf(e.originalEvent.propertyName));
如果(队列长度<1)
$node.trigger('transitioncomplete');
});
//无过渡,立即(几乎)开火
}否则{
setTimeout(函数(){
$node.trigger('transitioncomplete');
}, 5);
}
},
拆卸:函数(名称空间){
$(此).off('.x');
}
};
})(jQuery);
我做了一个活生生的例子


唯一的问题是,它只在元素本身具有转换属性时才起作用,而忽略子元素的转换。如果我将
transitioncomplete
切换到
transitionend
,则父事件处理程序和子事件处理程序都将在子转换完成后运行。是否有某种方法或更好的方法来确定元素或其子元素是否发生了转换?如果可能的话,我希望避免手动检查孩子们并检查他们的转换属性。(这无论如何都不可靠,因为即使有些孩子有过渡,也不意味着他们会在那一点上活跃起来)

所以你看,我确实检查了孩子们:

(函数($){
$.event.special.transitionsComplete={
设置:函数(数据、名称空间、事件句柄){
var-allTransitions=[];
w=窗口,
转换\u属性\u键='转换属性',
转换持续时间\键='转换持续时间',
$node=$(这个);
函数以递归方式收集传递(节点){
var style=w.getComputedStyle(节点),
nodeComputerdProperties=style.getPropertyValue(TRANSITION\u PROPERTY\u KEY).split(','),
nodeComputerDurations=style.getPropertyValue(转换\持续时间\键).split(',');
对于(变量i=0;i
我使用了遍历原始节点(根节点)和所有子节点(仅元素),过滤掉不带转换的元素,并收集转换属性到
队列
()。如您所见,我已经解决了
complete div
complete-p
之间的时间差,它们现在同时发射(几乎-几毫秒)

有两个警告,对此我没有解决办法:

  • 如果存在通过不同方式触发的转换,例如 示例一通过将
    .visible
    添加到
    div
    中触发,并且 其他通过添加
    .invisible
    ,它们将全部添加到
    队列中。事件永远不会触发,因为
    队列永远不会为空-我不知道如何解决这个问题
  • 如果存在快捷方式属性的转换(
    padding
    for 例如),可以触发多个
    transitionend
    事件,具有
    转换属性
    ,例如
    填充顶部
    填充右侧
    ,等等。。。这 当
    拼接(-1,1)
    从数组末尾删除项。我有一个朋友,但是 这可能会导致问题,因为它可能会删除
    队列
    。最好的解决方法是不要在快捷方式上转换 P
    (function($){
    
      $.event.special.transitionsComplete = {
    
        setup: function( data, namespaces, eventHandle ) {
    
            var allTransitions          = [];
                w                       = window,
                TRANSITION_PROPERTY_KEY = 'transition-property',
                TRANSITION_DURATION_KEY = 'transition-duration',
                $node                   = $( this );
    
            function collectTransitionsRecursively( node ) {
    
                var style                   = w.getComputedStyle( node ),
                    nodeComputedProperties  = style.getPropertyValue( TRANSITION_PROPERTY_KEY ).split( ', ' ),
                    nodeComputedDurations   = style.getPropertyValue( TRANSITION_DURATION_KEY ).split( ', ' );
    
                for( var i = 0; i < nodeComputedDurations.length; i++ )
                    if( nodeComputedDurations[ i ] !== '0s' )
                        allTransitions.push( nodeComputedProperties[ i ] );
    
                for( var childIndex = 0; childIndex < node.children.length; childIndex++ )
                    collectTransitionsRecursively( node.children[ childIndex ] );
            }
    
            function triggerTransitionsComplete( $onNode ) {
    
                console.log( "No transitions (left)." );
    
                $onNode.trigger('transitionsComplete');
            }
    
            function onNoTransitionsFound() {
    
                setTimeout( function() {
    
                    triggerTransitionsComplete( $node );
                });
            }
    
            collectTransitionsRecursively( this );
    
            if( allTransitions.length == 0 )
                return onNoTransitionsFound();
            else
                console.log( 'remaining', allTransitions );    
    
            $node.on('webkitTransitionEnd.x transitionend.x', function( e ){ 
    
                allTransitions.splice(allTransitions.indexOf(e.originalEvent.propertyName));
    
                if( allTransitions.length == 0 )
                    triggerTransitionsComplete( $node );
                else
                    console.log('remaining', allTransitions);
            });
        },
    
        teardown: function( namespaces ) {
    
          $( this ).off( '.x' );
        }
      };
    })(jQuery);
    
    
    var div = $('div'), p = $('p'), start = new Date().getTime();
    console.log('-- start --');
    div.addClass('visible');
    
    div.one('transitionsComplete', function(e){
        console.log('complete-div', (new Date().getTime() - start) / 1000);
    });
    
    //p.one('transitionsComplete', function(e){
    //    console.log('complete-p', (new Date().getTime() - start) / 1000);
    //});
    
    (function ($) {
    
        $.event.special.transitionsComplete = {
    
            setup: function (data, namespaces, eventHandle) {
                var TRANSITION_PROPERTY = 'transition-property';
                var TRANSITION_DURATION = 'transition-duration';
    
                var root = this;
                var queue = [];
                var $node = $(this);
    
                function filter(node) { // filter for treeWalker
                    /*** filters transitions which are a string with one '0s'. If more then '0s' is defined it will be catched when creating the queue ***/
                    var computedDuration = window.getComputedStyle(node, null)
                        .getPropertyValue(TRANSITION_DURATION);
    
                    return computedDuration === '0s' ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT;
                }
    
                filter.acceptNode = filter; // for webkit and firefox
    
                /** create the treeWalker to traverse only elements **/
                var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter, false);
    
                /** traverse all elements using treeWalker.nextNode(). First node is the root **/
                do {
                    var style = window.getComputedStyle(treeWalker.currentNode, null);
                    var computedProps = style.getPropertyValue(TRANSITION_PROPERTY).split(', ');
                    var computedDurations = style.getPropertyValue(TRANSITION_DURATION).split(', ');
    
                    /** push all props with duration which is not 0s **/
                    computedDurations.forEach(function (duration, index) {
                        duration !== '0s' && queue.push(computedProps[index]);
                    });
                } while (treeWalker.nextNode()); // iterate until no next node
    
                // no transitions, fire (almost) immediately
                if (queue.length === 0) {
    
                    setTimeout(function () {
                        $node.trigger('transitionsComplete');
                    }, 5);
    
                    return; // return out of the function to skip the transitions block
                }
    
                // there are transitions
                $node.on('webkitTransitionEnd.x transitionend.x', function (e) {
                    var propertyName = e.originalEvent.propertyName;
                    var indexOfProp = queue.indexOf(propertyName);
    
                    queue.splice(indexOfProp, 1);
    
                    if (queue.length < 1) {
                        console.log('Transitions Complete');
                        $node.trigger('transitionsComplete');
                    }
                });
    
            },
    
            teardown: function (namespaces) {
                $(this).off('.x');
            }
    
        };
    })(jQuery);
    
    if($('div').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend')) {
      $('div').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
        console.log("Fire after transitions");
      });
    } else {
      console.log("Fire immediately if there are no transitions");
    }