1

I've been trying since yesterday to do something a bit tricky (I guess).

I'm trying to do exactly what happens here: https://tympanus.net/Development/AnimatedResponsiveImageGrid/index2.html but this script is 8 years old and can't work with newer jQuery, anyway I wanted to redo it by myself.

What I need (well, what the marketing want me to do): Having a 6 images grid which randomly crossfade to another image, but one by one. They should never repeat themselves.

So far I've done this, but all the crossfade are made 6 by 6. I want to do it, one by one, in a random order.

HTML

<div class="img-bank">
  <img style="display:none" src="https://picsum.photos/210?image=0" />
  <img style="display:none" src="https://picsum.photos/210?image=11" />
  <img style="display:none" src="https://picsum.photos/210?image=21" />
  <img style="display:none" src="https://picsum.photos/210?image=31" />
  <img style="display:none" src="https://picsum.photos/210?image=41" />
  <img style="display:none" src="https://picsum.photos/210?image=51" />
  <img style="display:none" src="https://picsum.photos/210?image=61" />
  <img style="display:none" src="https://picsum.photos/210?image=71" />
  <img style="display:none" src="https://picsum.photos/210?image=81" />
  <img style="display:none" src="https://picsum.photos/210?image=91" />
  <img style="display:none" src="https://picsum.photos/210?image=101" />
  <img style="display:none" src="https://picsum.photos/210?image=111" />
  <img style="display:none" src="https://picsum.photos/210?image=121" />
  <img style="display:none" src="https://picsum.photos/210?image=131" />
  <img style="display:none" src="https://picsum.photos/210?image=141" />
  <img style="display:none" src="https://picsum.photos/210?image=151" />
  <img style="display:none" src="https://picsum.photos/210?image=161" />
  <img style="display:none" src="https://picsum.photos/210?image=171" />
  <img style="display:none" src="https://picsum.photos/210?image=181" />
  <img style="display:none" src="https://picsum.photos/210?image=191" />
</div>

<div class="container galery">
  <div class="row">
    <div class="col-4">
      <img class="img-fluid" src="https://placekitten.com/210/210?image=1" />
      <img style="display:none;" class="img-fluid" src="" />
    </div>
    <div class="col-4">
      <img class="img-fluid" src="https://placekitten.com/210/210?image=2" />
      <img style="display:none;" class="img-fluid" src="" />
    </div>
    <div class="col-4">
      <img class="img-fluid" src="https://placekitten.com/210/210?image=3" />
      <img style="display:none;" class="img-fluid" src="" />
    </div>
    <div class="col-4">
      <img class="img-fluid" src="https://placekitten.com/210/210?image=4" />
      <img style="display:none;" class="img-fluid" src="" />
    </div>
    <div class="col-4">
      <img class="img-fluid" src="https://placekitten.com/210/210?image=5" />
      <img style="display:none;" class="img-fluid" src="" />
    </div>
    <div class="col-4">
      <img class="img-fluid" src="https://placekitten.com/210/210?image=6" />
      <img style="display:none;" class="img-fluid" src="" />
    </div>     
  </div>
</div>

JS

$( document ).ready(function() {
  var ids = [];

  function initArray() {
    $(".img-bank img").each(function() {
      ids.push($(this).attr("src"));
    })    
  }

  function randomArray() {
    // copie du tableau d'ids car il va etre modifié
    var tempIds = ids.slice();
    // init du tableau de resultat
    var myIds = [];
    for (var i = 0; i < 6; i++) {
      // Recupere un int random
      var randomId = (Math.floor(Math.random() * tempIds.length) + 1);
      // Recupere la valeur random
      var myId = tempIds[randomId - 1];
      // Ajout de la valeur random au tableau de resultat
      myIds.push(myId);
      // Recupere l'index de la valeur random pour la suppression
      var pos = tempIds.indexOf(myId);
      // Suppression de la valeur choisie pour eviter de retomber dessus
      tempIds.splice(pos, 1);
    }
    return myIds;
  }

  initArray();
  
  function changeSrc() {
    var result = randomArray();
    $(".galery img:hidden").each(function(index) {
      $(this).attr("src", result[index]);   
    });
    $(".galery img").fadeToggle(1500);
  }  
  
  setInterval(function() {
    changeSrc();
  }, 2000);
  
});

LESS

.galery {
  margin-top: 30px;
  .row > div {
    position:relative;
    height: 240px;
    width: 240px;
    img {
      position: absolute;
      top: 0;
      left: 15;
    }    
  }  
}

https://jsfiddle.net/N_3G/ju0comn2/

Can someone help me with this please?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Touk
  • 99
  • 2
  • 9

1 Answers1

1

You can select a cell col-4 at random, then apply the logic to only the 2x img in that cell.

Without changing too much of your existing code, change to:

var cells = $(".galery .col-4");
var randomId = (Math.floor(Math.random() * cells.length));
var cell = cells.eq(randomId);
cell.find("img:hidden").each(function(index) {
  $(this).attr("src", result[index]);   
});
cell.find("img").fadeToggle(1500);

Updated fiddle: https://jsfiddle.net/ju0comn2/1/

Due to the nature of Math.random() you will notice it runs the same images in the same order - seed the random. You'll also get the same image replacing with the same image.


For a rudimentary fix for duplicated images, check if any of the visible images have the same src as the new src:

var result = randomArray();
var cells = $(".galery .col-4");    
var randomId = (Math.floor(Math.random() * cells.length));
var newsrc = result[0];

if ($(".galery img[src='" + newsrc + "']:visible").length > 0) {
   changeSrc();
}
else {
  var cell = cells.eq(randomId);
  cell.find("img:hidden").each(function(index) {
    $(this).attr("src", result[index]);   
  });
  cell.find("img").fadeToggle(1500);
}

This could be handled with a while loop to keep getting randomIds, but as long as you have more images than panels, the recursive call is unlikely to stack overflow.

Updated fiddle: https://jsfiddle.net/ju0comn2/2/

freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • See also: https://stackoverflow.com/questions/5927284/how-can-i-make-setinterval-also-work-when-a-tab-is-inactive-in-chrome – freedomn-m Oct 31 '18 at 14:08
  • Thank you ! It's stunning to be stuck 2 days and then read the solution so quickly ! I'm a bit sad to haven't found the solution myself but that's how you learn and I'm still a beginner. I'll read your code many times to understand it all, thank you it's really exactly what I was looking for. – Touk Oct 31 '18 at 14:32
  • Hum, reading it all, do I still need the randomArray function to store 6 random images since at line 37 you always take the first element of this array ? Does it means that I just need to get a random src from my .img-bank ? – Touk Oct 31 '18 at 14:42
  • You are correct, your `randomArray()` function can be reduced to a single random call now. I left it in as I wanted to limit the changes to just the part that changes the images (as stated "without changing too much of your existing code"). – freedomn-m Oct 31 '18 at 15:05
  • That does assume that you only have 2 images per cell (1 hidden), if you have more, then you'll need the array to match the number of images (eg you could change it so a whole row changes at once) – freedomn-m Oct 31 '18 at 15:06