Jump to content
Search Community

Horizontal Scrolling Section & sticking it when it come into the viewport.

whizbbig test
Moderator Tag

Recommended Posts

How can I use GSAP to animate cards within elementRef such that each card pauses when entering the viewport during a scroll, and as I scroll further, the card fades in opacity while moving to the left before the next card comes into view?

 

Sandbox Link

 

I have added the link of the sandbox so that I can explain my goals more clearly. You should view the preview in a next window in the editor :) only then will you be able to see the horizontal scroll. Thank you very much for your help  🙏

Link to comment
Share on other sites

Hi @Rodrigo,

I hope you're having a great day!

Thanks for sharing this, I've tried to apply information i got from the blog you shared in many differnet ways but now i am out of ideas i really don't know what special i should do to make them pin and fade away on scroll!!

 

I hope you've seen the sandbox link for understanding about the collision between horizontal scroll functionality that i have and scrolltrigger function

import { useMediaQuery, useRect } from '@studio-freight/hamo'
import cn from 'clsx'
import gsap from 'gsap'
import ScrollTrigger from 'gsap/ScrollTrigger'
import { useScroll } from '@/hooks/use-scroll'
import { clamp, mapRange } from '@/lib/maths'
import { useEffect, useRef, useState } from 'react'
import { useWindowSize } from 'react-use'

import s from './Horizontal.module.scss'
gsap.registerPlugin(ScrollTrigger)

export const HorizontalSlides = ({ children }: { children: React.ReactNode }) => {
    const elementRef = useRef<HTMLDivElement | null>(null);
    const isMobile = useMediaQuery('(max-width: 800px)')
    const [wrapperRectRef, wrapperRect] = useRect()
    const [elementRectRef, elementRect] = useRect()

    const { height: windowHeight } = useWindowSize()

    const [windowWidth, setWindowWidth] = useState<number>(0);

    useScroll(({ scroll }: { scroll: number }) => {
        setWindowWidth(window.innerWidth);
        if (!elementRect || !elementRef.current) return

        const start = wrapperRect.top - windowHeight
        const end = wrapperRect.top + wrapperRect.height - windowHeight

        let progress = mapRange(start, end, scroll, 0, 1)
        progress = clamp(0, progress, 1)

        const x = progress * (elementRect.width - windowWidth)

        const cards = Array.from(elementRef.current.children)

        gsap.to(cards, {
            x: -x,
            stagger: 0.033,
            ease: 'none',
            duration: 0,
        })
    })

    useEffect(() => {
        if (!elementRef.current) return;

        const onResize = () => {
            setWindowWidth(Math.min(window.innerWidth, document.documentElement.offsetWidth));
        };

        window.addEventListener('resize', onResize, false);
        onResize();

        Array.from(elementRef.current.children).forEach((card, index) => {
            let tl = gsap.timeline({
                scrollTrigger: {
                    trigger: card,
                    start: "left center-=500",
                    end: "right center+=500",
                    scrub: true,
                    markers: true,
                    horizontal: true,
                    pin: true,
                }
            });

            tl.to(card, {opacity: 0, duration: 1}, 0);
        });

        return () => {
            window.removeEventListener('resize', onResize, false);
            ScrollTrigger.getAll().forEach(st => st.kill());
        };
    }, [windowWidth]);

    return (
        <>
            <div
                className={s.wrapper}
                ref={wrapperRectRef}
                style={
                    elementRect && isMobile === false
                        ? { height: elementRect.width + 'px' }
                        : {}
                }
            >
                <div className={s.inner}>
                    {/* {isMobile === false ? ( */}
                    <div
                        ref={(node) => {
                            elementRef.current = node
                            elementRectRef(node)
                        }}
                        className={cn(s.overflow, 'hide-on-mobile')}
                    >
                        {children}
                    </div>
                    {/* ) : ( */}
                    <div className={cn(s.cards, 'hide-on-desktop')}>{children}</div>
                    {/* )} */}
                </div>
            </div>
        </>
    )
}

 

Link to comment
Share on other sites

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import the gsap-trial NPM package for using any of the bonus plugins: 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

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

Link to comment
Share on other sites

@GSAP Helper Thankyou for responding,

 

and now i understand the functionality i am expecting is more resembling the possiblity of using sliders so if you have any examples related to sliders that works on scroll. like when we scroll down from one section to a slider one it sticks there like the container is pinned and on scroll it slides in the elements/childrens from right horizontally and move to otther section vertically! :)

Link to comment
Share on other sites

Hi,

 

Honestly I'm having a few issues picturing exactly what you mean in your last post. We have a couple of ScrollTrigger collections in codepen that could serve as inspiration and good starting points for your project:

https://codepen.io/collection/AEbkkJ

 

https://codepen.io/collection/DkvGzg

 

 

Finally here is a demo that combines ScrollTrigger with the Observer Plugin:

See the Pen MWGVJYL by GreenSock (@GreenSock) on CodePen

 

If you don't find anything that helps, maybe post a site with a working version of what you're trying to do.

 

Happy Tweening!

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