Jan Castle Jan Castle - 3 months ago 15
CSS Question

jQuery queue does not work

What I'm trying to accomplish:

Let multiple cards in the queue slide in after each other on document ready and for the elements that arent visible on page load I want the same for them on scroll.

The problem:

All elements slide in at the same time. (Even though I'm using an each loop)




Example:



$( document ).ready(function(){
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});

$(window).scroll(function() {
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});

function readyAnimation (animationClass) {

var resetAnimationClass = "reset-animations";

$("." + animationClass).each(function() {

var elem = $(this);

if(elem.hasClass(animationClass)) {

if (isScrolledIntoView(elem) == true ) {
elem.delay(500).queue(function(){
elem.addClass(resetAnimationClass).dequeue();
})
}
}
});
}

function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();

var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();

return (docViewBottom >= elemTop && docViewTop <= elemBottom);
}

.card {
float: left;
width: 25%;
background: $brand;
height: 300px;
border: 1px solid white;
background: #333;
}

.slide-in-cards {
transform: translate3d(0, 50px, 0);
opacity: 0;
transition: transform 600ms cubic-bezier(0.52, 1.61, 0.56, 1), opacity 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
will-change: transform;
}

.reset-animations {
transform: translate3d(0, 0, 0);
opacity: 1;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
...








What I did so far:

My markup looks like this:

<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
...


And I want them so slide in after each other by using something like this:

function readyAnimation (animationClass) {

var resetAnimationClass = "reset-animations";

$("." + animationClass).each(function() {

var elem = $(this);

if(elem.hasClass(animationClass)) {

if (isScrolledIntoView(elem) == true ) {
elem.delay(500).queue(function(){
elem.addClass(resetAnimationClass).dequeue();
})
}
}
});
}


I add a class that resets their css to normal, the elements have the transition property

This function is called like this

$( document ).ready(function(){
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});

$(window).scroll(function() {
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});


The isScrolledIntoView function is from stackoverflow and looks like this

function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();

var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();

return (docViewBottom >= elemTop && docViewTop <= elemBottom);
}

Answer

Some thoughts:

  1. Remember that animations on separate elements run in parallel; each element has its own animation queues.

  2. You've said that you had an issue when more elements come into view. That's because you weren't eliminating them from the selection of elements to animate.

  3. Your if (elem.hasClass(animationClass)) check is unnecessary, as you've selected only elements that have that class.

So (see *** commented lines):

function readyAnimation(animationClass) {

  var resetAnimationClass = "reset-animations";

  var counter = 0;                                                          // ***
  $("." + animationClass).not("." + resetAnimationClass).each(function() {  // ***

    var elem = $(this);

    // *** No `if (elem.hasClass(animationClass))` here, we know it does
    if (isScrolledIntoView(elem) == true) {
      ++counter;                                                            // ***
      elem.delay(500 * counter).queue(function() {                          // ***
        elem.addClass(resetAnimationClass).dequeue();
      })
    }
  });
}

$(document).ready(function() {
  //readyAnimation("slide-in-left");
  readyAnimation("slide-in-cards");
});

$(window).scroll(function() {
  //readyAnimation("slide-in-left");
  readyAnimation("slide-in-cards");
});

function readyAnimation(animationClass) {

  var resetAnimationClass = "reset-animations";

  var counter = 0;
  $("." + animationClass).not("." + resetAnimationClass).each(function() {

    var elem = $(this);

    if (isScrolledIntoView(elem) == true) {
      ++counter;
      elem.delay(500 * counter).queue(function() {
        elem.addClass(resetAnimationClass).dequeue();
      })
    }
  });
}

function isScrolledIntoView(elem) {
  var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  var elemTop = $(elem).offset().top;
  var elemBottom = elemTop + $(elem).height();

  return (docViewBottom >= elemTop && docViewTop <= elemBottom);
}
.card {
  float: left;
  width: 25%;
  background: $brand;
  height: 300px;
  border: 1px solid white;
  background: #333;
}
.slide-in-cards {
  transform: translate3d(0, 50px, 0);
  opacity: 0;
  transition: transform 600ms cubic-bezier(0.52, 1.61, 0.56, 1), opacity 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}
.reset-animations {
  transform: translate3d(0, 0, 0);
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
<div class="card slide-in-cards">
  <img />
</div>
...