这个站的首页有一套三层动效:lenis 平滑滚动、GSAP ScrollTrigger 键盘编舞、motion/react 入场动画。它们让真人浏览时很爽,也让自动化截图变成噩梦。
症状:永远截不到目标区域
用 Playwright 给"作品区"截图,流程理论上很简单:滚过去、找到元素、悬停、按快门。实际执行时:
1. scrollTo(元素) → lenis 把滚动弹回原位
2. mouse.wheel 一格格滚 → 惯性余漂,坐标过时
3. boundingBox 稳定判定 → GSAP 视差让元素永远在"漂移"
4. 连续两次采样一致? → 等到超时也没有那一刻解法:一行构造参数
const page = await browser.newPage({
viewport: { width: 1600, height: 900 },
reducedMotion: "reduce", // 就是这一行
});这个站的动效体系尊重 prefers-reduced-motion——这是给无障碍用户的承诺。于是当 Playwright 模拟一个"开了减少动效"的用户时,lenis 和 GSAP 全部让位,滚动回归原生,页面变成静态文档,scrollIntoViewIfNeeded 一次到位。
无障碍支持不只是道德义务,它还是一套现成的"测试模式"。你为少数人做的让步,会成为你自己调试时的捷径。
附送一个测量陷阱
修滚动大字带的速度时,我用 DOMMatrix 读 transform 位移来测速,结果总能采到一个 17000px/s 的荒谬峰值。排查半天发现是循环滚动的取模跳变:x 从 -25% 归零的瞬间位移了四分之一带宽,被我当成了"速度"。
测量脚本里的每一个突变,先问自己:是真实行为,还是实现的副产品?