You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环在Canvas绘制图片时遇drawImage类型错误求助

解决Canvas drawImage 类型错误的问题

这个错误的核心原因是循环变量的作用域问题,加上图片加载的异步特性导致的,咱们一步步拆解解决:

问题分析

  1. 循环变量作用域bug:你用var i声明循环变量,它是函数级作用域,当图片的onload回调执行时,循环已经跑完了,i的值变成了8,这时候images[i]就是undefined,自然不符合drawImage要求的参数类型。
  2. 图片宽高获取时机错误:在设置src后立刻获取images[i].width和height,这时候图片还没加载完成,拿到的都是默认值0,完全没用。
  3. 异步加载的坐标计算:变量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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:54:48