umbriel
umbriel

Reputation: 751

Js infinte marquee text. Works on mouseover, but not on doc load

I have a strange problem. I have digged up this code snippet that allows a text row to be animated left and then repeated infinitely. While this works perfectly. I'd like to have all the rows to be animated on body load but much slower. And then when you mouseover on each of the rows the animation picks up more speed.

https://codepen.io/umbriel/pen/RjYqRR

So far I've tried stuff like looping each of the questions and then running the animation. But it still only grabbed one of the divs and animated it.

var el_text = questions[i].querySelectorAll('.intro-question-text');

for (var i = 0; i < el_text.length; i++) {
  el_text[i].style.transform = 'translate3d(' + qScrollPositions[i] + 'px,0,0)'
}

Any pointers? Thank you so much!

Upvotes: 0

Views: 39

Answers (1)

Kristaps
Kristaps

Reputation: 305

You can get it to do what you want by using the setInterval function (and swapping it out to a quicker one when the user hovers over the element).

var textCopy = document.querySelectorAll('.intro-question-text')
for (var i = 0; i < textCopy.length; i++) {
  var text = textCopy[i].innerHTML.repeat(5)
  textCopy[i].insertAdjacentHTML('beforeend', text)
}

var WIN_H,
    WIN_W,
    qFrame = [];

var questions = document.querySelectorAll('.intro-question');
var scrollRequest;
var qScrollPositions = [];
var passiveRepeaters = [];
var repeater;

function initIntroScript() {
  Array.prototype.map.call(questions, function(q, i) {
    addImageHover(i);
  })
  window.addEventListener('resize', resizeHandler);
  resizeHandler();
}

function addImageHover(i) {
  qFrame[i] = 0;
  qScrollPositions[i] = Math.floor(Math.random() * -200);
  questions[i].querySelector('.intro-question-text').style.transform = 'translate3d(' + qScrollPositions[i] + 'px,0,0)';
  questions[i].addEventListener('mouseenter', function() {
    //console.log("mouseenter -> " + i);
    clearInterval(passiveRepeaters[i]);
    repeater = setInterval(function() {
      scrollQuestionText(i);
    }, 10);
  });
  
  questions[i].addEventListener('mouseleave', function() {
    //console.log("mouseleave -> " + i);
    clearInterval(repeater);
    passiveRepeaters[i] = setInterval(function() {
      scrollQuestionText(i);
    }, 20);
  });
  
  passiveRepeaters[i] = setInterval(function() {
  	scrollQuestionText(i);
  }, 20);
}

function scrollQuestionText(i) {
  var shift = Math.floor(4 + WIN_W/800) * Math.min(0.2, qFrame[i] / 20);
  cancelAnimationFrame(scrollRequest);
  var el_text = questions[i].querySelector('.intro-question-text');
  qScrollPositions[i] = qScrollPositions[i] - shift;
  if (qScrollPositions[i] < -el_text.clientWidth / 2 - 5) {
    qScrollPositions[i] = 0;
  }
  el_text.style.transform = 'translate3d(' + qScrollPositions[i] + 'px,0,0)'
  qFrame[i]++;
}

initIntroScript();

function resizeHandler() { // NEEDS TO NOT BREAK ON RESIZE
  WIN_W = window.innerWidth;
  WIN_H = window.innerHeight;
}
body {
  font-family: sans-serif;
  font-size:4rem;
}
.intro-question {
    position: relative;
    color: #000000;
    cursor: pointer;
    transition: .3s;
    white-space: nowrap;
    padding: 0;
    backface-visibility: hidden;
    will-change: transform, color, background;
    flex-shrink: 2;
    /* opacity: 0; */
    transition: opacity .5s, transform 1s ease-out;
    z-index: 2;
}
.intro-question-text {
    backface-visibility: hidden;
    will-change: transform;
    position: relative;
    display: inline-block;
    transition: .5s opacity;
}
<div class="intro-questions">
  <div class="intro-question">
    <div class="intro-question-text white">
      Testing content in here
    </div>
  </div>
  <div class="intro-question">
    <div class="intro-question-text white">
      Content testing
    </div>
  </div>
  <div class="intro-question">
    <div class="intro-question-text white">
      Content stackoverflow please
    </div>
  </div>      
</div>

edit

You can increase the framerate by reducing the interval between the function calls, for example

  questions[i].addEventListener('mouseenter', function() {
    //console.log("mouseenter -> " + i);
    clearInterval(passiveRepeaters[i]);
    repeater = setInterval(function() {
      scrollQuestionText(i);
    }, 10);
  });

  questions[i].addEventListener('mouseleave', function() {
    //console.log("mouseleave -> " + i);
    clearInterval(repeater);
    passiveRepeaters[i] = setInterval(function() {
      scrollQuestionText(i);
    }, 20);
  });

  passiveRepeaters[i] = setInterval(function() {
    scrollQuestionText(i);
  }, 20);

if you do this and don't want the scrolling to speed up you can decrease the step size like this

var shift = Math.floor(4 + WIN_W/800) * Math.min(0.2, qFrame[i] / 10);

Upvotes: 1

Related Questions