在现代的网页设计中,滚动动画已经成为了一种非常受欢迎的设计趋势。它可以为用户提供更加沉浸式的体验,使内容在滚动时以动画的形式展现。在本文中,我们将探讨如何使用 GSAP 和 ScrollTrigger 来实现这种效果,并创建一个简单的示例来演示其功能。

什么是 GSAP?

GSAP(GreenSock Animation Platform)是一个强大的 JavaScript 动画库,它允许开发者创建高性能、兼容性好的动画效果。GSAP 提供了一系列的 API,使得创建动画变得非常简单和直观。

什么是 ScrollTrigger?

ScrollTrigger 是 GSAP 的一个插件,它允许你根据滚动位置来触发和控制动画。这意味着你可以在用户滚动到某个特定位置时开始、暂停、播放或反转动画。

示例:创建滚动动画

在我们的示例中,我们有几个全屏的 section,每个 section 都有自己的背景颜色和文本。我们还有一个 .pin-element,它将在滚动到特定位置时固定,并显示一系列的文本动画。

设置基础样式

首先,我们为 body 和 html 设置了基础样式,包括 marginpaddingoverflow。我们还使用了 scroll-snap-typescroll-snap-align 来实现滚动 snap 效果,这意味着当用户滚动时,内容会自动对齐到最近的 snap 点。

body, html {
    ...
    scroll-snap-type: y mandatory;
    scroll-snap-stop: always;
    ...
}

.section {
    ...
    scroll-snap-align: start;
    ...
}

使用 GSAP 和 ScrollTrigger

首先,我们需要注册 ScrollTrigger 插件:

gsap.registerPlugin(ScrollTrigger);

接下来,我们为每个 section 创建动画。例如,当 .c1 section 进入视口时,我们希望其内部的文本旋转360度:

gsap.to(".c1 p", {
    scrollTrigger: ".c1",
    duration: 2,
    rotation: 360,
});

对于 .pin-element,我们希望它在滚动到特定位置时固定,并显示一系列的文本动画:

let tl = gsap.timeline({
    scrollTrigger: {
        trigger: ".pin-element",
        start: "center center",
        endTrigger: ".z5",
        end: "top top",
        pin: true,
        pinSpacing: false,
        scrub: 0.5,
        markers: true,
    }
});

Demo演示

ScrollTrigger-snap.html

这个样例主要涉及滚动与CSS Snap相结合、pin的使用等。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GSAP ScrollTrigger Snap Demo</title>
    <style>
        body,
        html {
            margin: 0;
            padding: 0;
            /* overflow: hidden; */
            overscroll-behavior-y: none;
            scroll-snap-type: y mandatory;
            scroll-snap-stop: always;
            scroll-margin: 0px;
            scroll-padding: 0px;
            background-color: black;
        }

        .section {
            display: flex;
            width: 100vw;
            height: 100vh;
            scroll-snap-align: start;
            justify-content: center;
            align-items: center;
        }

        .section p {
            font-size: 4rem;
            text-align: center;
        }

        .c1 {
            background-color: white;
        }

        .c2 {
            color: white;
            background-color: black;
        }

        .c3 {
            background-color: white;
        }

        .c4 {
            color: white;
            background-color: black;
        }

        .pin-element {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            position: relative;
            width: 100vw;
            height: 100vh;
            min-height: 310px;
            background-color: black;
            color: rgb(63, 63, 63);
            top: 100vh;
            padding: 20px;
            /* padding-left: 10%; */
            box-sizing: border-box;
            overflow: auto;
        }

        .pin-element p {
            font-size: 2rem;
            width: 200px;
            flex-grow: 0;
            flex-shrink: 1;
            margin: 10px;
        }

        .nomore {
            color: white;
            height: 100vh;
            width: 100vw;
            scroll-snap-align: start;
        }
    </style>
</head>

<body>
    <section class="section c1">
        <p>Hello,</p>
    </section>
    <section class="section c2">
        <p>Here is</p>
    </section>
    <section class="section c3">
        <p>ScrollTrigger Demo</p>
    </section>
    <section class="section c4 yoyo">
        <p>Ah!</p>
    </section>

    <section class="pin-element">
        <p>永远相信,</p>
        <p>美好的事情,</p>
        <p>即将发生...</p>
    </section>

    <div class="nomore z1">z1</div>
    <div class="nomore z2">z2</div>
    <div class="nomore z3">z3</div>
    <div class="nomore z4">z4</div>
    <div class="nomore z5">z5</div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/ScrollTrigger.min.js"></script>
    <script>
        gsap.registerPlugin(ScrollTrigger);

        ScrollTrigger.defaults({
            toggleActions: "restart pause resume pause",
            // markers: true,
        });

        gsap.to(".c1 p", {
            scrollTrigger: ".c1",
            duration: 2,
            rotation: 360,
        });

        gsap.to(".c2", {
            scrollTrigger: {
                trigger: ".c2",
                toggleActions: "restart pause reverse pause"
            },
            duration: 1,
            backgroundColor: "white",
            color: 'black',
        });

        gsap.to(".c3", {
            scrollTrigger: {
                trigger: ".c3",
                toggleActions: "restart pause reverse pause"
            },
            duration: 1,
            backgroundColor: "black",
            color: 'white',
        });

        gsap.to(".yoyo p", {
            scrollTrigger: ".yoyo",
            scale: 2,
            repeat: -1,
            yoyo: true,
        });

        // 创建一个新的GSAP时间轴
        let tl = gsap.timeline({
            scrollTrigger: {
                trigger: ".pin-element",
                start: "center center",
                endTrigger: ".z5",
                end: "top top",
                pin: true,
                pinSpacing: false,
                scrub: 0.5,
                // markers: true,
            }
        });

        // 为.pin-element添加pin动画
        tl.to(".pin-element", {}, 0); // 这里的空对象{}是为了确保.pin-element的pin动画与其他动画同时开始

        // 为每个<p>元素添加一个动画,使其在滚动时变为高亮
        tl.add([
            gsap.to(".pin-element p:nth-child(1)", { color: "white", duration: 0.25 }),
            gsap.to(".pin-element p:nth-child(1)", { color: "rgb(63, 63, 63)", duration: 0.25, delay: 0.25 }),
            gsap.to(".pin-element p:nth-child(2)", { color: "white", duration: 0.25, delay: 0.25 }), 
            gsap.to(".pin-element p:nth-child(2)", { color: "rgb(63, 63, 63)", duration: 0.25, delay: 0.5 }),
            gsap.to(".pin-element p:nth-child(3)", { color: "white", duration: 0.25, delay: 0.5 }) 
        ], 0);

        // 为<p>元素添加垂直移动动画
        tl.fromTo(".pin-element p", { y: 120 }, { y: -10, duration: 1 }, 0);

    </script>
</body>

</html>

效果展示

2023-08-20-17.28.27.png

> 下载演示视频 <

这样的吸附效果正好可以使得你每次按下空格键或者↓方向键时就往下执行一步动画,有点Web PPT的感觉。

总结

GSAP 和 ScrollTrigger 提供了一个强大的工具集,使得创建滚动动画变得非常简单。通过这些工具,你可以为你的网站或应用程序添加吸引人的动画效果,提供更加沉浸式的用户体验。


A Student on the way to full stack of Web3.