如何在纯JavaScript中向随机元素添加类

时间:2017-09-29 20:09:41

标签: javascript html random requestanimationframe

我的ul里面有一些li。 我想随机选择li并添加.active类1秒,然后移除.active类并随机选择下一个li

我试图在不使用setInterval或Timeout的情况下这样做,所以我尝试使用requestAnimationFrame虽然我认为我的javascript逻辑在随机化方面不太正确。

目前我已经开始工作,但每次再次调用该函数时它会选择相同的li

<ul>
  <li class="light active"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
</ul>

Javascript

(function() {

var lights = document.getElementsByClassName("light");
var random = Math.floor(Math.random() * (lights.length - 1)) + 0;
var randomLight = lights[random];

function repeatOften() {
  randomLight.classList += randomLight.classList ? ' active' : ' light';
  requestAnimationFrame(repeatOften);
}
requestAnimationFrame(repeatOften);

})();

这是一支笔:https://codepen.io/H0BB5/pen/PJjapX?editors=0010

提前致谢!

3 个答案:

答案 0 :(得分:0)

在将来或多或少知道的时间内运行函数的正确选择是setTimeoutrequestAnimationFrame适用于在不中断渲染循环的情况下尽可能经常运行的事情,例如每秒60次(又名&#34; 60 fps&#34;)。

在您的情况下,您的更新速度相对较慢,每秒一次,因此setTimeout不会受到伤害。

您可能希望跟踪两个元素:您正在更改的元素和之前更改的元素,因此您可以重置它。

另外,classList.toggle会派上用场,因为它会添加或删除一个类,具体取决于它是否已经存在。

(function() {
  var lights = document.getElementsByClassName("light");
  var previousLight = null;

  function repeatOften() {
    if (previousLight) previousLight.classList.toggle('active')

    var random = Math.floor(Math.random() * (lights.length - 1)) + 0;
    var randomLight = lights[random];
    randomLight.classList.toggle(randomLight);
    previousLight = randomLight;
    setTimeout(repeatOften, 1000);
  }

  setTimeout(repeatOften, 1000);
})();

Here是更新的(稍有更改)笔。

答案 1 :(得分:0)

每次运行该功能时,您都需要更新闪烁的灯光。要每秒进行不同的光线变化,请检查动画帧时间是否为秒。

&#13;
&#13;
(function repeatOften(ts) {
  if (ts % 1000 < 10) {
    document.getElementsByClassName("active")[0].classList.remove('active');
    var lights = document.getElementsByClassName("light");
    lights[Math.floor(Math.random() * lights.length)].classList.add('active');
  }
  requestAnimationFrame(repeatOften);
})();
&#13;
li {
  background: 1px black
}

li.active {
  animation: blink 1s ease-in-out infinite;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}
&#13;
<ul>
  <li class="light active"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
</ul>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

  

我试图在不使用setInterval或Timeout

的情况下执行此操作

当前CSS动画完成时,您可以使用animationend事件来调用相同的函数

&#13;
&#13;
function fn() {
  var lights = document.querySelectorAll(".light");
  var random = Math.floor(Math.random() * lights.length);
  var randomLight = lights[random];
  repeatOften(randomLight)
};

function repeatOften(randomLight) {
  randomLight.className = "light active";
  randomLight.addEventListener("animationend", blink)
}

function blink() {
  this.className = "light";
  this.removeEventListener("animationend", blink);
  fn();
}

// handle first `li`
document.querySelector(".light.active")
.addEventListener("animationend", blink)
&#13;
.light.active {
  animation: blink 1s ease-in-out;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}
&#13;
<ul>
  <li class="light active"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
  <li class="light"></li>
</ul>
&#13;
&#13;
&#13;