Test if all images are loaded
Asked Answered
S

3

5

Here is my attempt at the ability to test if all images are loaded:

for (var i = 0; i < imgCount; i ++) {
    loadArr[i] = false
    imgArr[i] = new Image()
    imgArr[i].src='img'+i+'.png'
    imgArr[i].onload = function() {
        loadArr[i] = true //but wait! At the end of
                          //the loop, i is imgCount
                          //so this doesn't work.
    }
}

The problem is that once the loop is done, the variable i is imgCount. That means all the other "loaded" flags never get set to true when their images are loaded.

Is there some way to add a "loaded" property to an image, or is there some workaround to this problem?

Sinter answered 23/3, 2013 at 13:31 Comment(0)
D
7

You need to define the onload function using a closure:

for (var i = 0; i < imgCount; i ++) {
    loadArr[i] = false
    imgArr[i] = new Image()
    imgArr[i].src='img'+i+'.png'
    imgArr[i].onload = (function(i){
        return function(){ loadArr[i] = true }
    })(i);
}

Here's a jsFiddle which demonstrates this working in a similar scenario.

Also, note that the solution you've currently selected as the answer doesn't actually work:

imgArr[i].onload = (function() {
        loadArr[i] = true;
    })();

This function is evaluated immediately. This means that in the loop, each element of the loadArr is set to true as is the onload event. That code is functionally identical to:

imgArr[i].onload = loadArr[i] = true;
Daradarach answered 23/3, 2013 at 13:37 Comment(2)
Thanks, this is the easiest and most working answer. (can accept in 2 mins)Sinter
Wait, actually it doesn't work (j is set to the last index)Sinter
C
1

You must pass the index value to anonymous function like this,

for (var i = 0; i < imgCount; i++) {
    loadArr[i] = false
    imgArr[i] = new Image()
    imgArr[i].src = 'img' + i + '.png'
    imgArr[i].onload = function (index) {
        return function () {
            loadArr[index] = true //but wait! At the end of
            //the loop, i is imgCount
            //so this doesn't work.
        };
    }(i);
}
Cordelia answered 23/3, 2013 at 13:40 Comment(1)
I think you may have meant: (function(i){ imgArr[i].onload = function(){...}; })(i);Bound
S
-1

This is why closures were made! Your loop runs almost instantly, and it ends long before the first image is loaded. So i==imgCount right away, "skipping" all other values. Closures can avoid this and affect each value of i to a distinct image.

However in your case, I would indeed add a "loaded" attribute to each image.

// Construct your image array
for (var i = 0; i < imgCount; i++) {
    imgArr[i] = new Image();
    imgArr[i].src='img'+i+'.png';
}

//Then iterate over the array, adding a 'loaded' attribute when it occurs
imgArr.each(function(){
    $(this).onload(function() {
        $(this).attr('loaded','true');
    });
}
Stephniestepladder answered 23/3, 2013 at 13:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.