将 gsap 时间线添加到父反应组件

adding gsap timeline to parent react component

我有几个使用 GSAP 制作入口动画的 React 组件。例如,我有一个 ImageReveal 组件,它在加载时执行漂亮的滑动动画。

import React, { useEffect, useRef } from 'react';

import { gsap } from 'gsap';

import s from './ImageReveal.scss';

interface ImageProps {
  src: string;
  alt?: string;
  className?: string;
  imageRef?: string;
}

export const ImageReveal = ({ src, alt, className }: ImageProps) => {
  const containerRef = useRef(null);
  const swipeRef = useRef(null);
  const imageRef = useRef(null);

  const tl = gsap.timeline({ defaults: { ease: 'Power2.easeInOut' } });

  useEffect(() => {
    tl.to(containerRef.current, { css: { visibility: 'visible' }, duration: 0 })
      .fromTo(
        swipeRef.current,
        { height: '100%' },
        {
          height: '0%',
          duration: 1.4,
          clearProps: 'height',
        },
      )
      .from(imageRef.current, { scale: 1.6, duration: 1.4, delay: -1.6 });
  }, []);

  return (
    <div className={s(s.imageReveal, className)} ref={containerRef}>
      <div className={s.imageReveal__swipe} ref={swipeRef} />
      <img src={src} alt={alt} ref={imageRef} />
    </div>
  );
};

但是,我想在父组件时间轴的上下文中使用此组件的时间轴。因此,例如,如果我有一个 ImageHero 组件,它有自己的时间轴,并且我在网格内使用 ImageReveal 组件,有没有一种方法可以在我的内部使用此时间轴ImageHero,或任何其他类似的用例,这样我就不必在每次使用 ImageReveal 组件时都编写时间表?这也是我的 ImageHero 所以你可以明白我在说什么。

import React, { useEffect, useRef } from 'react';

import { HeadingReveal } from 'components/heading-reveal/HeadingReveal';
import { ImageReveal } from 'components/image-reveal/ImageReveal';
import { gsap } from 'gsap';

import s from './ImageHero.scss';

interface ImageHeroProps {
  slice: any;
}

export const ImageHero = ({ slice }: ImageHeroProps) => {
  const gridRef = useRef(null);
  const headingRef = useRef(null);

  const tl = gsap.timeline({ delay: 0.5, defaults: { ease: 'Power4.easeInOut', duration: 1 } });

  useEffect(() => {
    tl.to(gridRef.current, { css: { visibility: 'visible' }, duration: 0 }).from(
      headingRef.current,
      { y: 80 },
    );
  }, []);

  return (
    <div className={s.imageHero} ref={gridRef}>
      <div className={s.imageHero__container}>
        {slice.primary.heading && (
          <HeadingReveal tag="h1" className={s.imageHero__heading} headingRef={headingRef}>
            {slice.primary.heading.text}
          </HeadingReveal>
        )}
        {slice.items.map((content: any, index: number) => {
          return (
            <ImageReveal
              src={content.image.url}
              className={s.imageHero__image}
              key={`image-${index}`}
              alt={content.image.alt}
            />
          );
        })}
      </div>
    </div>
  );
};

我为任何有代码示例的人创建了一个非常小的 CodeSandbox。非常感谢!

https://codesandbox.io/s/red-tdd-04qz5

我不是 React 用户,所以可能有更好的设置方法(比如不让你的 useEffect 依赖于时间线和功能)但我让它工作了这样:https://codesandbox.io/s/weathered-frost-nkuj9?file=/src/components/image-grid/ImageGrid.js

我使用了 the forum thread I referenced in the comments 中的格式并将其应用于您的情况。