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");
}