46

我有以下代码,我的问题是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());
});

小提琴

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>

4

6 回答 6

95

transitionendtop在您的情况下,为每个转换的属性触发left.

您可以在 访问与事件关联的属性event.propertyName

没有“transition s end”事件,因此您可能需要一些技巧,例如transitionend仅过滤其中一个已转换属性的回调处理。例如:

function (event) {
    if (event.propertyName == 'top') {
        //put your code here
    }
});

附言。没有浏览器触发该MSTransitionEnd事件。它在 MS 文档中的某个时间点,但在 IE10 测试版发布之前的某个时间,它被标准transitionend事件所取代。

于 2013-09-08T22:01:53.400 回答
9

该事件会针对已转换的每个属性触发。

Fabricio 建议的propertyName方法是执行此操作的正确方法,但是如果您使用的是 jQuery,您也可以one();像这样使用。

$(document).one('transitionend webkitTransitionEnd MSTransitionEnd', function() {
   ...
});
于 2013-09-08T22:12:45.033 回答
6

对于任何寻求简单的一次性复制和粘贴解决方案的人(我只包含了必要的 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 中测试。

于 2016-05-10T14:54:53.373 回答
3

对于仍在寻找更强大的解决方案(例如“allTransitionEnd”事件)的任何人,我已经实现了一个jQuery“特殊事件”,更多的是作为我正在从事的工作的概念证明,但我可能会在 Github 上发布一个库。

查看JSBin

这很棘手,所以我不会解释太多,但它使得在元素上的所有转换结束后做一些事情变得非常容易:

$(function () {

    $element.on('allTransitionEnd', function () {
        // do something after all transitions end.
    });

});

它通过探测元素的转换属性来工作,然后绑定到本机transitionend事件(包括特定于供应商的事件)以跟踪已完成转换的属性。当所有都完成转换时,它会触发任何绑定的allTransitionsEnd处理程序,然后清除转换属性,以防它们也发生了变化,并在下次重新探测它们。

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

示例用例:

  • 淡出和缩小后删除一条闪光信息。
  • 在可重用组件(例如菜单或模式)中触发“打开”和“关闭”事件,消费者可能希望在转换结束后执行一些逻辑,而不是窥探 css 转换。

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

适用于最新版本的 Chrome、Firefox、Safari、Mobile Safari 以及 IE11 和 IE10。在 IE8 中不起作用,因为不支持转换。绑定到其他原生事件作为后备。

于 2014-09-14T08:46:37.973 回答
0

您可以使用该target属性过滤掉由子元素触发的事件,并propertyName仅在特定属性更改时才触发该事件。

const handleTransitionEnd = event => {
  if (event.target !== myDomElementRef) return;
  if (event.propertyName !== "height") return;

  // Do my things
};
于 2019-12-25T19:10:18.310 回答
-3

这是一个相对古老的问题,但我想我会分享我的答案:

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');
});
于 2015-01-08T00:49:55.360 回答