1

Sorry if the title doesn't accurately capture my question; wasn't sure how to write this in a single sentence.

Problem description: Let's say I have an array of colors and a bunch of divs. I want to cycle the div background color through the array colors, but also making sure each div starts at a different position in the color array.

Example: my color array is [red, blue, yellow, green]. The first div color starts as red, then cycles through blue, yellow, green before going back to red. Div2 starts as blue, then goes yellow, green, red, blue, and so on for as many div elements as I have.

The two potential solutions I can imagine are:

  1. Would I have to generate a new color array for each div? (maybe by adding 1 to a counter and doing a splice or push or pop operation)
  2. Could I loop through the original array, just starting from a different position for each div? (dynamically generate an offset based on its position - 1st div, 2nd, 3rd, etc.)

Are these both viable ways to solve the problem?

3 Answers 3

1

Sounds like all you need is modulo. Once you've identified the starting index for a particular element, increment the index modulo the array length. If the colors array is colors, then you could do something like

async function cycle(elm, index) {
  while (true) {
    elm.style.backgroundColor = colors[index];
    index = (index + 1) % colors.length;
    await delay(1000);
  }
}
cycle(someElement, 0);
// or
cycle(someOtherElement, 1);
// etc
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, this did the trick! I managed to adapt it for my use-case (setInterval and Array.forEach) and used a counter passed into the function instead of simply adding a 1.
When an answer solves your problem, you may consider marking it as Accepted (check the checkbox on the left) to indicate that the issue is resolved :)
I have a question for you about acceptance etiquette - you were the first answer and the modulo suggestion is what worked, but fqhv answered later with a little longer explanation and code example building off yours. Should I accept the first correct answer, or the more "complete" later answer?
1

Just for fun, this animation in CSS. The question is tagged as

.color-change {
  --animation-duration: 5s;
  display: inline-block;
  height: 100px;
  width: 100px;
  animation: colors var(--animation-duration) steps(1, end) infinite;
}
.color-change:nth-child(4n+2) { animation-delay: calc(var(--animation-duration) * -.25) }
.color-change:nth-child(4n+3) { animation-delay: calc(var(--animation-duration) * -.5) }
.color-change:nth-child(4n+4) { animation-delay: calc(var(--animation-duration) * -.75) }


@keyframes colors {
  from,
  to  { background: red; }
  25% { background: blue; }
  50% { background: yellow; }
  75% { background: green; }
}
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>

Comments

0

You do not need to generate a new array for each div, so while both of your proposed solutions could work, the second one is the better way to go.

When setting the initial color for each div, you simply need to select the color based off the index of the current div.

div[index].style.backgroundColor = colors[index];

Since you can have more divs than colors you need to start from the beginning of the array once the index of the div exceeds the number of colors. As CertainPerformance's answer shows, you can use the modulus of the index to easily "loop" the index back to the beginning. So the assignment becomes:

divs[index].style.backgroundColor = colors[index % colors.length];

Once you've done the initial color assignment one way to iterate through the colors is to simply find the index of the current color and increment one, again using the modulus in order to loop through the colors.

var currentColor = doc.style.backgroundColor;
var colorIndex = (colors.indexOf(currentColor) + 1) % colors.length;
doc.style.backgroundColor = colors[colorIndex];

Here is a complete example.

var colors = ['red', 'blue', 'yellow', 'green', 'purple'];

function assignInitialColors() {
  var divs = document.getElementsByClassName("color-change");
  for (var index in divs) {
    var colorIndex = index % colors.length;
    if(divs[index].style) {
      divs[index].style.backgroundColor = colors[colorIndex];
    }
  }

  setInterval(iterateColors, 2000);
}


function iterateColors() {
   var divs = document.getElementsByClassName("color-change");
    for (var index in divs) {
    var doc = divs[index];
    var currentColor = doc.style && doc.style.backgroundColor;
    if (currentColor) {
      var colorIndex = (colors.indexOf(currentColor) + 1) % colors.length;
      doc.style.backgroundColor = colors[colorIndex];
    }
  }
}

assignInitialColors();
div, .color-change {
  min-height: 60px;
  min-width: 60px;
  margin: 5px;
  float: left;
}
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>
<div class="color-change"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.