使用Canvas绘制瓦片图时为何出现Type Error且无法显示图像?
问题分析与修复方案
错误原因
- 异步函数处理不当:
createImageBitmap()是异步方法,返回的是Promise对象,你直接将其存入tiles字典,导致调用ctx.drawImage()时传入的是Promise而非可绘制的图像资源,触发TypeError。 - 索引计算错误:原代码中
i+8*u的索引逻辑会导致重复键名(比如第1行第1个tile和第0行第9个tile索引都是8),应该按行号×每行数量 + 列号的方式计算。
修复后的代码
JavaScript部分
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; var tileSize = 32; var tilex = Math.ceil(canvas.width / tileSize); var tiley = Math.ceil(canvas.height / tileSize); var tiles = {}; var images = ['performanceTask Assets/Grass.png', 'performanceTask Assets/Plant.png', 'performanceTask Assets/Stone Ground.png', 'performanceTask Assets/Struct.png', 'performanceTask Assets/Wall.png', 'performanceTask Assets/Props.png', 'performanceTask Assets/Shadow Plant.png', 'performanceTask Assets/Shadow.png', 'performanceTask Assets/player.png']; var atlasImage = new Image(); var tilesReady = false; // 标记瓦片是否全部加载完成 atlasImage.src = images[0]; atlasImage.onload = async function() { let x = 0 let y = 0 // 外层循环处理行(共8行) for (let row = 0; row < 8; row++) { // 内层循环处理每行的9个tile for (let col = 0; col < 9; col++) { // 等待异步操作完成,拿到实际的位图对象 const tileBitmap = await createImageBitmap(atlasImage, x, y, tileSize, tileSize); // 用行×9+列生成唯一索引 tiles["tiles" + (row * 9 + col)] = tileBitmap; x += tileSize; } y += tileSize; x = 0; } tilesReady = true; grassScreen(); // 加载完成后立即绘制 }; function grassScreen() { // 瓦片未加载完成时直接返回,避免报错 if (!tilesReady) return; ctx.drawImage(tiles['tiles1'], 100, 100); }; // 如果需要实时刷新画面可以保留,否则无需定时调用 // setInterval(grassScreen, 1000);
HTML部分(无需修改)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Work in Progress</title> <style> * { overflow: hidden; } html, body { margin: 0 !important; padding: 0 !important; } </style> </head> <body> <canvas id="canvas"></canvas> <script src="performanceTask.js"></script> </body> </html>
额外说明
- 使用
async/await确保异步生成的位图正确存入字典,避免Promise对象导致的绘制错误。 - 添加
tilesReady状态判断,防止在资源未加载完成时执行绘制逻辑。 - 调整索引计算方式,保证每个tile的键名唯一,避免覆盖问题。
内容的提问来源于stack exchange,提问作者user16581612
相关产品推荐
相关产品推荐

