循环在Canvas绘制图片时遇drawImage类型错误求助
解决Canvas drawImage 类型错误的问题
这个错误的核心原因是循环变量的作用域问题,加上图片加载的异步特性导致的,咱们一步步拆解解决:
问题分析
- 循环变量作用域bug:你用
var i声明循环变量,它是函数级作用域,当图片的onload回调执行时,循环已经跑完了,i的值变成了8,这时候images[i]就是undefined,自然不符合drawImage要求的参数类型。 - 图片宽高获取时机错误:在设置
src后立刻获取images[i].width和height,这时候图片还没加载完成,拿到的都是默认值0,完全没用。 - 异步加载的坐标计算:变量
u的累加是同步的,但图片加载是异步的,不过这个问题可以通过直接计算坐标来规避。
修复后的代码
var canvasModule = { elements: { canvas: document.getElementById('signature-canvas') }, render: function () { this.createImageOnCanvas(); }, getCanvasContext: function () { return this.elements.canvas.getContext('2d'); }, getCanvasWidth: function () { return this.elements.canvas.width; }, getCanvasHeight: function () { return this.elements.canvas.height; }, createImageOnCanvas: function () { var itemWidth = this.getCanvasWidth() / 7; var itemHeight = this.getCanvasHeight() / 3; var context = this.getCanvasContext(); var images = []; // 用let声明i,形成块级作用域,每个迭代的i都是独立的 for (let i = 1; i < 8; i++) { images[i] = new Image(); images[i].src = 'images/sample/1'+i+'.png'; images[i].onload = () => { // 图片加载完成后再获取宽高 const imgWidth = images[i].width; const imgHeight = images[i].height; // 直接计算当前图片的x坐标:(i-1)*itemWidth,不用依赖u的累加 const xPos = (i - 1) * itemWidth; context.drawImage(images[i], xPos, 0, itemWidth, itemHeight); // 如果需要保存宽高的话,这里赋值 // imagesWidth[i] = imgWidth; // imagesHeight[i] = imgHeight; } // 可选:添加图片加载失败的错误处理 images[i].onerror = () => { console.error(`图片加载失败:images/sample/1${i}.png`); } } } } $(document).ready(() => canvasModule.render());
关键修复点
- 用
let替代var声明循环变量:让每个循环迭代都拥有独立的i变量,确保onload回调执行时能拿到当前迭代的图片引用。 - 把图片相关操作移到
onload回调内:图片加载完成后才能获取正确的宽高,也才能安全地调用drawImage。 - 直接计算坐标:用
(i-1)*itemWidth代替同步累加的u,避免异步加载导致的坐标混乱。 - 修正
$(document).ready的调用:原代码里canvasModule.render()是直接执行函数,应该传入函数引用,确保DOM就绪后再执行。
内容的提问来源于stack exchange,提问作者Jaan
相关产品推荐
相关产品推荐

