2016-01-01 9 views
6

я получил следующее сообщение об ошибке «CanvasRenderingContext2D»:Не удалось выполнить «DrawImage» на

Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap)'

я увидел ссылку на ту же ошибку здесь, но реализация отличается от мин. Это игра, и она отображает некоторые изображения, но все же дает эту ошибку. Вот мой код:

Это линия, где хром состояния ошибка:

for (row = 0; row < numRows; row++) { 
    for (col = 0; col < numCols; col++) { 
     /* The drawImage function of the canvas' context element 
     * requires 3 parameters: the image to draw, the x coordinate 
     * to start drawing and the y coordinate to start drawing. 
     * We're using our Resources helpers to refer to our images 
     * so that we get the benefits of caching these images, since 
     * we're using them over and over. 
     */ 
     ctx.drawImage(resources.get(rowImages[row]), col * 101, row * 83); 
     } 
} 

Это ctx.drawImage(resources.get(rowImages[row]), col * 101, row * 83).

Это полная функция render(). Изображения содержатся в следующем массиве:

function render() { 
     /* This array holds the relative URL to the image used 
     * for that particular row of the game level. 
     */ 
     var rowImages = [ 
       'images/water-block.png', // Top row is water 
       'images/stone-block.png', // Row 1 of 3 of stone 
       'images/stone-block.png', // Row 2 of 3 of stone 
       'images/stone-block.png', // Row 3 of 3 of stone 
       'images/grass-block.png', // Row 1 of 2 of grass 
       'images/grass-block.png' // Row 2 of 2 of grass 
      ], 
      numRows = 6, 
      numCols = 5, 
      row, col; 

     /* Loop through the number of rows and columns we've defined above 
     * and, using the rowImages array, draw the correct image for that 
     * portion of the "grid" 
     */ 
     for (row = 0; row < numRows; row++) { 
      for (col = 0; col < numCols; col++) { 
       /* The drawImage function of the canvas' context element 
       * requires 3 parameters: the image to draw, the x coordinate 
       * to start drawing and the y coordinate to start drawing. 
       * We're using our Resources helpers to refer to our images 
       * so that we get the benefits of caching these images, since 
       * we're using them over and over. 
       */ 
       ctx.drawImage(resources.get(rowImages[row]), col * 101, row * 83); 
      } 
      } 


     renderEntities(); 
    } //END RENDER 

ресурсы представляют собой отдельный файл resources.js, который создает кэш для изображений, код следует в случае, если это помогает:

(function() { 
    var resourceCache = {}; 
    var loading = []; 
    var readyCallbacks = []; 

    /* This is the publicly accessible image loading function. It accepts 
    * an array of strings pointing to image files or a string for a single 
    * image. It will then call our private image loading function accordingly. 
    */ 
    function load(urlOrArr) { 
     if(urlOrArr instanceof Array) { 
      /* If the developer passed in an array of images 
      * loop through each value and call our image 
      * loader on that image file 
      */ 
      urlOrArr.forEach(function(url) { 
       _load(url); 
      }); 
     } else { 
      /* The developer did not pass an array to this function, 
      * assume the value is a string and call our image loader 
      * directly. 
      */ 
      _load(urlOrArr); 
     } 
    } 

    /* This is our private image loader function, it is 
    * called by the public image loader function. 
    */ 
    function _load(url) { 
     if(resourceCache[url]) { 
      /* If this URL has been previously loaded it will exist within 
      * our resourceCache array. Just return that image rather than 
      * re-loading the image. 
      */ 
      return resourceCache[url]; 
     } else { 
      /* This URL has not been previously loaded and is not present 
      * within our cache; we'll need to load this image. 
      */ 
      var img = new Image(); 
      img.src = url; 
      img.onload = function() { 
       /* Once our image has properly loaded, add it to our cache 
       * so that we can simply return this image if the developer 
       * attempts to load this file in the future. 
       */ 
       resourceCache[url] = img; 

       /* Once the image is actually loaded and properly cached, 
       * call all of the onReady() callbacks we have defined. 
       */ 
       if(isReady()) { 
        readyCallbacks.forEach(function(func) { func(); }); 
       } 
      }; 

      /* Set the initial cache value to false, this will change when 
      * the image's onload event handler is called. Finally, point 
      * the images src attribute to the passed in URL. 
      */ 
      resourceCache[url] = false; 

     } 
    } 

     function get(url) { 
     return resourceCache[url]; 
    } 

    /* This function determines if all of the images that have been requested 
    * for loading have in fact been completly loaded. 
    */ 
    function isReady() { 
     var ready = true; 
     for(var k in resourceCache) { 
      if(resourceCache.hasOwnProperty(k) && 
       !resourceCache[k]) { 
       ready = false; 
      } 
     } 
     return ready; 
    } 

    /* This function will add a function to the callback stack that is called 
    * when all requested images are properly loaded. 
    */ 
    function onReady(func) { 
     readyCallbacks.push(func); 
    } 

    /* This object defines the publicly accessible functions available to 
    * developers by creating a global Resources object. 
    */ 
    window.resources = { 
     load: load, 
     get: get, 
     onReady: onReady, 
     isReady: isReady 
    }; 
})(); 

Chrome также перечислены два других секции при той же ошибке:

var main = function() { 
    var now = Date.now(); 
    var delta = now - then; 

    update(delta/1000); 
    render(); 

    then = now; 

    //Request to do this again ASAP 
    requestAnimationFrame(main); 
} 

Ошибка на рендер-рендере();

и на последней строке моего файла, который вызывает основной() следующим образом:

// Let's play this game! 
var then = Date.now(); 
reset(); 
main(); 
+1

вы никогда не загружаете изображения, поэтому 'resources.get (rowImages [row])' ничего не может вернуть, поэтому 'drawImage' жалуется. – Kaiido

+0

Я перемещаю некоторый код и загружаю изображения сначала, чтобы это помогло. Спасибо – Janice

ответ

2

У вас есть груз, onready, механизм обратного вызова выглядит.

Так что я хотел бы сделать в качестве основной функции, чтобы начать все:

assets = ['images/water-block.png', 
      'images/stone-block.png', 
      'images/grass-block.png' 
     ]; 
var then = Date.now(); 
reset(); 
resources.onReady(main); 
resources.load(assets); 

даже если resources.get() будет нести на загрузке изображения, то есть асинхронный по своей природе, вы бы ошибку в любом случае, потому что DrawImage ожидать, что ресурс, который не должен быть загружен, а затем нарисован.

+0

хорошо вы знаете ресурс, который показывает синтаксис для этого асинхронно? Спасибо – Janice

+0

Вы пытались адаптировать мой псевдокод? Я написал это, прочитав ресурсы библиотеки, которые вы разместили. – AndreaBogazzi

+0

yes AndreaBogazzi У меня есть аналогичная реализация сейчас, не совсем в этом порядке, но странно, что я могу видеть все мои изображения в Internet Explorer, но в chrome я вижу только фоновые изображения. Я всегда думал, что Chrome - превосходный браузер. Ошибка, которую я получаю сейчас: Uncaught ReferenceError: враг не определен. Вот фрагмент кода из области, где я определил врага. – Janice

Смежные вопросы