当前位置: 首页 > news >正文

react gsap动画库使用详解之scroll滑动动画

简介

gsap 高性能的 JavaScript 动画库,在现代网页设计和开发中运用。

安装

npm install gsap

React 框架中使用

可以考滤使用 react-gsap-enhancer 库,或者 @gasp/react
类组件使用 react-gsap-enhancer 高阶组件,函数组件使用 @gasp/react 自定义 Hook。

npm install react-gsap-enhancer
#or
yarn add react-gsap-enhancer

ScrollTrigger

ScrollTrigger 用于在滚动时触发动画。如滚动到指定位置时触发动画、滚动到指定位置时结束动画、滚动到指定位置时重复动画等。

基本使用

import React from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";gsap.registerPlugin(useGSAP, ScrollTrigger);const TextAnimation = () => {useGSAP(() => {gsap.fromTo(".gasp-text",{y: 100, // 初始位置},{scrollTrigger: {trigger: ".gasp-text", // 触发动画的元素start: "top bottom-=100", // 动画开始的位置toggleActions: "play none none reverse", // 动画触发时的行为markers: true, // 显示标记},duration: 1, // 动画持续时间y: 0, // 动画结束时的位置});});return (<div><div className="gasp-text">hello world</div></div>);
};

常用属性

  • trigger: 触发动画的元素
  • start: 动画开始的位置,可以是相对于触发元素的位置,也可以是相对于视口的位置
  • end: 动画结束的位置,可以是相对于触发元素的位置,也可以是相对于视口的位置
  • toggleActions: 动画触发时的行为,可以是 “play”(播放)、”pause”(暂停)、”resume”(恢复)、”reset”(重置)、”restart”(重新开始)。 按顺序为 onEnter、onLeave、onEnterBack 和 onLeaveBack,默认值 play none none none。进入 离开 返回进入 返回离开
  • markers: 是否显示标记,用于调试

页面视差滚动

import { useEffect, useRef } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";gsap.registerPlugin(useGSAP, ScrollTrigger);export default function GaspScrollDemo() {const sectionsRef = useRef([]);const titlesRef = useRef([]);const descsRef = useRef([]);// 滚动触发的动画useGSAP(() => {sectionsRef.current.forEach((section, index) => {// 创建时间线const tl = gsap.timeline({scrollTrigger: {trigger: section,start: "top top",end: "bottom top",pin: true,pinSpacing: true,scrub: false,},});// 随机方向数组const directions = [{ x: -100, y: 0 },{ x: 100, y: 0 },{ x: 0, y: -100 },{ x: 0, y: 100 },{ x: -100, y: -100 },{ x: 100, y: 100 },{ x: -100, y: 100 },];// 进入动画tl.fromTo([titlesRef.current[index], descsRef.current[index]],{...directions[index],opacity: 0,scale: 0.5,rotation: Math.random() * 30 - 15,},{x: 0,y: 0,opacity: 1,scale: 1,rotation: 0,duration: 1,ease: "power2.out",});// 停留动画tl.to([titlesRef.current[index], descsRef.current[index]],{scale: 1.05,duration: 0.5,ease: "power1.inOut",},"+=0.2").to([titlesRef.current[index], descsRef.current[index]], {scale: 1,duration: 0.5,ease: "power1.inOut",});// 离开动画tl.to([titlesRef.current[index], descsRef.current[index]],{y: -100,opacity: 0,scale: 0.8,rotation: -Math.random() * 30 + 15,duration: 1,ease: "power2.in",},"+=0.5");});}, []);const sections = [{color: "bg-red-500",title: "Red Section",desc: "A vibrant red section with dynamic animations",},{color: "bg-orange-500",title: "Orange Section",desc: "Warm orange tones with smooth transitions",},{color: "bg-yellow-500",title: "Yellow Section",desc: "Bright yellow energy with playful movements",},{color: "bg-green-500",title: "Green Section",desc: "Fresh green space with natural flow",},{color: "bg-blue-500",title: "Blue Section",desc: "Calm blue atmosphere with gentle animations",},{color: "bg-indigo-500",title: "Indigo Section",desc: "Deep indigo depth with smooth transitions",},{color: "bg-purple-500",title: "Purple Section",desc: "Rich purple elegance with dynamic effects",},];return (<div className="relative">{sections.map((section, index) => (<divkey={index}ref={(el) => (sectionsRef.current[index] = el)}className={`${section.color} h-screen w-full relative overflow-hidden flex items-center justify-center`}><div className="text-center z-10 px-4"><h2ref={(el) => (titlesRef.current[index] = el)}className="text-6xl font-bold text-white mb-6">{section.title}</h2><pref={(el) => (descsRef.current[index] = el)}className="text-xl text-white/80 max-w-2xl mx-auto">{section.desc}</p></div></div>))}</div>);
}

