Jump to content

Rodrigo last won the day on May 2 2021

Rodrigo had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Rodrigo

  1. Just an FYI. GSAP has a selector method that could simplify this a bit, specially considering that React components tree is rendered starting with child components. The docs have a series of examples on how to use it with React and other frameworks as well: https://greensock.com/docs/v3/GSAP/UtilityMethods/selector() Happy Tweening!!!
  2. Ahhh, OK. Hopefully this is enough to get you started: https://nextjs.org/docs/api-reference/next/link#if-the-child-is-a-functional-component Unfortunately, as far as I know, the Link component doesn't expose a ref to the DOM element being rendered, so you have to create one by yourself using a component (as shown in the docs). Perhaps @elegantseagulls has some experience with this, normally the hover effects I add to links are quite simple and I create them with CSS transitions (this probably is going to cost me in the future ). Given what you're trying to achieve, you could also create a codepen sample in order to get a glance of what you're trying to do and port that to another sandbox using Next. Happy Tweening!!!
  3. Hello @mercurymirror and welcome to the GreenSock forums. If this is about route/page transitions, perhaps this post could be helpful: If not, please provide a live editable sample using either codesandbox or stackblitz. Happy Tweening!!!
  4. Excellent support Ladie and Gentlemen!!!! Also as a side note, with all those glowing SVGs I'm getting a lot of Light Sabers vibes in this thread
  5. Hey, @Cassie and @OSUblake did an amazing job on these guides, they should be more than enough to get you started with using GSAP in React: Finally you can check the installation guide in the docs: https://greensock.com/docs/v3/Installation Happy Tweening!!!
  6. @Prasanna Thanks for the follow up. Actually we already have updated the .npmrc file and the global configs. The global .npmrc file looks like this: registry=https://npm.greensock.com/ @gsap:registry=https://npm.greensock.com //npm.greensock.com/:_authToken=<token> As I mentioned this is happening on the local dev environment for a Next app on Ubuntu 20.04 using Yarn 3.1.1, on a Win 10 machine using Yarn 1.22.5 works as expected. Over the weekend I took the time to install Ubuntu 20.04 here at home and I'm seeing the same issue. This is the result: rodrigo@rodrigo-desktop:~/Web Apps/GSAP/yarn-bonus$ yarn add @gsap/shockingly gsap@npm:@gsap/shockingly ➤ YN0027: @gsap/shockingly@unknown can't be resolved to a satisfying range ➤ YN0035: The remote server failed to provide the requested resource ➤ YN0035: Response Code: 404 (Not Found) ➤ YN0035: Request Method: GET ➤ YN0035: Request URL: https://registry.yarnpkg.com/@gsap%2fshockingly ➤ Errors happened when preparing the environment required to run this command. I created a simple project using yarn init without any dependencies and the results are the same. No issues in Win 10/Yarn 1.22.5 and the same error in Ubuntu 20.04/Yarn 3.1.1. If I have time I'll see if I can remove yarn and install the latest 1.x version (which is no longer supported though) and see if it works with that. Finally I created an issue in Yarn, but it was marked as unreproducible by the bot so I don't know what amount of attention it'll attract: https://github.com/yarnpkg/berry/issues/4072 Best, Rodrigo.
  7. @Prasanna Someone at work actually uses Ubuntu and it's having issues with this. When running yarn add @gsap/shockingly it gives the following error: ➤ YN0027: @gsap/shockingly@unknown can't be resolved to a satisfying range ➤ YN0035: The remote server failed to provide the requested resource ➤ YN0035: Response Code: 404 (Not Found) ➤ YN0035: Request Method: GET ➤ YN0035: Request URL: https://registry.yarnpkg.com/@gsap%2fshockingly Also a message to my fellow GreenSockers, running this yarn add gsap@npm:@gsap/shockingly, result in this error as well in Ubuntu: ➤ YN0000: ┌ Resolution step ➤ YN0001: │ Error: gsap@npm:@gsap/shockingly isn't supported by any available resolver at pd.getResolverByDescriptor (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:432:5658) at pd.bindDescriptor (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:432:5047) at I (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:441:6932) at async Promise.all (index 0) at async Ke.resolveEverything (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:441:8197) at async /home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:444:2138 at async Fe.startTimerPromise (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:412:3730) at async Ke.install (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:444:2077) at async /home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:449:122 at async Function.start (/home/nidhal/.node/corepack/yarn/3.1.1/yarn.js:412:2287) ➤ YN0000: └ Completed ➤ YN0000: Failed with errors in 0s 7ms I don't know if this is related to the version of yarn that He has installed in his machine (I believe is 3.1.1), but while installing stuff in linux is a bit different that win/mac the resulting installed resource should be the same. Also is worth noticing that we're not using netlify for this, we're deploying on digital ocean using a docker image. For now we'll use the .tgz file and since is a private repo, there isn't a lot of issues with it, but it would be great to have a notion of what's the issue here. I did a search in the issues at Yarn's repo and didn't found anything so I'll create a ticket there and give feedback regarding this. Cassie, Jack. I don't know if this is the right place for this, since my issue is not related to Next and Netlify, if you want I can create a new thread in the forums specific for this. Best, Rodrigo.
  8. I don't want to be that annoying intransigent guy that defends something just because. While Nuxt routing could be a bit more confusing than Next's routing, is not at all complex and they share quite a few similarities: https://nuxtjs.org/docs/get-started/routing https://nuxtjs.org/docs/features/file-system-routing/ While I'm not trying to convince you about ditching Next in favor of Nuxt, I believe that both frameworks' routing systems are quite similar and offer the same functionalities and finally, a fair assessment of both cases can be done by looking the docs and demos on the subject. Happy Tweening!!!
  9. Hey, Based on these articles: https://dev.to/anxiny/page-transition-effect-in-nextjs-9ch https://ellismin.com/2020/05/next-page-transition/ I came up with this: https://github.com/rhernandog/next-gsap-transitions Live sample (nothing fancy, just a proof of concept): https://cranky-heyrovsky-83f0a9.netlify.app/ The only drawback in this approach is that you can't use the module approach for styling each page: https://dev.to/koraysels/comment/1f341 Also @John Polacek has this package, but I don't know if it is production-ready, John should be the one to tell us: https://github.com/johnpolacek/TweenPages Hopefully these help you get started. Finally if I was you I would invest time in using Nuxt since they have Vue's native animation solution implemented without any of this hassles. I recently did a little consulting for this site created with Nuxt and GSAP and works great: https://fcwisi1.ch/ Happy Tweening!!!!
  10. The GSAP instance is being stored in a reference that will be kept through re-renders, unless you update the ref.current value by hand: Perhaps that should be re-phrase to: "store the timeline in a reference using useRef()", but I believe the point is pretty clear. Finally Blake is right, in most cases when using HMR, an update to the code might keep state but reset other stuff, which can result in the DOM elements going to their initial state, which can conflict specially with .from() instances and other GSAP instances. In those cases the good ol' F5 key is the only solution for that. Happy Tweening!!!
  11. Hi and welcome to the GreenSock forums. In order to make the plugins work in Next you need to import them from the dist folder: import { ScrollTrigger } from "gsap/dist/ScrollTrigger"; Finally if you run into some issues with the register part, be sure to check for the window object and not the process.browser property: if (typeof window !== "undefined") { gsap.registerPlugin(ScrollTrigger); } Happy Tweening!!!
  12. That happens because all of them are in the DOM at the same time, you can solve that by tinkering with the position styles in order to take one or all of them from document flow or use the switch transition component: https://reactcommunity.org/react-transition-group/switch-transition Happy Tweening!!!
  13. The done callback should be able to do that on both cases enter/exit. Keep in mind that enter and exit are different things, similar to how GSAP handles display: "none"/"block". The real thing is that done and timeout are just used to update the state of the <Transition> component, nothing more. Depending on a specific state property the component is either rendered or not. I don't want to get into more specifics because, IMHO we don't need even more confusion about the usage of GSAP in a React app around here Here you can see the render method of the <Transition> component (a class component maintained by the React team, go figure ): https://github.com/reactjs/react-transition-group/blob/master/src/Transition.js#L342-L378 At the top you find the conditional rendering logic for it: const status = this.state.status if (status === UNMOUNTED) { return null } The status property changes between this values depending on the stage of the transition: export const UNMOUNTED = 'unmounted' export const EXITED = 'exited' export const ENTERING = 'entering' export const ENTERED = 'entered' export const EXITING = 'exiting' If you follow the logic in the componentDidUpdate hook and the associated callbacks you'll see that this isn't exactly setting up a nuclear reactor, is quite simple actually. In this sample you can check it in dev tools, is a bit outdated but the mechanics of it are pretty much the same. If you add a new element is mounted then animated in. If you remove an element is animated out and then unmounted from the DOM: https://stackblitz.com/edit/gsap-react-transition-group-list?file=transition-card.js Finally I don't know all the ins and outs of transition group but is a great package and certainly quite useful in some specific cases.
  14. @granularclouds Be more careful with your syntax <Transition in={key === color} onExt={exit} // onExit <--!!!!!!! onEntering={(el) => enter(el, i)} mountOnEnter unmountOnExit appear timeout={1500} > Happy Tweening!!!
  15. Indeed you are : const exit = (node) => { gsap.from(node, { duration: 1.5, delay: 0.5, opacity: 1, stagger: 0.5 }); }; You're creating a from instance. That basically takes the elements from the values you're passing to it in the config object to the current ones the DOM element has. So basically this code is saying: "Take this cards and animate them from opacity: 1 to their current opacity". Turns out that their current opacity is also one, so GSAP is actually doing it's job, but this is animating the opacity from one to one, so visually there is no change at all. This should work: const exit = (node) => { gsap.to(node, { duration: 1.5, delay: 0.5, opacity: 0, stagger: 0.5 }); }; Happy Tweening!!!
  16. The issue is that the in property in the <Transition> component has to be a boolean that defaults to false and now you're passing a string, so yeah the new element is being animated in when is mounted, but when the radio selection changes the elements are removed immediately, so basically is just acting as a conditional rendering logic, nothing more: https://reactcommunity.org/react-transition-group/transition#Transition-prop-in @granularclouds what you should do is create a way to loop through the object, then loop through the array of each object element and return the <Transition> component for each one. This code seems to do the trick: return ( <div className="App"> <div> <div className="radio-container"> /* ... */ </div> <div className="card-container"> <TransitionGroup> <div className="cards"> {(() => { let test = []; for(let key in colors) { const elements = colors[key].map((item, i) => <Transition in={key === color} key={item.title} onExit={exit} onEntering={(el) => enter(el, i)} mountOnEnter unmountOnExit appear timeout={1500} > <div className="card"> <h1> {item.title}</h1> <h6>{item.subtitle}</h6> </div> </Transition> ); test = [...test, ...elements]; } return test; })()} </div> </TransitionGroup> </div> </div> </div> ); This could also be broken into smaller components in order to keep the code cleaner and easier to read. Also is recommended to match the timeout property in the <Transition> component to the duration of the GSAP instance, the timeout property tells transition group when to remove the elements and update the enter/exit state properties. Happy Tweening!!!
  17. Hi, In the case of Next you need to import the file from the dist folder: import { ScrollTrigger } from "gsap/dist/ScrollTrigger"; Happy Tweening!!!
  18. Hi, The main problem here is that the code in the Navigation component is running before everything is being updated after creating the smooth scroller instance, that's why this only works in a HMR because the smooth scroll instance is already created. To be completely honest I haven't used any smooth scroll packages in production so I don't have a lot of knowledge in that regard, also I really don't like them, IMHO they create more problems than they solve and I really don't like anything that creates more problems that it solves in any aspect of life, but that's just a personal opinion. The only solution I can come up with that is actually working is to add a timeout in the Navigation component: const Navigation = () => { useEffect(() => { gsap.registerPlugin(ScrollTrigger); setTimeout(() => { gsap.to(".pin-item", { opacity: 1, x: 100, scrollTrigger: { trigger: ".pin-trigger", markers: true, pin: true, pinSpacing: false } }); }, 50); }, []); return ( <div className="pin-trigger"> <h1 className="pin-item">hello</h1> </div> ); }; But this is less than ideal and every React developer will tell you the same, but honestly I can't think of any other way and I don't have a lot of time to go through this and find out. You're using Next and I believe that the idea is to create an animated nav bar that animates down when the user scrolls down in order to make it visible, right? Perhaps you could create the animation in the navigation component and create the Scroll Trigger instance in the layout component where you could instantiate the smooth scroll package as well. You can do that using forward refs, you can read more about it here: https://reactjs.org/docs/forwarding-refs.html Here is a simple example: https://codesandbox.io/s/react-hover-forward-ref-ybtgs But those are just ideas since I have no experience with these smooth scroll packages in production. Perhaps @elegantseagulls has dealt with them and could offer some advice on the subject. Happy Tweening!!!
  19. Hi, Adding a start point to your ScrollTrigger instances seems to work: gsap.fromTo( w, { x }, { x: xEnd, scrollTrigger: { trigger: section, start: "top 92%", scrub: 0.5 } } ); Also it's a good idea to pass an array of dependencies to your useEffect hook in order to prevent it from running everytime the state or a property of the component is updated: useEffect(() => { // code here }, []); The array can have dependencies or not, read more about it here: https://reactjs.org/docs/hooks-effect.html Happy Tweening!!!
  20. Hi and welcome to the GreenSock forums. The issue is that right now you're executing the function, so as soon as the browser gets to that part of the code the playSound function is executed. GSAP has an excellent callback system that allows you to pass parameters, set scope, etc. This should work as expected: tl.to("#knapp", { background: "#a6a6a6", onComplete: playSound, onCompleteParams: ["knapp0"] }); Here you can learn more about callbacks, just scroll down to the Special Properties section: https://greensock.com/docs/v3/GSAP/gsap.to() Happy Tweening!!!
  21. You could also take a look at this sample by @mikel Happy Tweening!!!
  22. HI, Cassie is completely right, you need to move your GSAP code to a useEffect or useCallback hook. Most of the time a useEffect hook should be enough, but if you run into some issues you might need to switch to a useCalback or useLayoutEffect. Right now when react runs your code, it does it in the regular JS way, so it starts at the top and goes through it until everything is ran. The issue is that your GSAP code runs before the return statement that actually tells react what it should add to the DOM. A useEffect hook with an empty dependencies array: useEffect(() => { let frame_count = 9 let offset_value = 100 const t = gsap.to(imageViewer.current, { scrollTrigger: { trigger: imageScene.current, start: "top top", end: "+=" + (frame_count * offset_value), pin: true, scrub: true } }); // Clean up before unmounting the component/page return () => { t.kill(); ScrollTrigger.getAll().forEach(e => e.kill()); }; }, []); You can learn about the useEffect hook here: https://reactjs.org/docs/hooks-effect.html https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup Finally since you're using Next, is not really a good idea to check the process object to see if the code is running on the client or the server, that is basically an object created and used by webpack, is better to check if the window is undefined or not: if (typeof window !== "undefined") { gsap.registerPlugin(ScrollTrigger); } Happy Tweening!!!
  23. Hi, This is how the position parameter works: Happy Tweening!!!
  24. Hi, Just to add on Paul and Blake great advice, here are a couple of live samples in React that toggle a GSAP instance. This one uses a regular click handler: https://codesandbox.io/s/simple-gsap-instance-toggle-xc741 This one uses a state property to toggle the instance: https://codesandbox.io/s/gsap-toggle-instance-with-hooks-t9uqr Happy Tweening!!!
  25. Hi, Instead of creating the scrollbar instance as a constant inside a specific useEffect hook, create a reference in the scope of the component with a useRef hook, like that it will available in every method/hook in your component: const scroller = useRef(); useEffect(() => { scroller.current = document.querySelector(".scroller"); Scrollbar.init(scroller.current); setScrollBarCreated(true); }, []); Also in the last version of your codesandbox you're not setting the scroller default for scroll trigger and the code in your navigation probably won't do anything, so you might want to check that as well: const Navigation = () => { useEffect(() => { gsap.to("." + styles.logo, { opacity: 1, x: 100, scrollTrigger: { trigger: "#pin-target", pin: true, end: 900, pinSpacing: false } }); }, []); return ( <div> <h1 className="logo">hello</h1> </div> ); }; Happy Tweening!!!