shuhei m
shuhei m

Reputation: 67

Is this why im getting a typeerror?

var colourArray = [
  "rgb(248, 155, 165)",
  "rgb(248, 160, 170)",
  "rgb(248, 160, 180)",
  "rgb(248, 175, 195)",
  "rgb(249, 184, 195)",
  "rgb(248, 195, 215)",
  "rgb(248, 205, 235)",
  "rgb(248, 225, 225)",
  "rgb(248, 116, 138)",
];

changingColorsArray = [...colourArray];



function arrayRotate(arr, reverse) {
  if (reverse) arr.unshift(arr.pop());
  else arr.push(arr.shift());
  return arr;
}




var banner = document.getElementsByClassName('banner')[0].innerHTML

var bannerArray = banner.split('')



function applyColors(letters, colorArr) {
  for (let i = 0; i < letters.length; i++) {
    letters[i].style.color = colorArr[i];
  }
}


myInterval = setInterval(() => {

  arrayRotate(changingColorsArray, true);

  applyColors(bannerArray, changingColorsArray);
}, 1600);

My html

<div class="banner">Funny Klock</div>

so far ive gathered that letters[i] is accessing an index of an array

letters[i].style.color = colorArr[i];

hence cannot set the property of that item, unlike a span, div or class, PLEASE tell me if im right.

Plus, how would you access the color property and loop through the innerhtml to give each letter a different color

Upvotes: 0

Views: 56

Answers (1)

Diego D
Diego D

Reputation: 8163

Here's an example using the strategy I suggested in the comments.

I mostly focused on the "letterize" approach. So that there's a function letterizeElementContent that will change the content of each .banner element, creating a span embedding each letter of its original content.

Later, the function passed to setInterval, will just apply the desired style to each of the .letter span contained in the .banner elements, following the colour map specified in the colourArray that will be rotating at each interval passed.

const colourArray = [
  "rgb(248, 155, 165)",
  "rgb(248, 160, 170)",
  "rgb(248, 160, 180)",
  "rgb(248, 175, 195)",
  "rgb(249, 184, 195)",
  "rgb(248, 195, 215)",
  "rgb(248, 205, 235)",
  "rgb(248, 225, 225)",
  "rgb(248, 116, 138)",
]; 

//split the letters and embed them in spans for each .banner element
document.querySelectorAll('.banner')
  .forEach(banner => {
    letterizeElementContent(banner);
  });

//change color schema every 1.6s
let changingColorsArray = [...colourArray];
myInterval = setInterval(() => {
  //rotates the colors array  
  arrayRotate(changingColorsArray, true);
  //for each element having the banner class
  document.querySelectorAll('.banner')
    .forEach(banner => {
      //apply colors from changingColorsArray for each letter
      applyColors(banner, changingColorsArray);
    });
    
  }, 1600);

//converts the text content of the given element in html spans wrapping each letter
function letterizeElementContent(element){
  
  const textContent = element.textContent;
  
  element.dataset.original = textContent;  
  element.innerText = '';
  
  [...textContent].forEach( letter => {  
    const letterSpan = document.createElement('span');
    letterSpan.classList.add('letter');
    letterSpan.innerText = letter;
    element.append(letterSpan);  
  });  
}

function applyColors(element, colors){
  let i = 0;
  element
    .querySelectorAll('.letter')
      .forEach(letter => {
        if(++i > colors.length)
          i=1;        
        const color = colors[i-1];        
        //console.log(i, color);
        letter.style.color = color;
      });
}

function arrayRotate(arr, reverse) {
  if (reverse) arr.unshift(arr.pop());
  else arr.push(arr.shift());
  return arr;
}
.letter{
  /*border: solid 1px;*/
}

.banner{
  font-size: 3rem;
}
<div class="banner">Funny Klock</div>


<div class="banner">Second Clock</div>

Upvotes: 1

Related Questions