transitionend事件发生两次

时间:2013-09-08 21:57:00

标签: javascript css3

我有以下代码,我的问题是transitionend事件被触发两次。我不知道是什么原因造成的。我怀疑供应商前缀导致它,但他们没有。即使我只离开transitionendtransition,它仍会发射两次。

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

Fiddle

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>

6 个答案:

答案 0 :(得分:71)

在您的案例transitionendtop中,

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处理程序,然后清除转换属性,以防它们也发生变化,并在下次探测它们时再次进行探测。

当多个属性以不同的延迟和/或持续时间进行转换并且您希望在所有转换完成后执行某些操作时,这非常有用。

用例示例:

  • 淡出并缩小后删除一条Flash消息。
  • 触发&#34;打开&#34;并且&#34;关闭&#34;可重用组件中的事件,例如菜单或模态,消费者可能希望在转换结束后执行某些逻辑,而不会窥探css转换。

如果您只是转换一个属性,或没有不同的延迟和/或持续时间,那么一个简单的解决方案就可以正常工作。

适用于最新版本的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');
});