1 分钟阅读
逐字揭示与滚动叙事:动效的节奏感
#动效#Framer Motion#叙事
滚动叙事(scroll-driven storytelling)的魅力,在于把「阅读」变成「体验」:你滚动的每一寸,都驱动着画面或文字做出回应。其中「逐字揭示」是我最喜欢的技巧之一——一段话,随着你的滚动,一个字一个字地亮起来。
原理
核心是监听某个容器的滚动进度,再把进度映射到每个字符的透明度上。每个字符占据进度轴上的一个小区间,滚动到那里时,它恰好被点亮:
const { scrollYProgress } = useScroll({
target: ref,
offset: ['start 0.85', 'end 0.4'],
});
const opacity = useTransform(scrollYProgress, range, [0.16, 1]);一个经典的 React 陷阱
最初我直接在 map 循环里调用 useTransform,结果立刻报错——这违反了 Hooks 规则:Hook 只能在组件顶层调用,不能在循环里。
正确的做法,是把「单个字符」抽成一个独立组件,让它自己管理自己的 Hook:
function Char({ char, progress, range }) {
const opacity = useTransform(progress, range, [0.16, 1]);
return <motion.span style={{ opacity }}>{char}</motion.span>;
}这样每个字符都是独立的组件实例,Hook 数量稳定,逻辑清晰。
节奏感从哪里来
逐字揭示的成败,九成在节奏。我的经验:
- 区间要重叠——相邻字符的亮度区间互相咬合,才有「流动」而非「跳跃」。
- 起始亮度别设为零——
0.16的底色让文字始终可辨,不至于漆黑一片。 - 给滚动多一点余量——
offset别卡太死,让动画有进入和完成的缓冲。
结语
动效是叙事的一部分。逐字揭示之所以动人,不是因为它「炫」,而是因为它让读者意识到:是我在推动这段文字,是我在让它亮起来。这种参与感,是静态排版给不了的。
节奏,是动效的呼吸。