12k
All articles

使用 GSAP 的 ScrollTrigger 动画让您的 UI 焕发生机

基于 GSAP 的 ScrollTrigger 插件构建滚动驱动动画,涵盖 scrubbing、pinning 及视差效果,可自然响应用户的滚动行为。

OpenReplay Team
OpenReplay Team
使用 GSAP 的 ScrollTrigger 动画让您的 UI 焕发生机

基于滚动的动画可以将静态网站转变为引人入胜的交互式体验。虽然 CSS 动画对于基本效果很有用,但创建复杂的滚动驱动动画需要更强大的工具。GSAP 的 ScrollTrigger 插件正是这样的工具——让您能够创建由滚动位置触发的精美、高性能动画。

在本指南中,您将学习如何实现能够自然响应用户滚动的 ScrollTrigger 动画,并提供可在您的项目中立即使用的实用示例。

核心要点

  • ScrollTrigger 将动画与滚动位置连接,创造交互式体验
  • 使用 scrub 将动画进度直接与滚动位置绑定
  • 固定元素以创建高级的基于滚动的效果
  • 配置 startend 来精确控制动画触发时机
  • 在开发过程中使用 markers 来可视化触发点

什么是 ScrollTrigger,为什么要使用它?

ScrollTrigger 是一个 GSAP 插件,它将动画与滚动位置连接起来。与仅在元素进入视口时触发动画的基本”滚动触发”库不同,ScrollTrigger 提供了精确控制:

  • 基于滚动位置的动画开始和结束时机
  • 用户滚动时动画的进度(擦除效果)
  • 在用户滚动经过时固定元素
  • 创建复杂的基于滚动的交互

结果如何?动画感觉与用户滚动相连,而不仅仅是在触发时播放。

ScrollTrigger 入门

