AKFourSeven
AKFourSeven

Reputation: 1325

loop to create multiple canvas with multiple images not always displaying images

this may be an odd one to explain: I want to create dynamically a collection of canvas that will have a single image in it. And this displays (after much hassle and getting rid of the onload event) but when I try to refresh the page I sometimees get nothing on the screen. And when I was using thee onload event (to wait until the image is loaded) it would not display or display everything in the last canvas.

Here is a snippet of the code:

var sources = []//the array that contains the images
var divCanvas = document.getElementById('showcase-wrapper')
for(var i=0; i<sources.length; i++){
    img =  new Image()
    img.src = sources[i]
    canvas  = document.createElement('canvas')
    $(canvas).attr('id', i)
    canvas.height=300
    canvas.width=200
    var context = canvas.getContext('2d');
    //onload commented out allows expected display
    //img.onload = function() {
    context.drawImage(img, 0, 0);
    //} 
    divCanvas.appendChild(canvas)
}

I have seen many posts that seemed to look like mine and tried quite a few but to no avail.

Upvotes: 1

Views: 4189

Answers (3)

AKFourSeven
AKFourSeven

Reputation: 1325

I found the fix here:

https://developer.mozilla.org/docs/Web/Guide/HTML/Canvas_tutorial/Using_images#Drawing_images

Apparently they have dropped img.onload to have the function called when the body has finished loaded. Though, I still do not understand why my script or, ellisbben solution was not working.

If anyone as an answer for it, it would be very welcomed...

Upvotes: 1

crazyjoe
crazyjoe

Reputation: 471

I think the issue is that var context is overwritten before the img.onload event is triggered. The img.onload event only has a reference to global scope. This is why only the last image shows up. You need to find the correct context inside the event.

I can't test your code directly, but I think it should be something like this:

var sources = []//the array that contains the images
var divCanvas = document.getElementById('showcase-wrapper')
for(var i=0; i<sources.length; i++){
    img =  new Image();
    img.src = sources[i];
    img.id = i; //Allow img to remember its corresponding canvas/context
    canvas  = document.createElement('canvas');
    $(canvas).attr('id', i);
    canvas.height=300;
    canvas.width=200;
    var context = canvas.getContext('2d');
    divCanvas.appendChild(canvas);

    img.onload = function() {
        //Use the image id to get the correct context
        var canvas = document.getElementById(this.id);
        var context = canvas.getContext('2d');
        context.drawImage(this, 0, 0);
    } 
}

Upvotes: 2

ellisbben
ellisbben

Reputation: 6371

For consistent behavior, you must use onload. If you don't the canvas drawing code may execute before the image is loaded and the desired image will not be drawn.

It might be that the onloads that would draw to the other canvases are not being called because the Images are getting garbage collected before the event can fire.

Try adding

var images = [];

At the start of your code and

  images.push(img);

After the img = new Image() line.

If that doesn't work, try adding those images to the DOM tree-- img.setAttribute('style', 'display: none') first so you don't see them and they don't interfere with the document structure.

Upvotes: 1

Related Questions