Paint Worklet 必须通过 CSS.paintWorklet.addModule() 注册独立 JS 文件,仅支持 background-image 等有限 CSS 属性调用,运行于隔离线程,不共享 DOM,无 console/debugger,调试需依赖 Rendering 面板错误提示。

Paint Worklet 无法在普通 HTML 页面中直接运行,必须通过 CSS.paintWorklet 注册,且样式必须通过 background-image: paint(...) 等 CSS 属性触发,纯 JS 调用或内联 script 执行绘图逻辑会静默失败。
注册 Paint Worklet 脚本必须走 addModule(),不能用 import 或 script 标签
Paint Worklet 运行在独立的渲染线程(类似 Web Worker),不共享主页面 DOM、window 或 document。直接写 import './my-paint.js' 或用 <script src="..."></script> 加载会完全无效,控制台也无报错。
- 必须使用
CSS.paintWorklet.addModule('path/to/worklet.js')动态注册,路径需是同源 URL(支持相对路径、绝对路径、甚至 blob URL) - 该调用需在样式应用前完成,建议放在
<head>的<script>中,或确保在document.styleSheets插入前执行 - 模块文件必须是独立 JS 文件(MIME 类型
application/javascript),不能是内联<script type="module">
paint() 函数签名和参数含义容易被误解
Worklet 入口函数名为 paint,固定接收三个参数:ctx(PaintRenderingContext2D)、geometry(宽高对象)、properties(CSSStyleValue 映射)。它不是 Canvas 2D Context,不支持 ctx.drawImage、ctx.textBaseline 等部分 API。
-
ctx只有基础绘图方法:fillRect、strokeRect、clearRect、fillText、strokeText、beginPath、arc、lineTo、stroke、fill—— 没有save/restore、transform、clip(Chrome 115+ 开始支持clip,但非全平台) -
geometry.width和geometry.height是当前元素计算后的背景绘制区域尺寸(单位 px),不是元素 clientWidth/clientHeight -
properties只能读取在 CSS 中显式声明的--<name>自定义属性,且需提前在inputProperties数组中声明,否则返回undefined
CSS 中调用 paint() 必须匹配注册名,且只支持 background-image 等有限属性
注册时传入的模块路径不影响调用名;实际调用名由 Worklet 模块内 registerPaint 的第一个参数决定。名字不一致会导致 background-image: paint(misspelled) 渲染为透明,控制台也不报错。
立即学习“前端免费学习笔记(深入)”;
- 合法调用位置仅限:
background-image、border-image-source、list-style-image——mask-image和clip-path尚未支持(截至 Chrome 128) - 调用语法严格为:
paint(<name>, <arg1>, <arg2>, ...),其中<name>必须与registerPaint('<name>', ...)完全一致(区分大小写) - 传参只能是 CSS 值(如
red、42px、var(--size)),不能传 JS 对象或函数;Worklet 内通过properties.get('--arg1')获取解析后的CSSUnitValue或CSSTokenizedValue
调试困难:没有 console、不能 debugger,错误只静默丢弃
Paint Worklet 运行在隔离环境,console.log、alert、debugger 全部无效;语法错误或运行时异常(如访问 properties.get('--x').value 但未声明)不会抛出,只会让对应元素背景变空白。
- 唯一可观测方式是:在 Worklet 文件顶部加
throw new Error('test'),然后看 Chrome DevTools → Rendering → “Paint Worklet Errors” 是否出现(需开启 Rendering 面板的 “Debug painting”) - 推荐开发流程:先写一个最小可运行模块(只
ctx.fillRect(0,0,10,10)),确认注册和 CSS 调用通路;再逐步加逻辑,每次只增一行关键代码 - 注意缓存:Worklet JS 文件被浏览器强缓存,修改后需硬刷新(Ctrl+Shift+R)或禁用缓存(DevTools → Network → Disable cache)
最易忽略的是 inputProperties 声明和 CSS 自定义属性的绑定关系——漏写一条,对应值就是 undefined,而你根本看不到任何提示。


















