createPattern传入图片前必须确保其已加载完成,否则返回null导致fill()静默失败;正确做法是监听img.onload事件后再调用createPattern,并注意跨域、分辨率匹配及repetition参数限制。

createPattern 传入图片前必须确保图片已加载完成
直接把 <img alt="如何通过HTML的Canvas的createPattern方法用图片创建重复填充图案" > 元素传给 createPattern 却没等它加载完,是最多见的“图案不显示”原因。此时 createPattern 返回 null,后续调用 fill() 会静默失败,控制台也不报错。
正确做法是监听 img.onload,再创建 pattern:
const img = new Image();
img.src = 'tile.png';
img.onload = () => {
const pattern = ctx.createPattern(img, 'repeat'); // ✅ 此时 img 已就绪
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, 300, 200);
};
- 不要在
img.src = ...后立刻调用createPattern - 如果图片来自缓存,
onload仍会触发,但可能异步延迟极短——不能依赖“看起来能跑通” - 使用
fetch+createImageBitmap是更现代的替代方案,但需注意浏览器兼容性(Safari 15.4+ 支持)
第二个参数 'repeat' 可选值及其实际行为差异
createPattern 的第二个参数控制平铺方式,不是所有值都按直觉工作:
-
'repeat':横向 + 纵向重复(默认) -
'repeat-x':仅水平重复;'repeat-y':仅垂直重复 -
'no-repeat':只画一次,左上角对齐;不会拉伸,也不会居中 -
'space'和'round'在 Canvas 2D 中被忽略,始终退化为'repeat'(这是规范明确规定的)
例如想实现“水平平铺 + 垂直居中单次显示”,得手动计算 y 偏移,不能靠 pattern 类型自动处理。
立即学习“前端免费学习笔记(深入)”;
图片尺寸与 canvas 像素比不匹配导致模糊或锯齿
高 DPI 屏幕(如 Retina)下,若图片原始尺寸小(如 16×16),又被放大平铺,浏览器会插值渲染,产生模糊或发虚感。
- 优先使用和设备像素比匹配的图源(例如 @2x 图)
- 可通过
window.devicePixelRatio动态加载不同分辨率图片 - 避免用 CSS 缩放 canvas 元素本身——这会让整个 canvas 渲染缓冲区被缩放,pattern 也会一并模糊
- pattern 本身不支持设置抗锯齿开关;抗锯齿由 canvas 的
imageSmoothingEnabled控制,默认为true;设为false可得硬边效果(适合像素风)
跨域图片触发 SecurityError:无法用 createPattern
从其他域名加载的图片(即使 visibly 显示正常),若未开启 CORS,createPattern 会抛出 SecurityError: The operation is insecure.
- 检查网络面板里图片响应头是否含
Access-Control-Allow-Origin: * - 前端无法绕过此限制;服务端必须配 CORS 头
- 临时调试可用
img.crossOrigin = 'anonymous',但它只是发起带 CORS 的请求,不解决服务端没配的问题 - 本地 file:// 协议下加载本地图片也受限制,建议用轻量本地 server(如
npx serve)测试
pattern 创建失败没有中间状态可检测,只能靠 try/catch 捕获 SecurityError 并降级处理(比如改用纯色 fill)。



















