Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript transitionend事件触发两次_Javascript_Css - Fatal编程技术网

Javascript transitionend事件触发两次

Javascript transitionend事件触发两次,javascript,css,Javascript,Css,我有以下代码,我的问题是transitionend事件被触发了两次。我不知道是什么原因造成的。我怀疑是厂商的前缀造成的,但事实并非如此。即使我只离开transitionend和transition,它仍然会发射两次 CSS transition: 1s ease-out; document.addEventListener('click', function (e) { var submarine = document.querySelector('.submarine');

我有以下代码,我的问题是
transitionend
事件被触发了两次。我不知道是什么原因造成的。我怀疑是厂商的前缀造成的,但事实并非如此。即使我只离开
transitionend
transition
,它仍然会发射两次

CSS

transition: 1s ease-out;
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());
});
JS

transition: 1s ease-out;
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',函数(事件){
console.log(event.type+“”+new Date().getTime());
});
document.addEventListener('click',函数(e){
var subside=document.querySelector('.subside');
var submarineX=e.clientX-subside.offsetWidth/2;
var submarineY=e.clientY-subside.offsetHeight/2;
subside.style.left=submarineX+“px”;
subside.style.top=潜艇+“px”;
});
。潜艇{
位置:绝对位置;
排名:0;
左:0;
宽度:20px;
高度:20px;
背景色:红色;
边界半径:50%;
过渡:1s放松;
}

transitionend
为每个已转换的属性激发,在您的案例中是
top
left

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

没有“transitionsend”事件,因此您可能需要进行一些黑客操作,例如仅对一个已转换属性过滤
transitionend
回调处理。例如:

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


注意:没有浏览器触发
MSTransitionEnd
事件。它在MS文档中的某个时候出现过,但在IE10测试版发布之前的某个时候,它被标准的
transitionend
事件所取代。

该事件为每个已转换的属性触发

Fabrico建议的
propertyName
方法是实现这一点的正确方法,但是如果您使用jQuery,也可以使用
one()也是这样

$(document).one('transitionend webkitTransitionEnd MSTransitionEnd', function() {
   ...
});

对于仍在寻找更健壮的解决方案(如“allTransitionEnd”事件)的人,我已经实现了一个,更像是我正在研究的东西的概念证明,但我可能会在Github上推出一个lib

看看这本书

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

$(function () {

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

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

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

示例用例:

  • 在淡出和收缩后删除闪光信息
  • 触发可重用组件(如菜单或模式)中的“打开”和“关闭”事件,消费者可能希望在转换结束后执行某些逻辑,而无需窥探css转换
如果您只转换一个属性,或者没有不同的延迟和/或持续时间,那么简单的解决方案就可以了


适用于最新版本的Chrome、Firefox、Safari、Mobile Safari以及IE11和IE10。在IE8中不工作,因为不支持转换。绑定到另一个本机事件作为回退。

这是一个相对老的问题,但我想与大家分享我的答案:

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

对于任何想要一个简单的一次性复制粘贴解决方案的人(我只提供了必要的css)。这并没有回答这个问题,它确实回答了我在这里着陆时所寻找的东西

CSS:

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);
var elem=document.querySelector(“.my elem”);
var transitionCounter=0;
var transitionProp=window.getComputedStyle(elem,null)[“转换属性”]| |“”;
//我们只需要知道有多少个过渡
var numTransitionProps=transitionProp.split(“,”).length;
元素addEventListener(“transitionend”,(事件)=>{
//您可以阅读event.propertyName以了解结束的转换,
//但如果你只是想知道他们什么时候都完成了,那就没必要了。
if(转换计数器<(numTransitionProps-1)){
transitionCounter++;
}否则{
transitionCounter=0;//重置
警惕(“我做完了!!!”;//做你需要做的事
}
},假);

在IE11、Chrome 48和Firefox 37中测试。

您可以使用
target
属性筛选出由子元素触发的事件,并使用
propertyName
仅在特定属性更改时触发事件

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

  // Do my things
};

+1这也行得通,不过这样一来,每次进行转换时,你都必须附加回调。@Fabricio Matté是的,我知道这就是为什么我说这取决于具体情况。所以无论什么东西都可以让你的船漂浮。我使用它,但是
transitionend和WebKittTransitionEnd发射两次,所以我将它添加到
.one
$(this).off('WebKittTransitionEnd moztransitionend和transitionend transitionend')这实际上根本解决不了问题。。。对于每个被转换的属性,回调函数仍然会被激发请不要提交jQuery解决方案,当询问者显然没有使用它时…当你有一系列的转换,并且你想知道在没有硬编码转换属性的情况下何时完成所有转换时,这真是一个麻烦。@stoutie如果你不介意移动所有转换属性的话将转换样式和事件处理(例如,
:hover
)转换为JavaScript,您可以使用,它将为您提供一个干净的
onfinish
回调。不确定我是否遗漏了一些内容,但我相信要检查属性名称,您至少需要
event.propertyName