GSAP解锁动画的无限可能

前言

最近在看一些文章和官网的时候,都能看到一些酷炫的动画效果。就发现了GSAP这个好东西,可以说GSAP提升动画Level,减低动画难度。接下来看一下实现的GSAP常见动画。文章后面有仓库地址和在线观看地址。

不知道GSAP可以先去了解一下,就不写教学了。

GSAP官网 :Homepage | GSAP

正文

文字揭示效果

原理:将color设置为底色,揭示高亮的部分使用background-imagelinear-gradient实现,揭示过的部分也是使用background-imagelinear-gradient,再根据滚动距离设置background-position就可以了;还有最重要的一点要使用行内元素。

行内元素、块元素linear-gradient区别是有区别的,可以看出块元素linear-gradient会在整个元素背景上只出现一次,而行内元素不是这样的。

我们可以得到以下样式,接下来只要根据滚动确认distance就行了。

使用GSAP,根据滚动计算distance

tsx 复制代码
import React, { useEffect, useMemo, useRef, useState } from 'react';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/all';
import { useGSAP } from '@gsap/react';
import { Box, Text, Title } from './style';

gsap.registerPlugin(ScrollTrigger);

export default function Index() {
  const ALL_SCROLL_DISTANCE = 1200;
  const container = useRef(null);
  const text = useRef<HTMLDivElement>(null);
  const box = useRef(null);
  const sumLen = useRef(0);
  const [distance, setDistance] = useState(0);

  useGSAP(() => {
    if (text.current === null) {
      return;
    }
    const lineHeight: string = window.getComputedStyle(text.current).lineHeight;
    const textHeight = text.current.offsetHeight;
    const lines = Math.round(textHeight / Number(lineHeight.split('px')[0]));
    sumLen.current = lines * text.current.offsetWidth;

    const tl = gsap.timeline({
      scrollTrigger: {
        scroller: container.current,
        trigger: box.current,
        scrub: 2,
        pin: true,
        end: `+=${ALL_SCROLL_DISTANCE}`,
        onUpdate: self => {
          //前一半的进度
          const progress = self.progress;
          //设置距离
          setDistance((sumLen.current / ALL_SCROLL_DISTANCE) * progress * 100 * (ALL_SCROLL_DISTANCE / 100) * 2);
        },
      },
    });

    tl.to(box.current, {
      duration: ALL_SCROLL_DISTANCE / 2 / 1000, // 持续时间为总滚动距离的一半
      ease: 'none',
    });

    //后一半的动画,将整个文字高亮
    tl.to(box.current, {
      color: '#fff',
      duration: ALL_SCROLL_DISTANCE / 2 / 1000,
      ease: 'none',
    });
  }, []);

  return (
    <div
      ref={container}
      style={{
        height: '100vh',
        overflowY: 'auto',
        overflowX: 'hidden',
        backgroundColor: '#333',
      }}
    >
      <Title>
        <h2>down roll</h2>
      </Title>
      <Box ref={box}>
        <div>
          <Text
            ref={text}
            distance={distance}
            style={{
              wordBreak: 'break-all',
            }}
          >
            The rapid advancement of technology has transformed our daily lives in unprecedented ways. From smartphones
            to artificial intelligence, these innovations have made communication faster, work more efficient, and
            information more accessible.
          </Text>
        </div>
      </Box>

      <Title>
        <h2>End</h2>
      </Title>
    </div>
  );
}

滚动渐入效果

原理:使用GSAP根据滚动,将图片和文字移动一段距离

tsx 复制代码
 useGSAP(() => {
    gsap.to(title.current, {
      opacity: 0,
      scrollTrigger: {
        scroller: container.current,
        trigger: title.current,
        scrub: 2,
        // markers: true,
        start: 'top 180', // 动画开始位置
        end: 'bottom top',
      },
    });

    const leftList = [img1Ref.current, img3Ref.current];
    leftList.forEach(element => {
      gsap.from(element, {
        x: -50,
        scrollTrigger: {
          scroller: container.current,
          trigger: element,
          scrub: 1,
          // markers: true,
          start: 'top bottom', // 动画开始位置
          end: 'bottom bottom-=200',
        },
      });
    });

    const rightList = [img2Ref.current, img4Ref.current];

    rightList.forEach(element => {
      gsap.from(element, {
        x: 50,
        scrollTrigger: {
          scroller: container.current,
          trigger: element,
          scrub: 1,
          // markers: true,
          start: 'top bottom', // 动画开始位置
          end: 'bottom bottom-=200',
        },
      });
    });

    const elements = [p1Ref.current, p2Ref.current, p3Ref.current, p4Ref.current];
    elements.forEach(element => {
      gsap.from(element, {
        y: 60,
        opacity: 0,
        scrollTrigger: {
          scroller: container.current, // 如果你有自定义滚动容器
          trigger: element,
          scrub: 1,
          // markers: true,
          start: 'top bottom', // 动画开始位置
          end: 'bottom bottom-=200', // 动画结束位置
        },
      });
    });
  }, []);

在竖直滚动中横向滚动

原理:使用GSAPpin属性,计算出在滚动时需要平移的距离

tsx 复制代码
useGSAP(() => {
    if (box.current === null) {
      return;
    }
    gsap.to(box.current, {
      x: -(box.current.offsetWidth - window.innerWidth),
      scrollTrigger: {
        scroller: container.current,
        trigger: box.current,
        scrub: 2,
        // markers: true,
        end: '+=800',
        pin: true,
      },
    });
  }, []);

结语

感兴趣的可以去试试

仓库地址 :function-realization: 实现一些有趣的功能 (gitee.com)

在线观看地址: 卸任的博客 (hewkq.top)

相关推荐
We་ct20 小时前
LeetCode 15. 三数之和:排序+双指针解法全解析
前端·算法·leetcode·typescript
美狐美颜SDK开放平台20 小时前
直播场景下抖动特效的实现方案:美颜sdk开发经验分享
前端·人工智能·美颜sdk·直播美颜sdk·视频美颜sdk
草青工作室20 小时前
java-FreeMarker3.4自定义异常处理
java·前端·python
美狐美颜sdk21 小时前
抖动特效在直播美颜sdk中的实现方式与优化思路
前端·图像处理·人工智能·深度学习·美颜sdk·直播美颜sdk·美颜api
Mr Xu_21 小时前
Vue3 + Element Plus 实战:App 版本管理后台——动态生成下载二维码与封装文件上传
前端·javascript·vue.js
闻哥21 小时前
从 AJAX 到浏览器渲染:前端底层原理与性能指标全解析
java·前端·spring boot·ajax·okhttp·面试
比特森林探险记21 小时前
Vue基础语法与响应式系统详解
前端·javascript·vue.js
m0_6948455721 小时前
网站账号太多难管理?Enterr 开源自动化工具搭建教程
运维·服务器·前端·开源·自动化·云计算
光影少年21 小时前
react中redux的connect作用是什么
前端·react.js·前端框架
芋头莎莎21 小时前
基于MQTT通讯UNIapp程序解析JSON数据
前端·uni-app·json