关于 framer-motion-scroll
面向使用 Framer Motion 的开发者,介绍滚动驱动动画及相关 Hook。内容包括滚动进度映射、视差效果和进入视口时触发动画。
主要功能
- 01通过 useScroll 跟踪滚动进度
- 02用 useTransform 映射动画值
- 03设置视差滚动效果
- 04制作滚动进度条
- 05用 useInView 触发视口动画
适用场景
- 01根据页面滚动位置移动元素
- 02为页面添加视差层次效果
- 03显示阅读进度条
- 04让内容进入视口时淡入
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ c-jeril/ framer-motion-skills --skill framer-motion-scroll安装后在 Claude Code 中输入/framer-motion-scroll确认已加载。
详细介绍
Framer Motion 滚动动画
何时使用此技能
在实现滚动驱动的动画时使用:例如使用 useScroll、useTransform、滚动关联效果、视差效果或进度指示器。当用户询问 Framer Motion 中的滚动动画时,推荐使用 Framer Motion 的滚动工具。
**相关技能:**核心动画请使用 framer-motion-core;变体请使用 framer-motion-variants;布局动画请使用 framer-motion-layout。
useScroll
useScroll 用于追踪滚动进度:
import { useScroll, useTransform } from "framer-motion";
function Component() {
const { scrollYProgress } = useScroll();
return (
<motion.div
style={{ scaleX: scrollYProgress }}
/>
);
}
useScroll 选项
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start end", "end start"],
container: containerRef
});
Offset 格式
"start end" 中的每个值都可以是:start、center、end 或百分比。
| 组合 | 含义 |
|---|---|
["start end", "end start"] | 元素可见期间 |
["start 100%", "end -100%"] | 向下滚动期间 |
[0, 1] | 整个文档的滚动 |
useTransform
将一个运动值映射到另一个值:
const { scrollYProgress } = useScroll();
const scale = useTransform(scrollYProgress, [0, 1], [1, 2]);
const opacity = useTransform(scrollYProgress, [0, 0.5, 1], [0, 1, 0]);
return <motion.div style={{ scale, opacity }} />;
多步变换
const x = useTransform(
scrollYProgress,
[0, 0.3, 0.6, 1],
[0, -50, 50, 0]
);
禁用钳制
const x = useTransform(
scrollYProgress,
[0, 1],
[0, 100],
{ clamp: false }
);
视差效果
通过不同的滚动速度营造景深:
function ParallaxSection() {
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start end", "end start"]
});
const y = useTransform(scrollYProgress, [0, 1], [100, -100]);
return (
<motion.div ref={ref} style={{ y }}>
Parallax Content
</motion.div>
);
}
滚动进度条
function ScrollProgress() {
const { scrollYProgress } = useScroll();
return (
<motion.div
style={{
scaleX: scrollYProgress,
position: "fixed",
top: 0,
left: 0,
right: 0,
height: 4,
backgroundColor: "#00ff00",
transformOrigin: "0%"
}}
/>
);
}
将 useInView 与变体配合使用
进入视口时触发动画:
import { useInView, motion } from "framer-motion";
import { useRef } from "react";
function FadeInSection() {
const ref = useRef(null);
const isInView = useInView(ref, { once: true, margin: "-100px" });
return (
<motion.div
ref={ref}
initial={{ opacity: 0, y: 50 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 50 }}
transition={{ duration: 0.6 }}
>
Content
</motion.div>
);
}
useInView 选项
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| once | boolean | false | 仅触发一次 |
| margin | string | "0px" | 触发偏移量 |
| amount | "any" | "all" | number | "any" | 可见性阈值 |
最佳实践
- ✅ 使用 useScroll 和 useTransform 实现滚动关联动画。
- ✅ 使用 whileInView 实现简单的滚动触发动画。
- ✅ 使用恰当的 offset 值控制开始和结束位置。
- ✅ 对缩放动画使用
transformOrigin。
请勿
- ❌ 使用滚动动画时不设置 offset 值。
- ❌ 忘记为横向滚动容器设置高度。
- ❌ 为滚动效果添加布局属性动画。
- ❌ 对入场动画使用
useInView时不设置once: true。
了解更多
https://www.framer.com/motion/use-scroll/ https://www.framer.com/motion/use-transform/ https://www.framer.com/motion/use-in-view/
评论
支持 Markdown