PixeledCode Posted June 25, 2021 Posted June 25, 2021 Hi, I'm trying to implement a basic ScrollTrigger animation on Nextjs. It's basically changing sidebar background based on current position of scroll. You can check it's implementation here: Introduction - Budget Basics | Open Budgets India. Problem is initial load of page, which messes up the the start/end of scrolltrigger but resizing the browser fixes the position. I tried some solutions from this post: ScrollTrigger Unexpected Behavior with Smooth Scrollbar in React/NextJs - GSAP - GreenSock but they are not working in my case. All of the code is available here: budget-basic-next/[chapter].js at main · PixeledCode/budget-basic-next (github.com) but basically what I'm doing is useEffect(() => { gsap.registerPlugin(ScrollTrigger) setTimeout(handleSidebarAnimation, 100) return () => { ScrollTrigger.refresh() if (ScrollTrigger.getById('st-id')) { ScrollTrigger.getById('st-id').kill() } } }, []) and the function is function handleSidebarAnimation() { const articles = gsap.utils.toArray('article') articles.forEach((article) => { let sideLink = document.querySelector( `li[keyid=${article.getAttribute('id')}]` ) gsap.to(sideLink, { scrollTrigger: { markers: true, trigger: article, id: 'st-id', start: 'top 22%', end: 'bottom 18%', refreshPriority: 1, toggleActions: 'restart complete reverse reset', onEnter() { sideLink.classList.add('activeSidebar') }, onLeave() { sideLink.classList.remove('activeSidebar') }, onEnterBack() { sideLink.classList.add('activeSidebar') }, onLeaveBack() { sideLink.classList.remove('activeSidebar') }, }, }) }) } I know I'm probably doing something wrong and it's dom order which is creating issues on initial load (eg: coming from home page to the page with sidebar and animation.) but I am not able to find where. Any help is appreciated!
Cassie Posted June 25, 2021 Posted June 25, 2021 Hi there! Could you possibly put together a minimal demo? codesandbox has some Nextjs templates
PixeledCode Posted June 25, 2021 Author Posted June 25, 2021 Hi @Cassie thanks for replying. So I tried to setup and here is the codesandbox link: mystifying-nash-pp4kd - CodeSandbox I was testing and noticed something. The problem is not on the pages without images and so I believe that the images are being loaded late and then the ScrollTrigger is not refreshing on that change... Could this be an issue, and if yes, any idea on how to fix it? Thank You
PixeledCode Posted June 25, 2021 Author Posted June 25, 2021 58 minutes ago, PixeledCode said: Hi @Cassie thanks for replying. So I tried to setup but wasn't able to import css files, I'm ashamed. Here is the codesandbox link: mystifying-nash-pp4kd - CodeSandbox Anyway, I was testing and noticed something. The problem is not on the pages without images and so I believe that the images are being loaded late and then the ScrollTrigger is not refreshing on that change... Could this be an issue, and if yes, any idea on how to fix it? Thank You ok so this post helped. ScrollTrigger doesn't work properly on page with lazy load images - GSAP - GreenSock. I'm listening to images being loaded and then refreshing now. Fixing this I found another issue. Next.js have next/link for routing which makes routing possible without reloading. Kind of hot reloading but that also crashes gsap. You can possibly reproduce it by going to the link https://pp4kd-3001.sse.codesandbox.io and selecting first box 'Introduction', go to the bottom and selecting, 'read more'. Next page will be broken with total height similar to previous page but all of it is whitespace. Either removing scrolltrigger or removing next/link and using regular <a> tags fixes it.
OSUblake Posted June 25, 2021 Posted June 25, 2021 Hi @PixeledCode You codesandbox link isn't working, it's show a 502 error. Can you provide another one?
PixeledCode Posted June 25, 2021 Author Posted June 25, 2021 19 minutes ago, OSUblake said: Hi @PixeledCode You codesandbox link isn't working, it's show a 502 error. Can you provide another one? Hi, sorry about that. That was production mode build I made on Codesandbox, I think they don't keep them running for long. Here's the code: https://codesandbox.io/s/mystifying-nash-pp4kd?file=/pages/_app.js
OSUblake Posted June 25, 2021 Posted June 25, 2021 I'm having trouble understanding how your app even works, and it's really slow to navigate, but it looks like it you're not creating new scroll triggers when going to a different page. I added a line to log out the number of scroll triggers, but it only fires once. function handleSidebarAnimation() { console.log("TRIGGERS 1", ScrollTrigger.getAll().length); ... } And the cleanup never fires. useEffect(() => { setTimeout(handleSidebarAnimation, 100); window.addEventListener("scroll", handleScroll); return () => { const t = ScrollTrigger.getAll(); console.log("TRIGGERS 2", t.length); t.forEach((t) => t.kill()); window.removeEventListener("scroll", handleScroll); }; }, []); So that means ScrollTrigger doesn't know the new layout. You need to find a way to recreate your triggers on a new page, and kill the old ones. I would also use v3.6.1 for the time being as we are investigating a possible issue when navigating pages. I would also avoid using setTimeout as something could change in between that time period. If you need ScrollTrigger to recalculate, just use .refresh(). 1
PixeledCode Posted June 25, 2021 Author Posted June 25, 2021 15 minutes ago, OSUblake said: I'm having trouble understanding how your app even works, and it's really slow to navigate, but it looks like it you're not creating new scroll triggers when going to a different page. I added a line to log out the number of scroll triggers, but it only fires once. function handleSidebarAnimation() { console.log("TRIGGERS 1", ScrollTrigger.getAll().length); ... } And the cleanup never fires. useEffect(() => { setTimeout(handleSidebarAnimation, 100); window.addEventListener("scroll", handleScroll); return () => { const t = ScrollTrigger.getAll(); console.log("TRIGGERS 2", t.length); t.forEach((t) => t.kill()); window.removeEventListener("scroll", handleScroll); }; }, []); So that means ScrollTrigger doesn't know the new layout. You need to find a way to recreate your triggers on a new page, and kill the old ones. I would also use v3.6.1 for the time being as we are investigating a possible issue when navigating pages. I would also avoid using setTimeout as something could change in between that time period. If you need ScrollTrigger to recalculate, just use .refresh(). Thank you for this. My problem looks similar to the post you shared. Using normal <a> instead of next/link is working fine. I'll also try with v3.6.1 and see how it goes. And yeah, sorry for slow speed. I connected it with my strapi backend which is hosted on a really slow server so it's taking time for each navigation. 1
OSUblake Posted June 25, 2021 Posted June 25, 2021 17 minutes ago, PixeledCode said: Using normal <a> instead of next/link is working fine I'm not familiar with how next/link works, but it sounds like it's just reusing the same component instance instead of making a new one, which is why the useEffect only fires once. Not sure if there is way to disable that behavior. I know with Nuxt, Vue's version of Next, there is. 1
Solution OSUblake Posted June 25, 2021 Solution Posted June 25, 2021 I added chapter(s) to the dependency array, and now it looks like it's working. I also used v3.7.1. https://codesandbox.io/s/jovial-chaplygin-t3b86?file=/pages/[chapter].js 1
PixeledCode Posted June 25, 2021 Author Posted June 25, 2021 15 minutes ago, OSUblake said: I added chapter(s) to the dependency array, and now it looks like it's working. I also used v3.6.1. https://codesandbox.io/s/jovial-chaplygin-t3b86?file=/pages/[chapter].js You're right. It's working now. Thanks a lot! 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now