首先,让我们设置基础结构:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ScrollTrigger Demo</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: Arial, sans-serif;
        }
        
        section {
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .spacer {
            height: 100vh;
        }
        
        .box {
            width: 200px;
            height: 200px;
            background-color: #3498db;
            border-radius: 8px;
        }
    </style>
</head>
<body>
    <div class="spacer"></div>
    
    <section>
        <div class="box"></div>
    </section>
    
    <div class="spacer"></div>
    
    <!-- GSAP and ScrollTrigger -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
    
    <script>
        // Register the plugin
        gsap.registerPlugin(ScrollTrigger);
        
        // Your animations will go here
    </script>
</body>
</html>

基础 ScrollTrigger 动画

让我们从一个简单的动画开始,当元素进入视口时触发:

gsap.to(".box", {
    scrollTrigger: ".box", // 触发动画的元素
    x: 300, // 向右移动 300px
    rotation: 360, // 旋转 360 度
    duration: 1.5, // 动画持续时间
    ease: "power2.out" // 缓动函数
});

这段代码在盒子进入视口时移动并旋转它。但这只是触及表面。

理解 ScrollTrigger 配置

要释放 ScrollTrigger 的全部潜力,我们需要理解其配置选项:

gsap.to(".box", {
    scrollTrigger: {
        trigger: ".box", // 触发动画的元素
        start: "top center", // 当盒子顶部到达视口中心时开始
        end: "bottom center", // 当盒子底部到达视口中心时结束
        toggleActions: "play pause reverse reset", // 进入、离开、重新进入、重新离开时的动作
        markers: true, // 显示调试标记(生产环境中移除)
    },
    x: 300,
    rotation: 360,
    duration: 2
});

startend 属性定义动画何时激活和停用。格式为 "[触发元素位置] [视口位置]"

toggleActions 控制动画在四个关键时刻的行为:

  1. 进入触发区域时
  2. 离开触发区域时
  3. 向上滚动时重新进入触发区域
  4. 向上滚动时离开触发区域

选项包括:playpauseresumereverserestartresetcompletenone

使用 Scrub 创建滚动驱动动画

真正的魔法发生在 scrub 属性上,它将动画进度直接与滚动位置绑定:

gsap.to(".box", {
    scrollTrigger: {
        trigger: ".box",
        start: "top center",
        end: "bottom center",
        scrub: true, // 将动画进度与滚动位置链接
        markers: true
    },
    x: 300,
    rotation: 360,
    backgroundColor: "#e74c3c"
});

使用 scrub: true,动画会随着用户滚动而进行,甚至在向上滚动时反向播放。为了更平滑的动画,使用数值如 scrub: 0.5 来添加轻微延迟。

在滚动过程中固定元素

ScrollTrigger 最强大的功能之一是在用户滚动时将元素固定在位:

gsap.to(".box", {
    scrollTrigger: {
        trigger: ".box",
        start: "center center",
        end: "+=300", // 在开始位置后 300px 处结束
        pin: true, // 在动画期间固定盒子
        scrub: 1,
        markers: true
    },
    x: 300,
    rotation: 360,
    scale: 1.5,
    backgroundColor: "#9b59b6"
});

这会在动画播放时将盒子固定在位,创造类似视差的效果。end: "+=300" 意味着动画在超过开始点 300 像素后结束。

创建显现动画

让我们为文本或图像创建一个实用的显现动画:

<div class="spacer"></div>

<section class="reveal-section">
    <div class="reveal-container">
        <h1 class="reveal-text">滚动驱动动画</h1>
        <p class="reveal-text">使用 GSAP ScrollTrigger 创建引人入胜的用户体验</p>
    </div>
</section>

<div class="spacer"></div>
.reveal-section {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.reveal-container {
    max-width: 800px;
    text-align: center;
    overflow: hidden;
}

.reveal-text {
    opacity: 0;
    transform: translateY(50px);
}
// 显现动画
gsap.utils.toArray('.reveal-text').forEach(text => {
    gsap.to(text, {
        scrollTrigger: {
            trigger: text,
            start: "top 80%", // 当文本顶部距离视口顶部 80% 时开始
            toggleActions: "play none none none"
        },
        y: 0,
        opacity: 1,
        duration: 1,
        ease: "power2.out"
    });
});

这创建了一个干净的显现效果,当每个文本元素进入视口时触发。

创建视差效果

视差效果为您的网站增加深度。以下是创建方法:

<div class="parallax-container">
    <div class="parallax-bg"></div>
    <div class="parallax-content">
        <h1>视差效果</h1>
    </div>
</div>
.parallax-container {
    height: 100vh;
    position: relative;
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
}

.parallax-bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 120%; /* 移动所需的额外高度 */
    background-image: url('your-background-image.jpg');
    background-size: cover;
    background-position: center;
}

.parallax-content {
    position: relative;
    z-index: 1;
    color: white;
    text-align: center;
}
// 视差效果
gsap.to(".parallax-bg", {
    scrollTrigger: {
        trigger: ".parallax-container",
        start: "top bottom",
        end: "bottom top",
        scrub: true
    },
    y: -100, // 滚动时背景向上移动 100px
    ease: "none"
});

这创建了一个简单的视差效果,背景以不同于前景的速度移动。

水平滚动部分

创建水平滚动部分是另一个令人印象深刻的效果:

<div class="spacer"></div>

<section class="horizontal-scroll">
    <div class="horizontal-container">
        <div class="panel">面板 1</div>
        <div class="panel">面板 2</div>
        <div class="panel">面板 3</div>
        <div class="panel">面板 4</div>
    </div>
</section>

<div class="spacer"></div>
.horizontal-scroll {
    overflow: hidden;
    height: 100vh;
}

.horizontal-container {
    display: flex;
    width: 400%; /* 100% * 面板数量 */
    height: 100%;
}

.panel {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2rem;
}

.panel:nth-child(1) { background-color: #3498db; }
.panel:nth-child(2) { background-color: #2ecc71; }
.panel:nth-child(3) { background-color: #e74c3c; }
.panel:nth-child(4) { background-color: #9b59b6; }
// 水平滚动
gsap.to(".horizontal-container", {
    scrollTrigger: {
        trigger: ".horizontal-scroll",
        start: "top top",
        end: "+=3000", // 滚动距离
        pin: true,
        scrub: 1,
    },
    x: () => -(document.querySelector(".horizontal-container").offsetWidth - window.innerWidth),
    ease: "none"
});

这创建了一个在用户垂直滚动时水平滚动的部分。

性能优化技巧

如果实现不当,ScrollTrigger 动画可能会影响性能。以下是一些技巧:

  1. 谨慎使用 will-change:仅应用于实际动画的元素
  2. 避免动画布局属性:尽可能坚持使用 transform 和 opacity
  3. 批处理相似动画:使用 gsap.utils.toArray() 并循环遍历元素
  4. 在不需要时销毁 ScrollTriggers:对于单页应用程序使用 scrollTrigger.kill()
  5. 减少标记使用:在生产环境中移除 markers: true

常见问题故障排除

动画开始得太早/太晚

如果您的动画在意外时间触发,请检查您的 startend 值。使用 markers: true 来可视化触发点。

动画卡顿

为了更平滑的动画,使用 scrub: 0.5 或更高值而不是 scrub: true 来添加轻微延迟。

移动端兼容性问题

移动浏览器处理滚动事件的方式不同。在移动设备上彻底测试,并考虑使用 ScrollTrigger.matchMedia() 为不同屏幕尺寸创建不同的动画。

结论

使用这些技术,您可以创建自然响应用户交互的滚动动画,在不让用户感到overwhelmed的情况下增强您的 UI。从简单效果开始,随着您对 ScrollTrigger 功能的熟悉逐渐融入更高级的技术。

常见问题

ScrollTrigger 能与 React/Vue/Angular 一起使用吗?

可以,但您需要在组件挂载/卸载时正确设置和清理 ScrollTrigger 实例。

我可以将 ScrollTrigger 与其他动画库一起使用吗?

ScrollTrigger 是为 GSAP 设计的,但您可以使用其回调函数来触发其他库。

如何让 ScrollTrigger 动画响应式?

使用百分比进行定位,并在窗口大小调整时使用 ScrollTrigger.refresh() 刷新 ScrollTrigger。

ScrollTrigger 免费使用吗?

基本功能是免费的,但一些高级功能需要 GreenSock Club 会员资格。

如何调试 ScrollTrigger 动画?

使用 markers: true 来可视化触发点,并在回调函数中使用 console.log 来跟踪进度。

Listen to your bugs 🧘, with OpenReplay

See how users use your app and resolve issues fast.
Loved by thousands of developers

We use cookies to improve your experience. By using our site, you accept cookies.