如何利用 CSS.paintWorklet 在 Worker 线程中实现不占主线程的高性能背景动画

陌宇大大_8912

陌宇大大_8912

2026-05-01

784人浏览

原创

paint worklet 必须在主线程注册,其 paint() 在合成线程执行但初始化绑定主线程;动画逻辑应通过 sharedarraybuffer/atomics 或 postmessage 解耦,inputproperties + registerproperty() 实现跨线程状态同步,且 paint() 仅做轻量数学计算。

如何利用 css.paintworklet 在 worker 线程中实现不占主线程的高性能背景动画

Paint Worklet 必须注册在主线程,Worker 中无法直接使用

很多人误以为 paintWorklet 可以像 Web Worker 一样在独立线程里注册和运行,但事实是:浏览器强制要求 worklet.addModule() 只能在主线程调用,且注册后的 class 实例(即 paint() 函数)虽在合成线程(Compositor Thread)执行,但**初始化、模块解析、类定义仍绑定主线程**。试图在 Worker 中调用 CSS.paintWorklet.addModule() 会直接抛出 DOMException: Failed to execute 'addModule' on 'PaintWorklet': Cannot be called in a Worker。

所以“在 Worker 中实现 Paint Worklet”这个前提不成立——你不能绕过主线程注册,但可以做到「动画逻辑与主线程解耦」。

  • 主线程只负责一次性的 addModule() 注册和 CSS 属性设置(如 background-image: paint(anim))
  • 动画的时序控制、参数计算(如时间戳、噪声值、颜色插值)应交给 SharedArrayBuffer + Atomics 或 postMessage 驱动,避免在 paint() 内做耗时运算
  • Paint Worklet 的 paint() 函数本身必须轻量:只读共享内存或 inputProperties,不做循环、浮点运算密集操作

用 inputProperties + registerProperty() 把动画状态从主线程“喂”进 Paint Worklet

registerProperty() 是让主线程可控更新、Paint Worklet 安全读取的关键桥梁。它比直接传 canvas 或 ImageData 更高效,且天然跨线程同步(底层由 Blink 管理)。

例如你想实现一个随时间流动的波纹背景:

// 主线程
CSS.registerProperty({
  name: '--wave-time',
  syntax: '<number>',
  inherits: false,
  initialValue: 0
});
<p>CSS.paintWorklet.addModule('wave-paint.js');
</p></number>

然后在 wave-paint.js 中:

CSS婚礼策划服务机构宣传网站模板
CSS婚礼策划服务机构宣传网站模板

CSS婚礼策划服务机构宣传网站模板是一款适合提供婚礼策划和婚庆服务机构宣传网站模板下载。提示:本模板调用到谷歌字体库,可能会出现页面打开比较缓慢。

