回到文章列表

前端手艺

粒子可以飞,但别让整个网站一直喘

旧首页有两个画布不停重绘,还有固定 1.8 秒开场。动效没错,一直不肯停才有问题。

个人网站想要一点“科技感”,粒子背景几乎是条件反射。再来个节点连线、鼠标吸附、3D 倾斜和打字机,页面马上忙得像在加班。

旧版 Arcuid 就差不多是这样。我当时确实喜欢,后来也确实被它吵到了。

动效没罪,永动机有点烦

旧首页有两个一直跑的画布。粒子每帧两两算距离,复杂度接近 O(n²);擦除遮罩就算早已不在眼前,仍然勤勤恳恳地申请下一帧。

页面前面还有固定 1.8 秒 Loader。内容有时早就好了,用户仍要站在门口等动画演完。它最准确表达的信息是:“我正在阻止你看到已经加载好的页面。”

我把它们粗暴地分成三类

我把站内的动效粗略分成三类:

1. 状态动效

菜单展开、对话框出现、按钮变了状态。这类动画是给操作做回声,短一点就行。

2. 空间动效

文章进入视口、页面过渡、阅读进度。可以帮忙理清空间,但不能堵住正文。

3. 氛围动效

粒子、光晕、擦除画布都在这里。它们纯粹负责好看,所以设备吃不消或用户不想看时,也应该第一个消失。

然后定几条死规矩

  • 不阻塞正文出现;
  • prefers-reduced-motion: reduce 下停止连续动画;
  • 页面切到后台时暂停 requestAnimationFrame
  • Canvas 像素比最多使用 2,避免高 DPI 设备过度绘制;
  • 粒子数量根据容器宽度设置上限;
  • 只有实际包含效果的页面才加载对应脚本。
document.addEventListener('visibilitychange', () => {
  visible = !document.hidden;
});

if (!reducedMotion) {
  requestAnimationFrame(tick);
}

这段代码没什么高深的。页面藏到后台就停,用户选了减少动态效果也停。总不能因为我写了动画,它就获得了永久运行权。

卡顿也会被看见

按钮点下去有没有反应,字体会不会突然跳,首屏是不是被遮住,这些本来就是画面的一部分。不能设计稿里很高级,一跑起来像电脑快没电。

LCP、INP、CLS 可以帮忙量化,最后还是要回到几个普通问题:正文什么时候出现,按钮什么时候能点,没人看的动画什么时候肯停。

现在它们待在该待的地方

信号场和擦除实验都没删,只是搬进 Lab。首页留一点动静,文章页基本安静下来。

想玩的时候去实验室玩。想读文章的时候,字就老老实实待着。这样挺好。

看到这里了

要不要说两句

评论还没加载,往下滚到这里才会去请求。