lharby
lharby

Reputation: 3265

Cycle through list of images and display one at random for a short flash

I have the following html structure:

<ul class="posts">
    <li><img src="https://64.media.tumblr.com/1ff0b6435eaf4f2179e06cfbd9fca583/8fb2fa7b9e4b2d56-1f/s1280x1920/e1a986dea1f99a0cd9dcc7e672bb4a76254df4c4.jpg" class="hidden"></li>
    <li><img src="https://64.media.tumblr.com/70ec82e83c3c5835b10aec4927e253b8/8fb2fa7b9e4b2d56-d0/s540x810/c51483723f355f77a3ae6a17fe19da6525662b46.jpg" class="hidden"></li>
    <li><img src="https://64.media.tumblr.com/7d2f63f029ba23c1e4a6fe28fd6f52d7/8fb2fa7b9e4b2d56-80/s540x810/e6465ab8578c263f62075a2740b763822cbec270.jpg" class="hidden"></li>
    ...
</ul>

Setting the items with css:

.posts img {
    width: 100%;
    position: absolute;
}

.hidden {
    display: none;
}

.block {
    display: block;
}

This is my JS/jQuery:

const blockClass = 'block';
const hiddenClass = 'hidden';

function setRandomImage() {
    const randomIndex = (parseInt(Math.random() * $('.posts li').length));
    $('.posts img').removeClass(blockClass).addClass(hiddenClass); // remove block class and add hidden class from all elems. 
    sleep(2000);
    $(`.posts li:eq(${randomIndex}) img`).addClass(blockClass); // add block class to random item. 
    sleep(4000);
    $(`.posts li:eq(${randomIndex}) img`).removeClass(blockClass).addClass(hiddenClass); // remove block class and add hidden class to random item
    sleep(3000); // testing sleep function for 3s
}

setInterval(function () {
    setRandomImage();
}, 2000);

function sleep(milliseconds) {
    const date = Date.now();
    let currentDate = null;
    do {
        currentDate = Date.now();
    } while (currentDate - date < milliseconds);
}

The concept is to default all the images to be hidden. Pick a random index from the array of images, add the display block class to it, and then pause for an interval (I want the image to flash up very briefly) it should then be hidden again.

The pausing should be achieved using the sleep function. This seems to work if I just add in some console logs, and different sleep intervals, the log will not appear until after the interval.

Also if I debug the js, I can actually see that the image properties are being set properly. But once it is running in the browser the items are never visible. I am not sure if it is a performance issue or some quirk of jQuerys. I only want them to flash up like a strobe effect, but I have tried setting longer durations with the sleep function to see if that has any effect.

EDIT

If this is linked to performance, I would like to know a better way of implementing it, but as far as I can see it should be pretty low level.

JSFIDDLE

Upvotes: 0

Views: 268

Answers (1)

Louys Patrice Bessette
Louys Patrice Bessette

Reputation: 33933

Your sleep function is a browser killer!

It squarely blocks all JS execution by keeping it inside a while loop for a couple seconds (which is way to long), repetitively. So if you have a button on the website, the click event will not respond. Nothing will, in fact. Put simply, that is an horrible idea.

To achieve the effect you want, just have an interval to trigger a CSS @keyframes animation for the brief flash up effect.

Here is all you need:

function setRandomImage() {
  
  const randomIndex = parseInt(Math.random() * $(".posts li").length);
  
  // remove block class from all elems.
  $(".posts img").removeClass("block");
  
  // add block class to random item.
  $(`.posts li:eq(${randomIndex}) img`).addClass("block");

}

// The interval of 9 seconds
setInterval(function () {
  setRandomImage();
}, 9000);
setRandomImage();
.posts img {
  width: 100%;
  position: absolute;
  display: none;  /* The default hide is here */
}

.block {
  display: block !important;
  opacity: 0;
  animation: flashImg 2s;  /* That is the "flash" duration */
}

@keyframes flashImg {  /* And that is the flash animation */
  0% {opacity: 0;}
  10% {opacity: 1;}  /* play with the percentages to smooten the apparition */
  90% {opacity: 1;}
  100% {opacity: 0;}
}

li{
  list-style: none;  /* Removes li bullets */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="posts">
    <li><img src="https://64.media.tumblr.com/1ff0b6435eaf4f2179e06cfbd9fca583/8fb2fa7b9e4b2d56-1f/s1280x1920/e1a986dea1f99a0cd9dcc7e672bb4a76254df4c4.jpg"></li>
    <li><img src="https://64.media.tumblr.com/70ec82e83c3c5835b10aec4927e253b8/8fb2fa7b9e4b2d56-d0/s540x810/c51483723f355f77a3ae6a17fe19da6525662b46.jpg"></li>
    <li><img src="https://64.media.tumblr.com/7d2f63f029ba23c1e4a6fe28fd6f52d7/8fb2fa7b9e4b2d56-80/s540x810/e6465ab8578c263f62075a2740b763822cbec270.jpg"></li>
</ul>

Upvotes: 1

Related Questions