ScrollSmoother

ScrollSmoother 为基于 ScrollTrigger 的页面添加了垂直平滑滚动效果。

基本使用

import { useEffect, useRef, useState } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { ScrollSmoother } from "gsap/ScrollSmoother";
import { ScrollToPlugin } from "gsap/ScrollToPlugin";gsap.registerPlugin(useGSAP, ScrollTrigger, ScrollSmoother, ScrollToPlugin);export default function GaspScrollDemo() {const [activeSection, setActiveSection] = useState("box1");const sectionsRef = useRef([]);const titlesRef = useRef([]);const descsRef = useRef([]);// 创建动画时间线的函数const createAnimation = (index) => {const tl = gsap.timeline({scrollTrigger: {trigger: sectionsRef.current[index],start: "top center",end: "bottom center",toggleActions: "play none none reverse",},});tl.fromTo(titlesRef.current[index],{y: 100,opacity: 0,},{y: 0,opacity: 1,duration: 1,ease: "power2.out",});tl.fromTo(descsRef.current[index],{y: 50,opacity: 0,},{y: 0,opacity: 1,duration: 1,ease: "power2.out",},"-=0.5");return tl;};useGSAP(() => {// 创建平滑滚动const smoother = ScrollSmoother.create({wrapper: "#smooth-wrapper",content: "#smooth-content",smooth: 1.5,effects: true,});// 为每个部分创建 ScrollTriggersectionsRef.current.forEach((section, index) => {ScrollTrigger.create({trigger: section,start: "top center",end: "bottom center",onEnter: () => {setActiveSection(`box${index + 1}`);// 如果是第一屏,手动触发动画if (index === 0) {createAnimation(0);}},onEnterBack: () => {setActiveSection(`box${index + 1}`);// 如果是第一屏,手动触发动画if (index === 0) {createAnimation(0);}},});// 创建动画createAnimation(index);});// 初始加载时触发第一屏动画createAnimation(0);}, []);const goToBox = (id) => {gsap.to(window, {duration: 1,scrollTo: {y: `#${id}`,offsetY: 0,autoKill: false,},ease: "power2.inOut",});};const buttons = [{ id: "box1", color: "bg-red-500", activeColor: "bg-red-900" },{ id: "box2", color: "bg-orange-500", activeColor: "bg-orange-900" },{ id: "box3", color: "bg-yellow-500", activeColor: "bg-yellow-900" },{ id: "box4", color: "bg-green-500", activeColor: "bg-green-900" },{ id: "box5", color: "bg-blue-500", activeColor: "bg-blue-900" },{ id: "box6", color: "bg-indigo-500", activeColor: "bg-indigo-900" },];const sections = [{id: "box1",title: "Section 1",desc: "Welcome to Section 1",},{id: "box2",title: "Section 2",desc: "Welcome to Section 2",},{id: "box3",title: "Section 3",desc: "Welcome to Section 3",},{id: "box4",title: "Section 4",desc: "Welcome to Section 4",},{id: "box5",title: "Section 5",desc: "Welcome to Section 5",},{id: "box6",title: "Section 6",desc: "Welcome to Section 6",},];return (<div id="smooth-wrapper" className="h-screen overflow-hidden"><div className="fixed top-[30%] right-[10px] flex-col flex items-center gap-4 z-50">{buttons.map((button) => (<buttonkey={button.id}className={`w-10 h-10 transition-all duration-300 border-2 border-black ${activeSection === button.id ? button.activeColor : button.color}`}onClick={() => goToBox(button.id)}/>))}</div><div id="smooth-content" className="relative">{sections.map((section, index) => (<divkey={section.id}ref={(el) => (sectionsRef.current[index] = el)}id={section.id}className={`${buttons[index].color} h-screen w-full relative flex items-center justify-center`}><div className="text-center z-10 px-4 max-w-3xl"><h2ref={(el) => (titlesRef.current[index] = el)}className="text-6xl font-bold text-white mb-6">{section.title}</h2><pref={(el) => (descsRef.current[index] = el)}className="text-xl text-white/80">{section.desc}</p></div></div>))}</div></div>);
}

ScrollToPlugin

滚动到指定位置

基本使用

