Search the Community
Showing results for tags 'react'.
-
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.
- 20 replies
-
Hi everyone. I'd like to create an animation that plays in a loop and also plays when I scroll. Animation: animates the css clip-path property of the images according to the current index. Currently, when the component is mounted, the animation plays correctly but remains stuck on the last image of the array. And when I scroll, nothing happens. Does anyone have a solution or know where to find the bug ? Thank you in advance Demo link : https://stackblitz.com/edit/gsap-react-basic-f48716-ebgh4d?file=src%2FApp.js I was inspired by the following examples: https://codepen.io/GreenSock/pen/wvZjeGN?editors=1010 https://codepen.io/GreenSock/pen/XWzRraJ?editors=1010
-
code sandbox I'm new to GSAP and am struggling getting a certain animation to work using scrollTrigger when my elements are in a grid layout. The animation aims to move the content horizontally as the user scrolls, and I've taken out the relevant components into this code sandbox. Apologies if there's still too much code in there, but I wanted to make sure the code is representative of the components I have in my project, in case there are nuances causing the problem. In App.tsx, if you uncomment all the code, you'll find a grid layout containing a 'navbar' on the left, and the main content on the right. Currently, with the grid commented out, the animation works fine, but if you include the grid, it all breaks for reasons I don't understand. I've read through the common mistakes for GSAP and scrollTrigger and don't think this is covered. I also have a couple of other smaller issues as well please in the ExperiencePage.tsx component: toggleClass on scrollTrigger doesn't apply the .active class to components. the width variable isn't being updated as the browser window is resized, despite me setting invalidateOnRefresh to true and using a function to define the end attribute in the scrollTrigger configuration. Appreciate any help with this please.
- 12 replies
-
- scrolltrigger
- grid
-
(and 2 more)
Tagged with:
-
Hello, I'm trying to implement mounting and unmounting animations to conditionally rendered elements in my React component, similar to the example given in the Advanced React docs: {!joined && ( <div ref={usernameFormRef}> <Button onClick={() => onSubmit()}> Join </Button> </div> )} {joined && ( <div ref={controlsRef}> <Button onClick={() => onLeave()}> Leave </Button> </div> )} const [joined, setJoined] = useState(false); const { contextSafe } = useGSAP({ scope: controlsScope }); const tl = gsap.timeline(); const onSubmit = contextSafe(() => { tl.to(usernameFormRef.current, { opacity: 0, yPercent: 200, duration: 0.7, ease: "back.in(2)", onComplete: () => setJoined(true), }); tl.from(controlsRef.current, { opacity: 0, yPercent: 200, duration: 0.7, ease: "back.out(2)", }); }); const onLeave = contextSafe(() => { tl.to(controlsRef.current, { opacity: 0, yPercent: 200, duration: 0.7, ease: "back.in(2)", onComplete: () => setJoined(false), }); tl.from(usernameFormRef.current, { opacity: 0, yPercent: 200, duration: 0.7, ease: "back.out(2)", }); }); The problem I faced was that the onComplete function seemed to fire at the end of the timeline, not between each tween. This results in the tl.to unmounting/exit animation working as expected unlike tl.from which results in an abrupt mounting of the controlsRef element. I have also tried implementing without a timeline but ran into the same results. What exactly am I missing here? Any help would be much appreciated. I have also attached my component directly if more context is needed. MultiplayerControls.tsx
- 4 replies
-
- react
- conditional statements
-
(and 2 more)
Tagged with:
-
Hello, I have a couple of questions and one dead end that I can't seem to solve. I am attempting to create an ellipse carousel, essentially similar to this one made in a circle: https://codepen.io/GreenSock/pen/GRMqWvW My main issue lies in the fact that I'm attempting to move objects along the path using the progress parameter, and I don't know how to achieve this functionality. I have tried to add animation to the timeline, but currently, it isn't moving even with the basic rotation for the div, which acts as a wrapper. I've added numerous console.log statements to track progress changes, and they seem to be updating correctly. The relevant code for inspection is from line 65 to 177, with some comments interspersed. From the side problems I'm also struggling to track the active element using animation added to the timeline, similar to the example provided by GSAP example pin (lines 83-97, currently commented out). Currently, I am changing this value within the 'moveWheel' function at line 162. Here's StackBlitz link for the above questions: https://stackblitz.com/edit/stackblitz-starters-4p7twq?file=src%2Fcomponents%2FroundComponent.js Another issue I need assistance with is the 'convertToPath' function. I am attempting to obtain a path from an ellipse, but when I position the SVG beforehand (for example, by centering it using cx and cy values), obtaining the path doesn't reflect this position. Additionally, if I try to directly add a translate into the generated path, it doesn't work. How can I accomplish this correctly? I have provided separate code to visualize this problem: https://stackblitz.com/edit/stackblitz-starters-6mzrk4?file=src%2FApp.js P.S. Regarding the issue with converting the ellipse to a path, I've noticed that if I comment out line 57 within my code, it looks as it should, but now the entire path isn't visible ?. I've saved the StackBlitz project with a comment on that line. Perhaps you could provide me as I think with some simple solution to get a whole path of svg visible? Thanks in advance.
-
Why are the "duration" and "ease" properties not working? I checked, the element exists, but the properties are not added to it. I commented out one line in the styles.scss file, I recommend uncommenting it to see how the element should behave. I would be glad to hear your tips! DEMO
-
Hello! I think I got trouble understanding how should I use GSAP in my Next.js project, in particular, ScrollTriggers, how to initialize and kill them on resize and pathname change. Let me share you my component (it's a Prismic slice in case you wonder about the syntax). I removed some parts which are irrelevant. The aim of this code is to pin the smaller "intro" div, until we scroll through the whole container. Then it sticks to the bottom of it. This code actually works, but I've got a couple problems with it. 1. Resizing works really slow. It feels like a lot of stuff is happening in the background and it feels wrong. But it still kinda works. 2. Second issue is major and it's blocking me from going further. The line that kills ScrollTriggers applies to all the ScrollTriggers across the projects, including those from other components! How should I set it up properly? I will appreciate any advice! 'use client'; import { useRef } from 'react'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/dist/ScrollTrigger'; import { useGSAP } from '@gsap/react'; const Values = ({ slice }: ValuesProps): JSX.Element => { const container = useRef<HTMLDivElement>(null); const intro = useRef<HTMLDivElement>(null); const setupSTs = (offset: number) => { // I don't need a pin on mobile screens <= 768 if (window.innerWidth > 768) { ScrollTrigger.create({ trigger: container.current, start: 'top top', end: `bottom bottom-=${offset}`, pin: intro.current, }); } }; const initSTs = () => { // This line breaks my other components, but if I disable it, resizing for this component doesn't work anymore ScrollTrigger.getAll().forEach((ST) => ST.kill()); if (intro.current) { let introHeight = intro.current.clientHeight; let offset = window.innerHeight - introHeight; setupSTs(offset); } }; // Is it a correct use of useGSAP? useGSAP( () => { gsap.registerPlugin(ScrollTrigger); initSTs(); ScrollTrigger.addEventListener('refreshInit', initSTs); }, { scope: container } ); return ( <section ref={container} > <div className={styles.values__wrapper}> <div ref={intro} className={styles.values__intro}> (...) </div> <div className={styles.values__container}> (...) </div> </div> </section> ); }; export default Values;
- 7 replies
-
- scrolltrigger
- next.js
-
(and 2 more)
Tagged with:
-
I'm facing a problem with animate html inside foreignObject. when I click the button it animates. it works normally on desktop and Android devices and is debug responsive with iPhone on the Chrome dev tool. but when I'm testing in a real iPhone. it causing problems. the text and jumping big above the SVG and this is not i want. how can i fix it ? Please help me. this is the demo in codesandbox: animate html ìn foreignObject - CodeSandbox
-
Hi everyone, I am just starting with GSAP and React and want to adopt best practices from the beginning. I would appreciate your insights on my approach. My question concerns triggering an animation before a component re-renders, similar to the discussion in this topic. However, my scenario involves initiating the animation with a button's onClick event. Currently, I am using forwardRef and useImperativeHandle in React, which allows me to activate a function from a button in a separate component. This function triggers a fade-out animation in the component where the animation is defined. In the animation's onComplete callback, I modify a variable that is part of the prop in the main component, causing it to re-render. Is there a better way to achieve this effect? Also, if you have any comments or suggestions after reviewing my code, I would be extremely grateful to hear them. Here is link to the stackblitz with the minimal demo: https://stackblitz.com/edit/stackblitz-starters-v1vstg?file=src%2Fcomponents%2Fplaceholder.js PS. I forgot mention that I want this effect to works when the buttons are in different component than the animated content. I already add this functionality to the demo.
-
Hi, I have a Problem with my project on Vercel and GSAP Bonus Plugins. I don't know if i can paste the code in CodePen since it's Typescript and Next.js so i added some screenshots of the code. Locally everything works fine, but on Vercel i get this Building Log Errors: I have generated a PRIVJS_TOKEN and installed all Bonus Plugins via npm locally. In the console of the browser i get this errors:
-
I have a pinned section in my page, which makes the other Scroll triggers I have in different child components have their starting positions inaccurate. I tried refreshing the Scroll trigger(using ScrollTrigger.refresh()) in the main page(file) but the issue remained. Also I want to know if there is a way I can pass down an instance of Scroll trigger and Gsap to my other components, so If i refresh that one instance, it updates everywhere, or is there a better way to handle having multiple gsap and scroll triggers in different components but still being able to control them from the main page? Also I want to know if the better approach is to write all my animations in one useEffect with all the jsx in one page(file) or have some of the animations for different parts of the page as components which include their respective jsx. So pretty much everything in one page or components style ? I ask this because the component approach has been a headache for me, because one way or another the starting points end up inaccurate. I would apperciate if someone could help with a direction I could take. This is a simplified version https://stackblitz.com/edit/vite-react-tailwind-fpc1wz?file=src/App.jsx where I tried to refresh a child component but it didn't work
- 2 replies
-
- react
- components
-
(and 3 more)
Tagged with:
-
Hi guys, I am currently rebuilding my website and i am asking myself what is the bestway to share one timeline through multiple components ? let's say i have this architecture --Layout ----Header ----Component1 --------Component2 --------Component3 ----Footer And i want part of my header timeline starting after the one executed in component3 ? Currently i am using context but it feels a bit strange to me Provider.js const [globalTimeline, setGlobalTimeline] = useState( gsap.timeline({ paused: true }) ) // Global Timeline for animation <myContext.Provider value={{ globalTimeline, setGlobalTimeline: tl => setGlobalTimeline(tl), }} > {children} </myContext.Provider> Layout.js useEffect(() => { globalTimeline.addLabel('start'') globalTimeline.play() }, []) I call my context in every component and add my animation to the globalTimeline. Thank you
-
I am working on a navigation menu that uses a dot underneath the active link. I want to animate the dot by reparenting it using Flip when a user navigates to a different page. I found a helpful example of reparenting using Flip in a react project created by someone here, and I forked it. My fork is here: https://stackblitz.com/edit/vitejs-vite-9pac1m?file=src%2FApp.jsx I have added a new onClick handler `handleParentClick` that is triggered by each parent link. The handler gets the index of the link from a data attribute. I expected this to work, but each time I click a parent I get the following error: react-dom_client.js?v=14fad21f:16659 Uncaught TypeError: Cannot read properties of null (reading '_gsap') at Object._getCache2 [as getCache] (gsap.js?v=c3ccde3e:132:17) at ElementState2.update (gsap_Flip.js?v=e3486289:1024:101) at new ElementState2 (gsap_Flip.js?v=e3486289:1016:10) at gsap_Flip.js?v=e3486289:890:14 at Array.map (<anonymous>) at FlipState2.update (gsap_Flip.js?v=e3486289:889:39) at new FlipState2 (gsap_Flip.js?v=e3486289:883:12) at _parseState2 (gsap_Flip.js?v=e3486289:592:65) at Function.from (gsap_Flip.js?v=e3486289:1246:27) at App.jsx:32:10 I'm not sure how to troubleshoot this error and hoping someone can point me in the right direction.
-
I have a component with dynamic id usinguseId()hook from react. it generates a string that contains a colon ":R1fakq:" something similar to this. then I will use this id to trigger a scrollTo with ScrollToPlugin but it throws an uncaught error. I tried manually setting the id with a colon character and it render the same issue.
-
Hi Team, What I'm trying to achieve The overall effect is curvy timeline (vertical) that is revealed as the user scrolls down the page. As the user scrolls down the page, the curved line is drawn, dots are added to the line and content is revealed. The content is sourced from a CMS (rows), there are unknown number of rows, and the content in each row can vary in size/height The Tech This is all being done in React My approach I've broken the curvy line into multiple sections: Top - The start of the timeline (Data row 1) Middle 1 - The first Section (Data row 2) Middle 2 - The second section (data row 3) ...n middles sections Bottom - The end of the timeline Each is its own component which is responsible for the animation. Where I'm struggling All this, for the most part works OK. Where I'm getting unstuck is: 1) Nicely transitioning from row to row (leading dot on the motion path) 2) On scroll up removing the lead dot. I have a demo in stackbitz, I hope this is ok? I realise there's a bit going on in this so let me know if I need to simplify further. https://stackblitz.com/edit/react-ahd2tq?file=src%2FApp.js
- 3 replies
-
- svg
- motionpath
-
(and 1 more)
Tagged with:
-
I'm trying to convert the following React component from the codepen(Sorry, I couldn't get it to run there) to GSAP. I built it using css animations(with tailwindcss). My code right now depends on the Indextracker state. This tracks which images is visible at the moment. Whenever it changes, the pages refreshes and the tailwind classes change(these set the position/rotation of the element) and therefor animate it. I know that this is quite janky but that's why i'd like to use GSAP. I'm struggling to figure out where to place my gsap animations: How can I mix this state management with GSAP? Can I just put the animations in my forwardClick and backwardClick functions and would they then persist between rerenders? Here's a gif of what it looks like at the moment.
-
Hello, I'm not a pro, so forgive my vocabulary if it's not accurate... I am trying to find out how I could use GSAP to animate the value of a state managed by Zustand (React state management). Here is how basic Zustand works: Creating the store: const useStore = create((set) => ({ bears: 0, increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), removeAllBears: () => set({ bears: 0 }), })) Binding components: function BearCounter() { const bears = useStore((state) => state.bears) return <h1>{bears} around here...</h1> } function Controls() { const increasePopulation = useStore((state) => state.increasePopulation) return <button onClick={increasePopulation}>one up</button> } Let say I want to tween the value of the state bears from 0 to 100. I would like to understand how to do it using 2 different approaches: how would you do it using a method within the store? how would you do it using a function within the component? Or are those approaches wrong? Thank you!
-
Hello I have a list of links and wanted to create a hover effect that animates all elements in some way (ie reduce opacity) but do something different on the hovered element (ie animate a contained span). I have created a pen with a React functional component that uses gsap. In essence I am doing the following: - Create 2 lists of elements (hovered element, non hovered elements) - Create 2 gsap timelines - Trigger those timelines on mouseover and on mouseleave. I have 1 problem and 1 question. Question: am I using best practices? I have wrapped the code inside a gsap context and I'm reverting the context when the component lifecycle ends. However I have 2 eventlisteners that I am not sure if thery are removed when lifecycle of component ends. Problem: animation only happens once for each element. How can i persist the timeline effects? Any help and suggestions would be greatly appreciated. Thank you
-
So hi, im trying to get used to the new hook useGSAP and gsap.context from GSAP, so since i started with useEffect and useLayoutEffect, i allways had the same issue that the horizontal scrooll section has a conflict whit smootscroll, all other animations are working as spected. So here is my app component: import { useGSAP } from '@gsap/react'; import gsap from 'gsap-trial'; import ScrollSmoother from 'gsap-trial/ScrollSmoother'; import ScrollTrigger from 'gsap-trial/ScrollTrigger'; import { useRef } from 'react'; import BrandsSection from './BrandsSection'; import CodeSection from './CodeSection'; import ContactSection from './ContactSection'; import IntroSection from './IntroSection'; import Navbar from './Navbar'; import PresentationSection from './PresentationSection'; import ProjectSection from './ProjectSection'; import SkillSection from './SkillSection'; import { StyleProvider } from './context/NeumorphicStylesContext'; export const PortfolioApp = () => { const componente = useRef(); gsap.registerPlugin(ScrollTrigger, ScrollSmoother); useGSAP(() => { const ctx2 = gsap.context(() => { const smoother = ScrollSmoother.create({ smooth: 2, effects: true, normalizeScroll: true, }); ScrollTrigger.create({ trigger: ".box-c", pin: true, start: "10% center", end: "+=1750", markers: true }); ScrollTrigger.create({ trigger: ".box-b", pin: true, start: "45% center", end: "+=1750", markers: true }); }, componente); return () => ctx2.revert(); }, { scope: componente }); return ( <StyleProvider> <Navbar /> <div id="smooth-wrapper" ref={componente}> <div id="smooth-content" > <IntroSection /> <PresentationSection /> <ProjectSection /> <SkillSection /> <BrandsSection /> <CodeSection /> <ContactSection /> </div> </div> </StyleProvider> ); }; and here is the horizontal section wich fastly goes to other sectios like it doesnt wanted to reproduce the animation, and it works when smootscrolling is not active: import { useGSAP } from '@gsap/react'; import gsap from 'gsap-trial'; import { useRef } from 'react'; import { CarrouselProjects } from './CarrouselProjects'; import { DescriptionProject } from './DescriptionProject'; import style from './projects.module.scss'; const ProyectSection = () => { const container = useRef(); useGSAP(() => { const slider = document.querySelector(".container") const ctx = gsap.context(() => { const panels = gsap.utils.toArray(".panel"); gsap.to(panels, { xPercent: -100 * (panels.length - 1), ease: "none", scrollTrigger: { markers: true, trigger: ".container", pin: true, scrub: 1, snap: 1 / (panels.length - 1), end: () => "+=" + slider.offsetWidth } }); }, container); return () => ctx.revert(); }, { scope: container }); return ( <div ref={container}> <div className="container"> <div className="description panel"> <div className={style.Projects_projectsContainer}> <CarrouselProjects /> <DescriptionProject /> </div> </div> <div className="panel red"> <div className={style.Projects_projectsContainer}> <CarrouselProjects /> <DescriptionProject /> </div> </div> <div className="panel orange"> <div className={style.Projects_projectsContainer}> <CarrouselProjects /> <DescriptionProject /> </div> </div> <div className="panel purple"> <div className={style.Projects_projectsContainer}> <CarrouselProjects /> <DescriptionProject /> </div> </div> </div> </div> ); }; export default ProyectSection; i would really aprecietted your help and i will try to replacate the issue on codesandbox if this information its not enough
- 1 reply
-
- horizontal scroll
- smooth scroll
-
(and 1 more)
Tagged with:
-
Please Help Me recreate The awesome animation In React https://www.nathansmith.design Im stuck at infinite vertical scrolling and also the scrollup effect on main text ? I tried to understand with context of this post but it was too hard to do so because im new to the concept : Please do help me out
- 7 replies
-
- react
- infinityscroll
-
(and 3 more)
Tagged with:
-
Hi there! We just completed a major site redesign featuring ScrollTrigger in several modules. It's been awesome, thanks to all involved in making this happen! One issue that came up is illustrated in the Codepen. We have a few modules that "expand" with interaction, like the green Module 2. The horizontal scroll module works great, but if the module above is expanded, it throws off the start/end positions of the trigger. My initial solution was to add a resizeObserver on the height of the body, that would trigger a window.resize event. This was effective in conjunction with MatchMedia, but it's global and is interrupting other animations that are happening on-screen while the body size is changing. What's the best (and more "componentized" ) way to recalculate the trigger when its position changes like that? Note: I don't think it's necessarily relevant, but we are using React in a sort of unique set up... we are working within a modular CMS, so each module is its own React app, similar to how the Codepen is set up. Much thanks!
-
Hello everyone, I have problems with ScrollTrigger in React and Next.js ecosystem from time to time. There are times when ScrollTrigger does not update itself when the page content changes for any reason, and this causes the placement of triggers to be broken. In the solutions I encountered in the forum, it is generally recommended to run the ScrollTrigger.refresh() method after the content change, but there may not always be an event etc. that coincides with that exact moment. In short, I'm wondering if anyone can recommend a robust ScrollTrigger implementation method in CSR libraries like react or isomorphic frameworks like Next.js? Where should it be init, when should it be refreshed, is there a global solution you use for refresh, etc.? For example, I use a global resize detector when working with react and I don't have much problems, but I feel like there should be a much more logical way because when the window height changes because a new tab is opened in safari, it can unnecessarily refresh and cause jumps on the page, etc. Any suggestions would be appreciated.
- 4 replies
-
- react
- scrolltrigger
-
(and 1 more)
Tagged with:
-
Hello GSAP community, I'm working on a React project where I'm attempting to create a smooth page transition with GSAP and React Router. The specific effect I aim to achieve is this: when a user clicks on a button (which is text with a background image), I'd like the image within the text to grow and eventually become the background image of the new route. Here's the scenario in detail: - I have a list of clickable project cards on the homepage, each with text over a background image. - when clicking one of these text elements, I would like the background image to expand, filling the entire screen and then transitioning into the background of the next page So far, I have tried animating the scale of the element . However, I am running into two main issues: 1. The `scale` property does not seem to be the correct approach for making the image become the background smoothly. 2. The transition to the other route comes off as abrupt and I'm struggling to integrate the animation seamlessly into the page change. I would greatly appreciate any advice on how to create a seamless transition where the clipped background image expands to fill the screen and serves as a connector between the two routes. Here's a link to a current sample of the project on CodeSandbox: Codesandbox Exemple
- 4 replies
-
- react
- react-router-dom
-
(and 1 more)
Tagged with:
-
I'm trying to call a function inside GSAP - I'm using React, but I'm getting error in my console: App.jsx:59 Uncaught TypeError: Cannot read properties of undefined (reading 'scrollTo') This is the code: import gsap from "gsap"; import ScrollTrigger from "gsap/dist/ScrollTrigger"; import { ReactLenis, useLenis } from "@studio-freight/react-lenis"; gsap.registerPlugin(ScrollTrigger); const App = () => { const lenis = useLenis(({ scroll }) => { // called every scroll }); const [showSpan, setShowSpan] = useState(true); const mainTitleRef = useRef(null); const secondaryTitleRef = useRef(null); const wavingHandRef = useRef(null); const section1Ref = useRef(null); const section2Ref = useRef(null); useLayoutEffect(() => { pinSection(); animateTitles(); return () => { // Cleanup code when the component unmounts ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); }; }, []); // Empty dependency array to run once after the initial render const pinSection = () => { // Pin the section when it enters the viewport ScrollTrigger.create({ trigger: section1Ref.current, start: "top top", end: "1200 top", pin: true, markers: true, onLeave: () => { gsap.to(section1Ref.current, { opacity: 0, duration: 1, onComplete: scrollToSection2, }); // Set opacity to 1 when entering the trigger // scrollToSection2(); // gsap.add( function(){ scrollToSection2(); } ) }, onEnterBack: () => { gsap.to(section1Ref.current, { opacity: 1, duration: 1 }); }, }); }; const scrollToSection2 = () => { lenis.scrollTo(section2Ref.current, { duration: 5 }); }; As you can see scollToSection2 is a React function. Thank you for your help upfront!