Jump to content
Search Community

Adding ScrollTrigger animations to dynamically generated React markup

Lee Probert
Moderator Tag

Go to solution Solved by Lee Probert,

Recommended Posts

Posted

I have some simple sections being rendered in my React component but they are dynamically generated from a JSON file. All I need to do is pin each section to the top of the screen for an amount of time and then allow scrolling to the next section. I need to get the selector ID for each section and use that to identify the section as I scroll in and out.

 

Do I need to create an animation for each section like this or can I use the class storymode-section and hit them all in one go?

 

'use client';
import React, { useEffect, useRef, useState } from 'react';
import { gsap } from "gsap";
import { useGSAP } from '@gsap/react';
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { FakeStorymodeData } from '@/utils/FakeStorymode';
 
gsap.registerPlugin(useGSAP);
gsap.registerPlugin(ScrollTrigger);
 
interface StorymodeContentGSAPProps {
   
}
 
export const StorymodeContentGSAP: React.FC<StorymodeContentGSAPProps> = (props: StorymodeContentGSAPProps) => {
 
    const scrollRef = useRef<HTMLDivElement>(null);
    const [activeSection, setActiveSection] = useState<string>('Section 1');
    const [selectors, setSelectors] = useState<string[]>([]);
 
    useGSAP(() => {
        // add a ScrollTrigger for each section that will pin it to the top of the viewport for the duration of the viewport
        selectors.forEach((selector) => {
            const sectionElement = scrollRef.current?.querySelector(`#${selector}`);
            if (!sectionElement) return;
            gsap.to(sectionElement, {
                scrollTrigger: {
                    trigger: sectionElement,
                    start: "top top",
                    end: "bottom top",
                    pin: true,
                    pinSpacing: false,
                    onEnter: () => setActiveSection(selector),
                    onLeaveBack: () => setActiveSection(selector),
                }
            });
        }
        );
    }, {dependencies: [selectors], scope: scrollRef});
 
    useEffect(() => {
        // create an array of the section.id's
        const sectionIds = FakeStorymodeData.map((section) => section.id);
        setSelectors(sectionIds);
    }, []);
 
    return (
        <div ref={scrollRef} className="w-full h-full flex flex-col justify-start flex-shrink-0 overflow-y-auto prose ">
            {
                FakeStorymodeData.map((section, index) => {
                    return (
                        <section id={section.id} key={index} className={"storymode-section flex flex-col justify-start w-full p-2 mb-64 " }>
                            <header className="w-full bg-gray-300 p-2 rounded"><strong>STICKY HEADER</strong></header>
                            <h2>{section.header}</h2>
                            <p>{section.content}</p>
                        </section>
                    );
                })
            }
        </div>
    );
}
  • Solution
Posted

I got it working. Pretty much as described above. The only thing I had to add was the scroller property and link it to the ref of the <div/> that was scrolling. It isn't the Window.

  • Like 1

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...