Jump to content
Search Community

Video and text animation while scrolling

Minhaz19 test
Moderator Tag

Recommended Posts

I'm working on a project where I am expecting 4 texts to appear on the 4 sides of a video while scrolling. As I scroll down, I want the video to gradually reduce in size, and when scrolling up, it should increase in size again. I tried implementing this in React (Next JS), but it's not working as intended. Here's the code I've written. And I have attached a video of what I am looking for. Could anyone help me figure out what might be going wrong?

 

"use client";

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

const CompanyOverview = () => {
  const videoRef = useRef(null);
  const containerRef = useRef(null);
  const leftTextRef = useRef(null);
  const upTextRef = useRef(null);
  const rightTextRef = useRef(null);
  const bottomTextRef = useRef(null);

  useEffect(() => {
    const container = containerRef.current;
    const video = videoRef.current;
    const left = leftTextRef.current;
    const up = upTextRef.current;
    const right = rightTextRef.current;
    const bottom = bottomTextRef.current;

    gsap.registerPlugin(ScrollTrigger);

    const tl = gsap.timeline({
      scrollTrigger: {
        trigger: container,
        start: "top top",
        end: () => "+=" + window.innerHeight,
        scrub: 1,
        pin: true,
        pinSpacing: false,
      },
    });

    tl.fromTo(
      video,
      { height: "100vh", width: "100%", duration: 1 },
      { height: "200px", width: "200px", duration: 1 }
    );

    tl.fromTo(
        left,
        {autoAlpha: 0, x: "-100%", duration: 1 },
        { autoAlpha: 1, x: "0%", duration: 1 },
        "-=0.75"
      );
    tl.fromTo(
        up,
        {autoAlpha: 0, y: "100%", duration: 1 },
        { autoAlpha: 1, y: "0%", duration: 1 },
        "-=0.75"
      );
    tl.fromTo(
        right,
        {autoAlpha: 0, x: "100%", duration: 1 },
        { autoAlpha: 1, x: "0%", duration: 1 },
        "-=0.75"
      );
    tl.fromTo(
        bottom,
        {autoAlpha: 0, y: "0%", duration: 1 },
        { autoAlpha: 1, y: "-100%", duration: 1 },
        "-=0.75"
      );

    return () => {
      tl.kill();
    };
  }, []);

  return (
    <div
      ref={containerRef}
      className="flex items-center justify-center h-screen"
    >
     
      <video
        ref={videoRef}
        autoPlay
        loop
        muted
        playsInline
        className="object-cover max-w-full max-h-full"
      >
        <source
          src="a_video_link_here.mp4"
          type="video/mp4"
        />
      </video>
      <h1
        ref={leftTextRef}
        className="absolute left-60 text-secondary-50 text-6xl font-bold "
      >
        Empowering
      </h1>
      <h1
        ref={upTextRef}
        className="absolute top-60 text-secondary-50 text-6xl font-bold "
      >
        Empowering
      </h1>
      <h1
        ref={rightTextRef}
        className="absolute right-60 text-secondary-50 text-6xl font-bold "
      >
        Empowering
      </h1>
      <h1
        ref={bottomTextRef}
        className="absolute bottom-60 text-secondary-50 text-6xl font-bold "
      >
        Empowering
      </h1>
    </div>
  );
};

export default CompanyOverview;

 

Edited by Minhaz19
Link to comment
Share on other sites

Hi there! Vague details like 'it doesn't work the way I want' are very difficult for people to help with. Here are some tips that will increase your chance of getting a solid answer:

  • A clear description of the expected result - "I am expecting the purple div to spin 360degrees"
  • A clear description of the issue -  "the purple div only spins 90deg"
  • A list of steps for someone else to recreate the issue - "Open the demo on mobile in IOS safari and scroll down to the grey container" 
  • A minimal demo - if possible, using no frameworks, with minimal styling, only include the code that's absolutely necessary to show the issue. Please don't include your whole project. Just some colored <div> elements is great.

Here's a React starter template you can fork. 

Link to comment
Share on other sites

I see that you edited your question, but that didn't really help. Sorry. 

 

If you want help, please make sure you take the time to provide a minimal demo, like a CodePen or Stackblitz. And be very specific about EXACTLY what isn't working the way you wanted. It's not helpful to just say "here's a video...here's my code...please fix it for me." :)

We're happy to answer GSAP-specific questions. We just don't have the resources to provide free general consulting, logic troubleshooting, or "tell me how to build this cool effect I saw" tutorials. 

 

Once we see an isolated demo, we'll do our best to jump in and help with any GSAP-specific questions. 

Link to comment
Share on other sites

Hi there! I see you're using React -

Proper animation cleanup is very important with frameworks, but especially with React. React 18 runs in strict mode locally by default which causes your useEffect() and useLayoutEffect() to get called TWICE.

 

Since GSAP 3.12, we have the useGSAP() hook (the NPM package is here) that simplifies creating and cleaning up animations in React (including Next, Remix, etc). It's a drop-in replacement for useEffect()/useLayoutEffect(). All the GSAP-related objects (animations, ScrollTriggers, etc.) created while the function executes get collected and then reverted when the hook gets torn down.

 

Here is how it works:

const container = useRef(); // the root level element of your component (for scoping selector text which is optional)

useGSAP(() => {
  // gsap code here...
}, { dependencies: [endX], scope: container }); // config object offers maximum flexibility

Or if you prefer, you can use the same method signature as useEffect():

useGSAP(() => {
  // gsap code here...
}, [endX]); // simple dependency Array setup like useEffect()

This pattern follows React's best practices.

 

We strongly recommend reading the React guide we've put together at https://gsap.com/resources/React/

 

If you still need help, here's a React starter template that you can fork to create a minimal demo illustrating whatever issue you're running into. Post a link to your fork back here and we'd be happy to take a peek and answer any GSAP-related questions you have. Just use simple colored <div> elements in your demo; no need to recreate your whole project with client artwork, etc. The simpler the better. 

 

Finally this thread can offer some inspiration as well:

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...