gsap-综合动画

446 阅读4分钟

视频部分 需要 改成 本地视频

 // 注册ScrollTrigger插件
        gsap.registerPlugin(ScrollTrigger);

        // 英雄区域入场动画
        gsap.timeline()
            .from(".hero-title", {
                opacity: 0,          // 初始完全透明
                y: 50,               // 初始位置在下方50px
                duration: 1,         // 动画持续1秒
                ease: "power2.out"   // 缓动效果:快速开始,缓慢结束
            })
            .from(".hero-subtitle", {
                opacity: 0,          // 初始完全透明
                y: 30,               // 初始位置在下方30px
                duration: 1,         // 动画持续1秒
                ease: "power2.out"   // 缓动效果:快速开始,缓慢结束
            }, "-=0.5");            // 提前0.5秒开始,与前一个动画重叠

        // 英雄区域退场动画
        ScrollTrigger.create({
            trigger: ".hero",        // 触发元素
            start: "top top",        // 开始位置:元素顶部对齐视窗顶部
            end: "bottom top",       // 结束位置:元素底部对齐视窗顶部
            scrub: 1,               // 平滑滚动效果,值为1表示滚动响应的延迟程度
            pin: true,              // 固定触发元素
            onUpdate: (self) => {    // 滚动更新时的回调函数
                gsap.to(".hero-title", {
                    opacity: 1 - self.progress,    // 透明度随进度反向变化
                    x: -100 * self.progress,       // 向左移动大100px
                    duration: 0                    // 立即更新无过渡
                });
                gsap.to(".hero-subtitle", {
                    opacity: 1 - self.progress,    // 透明度随进度反向变化
                    x: 100 * self.progress,        // 向右移动,最大100px
                    duration: 0                    // 立即更新,无过渡
                });
            }
        });

        // 视频区域动画
        ScrollTrigger.create({
            trigger: ".video-section",    // 触发元素:指定哪个元素触发动画
            start: "top top",            // 开始位置:元素顶部对齐视窗顶部时触发
            end: "+=200%",               // 结束位置:从开始位置再往下滚动两个视窗高度
            pin: true,                   // 固定元素:在动画期间将元素固定在视窗中
            scrub: true,                 // 滚动同步:动画进度跟随滚动条移动,true表示有平滑效果
            markers: true,               // 显示标记:在开发时显示滚动触发的位置标记
            onUpdate: self => {          // 滚动更新时的回调函数
                const progress = self.progress;  // 获取滚动进度(0-1之间)
                const video = document.querySelector("#myVideo");
                
                if (progress <= 0.5) {    // 前半段:视频播放(0-50%的滚动进度)
                    if (video.duration) {
                        // 视频播放进度跟随滚动进度,progress * 2将0-0.5映射为0-1
                        video.currentTime = (progress * 2) * video.duration;
                    }
                   
                } else {                  // 后半段:文字动画(50-100%的滚动进度)
                    // 将0.5-1的进度映射为0-1,用于文字动画
                    const textProgress = (progress - 0.5) * 2;
                    
                    // 左侧文字动画
                    gsap.to(".video-text-left", {
                        x: 100 * progress * 2,    // 水平移动距离随进度变化
                        opacity: textProgress,     // 透明度随进度变化
                        duration: 0,              // 立即更新,无过渡动画
                        ease: "power2.inOut"      // 缓动效果:渐入渐出
                    });
                    
                    // 右侧文字动画
                    gsap.to(".video-text-right", {
                        x: -100 * progress * 2,    // 反方向水平移动
                        opacity: textProgress,     // 透明度随进度变化
                        duration: 0,              // 立即更新,无过渡动画
                        ease: "power2.inOut"      // 缓动效果:渐入渐出
                    });
                }
            }
        });

        // 文字滑入区域动画
        const slidingTexts = document.querySelectorAll('.sliding-text');

        // 设置文字初始状态
        gsap.set(slidingTexts, {
            opacity: 0,                // 初始完全透明
            x: (index) => index % 2 === 0 ? -100 : 100, // 奇数从左侧,偶数从右侧开始
            y: 30                      // 初始位置在下方30px
        });

        // 文字区域滚动触发器
        ScrollTrigger.create({
            trigger: ".text-section",   // 触发元素
            start: "top top",          // 开始位置:元素顶部对齐视窗顶部
            end: "+=100%",             // 结束位置:滚动一个视窗高度
            pin: true,                 // 固定触发元素
            scrub: 1,                  // 平滑滚动效果
            markers: true,             // 显示标记(调试用)
            onUpdate: (self) => {
                const progress = self.progress;
                slidingTexts.forEach((text, index) => {
                    const start = (index / slidingTexts.length);
                    const end = ((index + 1) / slidingTexts.length);
                    const textProgress = gsap.utils.clamp(
                        0,
                        1,
                        (progress - start) / (end - start)
                    );
                    
                    gsap.to(text, {
                        opacity: textProgress,        // 透明度随进度变化
                        x: index % 2 === 0 
                            ? -100 + (textProgress * 100) // 从左侧进入
                            : 100 - (textProgress * 100), // 从右侧进入
                        y: 30 - (textProgress * 30),  // 向上移动
                        duration: 0,                  // 立即更新
                        ease: "power2.inOut"          // 缓动效果:渐入渐出
                    });
                });
            }
        });

        // 图片画廊动画
        const gallerySection = document.querySelector('.gallery-section');
        const galleryItems = document.querySelectorAll('.gallery-item');

        // 设置初始状态
        gsap.set(galleryItems, {
            opacity: 0,
            y: 50
        });

        // 创建滚动触发动画
        ScrollTrigger.create({
            trigger: ".gallery-section", // 触发元素
            start: "top top",           // 开始位置:元素顶部对齐视窗顶部
            end: "+=100%",              // 结束位置:滚动一个视窗高度
            pin: true,                  // 固定触发元素
            scrub: 1,                   // 平滑滚动效果
            markers: true,              // 显示标记(调试用)
            onUpdate: (self) => {
                const progress = self.progress;
                galleryItems.forEach((item, index) => {
                    const start = (index / galleryItems.length);
                    const end = ((index + 1) / galleryItems.length);
                    const itemProgress = gsap.utils.clamp(
                        0,
                        1,
                        (progress - start) / (end - start)
                    );
                    
                    gsap.to(item, {
                        opacity: itemProgress,         // 透明度随进度变化
                        y: 50 - (itemProgress * 50),  // 从下方向上移动
                        duration: 0,                   // 立即更新
                        ease: "power2.inOut"           // 缓动效果:渐入渐出
                    });
                });
            }
        });

        // 卡片区域动画
        const cards = document.querySelectorAll('.card');

        // 设置初始状态
        gsap.set(cards, {
            opacity: 0,
            y: 30,
            scale: 0.95
        });

        // 创建卡片动画
        ScrollTrigger.create({
            trigger: ".section",         // 触发元素
            start: "top top",           // 开始位置:元素顶部对齐视窗顶部
            end: "+=100%",              // 结束位置:滚动一个视窗高度
            pin: true,                  // 固定触发元素
            scrub: 1,                   // 平滑滚动效果
            markers: true,              // 显示标记(调试用)
            onUpdate: (self) => {
                const progress = self.progress;
                cards.forEach((card, index) => {
                    const start = (index / cards.length);
                    const end = ((index + 1) / cards.length);
                    const cardProgress = gsap.utils.clamp(
                        0,
                        1,
                        (progress - start) / (end - start)
                    );
                    
                    gsap.to(card, {
                        opacity: cardProgress,         // 透明度随进度变化
                        y: 30 - (cardProgress * 30),  // 从下方向上移动
                        scale: 0.95 + (cardProgress * 0.05), // 缓慢放大
                        duration: 0,                   // 立即更新
                        ease: "power2.inOut"           // 缓动效果:渐入渐出
                    });
                });
            }
        });

        // 进度条动画
        gsap.to(".progress", {
            width: "100%",              // 宽度变化到100%
            ease: "none",               // 线性变化,无缓动效果
            scrollTrigger: {
                trigger: "body",         // 触发元素是整个页面
                start: "top top",        // 开始位置:面顶部对齐视窗顶部
                end: "bottom bottom",    // 结束位置:页面底部对齐视窗底部
                scrub: 0.3               // 平滑滚动效果,值较小表示响应更快
            }
        });