图片需onload后才可传给createpattern,跨域图须设crossorigin="anonymous";repeat参数控制平铺方向而非缩放;图案锚点固定于canvas原点(0,0);缩放旋转需用ctx变换矩阵,且图案创建后不随源图更新。

图片没加载完就调用 createPattern(),图案一定不显示;跨域图没设 crossOrigin="anonymous",图案会是空白——这两点踩中任意一个,你写的代码都白搭。
图片必须 onload 后才能传给 createPattern
很多人把 new Image() 和 createPattern() 写在一块,但图像还没下载完,createPattern() 就执行了,浏览器直接抛 InvalidStateError。这不是 bug,是规范强制要求。
- 必须等
img.onload触发后再调用ctx.createPattern(img, 'repeat') - 如果图加载失败(404、网络中断),
img.onerror里要处理,否则页面静默失败 - 不要用
img.complete === true做判断——它只反映缓存状态,不能代替 onload
跨域图片必须显式声明 crossOrigin
从 CDN、图床或第三方域名加载的图片,默认受同源策略限制。即使图片能正常显示在 <img> 标签里,createPattern() 仍会因安全限制返回空图案(无报错,但 fill 区域纯黑/透明)。
- 设置
img.crossOrigin = "anonymous",且服务端响应头需含Access-Control-Allow-Origin: *或对应域名 - 不能只写
crossorigin属性(HTML 属性名大小写不敏感,但 JS 赋值必须小写crossOrigin) - 本地 file:// 协议下加载本地图,也会触发跨域限制,建议用本地服务器调试(如
npx http-server)
repeat / repeat-x / repeat-y 的实际行为差异
createPattern() 的第二个参数不是“控制贴图怎么缩放”,而是“控制平铺方向和次数”。它不会改变原图尺寸,只决定重复逻辑。
-
'repeat':默认值,横向 + 纵向无限铺满整个 fill 区域 -
'repeat-x':只沿 x 轴重复,y 方向只画一行(顶部对齐) -
'repeat-y':只沿 y 轴重复,x 方向只画一列(左侧对齐) -
'no-repeat':原图按原始尺寸画一次,位置固定在 fill 区域左上角(不是 canvas 原点)
注意:fillRect(100, 100, 200, 200) 中的 (100, 100) 是绘制起点,但图案始终以 canvas 坐标系原点 (0, 0) 为锚点平铺——所以图案“起始位置”不随矩形移动。
想缩放/旋转纹理?得靠 ctx 变换,不是改图片
createPattern() 本身不接受 scale 或 angle 参数。想让纹理变密、变斜,只能操作 canvas 上下文的变换矩阵。
- 先
ctx.save(),再ctx.scale(0.5, 0.5)→ 图案单位变小,看起来更密集 -
ctx.translate(50, 50); ctx.rotate(Math.PI / 4);→ 整个平铺网格跟着旋转 - 变换后调用
fillRect(),最后别忘了ctx.restore(),否则后续绘图全歪 - 如果只想移动图案起点(比如整体右移 20px),用
ctx.transform(1, 0, 0, 1, 20, 0)更轻量
真正容易被忽略的是:图案一旦创建,就和源图像“快照绑定”——后续改 img.src 或重绘图案用的 <canvas></canvas>,已生成的 CanvasPattern 对象不会更新,必须重新 createPattern()。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











