如何在React中使用GSAP实现滚动触发的缩放切换效果?
需求与问题修复
交互需求
- 向下滚动至section1区域时,通过缓慢放大section1的操作逐步显示section2内容
- 向上滚动离开section2区域时,section1缩小恢复原状,重新显示section1内容
- 重复滚动时交互行为保持一致
原尝试代码(存在问题)
import React, { useEffect } from 'react'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; const SampleZoom () => { useEffect(() => { // Initialize gsap and ScrollTrigger gsap.registerPlugin(ScrollTrigger); // Get the innerHeight const { innerHeight } = window; // Define the zoom-out animation gsap.from("#section1", { scale: 2, // Zoom out by scaling down opacity: 0, // Make it fade in scrollTrigger: { trigger: "#zoom-out", start: "top top", // Start the animation at the top of the element end: `+=${innerHeight * 0.5}`, // End the animation after scrolling down by 50% of the viewport height scrub: 1, // Add scrubbing effect } }); // Define the zoom-in animation gsap.to("#section2", { scale: 1, // Zoom back in to normal size opacity: 1, // Make it fade in scrollTrigger: { trigger: "#zoom-in", start: "top top", // Start the animation at the top of the element end: `+=${innerHeight * 0.5}`, // End the animation after scrolling down by 50% of the viewport height scrub: 1, // Add scrubbing effect } }); }, []); return ( <div> <div id="section1"> <h2>ROBO</h2> </div> <div id="section2"> Hello world. I am Chitti, The Robot .. Speed 1 THz .. Memory 1 zettabyte. I'll be back. Get ready folks!" The most expensive movie made in India till date has finally released and has already broken all box office records. Enthiran! This is the same movie that was originally supposed to start in 1998 with Kamal Hassan playing the lead role, then with vikram in the early 2000 and went on to cast Shah Rukh Khan a couple of years back and finally released with Rajnikanth playing the lead role. I managed to watch the movie a week into its release and like a farewell note sent by an IT/ITES employee, I have mixed feeling. </div> </div> ); }; export default SampleZoom;
修复后的代码
import React, { useEffect } from 'react'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; import './SampleZoom.css'; // 引入配套样式 const SampleZoom = () => { useEffect(() => { gsap.registerPlugin(ScrollTrigger); // 创建时间线绑定同步动画 const timeline = gsap.timeline({ scrollTrigger: { trigger: "#container", start: "top top", end: "+=100vh", // 滚动一屏高度完成动画 scrub: true, toggleActions: "play reverse play reverse" // 适配滚动方向的动画行为 } }); // 同步执行:section1放大,section2逐步显示 timeline .to("#section1", { scale: 3, duration: 1 }) .to("#section2", { opacity: 1, duration: 1 }, 0); // 0表示与上一动画同时启动 // 清理ScrollTrigger防止内存泄漏 return () => { ScrollTrigger.getAll().forEach(trigger => trigger.kill()); }; }, []); return ( <div id="container"> <div id="section1"> <h2>ROBO</h2> </div> <div id="section2"> Hello world. I am Chitti, The Robot .. Speed 1 THz .. Memory 1 zettabyte. I'll be back. Get ready folks! The most expensive movie made in India till date has finally released and has already broken all box office records. Enthiran! This is the same movie that was originally supposed to start in 1998 with Kamal Hassan playing the lead role, then with vikram in the early 2000 and went on to cast Shah Rukh Khan a couple of years back and finally released with Rajnikanth playing the lead role. I managed to watch the movie a week into its release and like a farewell note sent by an IT/ITES employee, I have mixed feeling. </div> </div> ); }; export default SampleZoom;
配套样式文件(SampleZoom.css)
#container { height: 200vh; /* 容器高度设为两屏,提供滚动空间 */ position: relative; } #section1 { position: fixed; top: 0; left: 0; width: 100%; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: #fff; z-index: 1; transform-origin: center; /* 从中心向外放大 */ } #section2 { position: absolute; top: 100vh; left: 0; width: 100%; min-height: 100vh; padding: 2rem; box-sizing: border-box; opacity: 0; /* 初始状态隐藏 */ z-index: 0; }
关键修改说明
- 修复语法错误:修正组件定义的语法错误
const SampleZoom () =>→const SampleZoom = () => - 统一动画逻辑:使用GSAP Timeline将section1放大与section2显示绑定为同步动画,确保交互连贯
- 调整布局结构:设置容器高度为200vh提供滚动空间,section1设为fixed固定在视口,section2放在容器第二屏位置
- 优化ScrollTrigger配置:通过
toggleActions确保滚动方向切换时动画正确反向执行,添加清理函数避免内存泄漏 - 对齐初始状态:section2初始opacity设为0,随section1放大逐步显示,匹配需求中的"缓慢放大显示section2"效果
内容的提问来源于stack exchange,提问作者Allu Manikyam
相关产品推荐
相关产品推荐

