Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way (JavaScript or jQuery) to sequentially load images (prevent parallel downloads)

I have a page which contains a dozen of big images:

<div id="gallery">
  <img src="1.png" alt="" />
  <img src="2.png" alt="" />
  ...
</div>

Due to images' size, parallel downloading causes too long delay before anything shows.

Question: how to load images sequentially, so that 2.png only starts loading after 1.png has been fully loaded and displayed?

  • I don't want lazy loading (unless you know of a plugin which will always load images strictly in the same sequence, regardless of the current viewport)

  • This solution:Loading images sequentially doesn't work for me in latest Chrome, Firefox, IE. It will load all images at once, and then show them

  • The plugin suggested in this answer https://stackoverflow.com/a/25774333/525445 is somewhat functional but it makes 2, 3 or sometimes more requests at once, so not doing what it's supposed to

  • Then there's this plugin, also proposed in some answer: http://imagesloaded.desandro.com/ It's meant for something else though - to let you know when all images are loaded, which it does well. So I tried to put it to use like this:

    var $gallery = $("#gallery");
    $gallery.imagesLoaded( function() { $gallery.append(''); console.log("Image loaded"); }); $gallery.append('');

The idea here was - to dynamically add images one by one, on imagesLoaded event. However, it gets triggered only for the first image (although it's dynamically added as well), and for the second it doesn't. So the above code causes both images to show, but only 1 console.log() notification

Any suggestions appreciated.

like image 735
CodeVirtuoso Avatar asked Mar 17 '23 04:03

CodeVirtuoso


1 Answers

Basically you want to start with an empty container. The path to the images would be contained in a Javascript array, and then brought in one after another using a off-screen element loading methodology. Code:

<div id="gallery"></div>
  
<script>
var images = [
    { src: '1.png', alt: 'I am the first image' },
    { src: '2.png', alt: 'Second image' }
];

function loadImageSequentially(imagesArray, appendTo, loadImageAtIndex) {
    if (!loadImageAtIndex) loadImageAtIndex = 0; // assume first loading if not provided.
    if (!imagesArray[loadImageAtIndex]) return;

    var img = new Image();

    // attach listeners first
    img.onload = function() {
        appendTo.appendChild(img);
        loadImageSequentially(imagesArray, appendTo, loadImageAtIndex + 1);
    }
    img.onerror = function() {
        // remove listeners
        img.onload = img.onerror = null;
        img.src = 'error.png'; // if you have a placeholder error png to display, put it here.

        // life goes on...
        appendTo.appendChild(img); 
        loadImageSequentially(imagesArray, appendTo, loadImageAtIndex + 1);     
    }

    // assign attributes, which will start the loading.
    img.src = imagesArray[loadImageAtIndex].src;
    img.alt = imagesArray[loadImageAtIndex].alt;
}

// now run it.
var appendTo = document.getElementById('gallery')
loadImageSequentially(images, appendTo);
</script>

This example can be modularised and made better. But is left at such for the purpose of illustration.

like image 63
Calvintwr Avatar answered Apr 08 '23 23:04

Calvintwr