Paint Worklet 仅 Chrome/Edge ≥ 88 支持,须通过 CSS.paintWorklet.addModule() 异步加载同源独立 JS 模块,注册时不可用内联脚本或全局对象,输入仅限 CSS 自定义属性,paint() 中无 DOM 访问能力,ctx 仅支持基础绘图 API。

Paint Worklet 无法在 Safari 和 Firefox 中运行,Chrome/Edge ≥ 88 才支持;直接写 background: paint(grid) 而不注册或未加载模块,会报 Invalid property value 或静默失效——这不是写法错,是执行链断了。
Paint Worklet 必须用 CSS.paintWorklet.addModule() 加载独立 JS 文件
浏览器不允许内联脚本注册绘制器,<script>registerPaint(...)</script> 完全无效。模块必须是同源的、独立的 .js 文件,且需显式调用 addModule() 启动加载。
-
addModule()是异步操作,必须await或用.then()确保加载完成,再插入含paint()的 CSS,否则样式不生效 - 跨域资源(如 CDN 上的
grid.js)必须配Access-Control-Allow-Origin: *,否则控制台报Failed to fetch module - 文件内容不能有 ES6 模块外的全局引用(比如直接用
window),Worklet 运行在隔离上下文,无window、document或fetch
registerPaint() 类里不能访问 DOM,paint() 函数只有三个参数
常见错误是试图在 paint(ctx, geom, props) 里读取元素尺寸、调用 getBoundingClientRect() 或监听事件——全部不可行。所有输入必须通过 CSS 自定义属性传入,例如 --grid-size、--grid-color1。
-
ctx是CanvasRenderingContext2D,仅支持绘图 API(fillRect、stroke等),不支持drawImage或文本渲染(部分浏览器禁用) -
geom提供width和height(单位 px),不是元素实际尺寸,而是该背景绘制区域大小(受background-size影响) -
props只能读取已声明的inputProperties,漏写static get inputProperties()或属性名拼错,props.get()返回undefined
网格实现别硬套 Canvas 坐标逻辑,优先用整除+模运算对齐
想画 8px × 8px 的格子,不要用 for (let i = 0; i 然后 <code>fillRect(i, j, 8, 8) —— 当 geom.width 不是 8 的倍数时,最后一列会被截断,且抗锯齿可能导致边界模糊。更稳的方式是基于坐标模运算填色:
立即学习“前端免费学习笔记(深入)”;
paint(ctx, geom, props) {
const size = props.get('--grid-size').value || 8;
const color1 = props.get('--grid-color1').value || '#eee';
const color2 = props.get('--grid-color2').value || '#fff';
ctx.fillStyle = color1;
ctx.fillRect(0, 0, geom.width, geom.height);
ctx.fillStyle = color2;
for (let x = 0; x < geom.width; x += size) {
for (let y = 0; y < geom.height; y += size) {
if ((Math.floor(x / size) + Math.floor(y / size)) % 2 === 0) {
ctx.fillRect(x, y, size, size);
}
}
}
}
- 用
Math.floor(x / size)而非x % size === 0,避免浮点误差导致错位 - 先铺底色再叠网格,比反复切换
fillStyle更快,尤其格子密度高时 - 若需透明格子(如设计稿参考线),底色用
rgba(0,0,0,0.05),但注意部分旧 Chrome 对 alpha 渲染有偏移
替代方案:纯 CSS 实现简单网格更轻量、兼容性更好
如果只要静态、无动画、无动态参数的网格,repeating-linear-gradient 是更优解——零 JS、全浏览器支持、无加载延迟。
.grid-bg {
background-image:
repeating-linear-gradient(0deg, #000, #000 1px, transparent 1px, transparent 8px),
repeating-linear-gradient(90deg, #000, #000 1px, transparent 1px, transparent 8px);
background-size: 8px 8px;
}
- 两层渐变叠加形成十字线,
1px线宽 +8px间距,比 Canvas 绘制省性能 - 不支持 CSS 变量动态控制线宽/颜色,但可通过 JS 切换 class 或修改
style.backgroundImage替代 - Paint Worklet 真正优势在于:需要每帧重绘(如鼠标跟随网格变形)、依赖复杂计算(如 Voronoi 分割)、或与 Houdini 其他 API(如 Layout Worklet)联动时
最易被忽略的一点:Paint Worklet 的错误不会抛到主页面 console,而是在 Worklet 独立上下文里静默失败。调试时务必打开 DevTools → More Tools → Rendering → 勾选 “Paint flashing”,再检查对应元素是否有绿色闪动;没闪动,大概率是模块根本没注册成功。



















