将 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。非常感谢!
我不是 React 用户,所以可能有更好的设置方法(比如不让你的 useEffect
依赖于时间线和功能)但我让它工作了这样:https://codesandbox.io/s/weathered-frost-nkuj9?file=/src/components/image-grid/ImageGrid.js
我使用了 the forum thread I referenced in the comments 中的格式并将其应用于您的情况。
我有几个使用 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。非常感谢!
我不是 React 用户,所以可能有更好的设置方法(比如不让你的 useEffect
依赖于时间线和功能)但我让它工作了这样:https://codesandbox.io/s/weathered-frost-nkuj9?file=/src/components/image-grid/ImageGrid.js
我使用了 the forum thread I referenced in the comments 中的格式并将其应用于您的情况。