Менять цвет на каждой итерации цикла forEach в javascript?

#javascript #arrays #loops #iteration

#javascript #массивы #циклы #итерация

Вопрос:

У меня есть функция, которая на короткое время изменяет цвет элемента, а затем возвращает его к исходному цвету. В зависимости от уровня, на котором вы находитесь (это игра-головоломка), цикл forEach затем запускает эту функцию определенное количество раз (больше на более высоких уровнях). В настоящее время цвет, на который изменяется элемент, — это то, что я вручную ввел в код. Я пытаюсь найти способ изменять этот цвет каждый раз, когда forEach запускает функцию.

Например, допустим, вы находитесь на первом раунде, и forEach выполняется три раза, элемент будет мигать красно-белым, красно-белым, красно-белым. Мне нужно, чтобы он мигал красно-белым, сине-белым, розово-белым. Также необходимо вернуться к началу массива, когда в нем закончатся цвета. Например, на более высоком уровне forEach может выполняться 6 раз, поэтому итерация по массиву colors должна будет вернуться к началу один раз. Вот код:

 function showCircle(item, j, x) {
  setTimeout(function () {
let x = 0;
let colors = ['blue','pink','green']
let color = colors[x];
    var num = initArray[j];
    var element = document.getElementById(num)
    element.classList.add(`cell-glow-${color}`)
    window.setTimeout(function () {
      element.classList.remove(`cell-glow-${color}`)
    }, 400);
    j  ;
    x  
    console.log(color)
  }, speed() * j);
};

function showEachCircle(captureUserClicks) {
  initArray.forEach(showCircle);
  }
 

Очевидно, что выше происходит то, что функция showCircle каждый раз обнуляет x, поэтому она застревает на первой итерации. Но я не уверен, куда мне следует поместить эти переменные, чтобы они выполнялись правильно. Кроме того, я даже не начал задумываться, заставляя массив возвращаться к началу.

Есть идеи? Спасибо!

Комментарии:

1. Под «красно-белым, сине-белым, розово-белым» вы подразумеваете «сине-белый, розово-белый, зелено-белый»? Потому что do — это цвета в вашем коде.

2. что такое initarray?

3. Ах, так что цвета, которые я написал, совершенно произвольны. Прошу прощения за путаницу — я просто демонстрировал функциональность, но фактические значения (цвета) могут быть любыми.

4. InitArray определяется вне функции и представляет собой начальный массив, через который функция проходит, чтобы указать, какие элементы DOM должны быть изменены.

Ответ №1:

Проблема в том, что вы перезаписываете x и пытаетесь изменить число, j , которое передается.

Во-первых, полезно ознакомиться с определением forEach .

В частности, в функции, которую вы передаете, showCircle , item является текущим элементом массива, j текущим индексом цикла и x исходным массивом, в данном случае это было бы initArray . Затем вы перезаписываете x с let x = 0 помощью, и пытаетесь увеличить j , что ничего не даст, потому что оно увеличивается после его использования.

Я думаю, вы ищете что-то более похожее на это:

 // Declare these outside the loop
var x = 0;
var colors = ['blue','pink','green'];

function showCircle(num, j) {
  // Save the current value so it isn't overwritten by the loop/setTimeout combination
  let y = x;
  // Increment x
  x  ;
  setTimeout(function () {
    // Get the color, using the modulus operator (%) to start at the beginning again
    var color = colors[y % colors.length];
    // Get the element. num is the current item in the loop from initArray
    var element = document.getElementById(num);
    // Make it glow!
    element.classList.add(`cell-glow-${color}`)
    setTimeout(function () {
      // Make it not glow...
      element.classList.remove(`cell-glow-${color}`)
    }, 400);
    console.log(color);
    // j is the index of num in initArray
  }, speed() * j);
};

function showEachCircle(captureUserClicks) {
  initArray.forEach(showCircle);
}
 

Если вы не знакомы с оператором модуля (или остатка) % , он очень полезен для выполнения цикла, когда у вас есть ограниченный набор вещей, которые вы хотите перебрать, в данном случае colors . В этом примере с 3 цветами:

 0 % colors.length = 0
1 % colors.length = 1
2 % colors.length = 2
3 % colors.length = 0
4 % colors.length = 1
etc..
 

Комментарии:

1. большое вам спасибо! Я собираюсь подробно рассмотреть оба этих ответа, прежде чем соглашусь — в обоих, похоже, много действительно полезной информации, но я новичок, поэтому мне потребуется некоторая концентрация, прежде чем я выясню, какой из них использовать!

Ответ №2:

Вот как я бы это сделал:

  • Чтобы избежать x=0 выполнения при каждом вызове функции, мы собираемся поместить ее вне нее.
  • Для перебора массива цветов мы воспользуемся оператором modulo:
      `x = (x 1)%3`
     

    Это, вместо x того, чтобы получать значения 0, 1, 2 снова и снова.

  • array.forEach() вызовет функцию несколько раз, не дожидаясь завершения полной вспышки (с белого на красный и обратно на белый). Вместо этого мы будем использовать рекурсию. Как только полная прошивка будет выполнена, мы снова вызовем функцию, если это необходимо.

Вы можете увидеть рабочий пример во фрагменте:

 const initArray = [1,1,1,1,1,1];
const colors = ['red', 'green', 'blue'];
let x = 0;
let numberOfFlashes = 0;
function showCircle() {
  setTimeout(()=> {
    color = colors[x];
    console.log(color);
    setTimeout(()=> {
      console.log('white');
      numberOfFlashes  ;
      if(numberOfFlashes<initArray.length){
        showCircle();
      }
    }, 400);

    x = (x 1)%3;
  }, 400);
}

showCircle(); 

Теперь вы можете просто поместить свой код вместо журналов моей консоли, и он должен работать

Комментарии:

1. большое вам спасибо! Я собираюсь подробно рассмотреть оба этих ответа, прежде чем соглашусь — в обоих, похоже, много действительно полезной информации, но я новичок, поэтому мне потребуется некоторая концентрация, прежде чем я выясню, какой из них использовать!