Jump to content
Search Community

Search the Community

Showing results for tags 'react'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


X


CodePen


Company Website


other


Location


Interests

Found 266 results

  1. It has to look so: but the most I manage to achive is: I don't know how to make the second side of the V shape, I will be thirled for help by fixing my code or simply give me a new match code. thanks in advanced. attached is the current react code I'm using: css: * { box-sizing: border-box; } html, body { height: 100%; min-height: 100%; font-family: Roboto, sans-serif; background: #e2e0e0; } main { display: flex; position: relative; flex-direction: column; width: 100vw; height: 100vh; overflow: hidden; align-items: center; justify-content: center; } .cell { position: absolute; top: 0; left: 0; width: 100%; font-size: 26px; font-weight: 500; color: rgba(0, 0, 0, 0.87); user-select: all; display: flex; align-items: center; justify-content: center; background: #eee; height: 70%; transform-origin: center center; } .picker { position: relative; overflow: hidden; width: 80vw; height: 90vh; border-radius: 2px; background-color: #fff; box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); } js: import { useRef } from 'react'; import gsap from 'gsap'; import { Draggable } from 'gsap/all'; import { useGSAP } from '@gsap/react'; gsap.registerPlugin(Draggable); const App = () => { const pickerRef = useRef(null); const cellsRef = useRef([]); useGSAP(() => { gsap.defaults({ ease: 'none' }); const picker = pickerRef.current; const cells = cellsRef.current; const proxy = document.createElement('div'); const myWrapper = gsap.utils.wrap(0, 0.871); const cellWidth = 75; const numCells = cells.length; const cellStep = 1 / numCells; const wrapWidth = cellWidth * numCells; const baseTl = gsap.timeline({ paused: true }); gsap.set(picker, { width: wrapWidth - cellWidth, }); cells.forEach((cell, i) => { initCell(cell, i); }); const animation = gsap .timeline({ repeat: -1, paused: true }) .add(baseTl.tweenFromTo(1, 2)); const draggable = Draggable.create(proxy, { type: 'x', trigger: picker, inertia: true, onDrag: updateProgress, onThrowUpdate: updateProgress, snap: { x: snapX, }, onThrowComplete: () => { console.log('onThrowComplete'); // TODO: animation that injects selected card title }, })[0]; function snapX(x) { return Math.round(x / cellWidth) * cellWidth; } function updateProgress() { animation.progress(myWrapper(draggable.x / wrapWidth)); } function initCell(element, index) { gsap.set(element, { width: cellWidth, scale: 0.6, x: -cellWidth, y: 0, }); const tl = gsap .timeline({ repeat: 1 }) .to(element, { duration: 1, x: `+=${wrapWidth}`, y: '+=70' }, 0) .to( element, { duration: cellStep, color: '#009688', scale: 0.778, repeat: 1, yoyo: true, }, 0.5 - cellStep ); baseTl.add(tl, index * -cellStep); } }, []); return ( <main> <div ref={pickerRef} className="picker"> {Array.from({ length: 5 }, (_, index) => ( <div key={index} ref={(el) => (cellsRef.current[index] = el)} className="cell" > <div className="cell-content">{`Card ${index + 1}`}</div> </div> ))} </div> </main> ); }; export default App;
  2. Initially, I wanted to create a GSAP ScrollTrigger responsive split-screen pinning effect similar to what is showcased on deveb.co. However, I was never able to get it to work. As a result, I decided to simplify and go back to the basics, using this codepen project: OLD scroll left pin right mockup -- not responsive. It was during this process that I realized the root of my issue had always been the same: whenever the column pinning starts, it disappears, and when the animation ends, it reappears. I've spent hours searching through forums for solutions but haven't found a fix. I first tried using gsap.context(); to resolve the issue: // Scroll.jsx import React, { useLayoutEffect } from 'react'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; import './Scroll.css'; gsap.registerPlugin(ScrollTrigger); const Scroll = () => { useLayoutEffect(() => { let ctx = gsap.context(() => { ScrollTrigger.create({ trigger: ".gallery", start: "top top", end: "bottom bottom", pin: ".right", pinSpacing: true, markers: true, scrub: true, }); }); return () => ctx.revert(); }, []); return ( <> <div className="spacer"></div> <div className="gallery"> <div className="left"> <div className="detailsWrapper"> <div className="details"> <div className="headline"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> </div> <div className="details"> <div className="headline"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> </div> <div className="details"> <div className="headline"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> </div> </div> </div> <div className="right"> <div className="photos"></div> </div> </div> <div className="spacer"></div> <div className="spacer"></div> <div className="spacer"></div> </> ); }; export default Scroll; That didn't work, so I decided to use useGSAP(), but it still produces the same result. // Scroll.jsx import React, { useRef } from 'react'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; import { useGSAP } from '@gsap/react'; import './Scroll.css'; gsap.registerPlugin(ScrollTrigger); const Scroll = () => { const galleryRef = useRef(null); useGSAP( () => { ScrollTrigger.create({ trigger: galleryRef.current, start: "top top", end: "bottom bottom", pin: ".right", pinSpacing: true, scrub: true, markers: true, }); }, { scope: galleryRef } ); return ( <> <div className="spacer"></div> <div ref={galleryRef} className="gallery"> <div className="left"> <div className="detailsWrapper"> <div className="details"> <div className="headline"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> </div> <div className="details"> <div className="headline"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> </div> <div className="details"> <div className="headline"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> <div className="text"></div> </div> </div> </div> <div className="right"> <div className="photos"></div> </div> </div> <div className="spacer"></div> <div className="spacer"></div> <div className="spacer"></div> </> ); }; export default Scroll; I have reviewed the React & GSAP | GSAP | Docs & Learning, countless forums, and YouTube tutorials, but I’m still struggling to find a solution. I’m reaching out to you in the hope that you can help me. /* Scroll.css */ body { background: #EEF4FF; margin: 0; } .spacer { width: 100%; height: 50vh; background: #ddd; } .headline { background: #2D4E86; border-radius: 6px; height: 4em; width: 100%; } .text { margin: 0.8em 0 0 0; background: #2D4E86; border-radius: 6px; height: 1em; width: 100%; } .gallery { display: flex; outline: 1px solid red; height: auto; } .left { width: 50%; } .detailsWrapper { margin: auto; width: 80%; } .details { height: 100vh; outline: 1px solid green; display: flex; flex-direction: column; justify-content: center; } .right { position: sticky; top: 0; outline: 1px solid purple; width: 50%; height: 100vh; display: flex; flex-direction: column; justify-content: center; /* overflow: hidden; */ z-index: 1; } .photos { width: 40vw; height: 40vw; background: maroon; /* visibility: visible; */ } I’ve attached a video that visually demonstrates the issue, and I would be incredibly grateful for your assistance in resolving this. ScrollTrigger Pin Issue.mp4
  3. Hi, guyz I am Nadeem I am running into error that my svg is not actually morphing . Can anyone help me with this ....
  4. I'm just starting out with React and `useGSAP` and I'm running into an issue with out what appears to be the hook registering: react.development.js:1630 Uncaught TypeError: Cannot read properties of null (reading 'useRef') at useRef (react.development.js:1630:1) at useGSAP (index.js:32:1) However, despite this error - I can console.log the `useGSAP` hook, and also the `gsap` package and both are successfully loaded. This error message happens when I try to use useGSAP. This is the error message i'm getting: Segment.tsx:39 Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem. printWarning @ react.development.js:209 error @ react.development.js:183 resolveDispatcher @ react.development.js:1592 useRef @ react.development.js:1629 useGSAP @ index.js:32 (anonymous) @ Segment.tsx:39 react.development.js:1630 Uncaught TypeError: Cannot read properties of null (reading 'useRef') at useRef (react.development.js:1630:1) at useGSAP (index.js:32:1) at Segment.tsx:39:1 at renderWithHooks (react-dom.development.js:16305:1) at updateForwardRef (react-dom.development.js:19226:1) at beginWork (react-dom.development.js:21636:1) at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1) at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1) at invokeGuardedCallback (react-dom.development.js:4277:1) at beginWork$1 (react-dom.development.js:27451:1) here's what i have so far: import React, { forwardRef, useEffect, useCallback, useRef } from "react"; import { useActiveSegment, BkExpeditionContextValues, } from "src/BkExpedition/index"; import { mergeRefs } from "src/util/mergRefs"; import clsx from "clsx"; import gsap from "gsap/dist/gsap"; import { useGSAP } from "@gsap/react"; gsap.registerPlugin(useGSAP); export type SegmentProps = Omit< React.ComponentPropsWithoutRef<"section">, "onAnimationStart" | "onDragStart" | "onDragEnd" | "onDrag" | "onDragOver" > & { segmentKey: BkExpeditionContextValues["activeSegment"]; }; export const Segment = forwardRef<HTMLDivElement, SegmentProps>( (props, ref) => { const { segmentKey, className, children, ...restOfHtmlAttrs } = props; const { activeSegment, previousSegment } = useActiveSegment(); const isActive = activeSegment === segmentKey; const sectionRef = useRef<HTMLDivElement>(null); const animateInTL = useRef<gsap.core.Timeline>(); const animateOutTL = useRef<gsap.core.Timeline>(); useGSAP(() => { // console.log("sectionRef", sectionRef.current); // if (sectionRef.current === null) return; // // animateInTL.current = gsap // .timeline({ paused: true }) // .fromTo(sectionRef?.current, { x: "100%" }, { x: "0%" }); // animateOutTL.current = gsap // .timeline({ paused: true }) // .fromTo(sectionRef?.current, { x: "0%" }, { x: "-100%" }); }); useEffect(() => { if (previousSegment === null) { return; } if (activeSegment === segmentKey) { animateInTL?.current?.play(); return; } if (previousSegment === segmentKey) { animateOutTL?.current?.play(); return; } }, [activeSegment, previousSegment, segmentKey]); return ( <section ref={mergeRefs(ref, sectionRef)} {...restOfHtmlAttrs} aria-hidden={!isActive} className={clsx(className, styles.segment, isActive && styles.isActive)} style={{ transform: isActive ? "translateX(0%)" : "translateX(100%)", }} > {children} </section> ); }, ); Segment.displayName = "Segment"; Am i not registering the book in the right place? Should it be registered inside the function component? FWIW - I plan to use this component in Next.js. Any help would be really appreciated -Gabriel
  5. Hey, everybody! I want to ask you. How can I work with elements with GSAP that come with dangerouslySetInnerHtml, because during animation inline styles are not written in them, although I can see through devtools that such an attempt is made (elements are highlighted, but nothing appears in them)
  6. Hi there, I've been learning and really enjoying GSAP! Thanks for the wonderful docs, learning materials, and forum. I want to create an effect of an infinitely moving horizontal line, which moves FASTER or SLOWER in reaction to scroll. So passively, let's say the line scrolls at "duration 5". - If I scroll down, I want the line to move faster, e.g. at duration 5 - adjusted scroll velocity = 2. - If I scroll up, I want the line to move slower, e.g. at duration 5 + adjusted scroll velocity = 8. Here's a minimal demo of both effects individually, but I haven't been able to successfully combine them. I've tried to manually adjust the duration variable through ScrollTrigger's onUpdate, using "getVelocity()", but that didn't seem to work. I've left it blank in the demo. If someone could point me in the right direction of how to approach this, I can try to do it in the demo myself! Thanks again. (not sure how to embed stackblitz demo directly) https://stackblitz.com/edit/react-ejg7zb?embed=1&file=src%2FApp.js
  7. I 've been trying to solve this for days seeing the community and referring topics here in GSAP and tried various method but still could not solve this issue. As you can see from the code there are three div's and the second div has some content and I need to make one of the div's in it scroll horizontally while scrolling vertically. I have pinned the second div inorder to complete the horizontal scroll. It works sometime when I make corrections on the code and hit save. But when I refresh the page it stops working all the same. Also sometimes it works only when the cursor is on the left most side the horizontal scroll works. Any suggestions / help ? I have provided the codesandbox link for the same. https://codesandbox.io/p/sandbox/horizontal-scroll-q55rs3
  8. 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> ); }
  9. Hello! I Next.js I got a SectionHeadline component that I need to split into lines to apply animations. The problem is that when I apply SplitText plugin (like I do below) it messes with all of my nested components (it includes things lik WordsLoop slider that has some ScrollTriggers within. All of those scrolltriggers break and nothing works like expected. I wonder what am I doing wrong. The line splitting code (adding divs for each line works), but interestingly on autoreload it gives an error: NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. When I refresh the page, it's fine. What am I doing wrong? Thank you! "use client"; import { useGSAP } from "@gsap/react"; import gsap from "gsap"; import { SplitText } from "gsap/SplitText"; import type { PortableTextProps } from "next-sanity"; import { PortableText } from "next-sanity"; import { useRef } from "react"; import { WordsLoop } from "~/components/words-loop"; import { cx } from "~/lib/utils/styled"; export function SectionHeadline({ value, className, ...rest }: Pick<PortableTextProps, "value"> & React.ComponentPropsWithoutRef<"div">) { const headlineRef = useRef<HTMLDivElement>(null); useGSAP( () => { gsap.registerPlugin(SplitText); const split = new SplitText("p", { type: "lines" }); }, { scope: headlineRef } ); return ( <div ref={headlineRef} className={cx("block px-32 text-center font-serif text-title-90", className)} {...rest} > <PortableText value={value} components={{ marks: { strong: (p) => { return <strong className="font-heading text-title-70">{p.children}</strong>; }, em: (p) => { return <em className="italic">{p.children}</em>; }, wordsLoop: (p) => { if (!p.value.words) { return <span className="font-heading text-title-70">{p.children}</span>; } return <WordsLoop words={p.value.words} />; }, }, }} /> </div> ); }
  10. useEffect(() => { gsap.registerPlugin(ScrollTrigger, ScrollToPlugin); const section: any = scrollRef.current; const scrollContainer = section.querySelector(".scroll-container"); const scrubTween= gsap.to(scrollContainer, { x: () => -(scrollContainer.scrollWidth - section.offsetWidth + 104) + "px", ease: "none", scrollTrigger: { trigger: section, start: "center center", end: () => "+=" + (scrollContainer.scrollWidth - section.offsetWidth), pin: true, anticipatePin: 1, invalidateOnRefresh: true, scrub:0, onUpdate: (self) => { if (self.direction === -1) { // Scrolling upwards gsap.set(scrollContainer, { x: 0 }); // Reset horizontal scroll position } }, }, }); return () => { ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); }; }, [])
  11. Hello, first of all I apologize if my English is not very good. I don't write the language fluently This is my first post and I'm new to GSAP. Believe me, I didn't want to post this without trying to solve the animation problem first. I have an animation where, at the starting point, the cards appear stacked one below the other. As you scroll, each card moves up and eventually exits the screen, while the bottom card adjusts to position y:0. The problem arises when the animation is reversed. As shown in the preview, the cards do not return to their correct positions and the animation does not complete as expected. I hope someone can help me with this. Thank you! PD: Reload the page if the animation doesn't work as expected, I don't know what's going on. After reloading, it works fine. PREVIEW: https://stackblitz.com/edit/gsap-react-basic-f48716-vwwr1u?file=src%2FApp.js
  12. I've been trying all night to install and import Split text on react, I've tried various ways to import the plugin and this is my current code. import React, {useRef} from 'react' import { useGSAP } from '@gsap/react' import gsap from 'gsap' import { SplitText } from "gsap/SplitText" gsap.registerPlugin(SplitText) Here's the error message I keep getting: Internal server error: Failed to resolve import "gsap/SplitText" from "src/components/Onboarding.jsx". Does the file exist? On further investigation in the node_modules/gsap directory, I realized the SplitText.js file actually doesn't exist, has this feature been deprecated or am I just installing it wrong?
  13. Hello there, at first it works good, but after i enable pin it just jumps to the bottom and only works when scrolling back up, how can i pin it the same position and after the revealing is done, and then i can scroll pass that, thank you in advance, i attached a video (sorry for the compression, 1mb limit) const About = () => { gsap.registerPlugin(useGSAP,ScrollTrigger); const text = new SplitType('#target') gsap.from(text.chars, { scrollTrigger: { trigger: "#target", start: 'top 70%', end: 'top 00%', scrub: true, pinSpacing: false, markers: false }, opacity: 0.1, y: 20, stagger: 0.01 }) return ( <div className='about content-center items-center text-center overflow-hidden py-12 p-5 lg:px-72'> <p id='target' className='lg:text-5xl text-3xl font-bold text-neutral-200'> I’m Dilukshan, a fullstack web developer from Sri Lanka with a passion for creating dynamic and engaging digital experiences. </p> </div> ) } Desktop 8-6-2024 1-34-01 Am (2) (2) (2) (2).mp4
  14. Hello everyone, I am trying to create a slideshow based on the demo found at the end of this post. https://codepen.io/cassie-codes/pen/vYWvwXV Instead, my version uses React to try to recreate the same effect. However I am running into problems. Here is my code: slides.jsx import { useEffect, useRef } from "react"; import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { Observer } from "gsap/Observer"; import { projects } from "./projects"; import "./slideshow.scss"; gsap.registerPlugin(ScrollTrigger, Observer); const SlideShow = () => { const sectionsRef = useRef([]); const imagesRef = useRef([]); const slideImagesRef = useRef([]); const outerWrappersRef = useRef([]); const innerWrappersRef = useRef([]); const countRef = useRef(null); const currentIndex = useRef(0); const animating = useRef(false); useEffect(() => { const sections = sectionsRef.current; const images = imagesRef.current.reverse(); const slideImages = slideImagesRef.current; const outerWrappers = outerWrappersRef.current; const innerWrappers = innerWrappersRef.current; const count = countRef.current; const wrap = gsap.utils.wrap(0, sections.length); gsap.set(outerWrappers, { xPercent: 100 }); gsap.set(innerWrappers, { xPercent: -100 }); gsap.set(sections[0].querySelector(".slide__outer"), { xPercent: 0 }); gsap.set(sections[0].querySelector(".slide__inner"), { xPercent: 0 }); function gotoSection(index, direction) { animating.current = true; index = wrap(index); let tl = gsap.timeline({ defaults: { duration: 1, ease: "expo.inOut" }, onComplete: () => { animating.current = false; console.log("slide changed"); }, }); const currentSection = sections[currentIndex.current]; const heading = currentSection.querySelector(".slide__heading"); const nextSection = sections[index]; const nextHeading = nextSection.querySelector(".slide__heading"); gsap.set([sections, images], { zIndex: 0, autoAlpha: 0 }); gsap.set([sections[currentIndex.current], images[index]], { zIndex: 1, autoAlpha: 1, }); gsap.set([sections[index], images[currentIndex.current]], { zIndex: 2, autoAlpha: 1, }); tl.set(count, { text: index + 1 }, 0.32) .fromTo( outerWrappers[index], { xPercent: 100 * direction }, { xPercent: 0 }, 0 ) .fromTo( innerWrappers[index], { xPercent: -100 * direction }, { xPercent: 0 }, 0 ) .to(heading, { "--width": 800, xPercent: 30 * direction }, 0) .fromTo( nextHeading, { "--width": 800, xPercent: -30 * direction }, { "--width": 200, xPercent: 0 }, 0 ) .fromTo( images[index], { xPercent: 125 * direction, scaleX: 1.5, scaleY: 1.3 }, { xPercent: 0, scaleX: 1, scaleY: 1, duration: 1 }, 0 ) .fromTo( images[currentIndex.current], { xPercent: 0, scaleX: 1, scaleY: 1 }, { xPercent: -125 * direction, scaleX: 1.5, scaleY: 1.3 }, 0 ) .fromTo(slideImages[index], { scale: 2 }, { scale: 1 }, 0) .timeScale(0.8); currentIndex.current = index; } Observer.create({ type: "wheel,touch,pointer", preventDefault: true, wheelSpeed: -1, onUp: () => { if (animating.current) return; gotoSection(currentIndex.current + 1, 1); }, onDown: () => { if (animating.current) return; gotoSection(currentIndex.current - 1, -1); }, tolerance: 10, }); const logKey = (e) => { if ( (e.code === "ArrowUp" || e.code === "ArrowLeft") && !animating.current ) { gotoSection(currentIndex.current - 1, -1); } if ( (e.code === "ArrowDown" || e.code === "ArrowRight" || e.code === "Space" || e.code === "Enter") && !animating.current ) { gotoSection(currentIndex.current + 1, 1); } }; document.addEventListener("keydown", logKey); return () => { document.removeEventListener("keydown", logKey); }; }, []); return ( <div className="slideshow_container"> {projects.map((project, i) => ( <section className="slide" key={project.id} ref={(el) => (sectionsRef.current[i] = el)} > <div className="slide__outer" ref={(el) => (outerWrappersRef.current[i] = el)} > <div className="slide__inner" ref={(el) => (innerWrappersRef.current[i] = el)} > <div className="slide__content"> <div className="slide__container"> <h2 className="slide__heading">{project.projName}</h2> <figure className="slide__img-cont" ref={(el) => (slideImagesRef.current[i] = el)} > <img src={project.codeImgSrc} alt={project.codeImgAlt} /> </figure> </div> </div> </div> </div> <div className="overlay"> <div className="overlay__content"> <p className="overlay__count">{i + 1}</p> <figure className="overlay__img-cont" ref={(el) => (imagesRef.current[i] = el)} > <img src={project.demoImgSrc} alt={project.demoImgAlt} /> </figure> </div> </div> </section> ))} <div className="link_buttons"> <button>Code</button> <button>Demo</button> </div> </div> ); }; export default SlideShow; slideshow.scss I want this slideshow to take up only half the screen @font-face { font-family: "Bandeins Sans & Strange Variable"; src: url("https://res.cloudinary.com/dldmpwpcp/raw/upload/v1566406079/BandeinsStrangeVariable_esetvq.ttf"); } @import url("https://fonts.googleapis.com/css2?family=Sora&display=swap"); * { box-sizing: border-box; user-select: none; } ::-webkit-scrollbar { display: none; } figure { margin: 0; overflow: hidden; } html, body { overflow: hidden; margin: 0; padding: 0; height: 100vh; height: -webkit-fill-available; } .slide { height: 100%; width: 100%; top: 0; left: 50%; position: fixed; visibility: hidden; &__outer, &__inner { width: 100%; height: 100%; overflow-y: hidden; } &__content { display: flex; align-items: center; justify-content: center; position: absolute; height: 100%; width: 100%; top: 0; } &__container { position: relative; max-width: 1400px; width: 100vw; margin: 0 auto; height: 90vh; margin-bottom: 10vh; display: grid; grid-template-columns: repeat(10, 1fr); grid-template-rows: repeat(10, 1fr); grid-column-gap: 0px; grid-row-gap: 0px; padding: 0 1rem; } &__heading { --width: 200; display: block; text-align: left; font-family: "Bandeins Sans & Strange Variable"; font-size: clamp(5rem, 5vw, 5rem); font-weight: 900; font-variation-settings: "wdth" var(--width); margin: 0; padding: 0; color: #f2f1fc; z-index: 999; mix-blend-mode: difference; grid-area: 2 / 2 / 3 / 10; align-self: baseline; } &__img-cont { margin-top: 4rem; grid-area: 2 / 1 / 7 / 8; img { width: 100%; height: 100%; object-fit: cover; } } } .slide:nth-of-type(1) { visibility: visible; .slide__content { backdrop-filter: blur(10px); } } .slide:nth-of-type(2) { .slide__content { backdrop-filter: blur(10px); } } .slide:nth-of-type(3) { .slide__content { backdrop-filter: blur(10px); } } .slide:nth-of-type(4) { .slide__content { backdrop-filter: blur(10px); } } .overlay { position: fixed; top: 0; bottom: 0; left: 50%; right: 0; z-index: 2; &__content { max-width: 1400px; width: 100vw; margin: 0 auto; padding: 0 1rem; height: 90vh; margin-bottom: 10vh; display: grid; grid-template-columns: repeat(10, 1fr); grid-template-rows: repeat(10, 1fr); grid-column-gap: 0px; grid-row-gap: 0px; } &__img-cont { position: relative; overflow: hidden; margin: 0; grid-area: 4 / 3 / 9 / 5; img { position: absolute; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; } } &__count { grid-area: 3 / 5 / 4 / 5; font-family: "Bandeins Sans & Strange Variable"; font-size: clamp(3rem, 4vw, 15rem); margin: 0; padding: 0; text-align: right; border-bottom: 7px white solid; } } @media screen and (min-width: 900px) { .overlay__content, .slide__container { padding: 0 3rem; margin-top: 10vh; height: 80vh; } .overlay__img-cont { grid-area: 6 / 2 / 10 / 6; } .overlay__count { grid-area: 3 / 5 / 4 / 5; font-family: "Bandeins Sans & Strange Variable"; color: white; } .slide__img-cont { margin-top: 0; grid-area: 2 / 1 / 8 / 7; } .slide__heading { grid-area: 1 / 1 / 4 / 10; } } projects.js export const projects = [ { id: 1, projName: "test1", codeLink: "(some link)", demoLink: "(some other link)", codeImgSrc: "(some picture src)", codeImgAlt: "", demoImgSrc: "(some other picture src)", demoImgAlt: "", }, { id: 2, projName: "test2", codeLink: "(some link)", demoLink: "(some other link)", codeImgSrc: "(some picture src)", codeImgAlt: "", demoImgSrc: "(some other picture src)", demoImgAlt: "", }, { id: 3, projName: "test3", codeLink: "(some link)", demoLink: "(some other link)", codeImgSrc: "(some picture src)", codeImgAlt: "", demoImgSrc: "(some other picture src)", demoImgAlt: "", }, { id: 4, projName: "test4", codeLink: "(some link)", demoLink: "(some other link)", codeImgSrc: "(some picture src)", codeImgAlt: "", demoImgSrc: "(some other picture src)", demoImgAlt: "", }, ]; My major issue right now is that I cannot get the overflow: hidden; to apply correctly causing the old text and pictures to remain on the screen instead of being hidden. Also when the next slide animates, the current and next numbers on the counter render at the same time, overlapping for a moment. If anyone can help it would be appreciated. Thanks in advance!
  15. Hello, I'm struggling with making my timeline with ScrollTrigger work on resize. It works perfectly every time if I refresh the page, but it doesn't update properly on resize. I have applied both of below: invalidateOnRefresh: true x: () => value(instead of x: value) What am I doing wrong? I am attaching my whole component code (I have just stripped imports). The aim is to simply make it appear as horizontal scroll for the list. I will appreciate any help. Thank you. export function Companies({ data }: { data: Sanity.Company[] }) { const listRef = useRef<HTMLUListElement>(null); const itemsRef = useRef<(HTMLLIElement | null)[]>([]); const tlRef = useRef<gsap.core.Timeline | null>(null); useGSAP( () => { gsap.registerPlugin(ScrollTrigger); const mm = gsap.matchMedia(); mm.add("(min-width: 1024px)", () => { if (!itemsRef.current[0]) { return; } tlRef.current = gsap.timeline({ scrollTrigger: { trigger: listRef.current, start: "bottom bottom", end: `+=3000`, scrub: 2, pin: true, invalidateOnRefresh: true, }, }); tlRef.current.to("li:nth-child(-n + 5)", { y: "0%", stagger: 0.1, duration: 1, }); tlRef.current.to(listRef.current, { invalidateOnRefresh: true, x: () => `-${itemsRef.current[0]?.offsetWidth * itemsRef.current.length - window.innerWidth}`, duration: 4, }); }); }, { scope: listRef } ); return ( <ul className="grid grid-cols-2 gap-x-8 gap-y-24 px-15 pb-52 sm:grid-cols-3 lg:flex lg:w-fit lg:flex-nowrap lg:justify-between lg:gap-0 lg:px-32" ref={listRef} > {data?.map((company, index) => ( <li className={cx(["lg:pr-[7vw]", index < 5 ? "lg:translate-y-full" : ""])} key={index} ref={(el) => { itemsRef.current[index] = el; }} > <Company {...company} /> </li> ))} </ul> ); }
  16. const DotCursor: React.FC = () => { const dotRef = useRef<HTMLDivElement>(null); const { clientX, clientY } = useMousePosition(); const [isVisible, setIsVisible] = useState(false); const handleMouseEnter = () => { setIsVisible(true); }; const handleMouseLeave = () => { setIsVisible(false); }; const handleMouseMove = () => { setIsVisible(true); }; useGSAP( () => { const dot = dotRef.current; if (!dot) return; window.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseenter", handleMouseEnter); document.addEventListener("mouseleave", handleMouseLeave); const animateDot = () => { gsap.set(dot, { x: clientX, y: clientY, }); }; gsap.ticker.add(animateDot); return () => { window.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseenter", handleMouseEnter); document.removeEventListener("mouseleave", handleMouseLeave); gsap.ticker.remove(animateDot); }; }, { dependencies: [clientX, clientY] } ); return ( <div ref={dotRef} className="dot-cursor bg-orange-700" style={{ opacity: isVisible ? 1 : 0, position: "fixed", width: "10px", height: "10px", border: "solid 1px black", borderRadius: "20%", pointerEvents: "none", transform: "translate(-50%, -50%)", zIndex: 9999, }} /> ); }; export default DotCursor;
  17. Hello! I'm trying to create a carousel similar to this website: https://wtcabuja.com/ As you scroll in reference site, a single item stays in the middle, scrolling fills the progress below and when it completes, the next slide comes from the right side and vice versa for reverse. I tried implementing something similar by sliding an item using ScrollTrigger. But I don't know how can I manage to make multiple items slide back and forth on scroll. Here's a Stackblitz Minimal Demo of what I did. Any kind of help is appreciated. Thanks!
  18. Hi, I'm making project with React and GSSP. I want to make header effect that connect with scrolling. This is my project with codesandbox. https://codesandbox.io/p/devbox/cocky-ben-fgwh9p?file=%2Fsrc%2Futils%2FdataUtils.tsx%3A11%2C29 In my project I have got issue when click the navbar. When I click the navbar link, the navbar animation replay.
  19. Hello, I've started my React journey recently. For my final university college project, I want to create a "Your own adventure webcomic". I want to animate the every panels and in order to do so I had to use GSAP or "useGSAP" (I am proud of this one). I have watched those two videos to understand how it works: https://www.youtube.com/watch?v=DwU72sp_gGI https://youtu.be/l0aI8Ecumy8 But I am not sure if I have fully understood how it works. useGSAP automatically revert the animation at the end, so does it mean that I am not supposed to see things like this once the animation finished? Or is it only when the component is dismounted? I also wanted to ask if I use it properly. So here is an example of how I have used it in my code: const [isMounted, setIsMounted] = useState(false) const shakingRef = useRef(gsap.timeline({ repeat: 2, repeatDelay: 0 })); useEffect(() => { setIsMounted(true); }, []); useGSAP( () => { if (isMounted == true) { if (healthRef.current > elvan.health) { shakingRef.current .to(elvanRef.current, { xPercent: -5, yPercent: -5, duration: 0.1 }) .to(elvanRef.current, { xPercent: -0, yPercent: -0, duration: 0 }) .to(elvanRef.current, { xPercent: 5, yPercent: 5, duration: 0.1 }) .to(elvanRef.current, { xPercent: -0, yPercent: -0, duration: 0 }); } } }, { dependencies: [elvan.health], scope: elvanRef.current, } ); Thank you in advance for your answer (And sorry if I have made some mistakes, English is not my mother tongue).
  20. Hello, For my final university college project I want to create a "Your own adventure webcomic". I've recently started my React journey, and I wanted to animate some stuffs in this project. Here you can access a codesandbox for a better understanding for what is coming. I think that I have a misunderstanding of how the scope of useGsap works. Here is my problem, I have a parent component (StoryNarrative) and its child (StoryFragment). StoryNarrative create multiple iteration of StoryFragment. It is important to also note that a new StoryFragment is created whenever the state displayToNumber changes. displayToNumber is a number that changes everytime that the user clicks on a button. It tells StoryNarrative to loop StoryFragment based on an array from 0 to displayToNumber. I want the scope to be a div within the last iteration of StoryFragment that has been created. In order to do so, I have created a ref array (animatedRef) that refers every div. Once done, I have written that the scope should be the last element created. I thought that I could have two different ways to do so. Use animatedRef.current[animatedRef.current.length - 1] or animatedRef.current.[displayToNumber]. But it does not work as I thought. The console shows that for some reason, even after that a new div is created, React keeps using the old length for the first build of the component before changing when I use "animatedRef.current[animatedRef.current.length - 1]" but it does not do so when I use animatedRef.current.[displayToNumber]. But the problem is, however I write animatedRef.current.[displayToNumber] or animatedRef.current[animatedRef.current.length - 1] as the scope, it never refers to the last element created. With animatedRef.current[animatedRef.current.length - 1] it animates the element before the last and with animatedRef.current.[displayToNumber] it seems like the scope does not work at all. So if anyone have any idea of why this is happening please let me know. English is not my mothertongue so I may have done some mistakes, if something is not clear enough please let me know. And thanks in advance for your answers.
  21. I'm using the new useGSAP hook with gsap + scroll trigger. When I use the hook, my scrolltrigger pinned section seems to disappear. When I use the original way (using useIsomorphicLayoutEffect with GSAP Context) it seems to work exactly as expected. Im using packages: - GSAP business - useGSAP version 2.1.1. - React version 18.3.1 - React DOM version 18.3.1 Unfortunatley when I create a minimal demo, both methods work fine Is there something I should be looking for, or am i not using the hook correctly? See video here for example => https://vimeo.com/947131601?share=copy // this works useIsomorphicLayoutEffect(() => { const ctx = gsap.context(() => { gsap.to("#voting", { scrollTrigger: { trigger: "#voting", pin: "#voting", start: "top top", end: "bottom top", }, }); }); return () => ctx.revert(); }, []); // this does not work useGSAP(() => { gsap.to("#voting", { scrollTrigger: { trigger: "#voting", pin: "#voting", start: "top top", end: "bottom top", }, }); }, []);
  22. Hello everyone, I want to switch component to render using gsap but currently it overlaps eachother. my current code is: https://stackblitz.com/edit/stackblitz-starters-egrwn8?file=app%2Fpage.tsx
  23. Hi there, So I am using gsap for animation in a NextJs project and there are some component that has little animations that I am trying to test. To be direct I stimulate a user click interaction in the test and check to see if the "aria-*" attribute or "data-*" attribute has been updated to the correct state when the animation is done but all test fails. I am using the gsap `.then` callback to trigger this update when the animation is done. It works fine in the dev and prod env but the `.then` callback function fails to run in a test env. I have created a minimal demo of my issue, please find the link below https://stackblitz.com/edit/stackblitz-starters-mvcff3?file=app%2Fpage.test.tsx Thank you.
  24. Hi yall, I'm hoping I can get some help with some gsap animations in React. I have a UI i'm working on where an inactive segment animates by translating up, while a new active element translates to 0 from the bottom.. There is a noticeable flicker of no content before the animation starts. I don't know what I'm doing wrong to cause this. I first noticed it in my storybook. Here's a link to my code transferred to a codesandbox to demonstrate; this is the core of the logic where the animation happens: https://codesandbox.io/p/sandbox/gsap-expedition-w96d45?file=%2Fsrc%2Fcomponents%2FExpedition%2FSegment.tsx%3A189%2C28 You can recreate the animation sequence by clicking on the buttons at the top which should trigger the animations to change. Nothing will happen if you click the same button twice Caveat: I know I should be using useGsap hook - but I can't until we update our react version. So here i use a custom hook instead. Any help would really be appreciated!
  25. I am having an issue I have seen described in other contexts but haven't found a solution for. My project is using the Next.js framework for react, Smooth Scrollbar, and ScrollTrigger. I have a .to() with a scrollTrigger object inside that is in a <Navigation /> component. The text at the top of the page is just supposed to pin itself and scroll with the window, but it only works in some cases. I think I'm not fully understanding some lifecycle thing here. All these methods of reproducing my errors are also commented at the top of the index.js file in the sandbox With Smooth Scrollbar enabled, the scrollTrigger object stored in the <Navigation /> component, and the <Navigation /> component imported and nested in the main functional component, the effect does not work after refreshing the page. If you go into the scrollTrigger object in the <Navigation /> component and update one of the values (change the 'end' value to a different number) this will trigger a hot reload without refreshing the browser. If you scroll back to the top and scroll down, you will see the effect is now working. If you comment out the entire useEffect() hook in the main index.js component this will disable Smooth Scrollbar. If you save the file and refresh you will see the effect working as intended, without having to trigger a hot reload, but now there is no Smooth Scrollbar. If you reset the sandbox to the original state, uncomment the HTML in the main index.js components return, comment out the <Navigation /> component right above it, save and then refresh, you will see that the effect works on load, with Smooth Scrollbar, without having to trigger a hot reload, but now I've lost the ability to nest components. CodeSandbox link Direct link to results in browser (A little easier for refreshing) Any help would be greatly appreciated. I'm out of ideas at this point.
×
×
  • Create New...