Vincent
Vincent

Reputation: 53

draw image on canvas after load into array

I tried to create an array of Image to be displayed on a canvas, after each image is loaded. No errors, no draw...

    var x=...
var y=...
var canvas = document.getElementById(sCanvasName);
var context = canvas.getContext('2d');

var imageCardObj = [];

//vCards contains the images file names
for (var k=0;k<vCards.length;k++){
    imageCardObj[k] = new Image();

    var func = function(){
            var c = arguments[3];
            try{                
                c.drawImage(arguments[0], arguments[1], arguments[2]);
            }catch(e){
                alert(e.message)
            }
        }

        imageCardObj[k].onload = func(imageCardObj[k], x, y, context);

        imageCardObj[k].src = "res/img/"+vCards[k].trim()+".png";   

        x+=40;
    }

Upvotes: 0

Views: 2219

Answers (2)

user1693593
user1693593

Reputation:

You are calling the func() handler and gives the result to it to the image's onload handler. That won't work so well.. and you cannot pass arguments that way to a handler function.

Try this:

var func = function(){

    // "this" will be the current image in here

    var c = arguments[3];
    try{                
        c.drawImage(this, x, y); // you need to reference x and y
    }catch(e){
        alert(e.message)
    }
}

imageCardObj[k].onload = func;  // only a reference here

If you need different x and y's then you need to maintain those on the side, either in an additional array or use objects to embed the image, its intended x and y and use the url to identify the image in question inside the func() callback.

Also note that load order may vary as the last image loaded could finish before the first one so when you draw the image they may not appear in the same order.

You may want to do this instead:

var files = [url1, url2, url, ...],
    images = [],
    numOfFiles = files.length,
    count = numOfFiles;

// function to load all images in one go
function loadImages() {

    // go through array of file names
    for(var i = 0; i < numOfFiles; i++) {

        // create an image element
        var img = document.createElement('img');

        // use common loader as we need to count files
        img.onload = imageLoaded;
        //img.onerror = ... handle errors too ...
        //img.onabort = ... handle errors too ...

        img.src = files[i];

        // push image onto array in the same order as file names
        images.push(img);
    }
}
function imageLoaded(e) {

    // for each successful load we count down
    count--;
    if (count === 0) draw(); //start when all images are loaded
}

Then you can start the drawing after the images has loaded - the images are now in the same order as the original array:

function draw() {
    for(var i = 0, img; img = images[i++];)
        ctx.drawImage(img, x, y); // or get x and y from an array
}

Hope this helps!

Upvotes: 1

Vincent
Vincent

Reputation: 53

This is the final (working) version

var x=...
var y=...
var canvas = document.getElementById(sCanvasName);
var context = canvas.getContext('2d');
var imageCardObj = [];

    for (var k=0;k<vCards.length;k++){

        imageCardObj[k] = new Image();
         imageCardObj[k].xxx=x;

        var func = function(){              

            try{                
                context.drawImage(this, this.xxx, yStreet);                 
            }catch(e){
                alert(e.message)
            }
        }

        imageCardObj[k].onload = func;      
        imageCardObj[k].src = 'res/img/'+vCards[k].trim()+".png";   
        x +=40;         

Upvotes: 0

Related Questions