user7898237
user7898237

Reputation:

Why is javascript looping through elements but executing jQuery function on all of them simultaneously?

I have a text "HELLO" and I want to loop through every letter and animate it so it fades in and out.Here's my code.

EDIT: I put the answer in the snippet to see it in action.

Code:

$(document).ready(function() {
  var $letters = $('p[id^="letter-"');
  $letters.each(function(index) {
    $(this).css({
      'animation': 'pulse 500ms ' + index * 500 + 'ms' + ' linear'
    })
  });
});
html,
body {
  font-size: 45px;
}

p {
  position: absolute;
  left: 400px;
  top: 100px;
  color: rgba(0, 0, 0, 0);
}

@keyframes pulse {
  0% {
    color: rgba(0, 0, 0, 0);
  }
  25% {
    color: rgba(0, 0, 0, 0.5);
  }
  50% {
    color: rgba(0, 0, 0, 1);
  }
  75% {
    color: rgba(0, 0, 0, 0.5);
  }
  100% {
    color: rgba(0, 0, 0, 0);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id='letter-0'>H</p>
<p id='letter-1'>E</p>
<p id='letter-2'>L</p>
<p id='letter-3'>L</p>
<p id='letter-4'>O</p>

And here's a link to a pen. Instead of doing the animation one letter at a time, it's animating the whole thing at once.How can this be fixed? Shouldn't a loop finish executing all the commands and then move on to the next step? Maybe there's a better approach to this that I don't know of?

Upvotes: 1

Views: 51

Answers (2)

Brett DeWoody
Brett DeWoody

Reputation: 62871

One thing you should definitely correct is the naming of your ids. A single number is not a valid id.

A better option might be to name them something like letter-0, letter-1, etc.

Next, you can use the animation-delay property to offset the start of each animation. We'll use the shorthand animation property. To do this, we'll find each element with an id starting with letter-, then loop through them. For each consecutive letter we'll add the animation, and include an animation delay of 500ms * its position index in the string. For example, the first letter (index 0) will have an animation delay of 0ms. The second letter (index 1) will have an animation delay of 500ms, and so on.

$(document).ready(function() {
  var $letters = $('p[id^="letter-"');
  $letters.each(function(index) {
    $(this).css({
      'animation': 'pulse 500ms ' + index * 500 + 'ms' + ' linear'
    })
  });
});
html,
body {
  font-size: 45px;
}

p {
  position: absolute;
  left: 400px;
  top: 100px;
  color: rgba(0, 0, 0, 0);
}

@keyframes pulse {
  0% {
    color: rgba(0, 0, 0, 0);
  }
  25% {
    color: rgba(0, 0, 0, 0.5);
  }
  50% {
    color: rgba(0, 0, 0, 1);
  }
  75% {
    color: rgba(0, 0, 0, 0.5);
  }
  100% {
    color: rgba(0, 0, 0, 0);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id='letter-0'>H</p>
<p id='letter-1'>E</p>
<p id='letter-2'>L</p>
<p id='letter-3'>L</p>
<p id='letter-4'>O</p>

Upvotes: 0

Paul Abbott
Paul Abbott

Reputation: 7211

Use animation-delay in combination with your loop variable:

$(document).ready(function() {
  for (var i = 0; i < 5; i++) {
    $('#' + i).css({
      'animation': 'pulse 0.5s linear',
      'animation-delay': i + 's'
    })
  }
});
html,
body {
  font-size: 45px;
}

p {
  position: absolute;
  left: 400px;
  top: 100px;
  color: rgba(0, 0, 0, 0);
}

@keyframes pulse {
  0% {
    color: rgba(0, 0, 0, 0);
  }
  25% {
    color: rgba(0, 0, 0, 0.5);
  }
  50% {
    color: rgba(0, 0, 0, 1);
  }
  75% {
    color: rgba(0, 0, 0, 0.5);
  }
  100% {
    color: rgba(0, 0, 0, 0);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id='0'>H</p>
<p id='1'>E</p>
<p id='2'>L</p>
<p id='3'>L</p>
<p id='4'>O</p>

Upvotes: 2

Related Questions