Reputation: 35
I'm trying to draw multiple images to a HTML Canvas element using Javascript. Images are stored as URL's that are then assigned to an src of a javascript image object. The problem is that the images need to be loaded in a particular order. Here is my code so far:
var canvas = document.getElementById("render");
var context = canvas.getContext("2d");
var src = ["image.png","image.png","image.png","image.png"];
var image = [new Image,new Image,new Image,new Image,];
for (var i =0;i<image.length;i++) {
image[i].onload = function() {
context.drawImage(image[i],0,0,canvas.width,canvas.height);
}
image[i].src=src[i];
}
I believe the issue is with the image.onload function, as it is waiting for the images to load and images added later have a chance to load before a previous one. I am however unsure.
pure js is preferred, but not mandatory.
Upvotes: 2
Views: 2338
Reputation: 26899
You need to decouple the load
listener from drawing. Right now, you are immediately drawing as soon as an image loads. Wrap loading your images in a Promise
and use Promise.all()
. This will allow you to load all the images in whatever order they can be, but presented back to you in the same order you specified.
/**
* Promisify loading an image
* @param {String} imagePath The web location of the image
* @returns {Promise} A Promise that will resolve to an Image
*/
function loadImage(imagePath) {
return new Promise((resolve, reject) => {
let image = new Image();
image.addEventListener("load", () => {
resolve(image);
});
image.addEventListener("error", (err) => {
reject(err);
});
image.src = imagePath;
});
}
var canvas = document.getElementById("render"),
context = canvas.getContext("2d"),
imageSources = ["image.png", "image.png", "image.png", "image.png"];
Promise
.all(imageSources.map(i => loadImage(i)))
.then((images) => {
images.forEach((image) => {
context.drawImage(image, 0, 0, canvas.width, canvas.height);
});
}).catch((err) => {
console.error(err);
});
Upvotes: 7