animationend 监听器和 setTimeout

animationend listeners and setTimeout

这里是fiddlehttps://jsfiddle.net/8p2jjr18/

我们的想法是在原版 JS 中实现用户评价的淡入淡出旋转。问题是当函数在setTimeout中第四次运行时,selection中的第一个和后续元素没有得到.fade class。相反,.hidden class 立即应用(而不是等待 .fade class 应用和 class 上的动画结束)和它搞乱了整个画面。

我试图将 break; 放入 for 循环的末尾而不是 if 语句的末尾(参见下面的示例),但这完全破坏了一切(只是只发生一次迭代),我不知道为什么。

function rotateTestimonials() {
    for (var i = 0; i < testimonials.length; i++) {
        if (testimonials[i].className === "testimonial show") {
            testimonials[i].className = "testimonial fade";
            testimonials[i].addEventListener("animationend", function () {
                 testimonials[i].className = "testimonial hidden";
                if (i + 1 !== testimonials.length) {
                    testimonials[i+1].className = "testimonial show";
                }
                else {
                    testimonials[0].className = "testimonial show";
                }
            }, false);
        };
        break;
    };
}

我有两个问题:

  1. 为什么我不能将 break 指令放入 for 循环的末尾?

  2. 为什么函数在 setTimeout 循环的第四次和以后的迭代中没有按预期工作?

使用您当前的代码,随着时间的推移,您将继续添加 animationend 事件侦听器,从而在每个证明元素上产生多个事件侦听器。您需要做的只是附加一个事件侦听器,它根据元素的当前状态采取适当的操作。

有两种方法可以处理这个问题。首先是为每个元素创建一个事件侦听器。

    function createEventListener(i, testimonials){
      return function(){
        if (testimonials[i].className === "testimonial show"){
            testimonials[i].className = "testimonial fade";
        } else {
            testimonials[i].className = "testimonial hidden";
            testimonials[(i+1)%testimonials.length].className = "testimonial show";
        }
      }
    }

    var testimonials = document.getElementsByClassName("testimonials")[0].getElementsByClassName("testimonial");
    for (var i = 0; i < testimonials.length; i++) {
      testimonials[i].addEventListener("animationend", createEventListener(i, testimonials), false);
    }

这里每个元素都有自己的事件侦听器函数。当显示动画结束时,该函数被触发,元素被赋予淡入淡出 class。当淡入淡出动画结束时,该函数再次被触发,元素被隐藏,下一个元素显示为 class。 See updated fiddle

另一种方法是为父元素提供单个事件侦听器。由于 event bubbling.

,只要子元素触发 animationend 事件,就会触发此函数
    var testimonials = document.getElementsByClassName("testimonials")[0].getElementsByClassName("testimonial");
    var i = 0;
    document.getElementsByClassName('testimonials')[0].addEventListener('animationend', function(){
        if (testimonials[i].className === "testimonial show"){
            testimonials[i].className = "testimonial fade";
        } else {
            testimonials[i].className = "testimonial hidden";

            i = (i+1)%testimonials.length;
            testimonials[i].className = "testimonial show";
        }
    });

这里我们只有一个事件处理程序,它将在每个子动画事件上调用。它的功能与上面相同,检查当前元素的状态并相应地改变。 See updated fiddle