Looping with .each with delay in Jquery

2020-03-31 04:24发布

问题:

I am not good at jQuery so I am not sure if my assumptions are corrent.

I am using the isotope plugin, with which I want to insert elements one by one (and not everything at once) with a slight delay so it will also look like it (for the human eye)

to insert an item with isotope I use

$('#container').isotope( 'insert', $item);

so in order to insert one-by-one I am doing

$("#items_are_here").find('.item').each(function( index ) {
     setTimeout(function() {
            $('#container').isotope( 'insert', $(this));
         },3000);
    });

This however seems that the browser waits for something, and then displays them all at once

If I do

  setTimeout(function() {
   $("#items_are_here").find('.item').each(function( index ) {
          $('#container').isotope( 'insert', $(this));

        }); },3000);

everything works, but not one-by-one..

Is this the right way to do this? or am I over-complicating it?

here is fiddle. In it, there are 2 buttosn - insert all - which finds all .item and inserts them. And insert one-by-one which does the proposed way with delay. As you can see, there is no delay.

回答1:

    var $items=$("#items_are_here").find('.item');
    var i=-1;
    var delayed=setinterval(function() {
            if (++i<$items.length) $('#container').isotope( 'insert', $items.eq(i));
            else clearInterval(delayed); 
             },3000);

not tested. or

    var $container=$('#container');     
    $.fn.extend({
      onebyone :function ($ctnr,i) {
           if (!i) i = 0;
           var $o=$(this);
           setTimeOut(function() {
                 $ctnr.isotope( 'insert', $o.eq(i)); 
                 if (++i<$o.length) $o.onebyone(i); 
               },3000);
           return this; 
      }
    $("#items_are_here").find('.item').onebyone($container);


回答2:

Because .each() runs pretty instantaneous for each entry, you'll end up with a bunch of timeouts which are more or less the same. So after about 3 seconds, all timeouts expire and the items are added.

To prevent this, you'll to make the timeout dependent on the index of the item. So item 0 will be inserted after 3 seconds, item 1 will be inserted after 6 seconds, etc.

$("#items_are_here").find('.item').each(function( index ) {
  var item = $(this);
  setTimeout(function() {
    $('#container').isotope('insert', item);
  },3000 * (index + 1));
});


回答3:

$("#items_are_here").find('.item').each(function( index ) {
     setTimeout(function() {
            $('#container').isotope( 'insert', $(this));
         },3000);
    });

in the above context, $(this) is the window object, because it's inside setTimeout.

Modify your code to and try:

$("#items_are_here").find('.item').each(function( index ) {
     var item = $(this);
     setTimeout(function(index) {
            $("#container").isotope( 'insert', $(this))
     },index*3000);
    });


回答4:

$("#items_are_here").find('.item').each(function( index ) {
     var item = $(this);
     setTimeout(function(i) {
            $('#container').isotope( 'insert', i );
         },3000);
    });


回答5:

little late but my workaround was: hardcode a class to item like to_animate

the css:

.item.to_animate { opacity:0; display:block; } @keyframes TransitionClass{ 0% { opacity: 0;transform: scale(1.2); } 100% { opacity: 1;transform: scale(1); } } .animatefinish.TransitionClass{ animation-name: umScaleIn; animation-timing-function: cubic-bezier(0.19,1,.22,1); } .animatefinish.TransitionClass{ animation-duration: .8s; }

the snipped for isotope

    `$('#container').isotope( 'appended', $(el) ).after(function() {

      $('.item.to_animate').each(function(i) {
      var el = $(this);

              setTimeout(function() {

              el.addClass('TransitionClass animatefinish');

                  el.removeClass('to_animate')

              }, i * 200);

      });

    });`