很多framer做的网站都有滚动的动画效果,比如楼层中的一个图片从小变大,然后继续滚动到下一个楼层可以让slider 卡片自动横向滚动,然后继续到下一个楼层滚动出现打字效果等等。
这类随着页面滚动(Scroll-driven)触发或联动的复杂 UX 效果,在 Framer 社区非常流行(通常被称为 Scrollytelling 或 Scroll-linked Animations)。
在前端工程中(特别是像你们常用的 Astro / React / Tailwind 体系),从实现成本、性能表现、控速精度三个维度来看,主流有以下几套成熟的技术方案:
1. 核心技术方案对比
| 方案类别 | 代表技术/库 | 实现难度 | 性能 (FPS) | 推荐适用场景 |
| A. 零依赖原生 (CSS 规范) | CSS scroll-timeline | 简单 | 极高 (GPU) | 简单的滚动缩放、文字打字显示、滚动进度条等 |
| B. 轻量级轻量触发库 | AOS.js / ScrollReveal / IntersectionObserver | 极低 | 高 | 滚动到某个位置时“触发一次”的动画(如打字、淡入) |
| C. 精细平滑联动库 (推荐) | Lenis + GSAPScrollTrigger | 中等 | 高 | 楼层图片缩放、吸顶固定 + 横向滚动卡片 (Horizontal Slider) |
| D. 声明式/框架专属 | Framer Motion (React/Next.js) | 低~中 | 中~高 | React / Next.js 项目中,追求极快开发效率的场景 |
2. 经典交互场景的具体实现思路
针对你提到的三个具体效果,前端的标准落地方式如下:
场景一:楼层图片“从小变大”(Scale / Expand on Scroll)
- 核心原理:将图片容器设为 Sticky 吸顶,随着
scrollTop的增加,动态改变scale(0.8 -> 1)和border-radius。 - 最佳方案:
- 轻量:CSS 原生
animation-timeline: scroll()(针对现代浏览器)。 - 全兼容:GSAP
ScrollTrigger的scrub: true(让动画与滚动进度 1:1 强绑定)。
- 轻量:CSS 原生
// GSAP 方案示例:图片随滚动变大并撑满屏幕
gsap.to(".hero-image", {
scale: 1,
borderRadius: "0px",
scrollTrigger: {
trigger: ".image-section",
start: "top top", // 当楼层顶部到达视口顶部
end: "+=100%", // 滚动的距离
scrub: 1, // 带有平滑阻尼的滚动联动
pin: true // 吸顶固定,直到动画结束
}
});
场景二:滚动到楼层时,横向 Slider 卡片自动平移(Horizontal Scroll Pin)
- 核心原理:“假横向,真纵向”。把外层
section设为height: 300vh(或者根据卡片总宽度动态计算),将卡片容器position: sticky吸顶。当用户向下滚动页面时,实际上是将内层卡片列表沿 X 轴向左平移transform: translateX(-Xpx)。 - 最佳方案:GSAP ScrollTrigger (Pin)。这是业界(包括苹果官网、Framer 导出的代码)做横向滚动楼层的绝对标准方案。
// GSAP 方案示例:纵向滚动驱动横向滑动
const cards = document.querySelector(".cards-wrapper");
gsap.to(cards, {
x: () => -(cards.scrollWidth - window.innerWidth),
ease: "none",
scrollTrigger: {
trigger: ".horizontal-section",
start: "top top",
end: () => "+=" + cards.scrollWidth,
pin: true, // 固定当前楼层
scrub: 1, // 强绑定滚动进度
invalidateOnRefresh: true,
}
});
场景三:滚动到楼层时触发“打字效果”(Typewriter Effect)
- 核心原理:此效果不需要强行与滚动进度 1:1 绑定(不用随着往下滑动逐字出来,那样体验反而很生硬),只需要在进入视口时触发一次打字即可。
- 最佳方案:
IntersectionObserver+ Typed.js (或原生 setInterval)。- 用
IntersectionObserver监测该文本楼层是否进入视口threshold: 0.5(进入 50%)。 - 触发一次打字动画或 Tailwind 的字数展开动画。
- 用
3. 给团队的技术选型建议 (Tech Stack Recommendation)
如果你们的技术栈主打 Astro / Vue / React / Tailwind,建议使用以下组合拳:
- 基础平滑滚动:Lenis.js
- Framer 网站之所以看起来非常优雅,很大一部分原因在于它们使用了平滑阻尼滚动(Smooth Scroll)。
- 强烈推荐在项目根部引入 Lenis(极轻量,性能远超旧时代的 Locomotive Scroll),它能瞬间赋予网页“Framer 级”的高级滚动手感。
- 复杂联动:GSAP + ScrollTrigger
- 处理横向滚动卡片、吸顶卡片叠楼层(Cards Stacking)、图片放大等交互,GSAP 是性能最稳、功能最全的选择。
- 性能与体验防坑指南(UX Guidelines):
- 移动端降级:横向滚动卡片在手机端(Touch screen)体验通常很差,建议在移动端(
< 768px)降级为原生横向滑动(overflow-x: auto+snap-x)或纯纵向平铺。 - 只用硬件加速属性:滚动联动中只修改
transform(scale, translate) 和opacity,绝对不要去动width,height,margin等会导致重排(Reflow)的属性,否则在低端设备上会导致卡顿。
- 移动端降级:横向滚动卡片在手机端(Touch screen)体验通常很差,建议在移动端(