0

So I've only been working a couple of months in ReactJS, so please excuse me if the solution is simple.

I'm using the intersection observer from react-use to trigger a gsap animation once the desired section is in viewport. Now I don't want it to animate out, only animate in (once on initial load). I follow a tutorial, but their explanation was only to comment out the fade out animation, which is not working for me.

My code looks something like this:

const App = () =>{

 const sectionRef = useRef(null);

 const headlineFirst = ".animate-this-div"

 const intersection = useIntersection(sectionRef, {root: null,rootMargin: 
 "0px",threshold: 0.4});

 const fadeIn = () => {gsap.to(headlineFirst, 1, {opacity: 1,y:11,})};

 const fadeOut = () => {

 // gsap.to(headlineFirst , 1, {

 // opacity: 1,

 // y:49,

 // })

};



intersection && intersection.intersectionRatio < 0.4
? fadeOut()
: fadeIn(headlineFirst);

return (

<div ref={ sectionRef } className="some-div">

 <div className="animate-this-div"></div>

</div>

It must probably be the ternary operator. Would an "if statement" work instead, how would that "if statement" look (sorry still a noob at ReactJS)? Any advise would be SUPER appreciated

Figo22
  • 21
  • 1

1 Answers1

0

Scroll Trigger is just a plugin that helps you control a GSAP animation (single tween or timeline). What gets controlled uses the same approach as any other GSAP instance:

import React, { useRef, useEffect } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

const boxStyle = {
  opacity: 0,
  transform: "translateY(50px)"
};

export default function App() {
  const boxes = useRef([]);
  const boxesContainer = useRef();

  useEffect(() => {
    gsap.to(boxes.current, {
      scrollTrigger: {
        trigger: boxesContainer.current,
        start: "top 20%",
        markers: true
      },
      duration: 0.5,
      stagger: 0.1,
      opacity: 1,
      y: 0
    });
  }, []);

  return (
    <main>
      <section className="h-screen w-full bg-indigo-600">
        <h1 className="text-center text-3xl text-white font-bold px-4 py-8">
          ScrollTrigger React
        </h1>
      </section>
      <div
        id="boxContainer"
        className="w-full h-screen bg-green-700 py-2"
        ref={boxesContainer}
      >
        <div
          style={boxStyle}
          className="box w-1/4 bg-white h-24 m-2"
          ref={e => (boxes.current[0] = e)}
        />
        <div
          style={boxStyle}
          className="box w-1/4 bg-white h-24 m-2"
          ref={e => (boxes.current[1] = e)}
        />
        <div
          style={boxStyle}
          className="box w-1/4 bg-white h-24 m-2"
          ref={e => (boxes.current[2] = e)}
        />
        <div
          style={boxStyle}
          className="box w-1/4 bg-white h-24 m-2"
          ref={e => (boxes.current[3] = e)}
        />
      </div>
      <section className="h-screen w-full bg-indigo-600" />
    </main>
  );
}

The code above assumes that you have a series of elements with the class box inside another element with an id of boxesContainer and each box has an opacity of 0 and a Y translate applied to it. That code will animate each box for 0.5 seconds with a stagger time of 0.1 seconds, when the top of the boxes parent container, reaches the point that is 20% from the top of the viewport.

Live sample:

https://codesandbox.io/s/unruffled-wozniak-ho12x?file=/src/App.js

Rodrigo
  • 1,638
  • 1
  • 15
  • 27
  • Thank you Rodrigo, appreciate it. That solves a lot but the only problem I have with this is what if I had to give one of those "boxes" it own animation values. ScrollTrigger seems to ignore the delay. Here is a live sample: https://codesandbox.io/s/zen-dew-fr0xv?file=/src/App.js:0-1274 Please note I'm trying to stagger the P text with the Headings. Or is there a way I can write one useEffect but assign different animation values to different divs? – Figo22 Apr 17 '21 at 00:58