Бесконечная замена фона у массива блоков в рандомное время
Моя задача состоит в том, что бы при старте страницы у массива блоков в случайное время в диапазоне 5 секунд менять фон на случайный из заранее созданного массива. У меня будет примерно 20 таких блоков, я не могу понять как такое провернуть не забивая стек. Прошу помощи
let rhombus = Array.from(document.querySelectorAll('.cont__item'));
let colorBg = ['red','purple','lightseagreen'];
function autoNext() {
eachBg(rhombus);
setTimeout(autoNext, 10000);
}
function eachBg(array) {
array.forEach(element => {
randomBg(element);
});
};
function randomBg(element) {
let randomId = randomInteger(0, 3);
let randomNum = randomInteger(1, 5) * 1000;
setTimeout(function(){
element.style.backgroundColor = colorBg[randomId];
console.log(element)
}, randomNum);
};
function randomInteger(min, max) {
let rand = min + Math.random() * (max + 1 - min);
return Math.floor(rand);
};
setTimeout(autoNext, 2000);
.b-cont {
display: flex;
flex-wrap: wrap;
}
.b-cont .cont__item {
width: 50px;
height: 50px;
margin: 5px;
background: #000;
color: #ffffff;
}
<div class="b-cont">
<div class="cont__item">
</div>
<div class="cont__item">
</div>
<div class="cont__item">
</div>
<div class="cont__item">
</div>
<div class="cont__item">
</div>
</div>
Ответы (2 шт):
Попробовал сделать такое через классы: для каждого элемента создается свой экземпляр, который и запускается.
Так же, как у вас, задержку задавал через вложенный setTimeout (вместо setInterval), как написано здесь: https://learn.javascript.ru/settimeout-setinterval
class ColoredBlock {
constructor({element, maxTimeout, colors}) {
this._element = element;
this._maxTimeout = maxTimeout;
this._colors = colors;
}
_runInterval = () => {
this._setRandomColor();
this._timer = setTimeout(this._runInterval, this._getRandomTimeout());
}
start() {
this._timer = setTimeout(this._runInterval, this._getRandomTimeout());
}
stop() {
clearTimeout(this._timer);
}
_getRandomTimeout() {
return Math.random() * this._maxTimeout;
}
_getRandomColor() {
const randomInt = Math.floor(Math.random() * this._colors.length);
return this._colors[randomInt];
}
_setRandomColor() {
this._element.style.backgroundColor = this._getRandomColor();
}
}
const maxTimeout = 5000;
const colors = ['red','purple','lightseagreen'];
const blocks = document.querySelectorAll('.cont__item');
blocks.forEach(blockElement => {
const block = new ColoredBlock({element: blockElement, maxTimeout, colors});
block.start();
});
.b-cont {
display: flex;
flex-wrap: wrap;
}
.b-cont .cont__item {
width: 50px;
height: 50px;
margin: 5px;
background: #000;
color: #ffffff;
}
<div class="b-cont">
<div class="cont__item">
</div>
<div class="cont__item">
</div>
<div class="cont__item">
</div>
<div class="cont__item">
</div>
<div class="cont__item">
</div>
</div>
Я не сразу обратил внимание, что Вы хотите у каждого блока индивидуальный таймер.
Вот мой вариант:
const blocks = [...document.querySelectorAll('.block')];
const colors = ['red', 'purple', 'lightseagreen', 'green', 'orange'];
const getRndTime = (max) => Math.random() * max;
const getRndColor = () => colors[~~(Math.random() * colors.length)];
const update = (e) => {
e.style.background = getRndColor();
setTimeout(update, getRndTime(5000), e);
}
(function start() {
blocks.map(e => update(e));
})();
.container {
display: flex;
flex-wrap: wrap;
}
.block {
height: 60px;
flex: 1 1 20%;
}
<div class="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
Хочу обратить ваше внимание, что статистически нет особой разницы между одновременной работой N таймеров, и работой одного с временным диапазоном в N раз меньше, который меняет цвет случайного элемента.
Сравните результат:
const blocks = [...document.querySelectorAll('.block')];
const colors = ['red', 'purple', 'lightseagreen', 'green', 'orange'];
const getRndTime = (max) => Math.random() * max;
const getRndBlock = () => blocks[~~(Math.random() * blocks.length)];
const getRndColor = () => colors[~~(Math.random() * colors.length)];
const update = () => {
getRndBlock().style.background = getRndColor();
setTimeout(update, getRndTime(5000 / 15));
}
(function start() {
blocks.map(e => e.style.background = getRndColor());
update();
})();
.container {
display: flex;
flex-wrap: wrap;
}
.block {
height: 60px;
flex: 1 1 20%;
}
<div class="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>