简体   繁体   中英

Changing colors in array elements using javascript

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM