我有以下代码,我的问题是transitionend
事件被触发两次。我不知道是什么原因造成的。我怀疑供应商前缀导致它,但他们没有。即使我只离开transitionend
和transition
,它仍会发射两次。
CSS
transition: 1s ease-out;
JS
document.addEventListener('click', function (e) {
var submarine = document.querySelector('.submarine');
var submarineX = e.clientX - submarine.offsetWidth / 2;
var submarineY = e.clientY - submarine.offsetHeight / 2;
submarine.style.left = submarineX + "px";
submarine.style.top = submarineY + "px";
});
document.addEventListener('transitionend', function (event) {
console.log(event.type + " " + new Date().getTime());
});
document.addEventListener('transitionend', function (event) {
console.log(event.type + " " + new Date().getTime());
});
document.addEventListener('click', function (e) {
var submarine = document.querySelector('.submarine');
var submarineX = e.clientX - submarine.offsetWidth / 2;
var submarineY = e.clientY - submarine.offsetHeight / 2;
submarine.style.left = submarineX + "px";
submarine.style.top = submarineY + "px";
});
.submarine {
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
background-color: red;
border-radius: 50%;
transition: 1s ease-out;
}
<div class="submarine"></div>
答案 0 :(得分:71)
transitionend
和top
中, left
会针对已转换的每个媒体进行触发。
您可以在event.propertyName
。
没有“transition s end”事件,因此您可能需要一些hackiness,例如仅对其中一个转换属性过滤transitionend
回调处理。 E.g:
function (event) {
if (event.propertyName == 'top') {
//put your code here
}
});
PS。没有浏览器触发MSTransitionEnd
事件。它在MS文档中的某个时刻,但在IE10测试版发布之前的某个时候,它被标准的transitionend
事件所取代。
答案 1 :(得分:7)
事件将针对已转换的每个属性触发。
Fabricio建议的propertyName
方式是执行此操作的正确方法,但根据具体情况,您也可以使用one();
,就像这样。
$(document).one('transitionend webkitTransitionEnd MSTransitionEnd', function() {
...
});
答案 2 :(得分:4)
对于任何寻找简单,一次性复制和粘贴解决方案的人(我只包括必要的css)。这并没有回答这个问题,它解决了我在这里登陆时所寻找的问题。
CSS:
.my-elem {
transition: height 0.5s ease-out, opacity 0.5s ease-out;
}
JavaScript的:
var elem = document.querySelector(".my-elem");
var transitionCounter = 0;
var transitionProp = window.getComputedStyle(elem , null)["transition-property"] || "";
// We just need to know how many transitions there are
var numTransitionProps = transitionProp.split(",").length;
elem.addEventListener("transitionend", (event) => {
// You could read event.propertyName to find out which transition was ended,
// but it's not necessary if you just want to know when they are all done.
if (transitionCounter < (numTransitionProps - 1)) {
transitionCounter++;
} else {
transitionCounter = 0; // reset
alert("I'm done!!!"); // do what you need to
}
}, false);
在IE11,Chrome 48和Firefox 37中测试。
答案 3 :(得分:3)
对于仍在寻找更强大解决方案的人,例如&#34; allTransitionEnd&#34;事件,我已经实现了jQuery "special event",更多的是作为我正在处理的事情的概念证明,但我可能会在Github上发布一个lib。
查看JSBin。
这很棘手,所以我不会解释太多,但是在所有过渡结束后,它会让事情变得非常容易:
$(function () {
$element.on('allTransitionEnd', function () {
// do something after all transitions end.
});
});
它通过探测转换属性的元素,然后绑定到本机transitionend
事件(包括供应商特定),以跟踪已完成转换的属性。当所有转换完成后,它会触发任何绑定的allTransitionsEnd
处理程序,然后清除转换属性,以防它们也发生变化,并在下次探测它们时再次进行探测。
当多个属性以不同的延迟和/或持续时间进行转换并且您希望在所有转换完成后执行某些操作时,这非常有用。
用例示例:
如果您只是转换一个属性,或没有不同的延迟和/或持续时间,那么一个简单的解决方案就可以正常工作。
适用于最新版本的Chrome,Firefox,Safari,Mobile Safari以及IE11和IE10。不能在IE8中工作,因为不支持转换。绑定到其他本机事件作为后备。
答案 4 :(得分:0)
您可以使用target
属性过滤掉由子元素触发的事件,并使用propertyName
仅在特定属性更改时触发事件。
const handleTransitionEnd = event => {
if (event.target !== myDomElementRef) return;
if (event.propertyName !== "height") return;
// Do my things
};
答案 5 :(得分:-2)
这是一个相对古老的问题,但我想我会分享我的答案:
function OnTransitionEvent() {
var t,
el = document.createElement('transitionElement');
var transitions = {
'transition' : 'transitionend',
'OTransition' : 'oTransitionEnd',
'MozTransition' : 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (t in transitions){
if (el.style[t] !== undefined){
return transitions[t];
}
}
}
var transitionEvent = OnTransitionEvent();
$(document).one(transitionEvent, function() {
console.log('done');
});