简体   繁体   中英

javascript Uncaught TypeError while drawing on HTML5 Canvas

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 ?

There are several possible error sources in you code:

  1. 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 } 
  2. 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"; }) 

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM