I'm new to javascript. I'm working on sorting visualization and I want to change the color of array elements one by one. I tried to do it but they all change at the same time layout
function selectionSort(main_arr)
{
var arr_slots = document.getElementById("draw-area").childNodes;
for (var i=0; i<main_arr.length; i++)
{
arr_slots[i].style.backgroundColor="red";
(function(index)
{
setTimeout(function()
{
arr_slots[index].style.backgroundColor="#f2f2f2";
},1000);
})(i)
}
}
setTimeout begins an asynchronous process where it waits and then triggers its callback. Your loop iterates over all the elements almost instantly. You need to rework your code so that the next element's color change timer is triggered by the previous color change.
Your setTimeout is set to go off after 1 second for all items in your loop. This is not cumulative, so basically the loop will complete quickly (almost instantly from your pointof view) with "i" number of setTimeouts, all firing after one second.
You need to use "i" to set the timer to increment to whatever time you need (also you don't need to wrap your setTimeout in a anonymous self executing function. So something like this might work
function selectionSort(main_arr) {
var arr_slots = document.getElementById("draw-area").childNodes;
for (var i=0; i < main_arr.length; i++) {
arr_slots[i].style.backgroundColor="red";
setTimeout(function() {
arr_slots[index].style.backgroundColor="#f2f2f2";
}, i * 1000);
}
}
This will make each timer fire one second after the other, starting at 0 seconds. The timing can be adjusted in a few ways
i * 100 // every tenth of a second
(i * 100) + 2000 // every tenth of a second starting after 2 seconds
You could also add easing, but I won't go into that here (mostly because I can't spin one off the top of my head)
This type of thing is usually handled pretty well using css potentially, or if you investigate a library like animejs, it makes staggering changes to elements pretty easy.
Also have a look at document.querySelectorAll, so you could use it like
var array_slots = document.querySelectorAll("#draw-area > *");
// or whatever the css selector is
array_slots.forEach(function(element) {
// element returns the html element in the array_slots list
// do whatever code you need here
});
Hope that helped.
What went wrong
Your for loop sets all the setTimeout
's at the same time. So the timeouts execute all at the same time.
What to do instead:
1. Use recursion
const messages = [ 'Message #1', 'Message #2', 'Message #3', ]; showMessages(messages, 0) function showMessages( messages, index ) { // don't run when the index cannot select a message, because it is done iterating over the array if( messages.length === index) return; console.log( messages[index] ); index = index += 1; window.setTimeout( () => { showMessages( messages, index ); }, 1000); }
2. calculate different timeouts using the indexes
const messages = [ 'Message #1', 'Message #2', 'Message #3', ]; for(let index=0; index<messages.length; index++) { window.setTimeout( () => { console.log( messages[index] ); }, 1000*index); }
There are probably more approaches, but these seem to be the most basic.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.