gpt4 book ai didi

javascript - 始终触发且仅触发一次的 "transitionend"事件

转载 作者:行者123 更新时间:2023-12-03 21:48:42 32 4
gpt4 key购买 nike

我需要一个特殊的类似 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);

我做了一个活生生的例子here .

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

最佳答案

我用过 treeWalker api遍历原始节点(根)和所有子节点(仅限元素),过滤掉没有转换的元素,并将转换属性收集到队列 ( fiddle )。正如您所看到的,我已经解决了 complete-divcomplete-p 之间的时间差,并且它们现在同时触发(几乎 - 几毫秒) .

有两个警告,我没有解决方法:

  1. 如果存在通过不同方式触发的转换,例如示例一是通过将 .visible 添加到 div 来触发的,并且其他通过添加.invisible,它们都会被添加到队列中。该事件永远不会触发,因为队列永远不会为空 - 我不知道如何解决这个问题。
  2. 如果快捷方式属性存在转换(padding例如),可以使用 transition-property 触发多个 transitionend 事件,例如 padding-toppadding-right等...这个将导致数组很快清空,如 splice(-1, 1)从数组末尾删除项目。我有一个 workaround , 但这可能会导致问题,因为它可能会删除队列。最好的解决方法是不要通过快捷方式进行转换属性。

treeWalker 的代码基于 Ban Nadel 的 - Finding HTML Comment Nodes In The DOM Using TreeWalker .

最后的代码:

(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);

关于javascript - 始终触发且仅触发一次的 "transitionend"事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32469577/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com