事件在结束的转换上激发
首先
而不是最后,这不是我们想要的行为。有什么解决方法吗?
document.querySelector('a').addEventListener('transitionend', function(){
var time = (new Date().getMinutes()) + ':' + (new Date().getSeconds());
console.log('transitionEnd - ', time);
});a{
display:block;
opacity:.5;
width:100px;
height:50px;
background:lightblue;
}
a:hover{
width:200px;
height:100px;
background:red;
transition: 4s width, /* <-- "transitionEnd" should fire after this */
2s height,
.5s background;
}Hover me
现在我检查了Chrome (我不使用那个浏览器),我看到该事件被调用了3次,每个转换一个。无论如何,我需要它在最后一个,在Firefox中触发。(我不知道元素上有多少个转换,想知道哪个是最后一个)
发布于 2017-05-26 23:18:26
返回一个名为
在事件对象中。
来源
因此,您可以测试所需的属性,并使用简单的逻辑来过滤回调:
document.querySelector('a').addEventListener('transitionend', function(event){
if(event.propertyName !== 'width') return;
console.log('transitionEnd - width!');
});发布于 2016-11-11 02:31:38
一个有点老生常谈的解决方案可能是试图找出哪个css属性具有最长的总持续时间。您可以使用
在您的
元素,并将所有
和
属性。
您可以在触发三次的常规事件处理程序中做到这一点(它非常快),或者创建一个函数来预先计算您正在寻找的属性名称。
这种方法的主要问题是:
Css允许您使用
和
在一条语句中,你可能需要做更多的计算。
当您要更改计算样式时,可能很难预测计算的样式是什么。
样式悬停时,或在过渡之前/之后添加新类时。
var getValues = function(str) {
return str
.replace(/[A-Z]/gi, "")
.split(", ")
.map(parseFloat);
};
var getMaxTransitionProp = function(el) {
var style = window.getComputedStyle(el);
var props = style.transitionProperty.split(", ");
var delays = getValues(style.transitionDelay);
var durations = getValues(style.transitionDuration);
var totals = durations.map(function(v, i) {
return v + delays[i];
});
var maxIndex = totals.reduce(function(res, cur, i) {
if (res.val > cur) {
res.val = cur;
res.i = i;
}
return res;
}, {
val: -Infinity,
i: 0
}).i;
return props[maxIndex];
}
var lastEventListenerFor = function(el, cb) {
var lastProp = getMaxTransitionProp(el);
return function(e) {
if (e.propertyName == lastProp) {
cb(e);
}
};
}
var a = document.querySelector("a");
var cb = function(e) {
console.log("End");
};
a.addEventListener("transitionend", lastEventListenerFor(a, cb));a {
display: block;
opacity: .5;
width: 100px;
height: 50px;
background: lightblue;
transition: 3s width,
/* <-- "transitionEnd" should fire after this */
2s height, .5s background;
}
a:hover {
width: 200px;
height: 100px;
background: red;
}Hover me
发布于 2017-04-19 22:31:40
我现在可能是老问题了,但遇到了同样的麻烦。以这种方式解决:
document.querySelector('a').addEventListener('click', function(e){
this.classList.toggle('animate');
let style = window.getComputedStyle(this, null);
Promise.all(style.transition.split(',').map((prop) => {
prop = prop.trim().split(/\s+/);
return Promise.race([
new Promise((resolve) => {
let h = (e) => {
if (e.propertyName == prop[0])
resolve('transitionEnd ' + prop[0]);
};
this.addEventListener('transitionend', h, {once:false});
}),
new Promise((resolve) =>
setTimeout(
() => resolve('TIMEOUT ' + prop[0]),
prop[1].replace(/s/,'')*1000 + 100
)
)
])
}))
.then((res) => {
console.log(res + 'DONE!!!!');
/* do your stuff */
});
});解释:
首先,我们确定哪些属性实际上应该更改,然后拆分/映射/转换它以执行操作。通常它的格式如下:
“宽4s缓0,高2s缓0,..”
接下来我们使用Promise.race,因为并不总是触发transitionEnd (属性对于两个状态是相同的,或者属性名称在规则和事件中不匹配(背景可以是背景色),等等),我们需要tp回退到简单的超时
最后,我们等待每个属性的所有timeout/eventListeners
免责声明:
这是一个例子,我承认它使用了很多
魔法
,并且错过了很多检查
即使动画被取消,"callback“也会被触发(超时也会被触发)
需要ES6 :)
你可以玩它
jsfiddle
https://stackoverflow.com/questions/40530990
复制相似问题