Implementing click events to control GSAP animations in Next.js

I'm having trouble figuring out how to pause/start an animation using GSAP in Nextjs. Specifically, I can't seem to work with a tl.current outside the useEffect hook within this component. My goal is that when I click on the first .imgWrapper element, I want the tl.current to toggle and either pause or start the animation. However, despite my efforts, I haven't been able to make it work.

export const Projects = () => {
  const projects = useRef();
  const projectTitle = useRef(null);
  const tl = useRef();
  const q = gsap.utils.selector(projects);

  useEffect(() => {
    tl.current = gsap
      .timeline()
      .from(q(".singleProject:nth-child(2)"), {
        y: 2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        paused: false,
      })
      .to(q(".singleProject:nth-child(2)"), {
        y: -2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        paused: false,
      });
    tl.current = gsap
      .timeline()
      .from(q(".singleProject:nth-child(3)"), {
        y: 2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 1,
      })
      .to(q(".singleProject:nth-child(3)"), {
        y: -2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 1,
      });
    tl.current = gsap
      .timeline()
      .from(q(".singleProject:nth-child(4)"), {
        y: 2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 2,
      })
      .to(q(".singleProject:nth-child(4)"), {
        y: -2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 2,
      });
   
  }, []);
  const [animate_1, setAnimate_1] = useState(false);
  const [animate_2, setAnimate_2] = useState(false);
  const [animate_3, setAnimate_3] = useState(false);

  return (
    <section
      ref={projects}
      id="projects"
      className={`${animate_1 && "animated_1"} ${animate_2 && "animated_2"} ${animate_3 && "animated_3"} w_100 h_100vh flex flexColumn flexAlignCenter flexCenter p4em`}
    >
      <div className="projectsLoading flex flexCenter flexAlignCenter w_100 h_100">
        <h2>LOADING PROJECTS</h2>
      </div>
      <div className={`singleProject w_100 flex flexStart`}>
        <div className="imgWrapper" onClick={() => some code}>
          <img src={"https://www.aimanalmureish.com/img/lego.jpg"} />
        </div>
      </div>
      <div className="singleProject w_100 flex flexEnd">
        <div className="imgWrapper">
          <img
            onClick={() => {
              setAnimate_2(!animate_2);
            }}
            src={"https://www.aimanalmureish.com/img/jordan.png"}
          />
        </div>
      </div>
      <div className="singleProject w_100 flex flexStart">
        <div className="imgWrapper">
          <img
            onClick={() => setAnimate_3(!animate_3)}
            src={"https://www.aimanalmureish.com/img/ferrari.png"}
          />
        </div>
      </div>
    </section>
  );
};

After console logging tl.current.pause(), this is what shows up in the console https://i.stack.imgur.com/xo0LR.png.

Any assistance would be greatly appreciated. Thank you!

Answer №1

This updated answer provides a solution to the question.

The code snippet below shows how the Projects component is implemented:

