Ellysson Miike
Ellysson Miike

Reputation: 133

JavaScript: How to load images sequentially

Sorry about my English, this is not my native language.

I'm trying to compress multiple images from a input file. But when I tried to put the

img.onload = function() {}

inside the for loop that contains the sequence of files, the results of the append are totally out of order.

Load sequence out of order

I need the images in sequence because I am mounting a PDF with the images, bus number, and photo date.

The original images are too big, 3MB+. And the resultant .pdf file is 62MB. It's unavailable.

var filesInput = $("#file"); filesInput.on("change", function(e) {

$("#divImagesFrame").show();

/* Manipulação das fotos */ 
var files = e.target.files;
var result = $("#divImagesFrame");
var filesLength = this.files.length;

var page = 1;
var count = 6;

$("#blur, #pageName").html($("#txtCliente").val());

result.append("<div class='pageTitle'><div class='pageBox'>" + page + "</div><span>" + $("#txtCliente").val() + "<span class='localName'>" + $("#txtCampanha").val() + "</span></span></div>");

for (let i = 0; i < this.files.length; i++) {

    qtdFotos++;
    let url = URL.createObjectURL(this.files[i]);
    let img =  new Image();
    img.src = url;

    console.log("ID outside img.load: " + i);

    img.onload = function(){

    console.log("ID inside img.load: " + i);

    var busNumber = files[i].name.toString().split(".")[0]; 
        var dataFoto = files[i].lastModified;
        var d = new Date(dataFoto);
        d.toLocaleString(); 

    var canvas = document.createElement('canvas');
    canvas.width = 460;
    canvas.height = 360;
    ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0,0, canvas.width, canvas.height);

    var imageFile = canvas.toDataURL("image/JPEG", 1.0);

    /* In this result.append, if I put the image source = img.src the order of images stay ok, but the size is much larger */
    result.append("<div class='imageFrame' style='width:460px; border-radius:10px; height:360px; float:left; margin:14.01px 20px; box-shadow:1px 1px 3px 0.8px #999;'>" +
            "<div style='float:left;border-radius:10px 10px 0 0; background:linear-gradient(-90deg,#105e86,#125e86); display:block; width:450px; height:40px; font-weight:550; font-size:23px; line-height:40px; padding-left:10px; color:#FFF;'>" + busNumber + "<span style='font-size:18px; float:right; margin-right:20px;'>" + d.toLocaleDateString() + "</span></div>" +
            "<img width='460px' height='320px' style='border-radius:0 0 10px 10px; margin-bottom:5px;' src='" + imageFile + "'/></div>");

    }


}

sammiCreateBook();
});

Here is how it has to be:

I want the result like this

And here is the result of img.load, totally out of order.

Result of img.load

I hope can you help me, thank you very much.

Problem solved

Hi guys. Thank you. The problem has been solved using javascript promises to verify if each function has been completed. Thanks again!

Upvotes: 1

Views: 1225

Answers (1)

jakub_jo
jakub_jo

Reputation: 1634

  1. Store the image's URLs in an array
  2. Define a function which executes your loading behaviour (the block inside your for loop)
    • At the beginning of your function you need to take the first URL from that array and remove it
    • At the end of your function body you need to invoke the function again.
  3. Invoke the function.

Here's an example:

var images = [
    '1.jpg',
    '2.jpg',
    '3.jpg',
];

var loadImage = function() {
    if (!images.length) {
        // Will be executed when all images are loaded
        return;
    }

    var image = images.shift();

    console.log('loading image ' + image);

    // Your for-loop logic here

    ...

    img.onload = function() {
        console.log('image loaded ' + image);
        // Your onload logic here ...

        // -> important!
        loadImage();
    };
}

loadImage();

Upvotes: 1

Related Questions