Reputation: 5074
I want to create a 'random selector' behaviour where the function iterates through an array for a period of time (example: 3 seconds, 5 seconds) while displaying all of array elements fast throughout the iteration until the iteration ends. Just imagine seeing all the elements displayed in a label one after another until it finally stops at an element.
My code so far:
var places = ["Curry Leaf", "Subway", "Burger King"];
function execute_randomizer() {
var place_label = document.getElementById("place_label");
for (var i = 0; i < 100; i++) {
var selected_place = places[Math.floor(Math.random() * places.length)];
setTimeout(function () {
place_label.innerText = selected_place;
}, 400);
}
}
This runs through the iteration and displays an element when the loop is done but it doesn't show each iteration's element. How can I amend this?
EDIT
Even if there's 3 elements, the animations must re-iterate through the array until the duration is completed
Upvotes: 0
Views: 915
Reputation: 386540
You could use a closure over the value and a different time for each timeout.
var places = ["Curry Leaf", "Subway", "Burger King"];
function execute_randomizer() {
var place_label = document.getElementById("place_label");
for (var i = 0; i < 10; i++) {
var selected_place = places[Math.floor(Math.random() * places.length)];
setTimeout(function (value) {
return function () {
place_label.innerText = value;
};
}(selected_place), i * 100);
}
}
execute_randomizer();
<div id="place_label"></div>
For a first run through, you could show each element and then take a random element at last value.
function execute_randomizer() {
function cb (value) {
return function () {
place_label.innerText = value;
};
}
var place_label = document.getElementById("place_label");
place_label.innerText = '';
for (var i = 0; i < places.length; i++) {
setTimeout(cb(places[i]), 200 + i * 200);
}
setTimeout(cb(places[Math.floor(Math.random() * places.length)]), 200 + places.length * 200);
}
var places = ["Curry Leaf", "Subway", "Burger King"];
execute_randomizer();
<div id="place_label"></div>
Upvotes: 1
Reputation: 164
I think it might be better if you would put the whole function in a timeout. (I'm not sure and didn't test, but that's what I would try).
What I mean is that you just build a function that creates your randomizer and fills in your field. After that you put a timeout to call the same function again + keep a counter that you pass as parameter.
An example of what I mean below: (didn't test it)
var places = ["Curry Leaf", "Subway", "Burger King"];
execute_randomizer(0); /* Start for the first time */
function execute_randomizer(times) {
if(times == 100)
return; /* stop execution */
var place_label = document.getElementById("place_label");
var selected_place = places[Math.floor(Math.random() * places.length)];
place_label.innerText = selected_place;
setTimeout(function () {
execute_randomizer(times+1)
}, 400);
}
Upvotes: 0
Reputation: 6218
Your for
finishes iterating before the setTimeout
runs, then the function passed to setTimeout
runs 100 times using the last value of selected_place
.
More about this behavior in setTimeout in for-loop does not print consecutive values
Another problem that I noticed is that your setTimeout will trigger after 400ms, since the for
loop will finish in about 1 ms, the function passed to setTimeout
will trigger 100 times one after another with no delay in between, for this, I replaced the delay argument of setTimeout from 400
to 400 * i
.
var places = ["Curry Leaf", "Subway", "Burger King"];
function execute_randomizer() {
var place_label = document.getElementById("place_label");
for (var i = 0; i < 100; i++) {
var selected_place = places[Math.floor(Math.random() * places.length)];
(function(selected_place){
setTimeout(function () {
place_label.innerText = selected_place;
}, 400 * i);
})(selected_place);
}
}
execute_randomizer();
<span id="place_label"></span>
Upvotes: 1
Reputation: 452
You should change your loop because right now you go in loop 100 times in maybe one millisecond and order 100
of change text but once again in the same time.
So better is wait for time out 400 ms
and then make next iteration.
Please remember time out is async.
Upvotes: 0