Reputation: 8792
I am trying to draw a series of images on an HTML5 Canvas . For eg - For the word APPLE , I am trying to put 5 pictures - A.png, B.png, C.png etc in series to display the word . My code is as below:
var x = 100;
var word = "APPLE";
var imageArray = new Array();
for (var i = 0; i < word.length; i++) {
imageArray[i] = new Image();
imageArray[i].onload = function() {
context.drawImage(imageArray[i], x, 25, 70, 70); // canvas context
x += 80;
};
imageArray[i].src = "images/"+word.charAt(i)+".png";
}
I get an Error -
javascript Uncaught TypeError: Type error
Can someone please explain me why is occuring and what is the best way to achieve this ?
Upvotes: 1
Views: 1350
Reputation: 32598
After your loop exits, imageArray
and i
are kept inside the onload functions you created. i
incremented again after your last iteration so it is now pointing to an undefined element in your array. You can use a function to create a new scope:
for (var i = 0; i < word.length; i++) {
imageArray[i] = new Image();
imageArray[i].onload = (function(i){
return function() {
// i in here is now the outer function parameter instead
// of the i in the function that creates the images
context.drawImage(this, x+i*80, 25, 70, 70);
}
})(i);
imageArray[i].src = "images/"+word.charAt(i)+".png";
}
Tharabas answer is generally nicer, however forEach
won't work in IE < 9
Upvotes: 2
Reputation: 3422
There are several possible error sources in you code:
if you want to iterate over every letter in your word, you should stop at the end of the word and not at index 10:
var word = "APPLE"; // has 5 letters
for (var i = 0; i < word.length; i++) {
// ... do your code
}
Within the callback onload = function() ...
you access the imageArray[i]
which is not what you intend to, as the value of i
modifies and at the time it is called, you access the first element behind your desired array. Additionally, you can not rely on each letter being loaded in the correct sequence. You can avoid both of these error, by using forEach
:
var word = "APPLE"; // again, the 5 letter word
// transform the word to an array ['A', 'P', 'P', 'L', 'E']
var letters = word.split('');
letters.forEach(function(letter, index) {
var image = new Image();
image.onload = function() {
context.drawImage(image, x + index * 80, 25, 70, 80);
}
image.src = "images/" + letter + ".png";
})
Upvotes: 3