canvas.drawImage()不是唯一插入图片方式,但所有图片必须先加载为Image对象再绘制;需在onload回调中调用drawImage();支持2/4/9参数签名;跨域图片需设置crossOrigin且服务端配CORS头,否则canvas被污染。

canvas.drawImage() 是唯一可靠的方式
直接往 里“插入”图片不存在——canvas 没有类似 的内置加载和渲染机制。所有图片都必须先用 JavaScript 加载为 Image 对象,再通过 drawImage() 方法绘制到画布上。跳过这一步会报错或显示空白。
必须等图片加载完成才能 drawImage()
Image 是异步加载的,如果在 img.src = 'xxx.png' 后立刻调用 drawImage(),图片很可能还没就绪,结果是画布上什么也没有,控制台也无报错。这是新手最常踩的坑。
- 正确做法:把
drawImage()放进img.onload回调里 - 错误写法:
const img = new Image(); img.src = 'logo.png'; ctx.drawImage(img, 0, 0); // ❌ 此时 img 还没加载完
- 正确写法:
const img = new Image(); img.onload = () => { ctx.drawImage(img, 0, 0); }; img.src = 'logo.png'; // ✅ src 赋值放最后
drawImage() 有三种参数签名,别传错数量
传参不匹配会导致静默失败或拉伸变形。记住核心区别:
- 2 参数:
drawImage(img, x, y)—— 原尺寸、指定左上角位置 - 4 参数:
drawImage(img, x, y, width, height)—— 拉伸/缩放到指定宽高 - 9 参数:
drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh)—— 先从原图裁剪(sx,sy,sw,sh),再绘制到目标区域(dx,dy,dw,dh)
例如想只取原图右下角 100×100 像素,放大到画布上 200×200 区域:
ctx.drawImage(img, img.width - 100, img.height - 100, 100, 100, 50, 50, 200, 200);
立即学习“前端免费学习笔记(深入)”;
CORS 问题会让 drawImage() 失败且无法捕获异常
如果图片来自其他域名(比如 CDN 或用户上传的外链),而服务器没配 Access-Control-Allow-Origin,drawImage() 仍会执行,但后续调用 ctx.getImageData() 或导出 toDataURL() 会直接抛 SecurityError。这个限制不可绕过,也**不会触发 img.onerror**。
- 本地开发时,用
img.crossOrigin = 'anonymous'显式声明跨域请求(即使同域也建议加) - 确保图片服务端返回了正确的 CORS header,否则 canvas 会被污染
- 调试技巧:绘制后立即执行
ctx.getImageData(0,0,1,1),若报错说明已污染
实际使用中,最麻烦的不是怎么画,而是图片加载时机和跨域权限这两关——它们不出错时不显眼,一出错就整个功能瘫痪,而且错误信息极其隐蔽。











