Dubstaphone
Dubstaphone

Reputation: 418

How can I create an efficient infinitely looping waving text animation?

This is the effect I am trying to create (JSFiddle):

$('.header h1 span').each(function() { // each letter is contained inside a <span> element
    var that = $(this);
    setTimeout(function() {
        that.animate({
                top: "-10px"
            }, animateTime / 2)
            .animate({
                top: "10px"
            }, animateTime / 2);
    }, that.index() * 100);
});

Result:

dzzpop

It appears to be successful. However, I ran into the problem of it looking like this after switching tabs, then coming back:

dzzpop

In the fiddle above, I've tried to "fix" this by making the animation stop when the tab is unfocused. It's better than when I WASN'T checking for tab unfocusing, but it still has problems. This is the code I'm using to do that:

var running = true;

document.addEventListener('visibilitychange', function(){
    console.log("Running:" + running);
    running = !document.hidden;
    if(!running) clearQueues();
})

If the user spends less than a couple seconds unfocused from the tab, the animation looks like the second GIF again, and I don't see a way to avoid that. I've tried using requestAnimationFrame() but I can't figure out how to make it behave correctly.

So, my question is: how do I prevent the animation from being affected by the tab being unfocused?

Bonus points (figuratively) if you can help me make it more efficient on mobile, too.

Upvotes: 4

Views: 706

Answers (1)

JonSG
JonSG

Reputation: 13152

I'm not sure if this solves the stuttering for you or not. This strategy is similar in concept to what you are doing, but uses CSS animation rather than js.

(function(){
  
  var el = document.querySelectorAll(".wavey")[0];
  var oldText = el.innerText
  var newHtml = "";
  for (var i in el.innerText) { newHtml += ("<span style='animation-delay: " + i/10 + "s;'>" + oldText[i] + "</span>"); }
  el.innerHTML = newHtml;
  
})();
@keyframes wave {
  from { transform: translateY(0); }
  to { transform: translateY(-1em); }
}

h1.wavey { margin-top: 2em; }

h1.wavey span {
  display: inline-block;
  animation-duration: 1s;
  animation-name: wave;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-timing-function: ease-in-out;
}
<h1 class="wavey">Hello World</h1>

Upvotes: 1

Related Questions