次のエラーが発生しました。
Uncaught TypeError: 'CanvasRenderingContext2D'で 'drawImage'の実行に失敗しました:指定された値はタイプ '(HTMLImageElementまたはHTMLVideoElementまたはHTMLCanvasElementまたはImageBitmap)'ではありません
ここで同じエラーへの参照を見ましたが、実装は地雷とは異なりました。これはゲームであり、いくつかの画像をレンダリングしますが、それでもこのエラーが発生します。これが私のコードです:
これは、chromeがエラーを示している行です。
_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は、同じエラーの下に他の2つのセクションもリストしました。
_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);
}
_
エラーはrender呼び出しrender()にあります。
そして、次のようにmain()を呼び出すファイルの最後の行:
_// Let's play this game!
var then = Date.now();
reset();
main();
_
ロード、オンレディ、コールバックメカニズムは次のようになります。
だから私はすべてを開始するためのメイン関数として行います:
_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はリソースがそこにあることを想定しており、読み込まれてから描画されないため、エラーが発生します。