Benn Benn - 1 year ago 505
Javascript Question

How to delay jQuery Waypoint for each item in order to create staggering effect?

I am trying to delay waypoint for every next item by 0.2s. I tried with set timeout but by the time the first few items load the timeout has already expired.

Fiddle 1

$(function() {

$(".item").each(function(index, element) {
var $this = $(this);

var $delay = $(this).data('delay');
setTimeout(function() {

$this.waypoint(function() {

$(this.element).addClass('show');

}, {
offset: '90%',
});

}, $delay);


});

});


Than I tried adding the delays inside the waypoint but the last items get longer delays since they are not in the view

$(function() {

$(".item").each(function(index, el) {

new Waypoint({
element: el,
handler: function() {
var element = $(this.element),
delay = element.attr('data-delay');
setTimeout(function() {
element.addClass('show');
}, delay);
this.destroy();
},
offset: '90%'
});

});

});


Fiddle 2

any help is appreciated.

Answer Source

In order to create this staggered effect without knowing how many items will be in view and trying to do all the acrobatics described in other answers and comments, you can instead use the waypoint to feed a queue and process items in that queue at your staggered interval. This is true in general, not just for animation and not just for Waypoints.

$(function() {
  var itemQueue = []
  var delay = 200
  var queueTimer

  function processItemQueue () {
    if (queueTimer) return // We're already processing the queue
    queueTimer = window.setInterval(function () {
      if (itemQueue.length) {
        $(itemQueue.shift()).addClass('show');
        processItemQueue()
      } else {
        window.clearInterval(queueTimer)
        queueTimer = null
      }
    }, delay)
  }

  $(".item").waypoint(function () {
    itemQueue.push(this.element)
    processItemQueue()
  }, {
    offset: '90%'
  })
})

Fiddle