export const Projects = () => {
  const projects = useRef();
  const projectTitle = useRef(null);
  const tl = useRef();
  const first = useRef();
  const second = useRef();
  const third = useRef();
  const q = gsap.utils.selector(projects);

  useEffect(() => {
    // Animation for first child
    first.current = gsap
      .timeline()
      .from(q(".singleProject:nth-child(2)"), {
        y: 2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        paused: false,
      })
      .to(q(".singleProject:nth-child(2)"), {
        y: -2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        paused: false,
      });

    // Animation for second child
    second.current = gsap
      .timeline()
      .from(q(".singleProject:nth-child(3)"), {
        y: 2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 1,
      })
      .to(q(".singleProject:nth-child(3)"), {
        y: -2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 1,
      });

    // Animation for third child
    third.current = gsap
      .timeline()
      .from(q(".singleProject:nth-child(4)"), {
        y: 2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 2,
      })
      .to(q(".singleProject:nth-child(4)"), {
        y: -2000,
        ease: Linear.easeNone,
        opacity: 1,
        duration: 20,
        repeat: -1,
        delay: 2,
      });
  }, []);
  
  // State variables for animation control
  const [animate_1, setAnimate_1] = useState(false);
  const [animate_2, setAnimate_2] = useState(false);
  const [animate_3, setAnimate_3] = useState(false);

  return (
    <section
      ref={projects}
      id="projects"
      className={`${animate_1 && "animated_1"} ${animate_2 && "animated_2"} ${
        animate_3 && "animated_3"
      }
       w_100 h_100vh flex flexColumn flexAlignCenter flexCenter p4em`}
    >
      <div className="projectsLoading flex flexCenter flexAlignCenter w_100 h_100">
        <h2>LOADING PROJECTS</h2>
      </div>
      <div ref={first} className={`singleProject w_100 flex flexStart`}>
        <div
          className="imgWrapper"
          onMouseEnter={() => {
            first.current.paused(true);
            second.current.paused(true);
            third.current.paused(true);
          }}
          onMouseLeave={() => {
            first.current.paused(false);
            second.current.paused(false);
            third.current.paused(false);
          }}
        >
          <img src={"https://www.aimanalmureish.com/img/lego.jpg"} />
        </div>
        {/* <div className="projectDetails flex flexColumn flexAlignStart flexCenter">
          <h2 ref={projectTitle}>PROJECT TITLE</h2>
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem,
            veniam! Reiciendis, totam explicabo quisquam dolorem quibusdam sit
            dignissimos corporis veniam.
          </p>
        </div> */}
      </div>
      <div ref={second} className="singleProject w_100 flex flexEnd">
        <div className="imgWrapper">
          <img
            onMouseEnter={() => {
              first.current.paused(true);
              second.current.paused(true);
              third.current.paused(true);
            }}
            onMouseLeave={() => {
              first.current.paused(false);
              second.current.paused(false);
              third.current.paused(false);
            }}
            src={"https://www.aimanalmureish.com/img/jordan.png"}
          />
        </div>

        {/* <div className="projectDetails flex flexColumn flexAlignStart flexCenter">
          <h2 ref={projectTitle}>PROJECT TITLE</h2>
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem,
            veniam! Reiciendis, totam explicabo quisquam dolorem quibusdam sit
            dignissimos corporis veniam.
          </p>
        </div> */}
      </div>
      <div ref={third} className="singleProject w_100 flex flexStart">
        <div className="imgWrapper">
          <img
            onMouseEnter={() => {
              first.current.paused(true);
              second.current.paused(true);
              third.current.paused(true);
            }}
            onMouseLeave={() => {
              first.current.paused(false);
              second.current.paused(false);
              third.current.paused(false);
            }}
            src={"https://www.aimanalmureish.com/img/ferrari.png"}
          />
        </div>
      </div>
    </section>
  );
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most effective method for embedding a Kotlin program into a website?

I have created a combat simulation tool in Kotlin for an online gaming community. Users can input the combat levels of two players, choose the number of duels to simulate, and then initiate the simulation which will provide win percentages and other stats. ...

Troubleshooting methods for repairing Node.js Package Manager

Currently, I am developing a website on Android phone using Termux with Next.js. Everything was functioning properly until recently when I created a new project using npx create-next-app and attempted to run it with npm run dev, encountering the following ...

Deactivate the button while you wait for the Google Maps directionService

When utilizing the Google Maps service to plot a route with multiple waypoints and under slow 3G conditions, I need to deactivate an HTML button until the new route is traced. calculateRoad(departure: any, arrival: any) { const request = { origin: ...

Using Python and Selenium to manipulate the webpage and execute JavaScript can help reconstruct the true HTML structure

I have a very basic Selenium code snippet that I am running: <input name="X" id="unique" value="" type="text"> <script> document.getElementById("unique").value="123"; </script> While I can retrieve the input value "123" using driv ...

Attempting to extract text by utilizing the getText() function in Selenium along with Javascript

Attempting to use the getText() method in Selenium and Javascript, but encountering issues. const {Builder, By, Key, until} = require('selenium-webdriver'); (async function example() { let driver = await new Builder().forBrowser('chrom ...

When accessing the JavaScript date object, no output is being returned

I have a calendar layout consisting of floated div elements, rather than using an actual <table>. My goal is to allow the user to click anywhere on a row to add a new booking. The challenge lies in accurately calculating the time at which they clicke ...

How can you make the table rows in jQuery scroll automatically while keeping the table header fixed in

Many solutions exist for making the header fixed and the table scrollable using code samples or plugins. However, my specific goal is to have the table data rows scroll automatically once they are loaded while keeping the header fixed in place. Is there a ...

Tips for waiting on image loading in canvas

My challenge involves interacting with the image loaded on a canvas. However, I am uncertain about how to handle waiting for the image to load before starting interactions with it in canvas tests. Using driver.sleep() is not a reliable solution. Here is ...

Using JQuery to access the element within a span

I am completely new to jQuery and still learning as I go. Here is a snippet of the code I'm working on: <div class = 'buttons'> <span> <input type='button' value='BUTTON1' id='button1'> ...

What is the reason behind only the final input value being shown on the screen?

I'm encountering an issue with my input fields. I have a total of five input fields. After filling all of them and clicking the button to display them on the screen, only the last one I entered is shown in all places... (let me know if this explanatio ...

Lowest value malfunctioning

I have encountered an issue with setting minimum values for 4 things. All 4 things are supposed to have the same minimum value as the first thing, but when moving the slider, everything goes back to normal and works fine. Where could the problem be origina ...

Utilizing PHP for Interactive JavaScript Modals

Encountering an issue with my JavaScript. The modal initially functions correctly, but upon clicking it for the second time, two modals appear - one from the previous click and another new one. The stacking of modals continues each time the button is cli ...

having difficulty placing 3 pop-up windows on a single page

Struggling to implement multiple popups on my page, each with a unique ID assigned. Any assistance would be greatly appreciated. Here is the code snippet: .fa { font-size: 50px; cursor: pointer; user-select: none; } .fa:hover { font-size:20px; t ...

What is the best way to divide an array into pairs and store them in separate arrays?

I'm attempting to challenge my JavaScript skills and faced with a dilemma. There is an array containing data var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];. The goal is to pair the elements and generate a new array of arrays such as var newArray = [[1 ...

Having trouble sending data through a jQuery AJAX request?

When I make a post request using jQuery AJAX to an ActionResult method, I encounter the following issue: $("#itemTextbox, #itemTextboxNew, #quantity1Textbox").on("keydown", function (e) { if ((e.keyCode == 120){ var GetReportLast5SellAndBuyURL="/Trd/Se ...

What could be causing the Express server to return an error despite everything being in order?

I am new to exploring express.js and attempting to create a basic sign-in example server. I have set up a database object with a users array containing objects, each with email and password properties. Despite using body-parser to convert the body into a j ...

Encountering difficulties with "removeChild" in React when attempting to dynamically update an array

In my React component's state, I have an array called "personArray." The component includes a search bar that triggers an API request and updates the "personArray" based on user input. In the render method, I map through this "personArray" to display ...

Class component proceeding without waiting for function completion

My function, getactivity(), pulls and sorts data from an API and returns the sorted data in answer1 format. However, I am facing a problem where whenever I run the function to retrieve the data, it keeps returning nothing. Here is the full code: import Re ...

How do I connect to a SOAP WebService in Node.js?

I am embarking on my first journey into accessing a Web Service. Specifically, I am attempting to connect to the Banxico SOAP Webservice in order to retrieve the exchange rate of the peso (M.N.) to the dollar. I am using Node with Express and have been re ...

Utilizing Firebase 9.0.1 Functions in Vue.js 3

As a newcomer to Vue, I decided to tackle my second tutorial which involved integrating Firebase backend with Vue. However, the tutorial was based on Vue 2 and an older version of Firebase. Determined to stay current, I set out to replicate the project usi ...