프론트엔드 웹/React

gsap에서 배경 sticky하게 하고 애니메이션 적용 (+) multiple element에 동시에 애니메이션 효과 적용

세리둥절 2023. 6. 15. 21:04
반응형

GSAP으로 배경이 Sticky하게 걸려있는 상황에서 element등이 올라오도록  애니메이션 적용하기

이런식으로 스크롤에 따라서 요소들이 부드럽게 움직이는 것이 요즘 프론트 퍼블리싱 트렌드인 것 같다

네이버는 카드가 겹쳐지면서 조금씩 뒤로 가는 듯한 모습을 구현했다

 

이것을 GSAP의 ScrollTrigger를 활용해서 비슷하게 만들어보자!

 

 

코드

슬라이드2 안에서 카드1, 카드2, 카드3이 순서대로 올라오는 구조

const Slide2 = styled.div`
    display: flex;
    padding-bottom: 1000px; //스크롤이 충분히 내려가도록 padding
`;
const ThumbnailCard = styled.div<{color: string}>`
    position: absolute;
    display: flex;
    width: 560px;
    height: 550px;
    background-color: ${(props) => props.color};
`;
const Card1 = styled(ThumbnailCard)`
    z-index: 10;
`
const Card2 = styled(ThumbnailCard)`
    top: 70px;
    left: 60px;
    z-index: 20;
`
const Card3 = styled(ThumbnailCard)`
    top: 140px;
    left: 120px;
    z-index: 30;
`

 

하나씩 차례차례 아래에서 등장하는 애니메이션과

네이버처럼 돌아가는 애니메이션

 

2개 이상의 요소에 동시에 애니메이션 효과를 주고 싶을 때는 .add('point1') 처럼 어느 지점을 정해둔 다음에 애니메이션의 시작 지점을 동시에 설정해주면 된다. 

const Example = () => {

    useEffect(() => {
        gsap.registerPlugin(ScrollTrigger);
    
        const timeline = gsap.timeline({
          scrollTrigger: {
            trigger: `.slide2`,
            start: "top top",
            end: "+=100%",
            pin: true,
            markers: false,
            scrub: 0.3,
          },
        });

		/* 차례차례 아래에서 등장하는 애니메이션 */
        timeline
        .fromTo(".card1", {y: 1000}, {y: 0, duration: 0.5})
        .fromTo(".card2", {y: 1000}, {y: 0, duration: 0.5, delay: 0.5})
        .fromTo(".card3", {y: 1000}, {y: 0, duration: 0.5, delay: 1});

        /* 네이버와 동일한 애니메이션 */
        timeline
        .to(".card1", {scale: 0.95, duration: 0.5})
        .fromTo(".card2", {y: 1000}, {y: 50, duration: 1})
        .add('point1')
        .to(".card1", {scale: 0.9, duration: 0.5}, 'point1')
        .to(".card2", {scale: 0.95, duration: 0.5}, 'point1')
        .fromTo(".card3", {y: 1000}, {y: 100, duration: 1})
        .add('point2')
        .to(".card1", {scale: 0.85, duration: 0.5}, 'point2')
        .to(".card2", {scale: 0.9, duration: 0.5}, 'point2')
        .to(".card3", {scale: 0.95, duration: 0.5}, 'point2')
        ;

      }, []);
      
    return (
        <Container >
            <Slide2 className="slide2" >
                <InnerContainer className="row">
                    <MessageWithLink/>
                    <CardContainer>  
                        <CardBox>
                            <Card1 className="card1" color='#007F9B' />
                            <Card2 className="card2" color='#0058AB' />
                            <Card3 className="card3" color='#2394FF' />
                        </CardBox>
                    </CardContainer>
                </InnerContainer>
            </Slide2>
        </Container>

    )
}

export default Example;
반응형