import { useEffect, useRef, useState } from "react";
import { gsap } from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { ScrollToPlugin } from "gsap/ScrollToPlugin";gsap.registerPlugin(useGSAP, ScrollTrigger, ScrollToPlugin);export default function GaspScrollDemo() {const [activeSection, setActiveSection] = useState("box1");const sectionsRef = useRef([]);useGSAP(() => {// 为每个部分创建 ScrollTriggersectionsRef.current.forEach((section, index) => {ScrollTrigger.create({trigger: section,start: "top center",end: "bottom center",onEnter: () => setActiveSection(`box${index + 1}`),onEnterBack: () => setActiveSection(`box${index + 1}`),});});}, []);const goToBox = (id) => {gsap.to(window, {duration: 1,scrollTo: {y: `#${id}`,offsetY: 0,autoKill: false,},ease: "power2.inOut",});};const buttons = [{ id: "box1", color: "bg-red-500", activeColor: "bg-red-900" },{ id: "box2", color: "bg-orange-500", activeColor: "bg-orange-900" },{ id: "box3", color: "bg-yellow-500", activeColor: "bg-yellow-900" },{ id: "box4", color: "bg-green-500", activeColor: "bg-green-900" },{ id: "box5", color: "bg-blue-500", activeColor: "bg-blue-900" },{ id: "box6", color: "bg-indigo-500", activeColor: "bg-indigo-900" },];return (<div className="box"><div className="fixed top-[30%] right-[10px] flex-col flex items-center gap-4">{buttons.map((button) => (<buttonkey={button.id}className={`w-10 h-10 transition-all duration-300 border-2 border-black ${activeSection === button.id ? button.activeColor : button.color}`}onClick={() => goToBox(button.id)}/>))}</div><divref={(el) => (sectionsRef.current[0] = el)}id="box1"className="bg-red-500 h-screen w-full"/><divref={(el) => (sectionsRef.current[1] = el)}id="box2"className="bg-orange-500 h-screen w-full"/><divref={(el) => (sectionsRef.current[2] = el)}id="box3"className="bg-yellow-500 h-screen w-full"/><divref={(el) => (sectionsRef.current[3] = el)}id="box4"className="bg-green-500 h-screen w-full"/><divref={(el) => (sectionsRef.current[4] = el)}id="box5"className="bg-blue-500 h-screen w-full"/><divref={(el) => (sectionsRef.current[5] = el)}id="box6"className="bg-indigo-500 h-screen w-full"/></div>);
}

更多使用示例

http://www.lryc.cn/news/574136.html

相关文章:

  • 分布式系统 - 分布式锁及实现方案
  • 【开源工具】一键解决使用代理后无法访问浏览器网页问题 - 基于PyQt5的智能代理开关工具开发全攻略
  • 爬虫002-----urllib标准库
  • 企业主动风险管理破局供应链“黑天鹅”,善用期货
  • PDF-XSS
  • 游戏盾高效防范DDoS攻击的安全防护
  • 跨平台是.NET Framework4.5与.NET8的核心区别
  • 用ESP8266+MQTT构建完全属于自己的物联网平台
  • Life:Internship in OnSea Day 1
  • Excel工具箱WPS版 增强插件 文本处理、批量录入 数据对比 高级排序
  • vivado使用非自带的第三方编辑器
  • 采集MFC软件的数据方法记录
  • Redis Stream 消息队列详解及 PHP 实现
  • 光伏电站 “智慧大脑”:安科瑞 Acrel-1000DP 分布式监控系统技术解析
  • 单片机测ntc热敏电阻的几种方法(软件)
  • 【Android】Activity 的生命周期和启动模式
  • SAP将指定EXCEL工作SHEET的数据上传到内表
  • 基于 BERT 与语义角色标注的细粒度中文仇恨言论检测
  • 剑指offer40_数字序列中某一位的数字
  • 中国风国潮通用PPT模版
  • 【项目管理】项目管理资料文档模板(ZIP,PPT,WORD)
  • 榕壹云无人售货机管理系统:开源架构赋能私有化部署,打造智能零售技术解决方案
  • AI 领航设计模式学习:飞算 JavaAI 解锁单例模式实践新路径
  • 在测试中,如何判断是前端 Bug 还是后端 Bug?
  • 错误: 程序包androidx.fragment.app不存在 import android
  • 实现 el-table 中键盘方向键导航功能vue2+vue3(类似 Excel)
  • Flutter ListTile 徽章宽度自适应的真正原因与最佳实践
  • iOS 为图片添加水印
  • 基于openfeign拦截器RequestInterceptor实现的微服务之间的夹带转发
  • react快速开始项目模板