houdini 动画不能直接用 html 或标准 css 动画触发,animation/paint worklet 运行于独立线程,仅响应 css 自定义属性变化,须通过 addmodule 加载 js 模块并显式注册(如 registeranimator/registerpaint),且依赖主线程 js 驱动或正确配置 inputproperties 与 timeline。

不能直接用 HTML 做 Houdini 动画 —— Animation Worklet 和 Paint Worklet 都不接受 HTML 元素或 DOM 操作,它们运行在独立线程,只响应 CSS 自定义属性变化,且必须通过 CSS.paintWorklet.addModule() 或 CSS.animationWorklet.addModule() 加载 JS 模块。
为什么写 <div> + <code>animation: xxx 不会触发 Animation Worklet
因为标准 CSS animation 属性绑定的是 @keyframes,不是 Worklet。Animation Worklet 要求你显式注册一个 worklet 类,并用 animate() 方法手动驱动;它不接管任何已有 CSS 动画声明。
常见错误现象:
- 写了
animation: my-worklet-anim 2s infinite,但控制台报错Invalid property value - 加了
@keyframes my-worklet-anim,但浏览器完全忽略,无任何效果 - 忘记调用
CSS.animationWorklet.addModule('anim.js'),导致registerAnimator不生效
正确路径是:JS 注册 animator → CSS 设置 animation-timeline 或用 JS 调用 element.animate() 并传入 worklet 动画对象。
registerAnimator 必须配合 element.animate() 才生效
Animation Worklet 的核心不是“替换 CSS 动画”,而是提供一个可编程的、主线程解耦的动画执行器。它只在你显式调用 Element.animate() 并传入 { animator: 'xxx' } 时才启动。
实操要点:
- 模块文件(如
scroll-fade-animator.js)里必须调用registerAnimator('scroll-fade', class { ... }) - 主页面 JS 中需先加载:
CSS.animationWorklet.addModule('scroll-fade-animator.js') - 然后才能这样驱动:
elem.animate({ opacity: [0, 1] }, { animator: 'scroll-fade', timeline: new ScrollTimeline({ source: document.scrollingElement }) }) -
timeline参数不是可选的 —— 缺少它,worklet 不会收到时间信号,animate()会退化为普通 CSS 动画
Paint Worklet 是唯一能“从 HTML 触发”的 Houdini API,但仍有硬限制
你可以把 background-paint: my-painter 写在任意元素的 CSS 里,看起来像“HTML 直接用了”,但背后依赖三个不可省略的前提:
- 浏览器支持
'paintWorklet' in CSS(截至 2026 年 4 月,Chrome / Edge 稳定版支持,Firefox 仍实验性,Safari 无支持) -
CSS.paintWorklet.addModule('painter.js')必须成功执行,且模块中调用registerPaint() - CSS 中引用的函数名(如
my-painter)必须与registerPaint('my-painter', ...)完全一致,大小写敏感 - 自定义属性(如
--progress)必须在static get inputProperties()中显式声明,否则properties.get()返回undefined
例如,想让一个按钮随滚动变色,不能只写:button { --progress: 0.5; background-paint: scroll-hue; } —— --progress 必须由 JS 实时更新,且该属性名必须出现在 worklet 的 inputProperties 数组里。
Worklet 模块无法访问 DOM、window、document,调试要换思路
Worklet 运行在隔离的渲染线程,所有 console.log、fetch、setTimeout、getComputedStyle 都不可用。一旦出错,只会静默失败或抛出 Failed to execute 'addModule' 类错误。
容易被忽略的关键点:
- 不能在 worklet 类里读取
document.body.scrollTop—— 必须靠外部 JS 把值设为 CSS 自定义属性,再由properties.get()拿到 - 不能用
ctx.drawImage()绘制远程图片 ——ctx是PaintRenderingContext2D,仅支持createPattern或本地ImageBitmap(需提前用createImageBitmap()解码并传入) - 调试时别依赖
console.log:改用debugger断点(Chrome DevTools > Sources > Worklets 标签页),或在主 JS 中监听error事件捕获模块加载失败 - 每次修改 worklet JS 文件后,必须硬刷新页面 —— 浏览器不会自动重载已注册的 worklet











