使用JavaScript在循环中等待transitionend

时间:2015-09-06 12:24:25

标签: javascript css3 transition transitionend

我已经习惯了使用jQuery,我似乎无法弄清楚如何在普通的Javascript中做到这一点。我不想使用jQuery,因为这是我在网站上使用的唯一代码段,而且库太大而不能用于此目的。

这是jQuery脚本(正常工作):http://jsfiddle.net/1jt6dhzu/2/

h2 {
    opacity: 1;
    transition: opacity 700ms;
}
h2.fade-out {
    opacity: 0;
}


document.addEventListener("DOMContentLoaded", function () {
    var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
    var j, i = 4,
        n = whatAmI.length,
        heading = document.querySelector(".page-header > h2");

    function changeSubTitle() {
        setTimeout(function () {
            j = Math.floor(Math.random() * n - 1);
            if (j >= i) j += 1;

            heading.classList.add("fade-out");

            setTimeout(function () {
                heading.children("span")[0].innerHTML = whatAmI[j];
                heading.classList.remove("fade-out");
                setTimeout(changeSubTitle, 700);
            }, 700);
        }, 1000);
        i = j;
    }
    changeSubTitle();
});

我想换掉香草JS。循环的很大一部分可以保留,但是,必须替换超时和回调。我想因为我不需要IE9支持我可以用css3过渡和添加类来做到这一点。 This is what I have so far

def new_business(request):
    if request.method == 'POST':
        form = NewBusinessForm(request.POST)
        if form.is_valid():
            # process form data
            obj = Listing() #gets new object
            obj.business_name = form.cleaned_data['business_name']
            obj.business_email = form.cleaned_data['business_email']
            obj.business_phone = form.cleaned_data['business_phone']
            obj.business_website = form.cleaned_data['business_website']
            #finally save the object in db
            obj.save()
            return HttpResponseRedirect('/')
        ....

不幸的是,这不起作用。对于transitionend上的事件,交换timeOuts(除了最外层的)之外可能会更好。但我不确定如何实现这个crossbrowser(IE 10及更高版本,以及其他主流浏览器)。

1 个答案:

答案 0 :(得分:2)

你已经完成了几乎所有的事情吧,删除了以jQuery特有的方式实现的children方法。与我之前发布的相反,JS确实有一个children函数,它返回一个HTMLCollection,但它不能通过提供类型为param来基于元素类型进行过滤。它返回所有子节点,我们必须通过使用子元素的索引或通过检查元素的类型来选择正确的子节点。

对于此示例(为简单起见),请替换

heading.children("span")[0].innerHTML = whatAmI[j];

heading.children[0].innerHTML = whatAmI[j]; // since span is the first and only child

heading.querySelector("span").innerHTML = whatAmI[j];

它应该按预期工作。



document.addEventListener("DOMContentLoaded", function() {
  var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
  var j, i = 2,
    n = whatAmI.length,
    heading = document.querySelector(".page-header > h2");

  function changeSubTitle() {
    setTimeout(function() {
      j = Math.floor(Math.random() * (n - 1));
      if (j >= i) j += 1;

      heading.classList.add("fade-out");

      setTimeout(function() {
        heading.querySelector("span").innerHTML = whatAmI[j];
        heading.classList.remove("fade-out");
        setTimeout(changeSubTitle, 700);
      }, 700);
      i = j;
    }, 1000);
  }
  changeSubTitle();
});

h2 {
  opacity: 1;
  transition: opacity 700ms;
}
h2.fade-out {
  opacity: 0;
}

<header class="page-header">
  <h1>Bananas</h1>

  <h2><span>A phone</span></h2>

</header>
&#13;
&#13;
&#13;

使用 transitionend

transitionend是单个事件侦听器,只要元素属性的转换结束,就会附加并触发它。它将在添加和删除淡出条目后被触发,因此,我们必须手动检查事件触发时元素的状态,然后根据它进行操作。

这里我使用getComputedStyle属性来检查元素的opacity状态,如果它处于淡出状态,则更改文本并删除淡出类(或)否则调用再次changeSubTitle功能。

if (window.getComputedStyle(heading).opacity == 0) {
  heading.querySelector("span").innerHTML = whatAmI[j];
  heading.classList.remove("fade-out");
} else
  changeSubTitle();

&#13;
&#13;
document.addEventListener("DOMContentLoaded", function() {
  var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
  var j, i = 2,
    n = whatAmI.length,
    heading = document.querySelector(".page-header > h2");

  function changeSubTitle() {
    setTimeout(function() {
      j = Math.floor(Math.random() * (n - 1));
      if (j >= i) j += 1;

      heading.classList.add("fade-out");
      i = j;
    }, 1000);
  }
  heading.addEventListener('transitionend', function() {
    if (window.getComputedStyle(heading).opacity == 0) {
      heading.querySelector("span").innerHTML = whatAmI[j];
      heading.classList.remove("fade-out");
    } else
      changeSubTitle();
  });
  changeSubTitle();
});
&#13;
h2 {
  opacity: 1;
  transition: opacity 700ms;
}
h2.fade-out {
  opacity: 0;
}
&#13;
<header class="page-header">
  <h1>Bananas</h1>

  <h2><span>A phone</span></h2>

</header>
&#13;
&#13;
&#13;

或者(就像你评论的那样),你也可以检查元素上的类,然后相应地做出决定。与我之前的方法相比,这似乎是一种更简单的方法。

if (heading.classList.contains("fade-out")) {
  heading.querySelector("span").innerHTML = whatAmI[j];
  heading.classList.remove("fade-out");
} else
  changeSubTitle();

&#13;
&#13;
document.addEventListener("DOMContentLoaded", function() {
  var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
  var j, i = 2,
    n = whatAmI.length,
    heading = document.querySelector(".page-header > h2");

  function changeSubTitle() {
    setTimeout(function() {
      j = Math.floor(Math.random() * (n - 1));
      if (j >= i) j += 1;

      heading.classList.add("fade-out");
      i = j;
    }, 1000);
  }
  heading.addEventListener('transitionend', function() {
    if (heading.classList.contains("fade-out")) {
      heading.querySelector("span").innerHTML = whatAmI[j];
      heading.classList.remove("fade-out");
    } else
      changeSubTitle();
  });
  changeSubTitle();
});
&#13;
h2 {
  opacity: 1;
  transition: opacity 700ms;
}
h2.fade-out {
  opacity: 0;
}
&#13;
<header class="page-header">
  <h1>Bananas</h1>

  <h2><span>A phone</span></h2>

</header>
&#13;
&#13;
&#13;

上述两个代码段均已在最新版本的Firefox,Chrome,Opera,IE11和IE10(使用仿真)中进行了测试。它应该适用于Mac上最新版本的Safari。对于Windows,我认为Safari版本已停止使用5.1.x并且仍然仅触发webkitTransitionEnd事件。为了迎合这些浏览器,可以使用this SO thread中提到的方法。