0
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

shuhei m
  • 67
  • 5
  • 2
    PLease [edit] your question to include a [mre]. – 0stone0 Dec 19 '22 at 15:56
  • 3
    You can't style letters being part of a string. But you can style html elements.. so it means you should embed each one of those letters in a standalone span. Unless you come up with a better solution that I can't think of – Diego D Dec 19 '22 at 15:57
  • there's an old jQuery plugin called "lettering.js" that facilitates stuff like this. – Pointy Dec 19 '22 at 16:00
  • Please use `Array.from(banner)`, not `banner.split("")`. See [How do I split a string into an array of characters?](/a/38901550/4642212). – Sebastian Simon Dec 19 '22 at 16:03
  • so am i right in assuming the type error is due to trying to set a property on an array item? – shuhei m Dec 19 '22 at 16:14
  • 1
    You don't just have to 'assume', you can always debug. [Try it](https://developer.chrome.com/docs/devtools/javascript/) – Dilshan Dec 19 '22 at 16:21
  • you were accessing to the `style` property of a string value (one character of a string is still a string) .. there's not such property. It doesn't matter if it was an element of an array. It was a string. You cannot style a string.. the style property belongs to HTMLElement so you had to reimagine your strategy. Something I attempted in my answer – Diego D Dec 19 '22 at 16:27
  • ...and FYI `const value = 'test'; console.log(typeof value); //->string console.log(typeof value[0]); //->string` – Diego D Dec 19 '22 at 16:32

1 Answers1

1

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>
Diego D
  • 6,156
  • 2
  • 17
  • 30