Framer Motion新手如何实现滚动触发的复杂交互动画?
Framer Motion 滚动触发式复杂动画实现思路
以下是可直接落地的实现思路:
- 基础滚动触发逻辑搭建
优先用Framer Motion内置的能力实现,不需要额外引入第三方滚动监听库。如果是单个元素进入视口触发动画的场景,直接给motion标签元素加whileInView属性,配合viewport参数自定义触发时机:比如设置viewport={{ amount: 0.3, once: false }}就是元素露出30%时触发动画,once参数控制动画是否只触发一次。如果需要动画和滚动进度完全绑定,拖动滚动条时动画可进可退,就用useScroll钩子获取全局滚动进度scrollYProgress,这个值会在0(页面顶部)到1(页面底部)之间实时变化。 - 多阶段逐步动画映射
用useTransform钩子把滚动进度映射成你需要的动画属性值,就可以实现随滚动逐步触发的效果。比如你要做4个元素依次入场的效果,就把0-0.25的滚动进度区间映射到第一个元素的透明度从0到1,0.25-0.5映射到第二个元素的Y轴位移从-30px到0,0.5-0.75映射到第三个元素的缩放从0.8到1,0.75-1映射到第四个元素的旋转角度从0到10度,滚动的时候所有动画就会跟着滚动进度依次触发,完全匹配需求。 - 性能优化注意事项
做滚动动画时尽量用x、y、opacity、scale这类不会触发页面重排的属性做动画,避免使用margin、top、left等属性,能大幅降低卡顿概率。如果只需要监听单个元素的可见性,优先用whileInView而不是全局的useScroll,减少不必要的全局状态监听带来的性能损耗。
示例代码参考:
import { motion, useScroll, useTransform } from 'framer-motion' export default function CustomScrollAnimation() { // 获取全局滚动进度 const { scrollYProgress } = useScroll() // 滚动0%-20%阶段:第一个元素淡入 const item1Opacity = useTransform(scrollYProgress, [0, 0.2], [0, 1]) // 滚动20%-40%阶段:第二个元素从下方滑入 const item2Y = useTransform(scrollYProgress, [0.2, 0.4], [60, 0]) // 滚动40%-60%阶段:第三个元素缩放出现 const item3Scale = useTransform(scrollYProgress, [0.4, 0.6], [0.7, 1]) return ( <div style={{ height: '300vh', padding: '100px 20px' }}> <motion.div style={{ opacity: item1Opacity, marginBottom: '100px' }}> 第一个随滚动淡入的元素 </motion.div> <motion.div style={{ y: item2Y, marginBottom: '100px' }}> 第二个随滚动滑入的元素 </motion.div> <motion.div style={{ scale: item3Scale }}> 第三个随滚动缩放出现的元素 </motion.div> {/* 单元素进入视口触发动画写法 */} <motion.div initial={{ opacity: 0, x: -30 }} whileInView={{ opacity: 1, x: 0 }} viewport={{ amount: 0.5, once: true }} transition={{ duration: 0.5 }} style={{ marginTop: '200px' }} > 元素露出一半时触发,仅触发一次 </motion.div> </div> ) }
内容的提问来源于stack exchange,提问作者Mohammed Saber Mohammed
相关产品推荐
相关产品推荐