下载
// wave-paint.js(Paint Worklet 模块)
class WavePainter {
  static get inputProperties() { return ['--wave-time']; }
  paint(ctx, geom, props) {
    const t = props.get('--wave-time').value;
    // 仅用 t 做简单三角函数,不查表、不 new Array
    for (let y = 0; y 
  • 主线程用 requestAnimationFrame 或 Web Worker + Atomics 持续更新 element.style.setProperty('--wave-time', t)
  • Paint Worklet 自动收到新值,无需手动同步;inputProperties 是只读代理,无 GC 开销
  • 避免在 paint() 中调用 Date.now() 或 performance.now() —— 时间必须由主线程提供,否则会因合成线程无事件循环而读到错误时间

高频更新 --wave-time 时,主线程仍可能卡顿?用 Worker + Atomics 控制节奏

如果每帧都走 requestAnimationFrame + setProperty,高频更新(如 60fps)本身就会触发样式重计算,尤其当大量元素监听同一自定义属性时,主线程压力不小。这时可用 SharedArrayBuffer 让 Worker 承担计时和写入责任。

主线程只需一次分配共享内存,并监听变化:

// 主线程
const sab = new SharedArrayBuffer(4);
const timeView = new Float32Array(sab);
<p>// 启动 Worker 控制时间流
const worker = new Worker('time-worker.js');
worker.postMessage({ sab });</p><p>// 在 rAF 中轮询(轻量!)
function tick() {
const t = Atomics.load(timeView, 0);
element.style.setProperty('--wave-time', t);
requestAnimationFrame(tick);
}
tick();
</p>

Worker 内部:

// time-worker.js
self.onmessage = ({ data }) => {
  const timeView = new Float32Array(data.sab);
  let t = 0;
  const interval = setInterval(() => {
    t += 0.02; // 控制动画速率
    Atomics.store(timeView, 0, t);
  }, 16);
};
  • 主线程不再主动计算 t,只做原子读取 + 属性设置,rAF 负载极低
  • Worker 独立计时,不受主线程帧率抖动影响(比如主线程卡顿时,Wave 动画仍匀速)
  • 注意:Safari 目前不支持 SharedArrayBuffer(需 cross-origin-isolated 上下文),生产环境需降级为 postMessage,但频率建议压到 ≤30fps 避免消息队列积压

Paint Worklet 的 canvas 上下文不是完整 2D API,别依赖 fillText 或 getImageData

ctx 在 Paint Worklet 中是受限的:fillText、getImageData、createPattern、filter 等均不可用,且 ctx.canvas 为 null。它只暴露最基础的绘图能力,目标是保证合成线程能快速光栅化。

  • 支持的操作:fillRect、strokeRect、clearRect、beginPath、lineTo、stroke、fill、save/restore、translate、scale
  • 不支持:drawImage(无法传入外部图片)、createLinearGradient(但可用 ctx.fillStyle = 'rgb(...)' 动态设色)
  • 性能陷阱:在 paint() 中反复调用 ctx.beginPath() + 大量 lineTo() 渲染复杂路径,会显著拖慢光栅化——应尽量用 fillRect 或预计算顶点数组(存在 inputProperties 中)

真正高性能的背景动画,往往靠数学生成(正弦/噪声/分形),而非像素操作。一旦开始想“怎么把 Canvas 图片塞进去”,就说明已经偏离了 Paint Worklet 的设计意图。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

css

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
css
css

css是层叠样式表,用来表现HTML或XML等文件样式的计算机语言,不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。php中文网还为大家带来html的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

4296

6

css居中
css居中

css居中:1、通过“margin: 0 auto; text-align: center”实现水平居中;2、通过“display:flex”实现水平居中;3、通过“display:table-cell”和“margin-left”实现居中。本专题为大家提供css居中的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.27

957

5

css如何插入图片
css如何插入图片

cssCSS是层叠样式表(Cascading Style Sheets)的缩写。它是一种用于描述网页或应用程序外观和样式的标记语言。CSS可以控制网页的字体、颜色、布局、大小、背景、边框等方面,使得网页的外观更加美观和易于阅读。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.28

1798

6

css超出显示...
css超出显示...

在CSS中,当文本内容超出容器的宽度或高度时,可以使用省略号来表示被隐藏的文本内容。本专题为大家提供css超出显示...的相关文章,相关教程,供大家免费体验。

2023.08.01

3366

7

css字体颜色
css字体颜色

CSS中,字体颜色可以通过属性color来设置,用于控制文本的前景色,字体颜色在网页设计中起到很重要的作用,具有以下表现作用:1、提升可读性;2、强调重点信息;3、营造氛围和美感;4、用于呈现品牌标识或与品牌形象相符的风格。

2023.08.10

6725

11

什么是css
什么是css

CSS是层叠样式表(Cascading Style Sheets)的缩写,是一种用于描述网页(或其他基于 XML 的文档)样式与布局的标记语言,CSS的作用和意义如下:1、分离样式和内容;2、页面加载速度优化;3、实现响应式设计;4、确保整个网站的风格和样式保持统一。

2023.08.10

5731

7

css三角形怎么写
css三角形怎么写

CSS可以通过多种方式实现三角形形状,本专题为大家提供css三角形怎么写的相关教程,大家可以免费体验。

2023.08.21

1957

9

css设置文字颜色
css设置文字颜色

CSS(层叠样式表)可以用于设置文字颜色,这样做有以下好处和优势:1、增加网页的可视化效果;2、突出显示某些重要的信息或关键字;3、增强品牌识别度;4、提高网页的可访问性;5、引起不同的情感共鸣。

2023.08.22

2711

5

css禁止点击事件
css禁止点击事件

实现css禁止点击事件的方法有使用CSS的pointer-events属性和使用JavaScript禁用点击事件。本专题为大家提供点击事件相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

2353

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 5.8万人学习

CSS教程
CSS教程

共754课时 | 96.1万人学习