#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. большое вам спасибо! Я собираюсь подробно рассмотреть оба этих ответа, прежде чем соглашусь — в обоих, похоже, много действительно полезной информации, но я новичок, поэтому мне потребуется некоторая концентрация, прежде чем я выясню, какой из них использовать!