Saya telah membuat skrip animasi biner yang diaktifkan dengan mengklik tombol.

Menggunakan kode saat ini Anda dapat mengklik beberapa kali dan itu akan berhenti setelah setiap iterasi. Namun, ketika saya mencoba untuk memperbaiki kode (saat ini dikomentari di bawah), itu berfungsi dengan baik dengan satu klik, tetapi tidak berhenti berulang jika Anda mengklik lebih dari sekali.

Adakah yang bisa membantu menghentikan infinite loop, atau mengetahui cara yang lebih baik untuk mencapai hasil yang sama?

Ini codepennya: https://codepen.io/rbradshaw/pen/ZEYmjpx

Berikut kodenya:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Binary</title>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg" xml:lang="en" id="binaryarea" width="400px" height="95px">
    <rect id="binarybackground" width="100%" height="100%" />
    <text>
        <tspan x="2" y="15" id="binary"></tspan>
        <tspan x="2" y="30" id="binary"></tspan>
        <tspan x="2" y="45" id="binary"></tspan>
        <tspan x="2" y="60" id="binary"></tspan>
        <tspan x="2" y="75" id="binary"></tspan>
        <tspan x="2" y="90" id="binary"></tspan>
    </text>
  </svg>
  <br><br>
  <button onclick="runBinary()">Click me</button>

  <script src="script.js"></script>
</body>
</html>
const binary = document.querySelectorAll('#binary');
document.getElementById("binaryarea").addEventListener("load", setBinary);

function runBinary(){
  //uncomment out from here
  // binActions = [];
  // iterations = 10;
  //to here
  iterLength = 20;

  //comment from here
  var binActions1 = setInterval(changeBinary, iterLength);
  var binActions2 = setInterval(changeBinary, iterLength);
  var binActions3 = setInterval(changeBinary, iterLength);
  var binActions4 = setInterval(changeBinary, iterLength);

  setTimeout(() => {
    clearTimeout(binActions1);
    clearTimeout(binActions2);
    clearTimeout(binActions3);
    clearTimeout(binActions4);
  }, 2000)
  //to here

  //uncomment out below from here
//   for(i = 0; i < iterations; i++) {
//     binActions[i] = setInterval(changeBinary, iterLength);
//   }   

//   setTimeout(() => {
//     binActions.forEach((_, idx) => {
//       clearTimeout(binActions[idx])
//     })
//   }, 2000)
  //to here
}

function changeBinary() {
  var rec = Math.floor(Math.random() * binary.length);
  var position = Math.floor(Math.random() * binary[0].textContent.length);
  oldtext = binary[rec].textContent;

  if (binary[rec].textContent[position] == "1") {
    newtext = getNewStr(oldtext, position, "0");
    binary[rec].textContent = newtext;
  } else {
      newtext = getNewStr(oldtext, position, "1");
    binary[rec].textContent = newtext;
  }   
}

function getNewStr(string, index, replace) {
  return string.substring(0, index) + replace + string.substring(index + 1);
}

function binaryString(charlen) {
  var str = "";
  for(i = 0; i < charlen; i++) {
      str += Math.floor(Math.random() * 2)
  }  
  return str
}

function setBinary() {
  binary.forEach(row => {
    row.textContent = binaryString(45);
  })
}

Setiap bantuan dihargai, terima kasih.

1
Ryan Bradshaw 21 Januari 2020, 10:39

2 jawaban

Jawaban Terbaik

Anda perlu menghapus interval dengan intervalID lama sebelum memulai interval baru.

Cara terpendek adalah dengan menggunakan variabel global untuk intervalID yang disediakan dari setInterval dan hapus interval jika diperlukan, tanpa interval tetap.

Yang bisa dipikirkan adalah larik global menjalankan intervalId, seperti

// global
var intervals = [];

Dan fungsi untuk menghapus semua interval

function clearIntervals() {
    intervals.forEach(clearTimeout);
    intervals.length = 0;            // empty array by keeping the object reference
}

Kemudian di

function runBinary() {

Hapus interval lama

clearIntervals();

Dan tambahkan interval ke intervals

intervals.push(binActions1, binActions2, binActions3, binActions4);

Serta jarak bebas dari interval.

intervals.push(setTimeout(clearIntervals, 3000));

Yang terakhir mencegah menggantung di atas interval dengan interval tetap.

1
Nina Scholz 21 Januari 2020, 09:33

Anda tidak mendeklarasikan binActions sebagai variabel lokal dan karena itu akan dicakup menjadi global.

Lain kali Anda mengekliknya, itu akan menimpa larik binActions dan setTimeout Anda akan menghapus interval baru dan bukan interval lama.

Cukup gunakan let atau var dan itu harus diperbaiki.

var binActions
1
Radu Diță 21 Januari 2020, 07:47