3mo Posted June 12, 2023 Share Posted June 12, 2023 (edited) Hello, I'm new to GSAP, so I apologize in advance if my problem could have been solved simply. I have an HTML structure that looks like this: <div class="chapter chapter-1"> <div class="page page-1"> <div class="sheet"> <p class="storyline">Lorem ipsum dolor sit amet consectetur adipisicing elit. Adipisci commodi optio fugiat eum porro provident necessitatibus vitae. Quis, doloremque inventore recusandae aperiam dolore adipisci blanditiis est dolorum architecto dicta quasi?</p> <i class="fa-solid fa-circle-left reading-btn previous-chapter"></i> <i class="fa-solid fa-circle-chevron-right reading-btn next-page"></i> </div> </div> Of course, there are several chapters (chapter-1, chapter-2, ...) which themselves have several pages (page-1, page-2, ...). I'd like to run a SplitType animation on my <p class="storyline"> each time it or its parent <div class="sheet"> enters the viewport. To achieve this, I wrote the following code: for (let indexPage = 0; indexPage < storyLines.length; indexPage++) { const numPage = indexPage + 1; console.log('Chapter ' + numChapter); console.log('Page ' + numPage); // I used this console.log only to make sure I had the right chapter and page number const line = new SplitType(`.chapter-${numChapter} .page-${numPage} .storyline`, { types: 'chars' }); gsap.fromTo(`.chapter-${numChapter} .page-${numPage} .char`, { y: 100, opacity: 0 }, { y: 0, opacity: 1, stagger: 0.1, duration: 3, delay: 3, ease: 'power4.out', scrollTrigger: { trigger: `.chapter-${numChapter} .page-${numPage} .storyline`, toggleActions: "play none reverse none" } } ) } This loop is itself in another loop: for (let indexChapter = 0; indexChapter < chapters.length; indexChapter++) { const numChapter = indexChapter + 1; I've encountered two main problems: either the animations don't trigger, or they trigger at the same time, so by the time I got to the next page, the animation had already begun. Thank you in advance, my code is not clean, I apologize. See the Pen Rwqrrga by IListenToLofi (@IListenToLofi) on CodePen Edited June 14, 2023 by 3mo CodePen URL Link to comment Share on other sites More sharing options...
GSAP Helper Posted June 12, 2023 Share Posted June 12, 2023 It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or CodeSandbox that demonstrates the issue? Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer. Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo: See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen If you're using something like React/Next/Vue/Nuxt or some other framework, you may find StackBlitz easier to use. We have a series of collections with different templates for you to get started on these different frameworks: React/Next/Vue/Nuxt. Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. Link to comment Share on other sites More sharing options...
3mo Posted June 12, 2023 Author Share Posted June 12, 2023 31 minutes ago, GSAP Helper said: It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or CodeSandbox that demonstrates the issue? Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer. Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo: If you're using something like React/Next/Vue/Nuxt or some other framework, you may find StackBlitz easier to use. We have a series of collections with different templates for you to get started on these different frameworks: React/Next/Vue/Nuxt. Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. Alright, I will try. Link to comment Share on other sites More sharing options...
Carl Posted June 12, 2023 Share Posted June 12, 2023 at a first glance your code looks pretty good. no glaring errors but of course I have no idea how a dynamic selector like `.chapter-${numChapter} .page-${numPage} .storyline` is actually accurate or working, which is why a minimal demo is so important. perhaps using something like this as a starting point will help. See the Pen VwVLOBB by snorkltv (@snorkltv) on CodePen Add complexity until it breaks. I don't know what splitType is so I used GreenSock's SplitText Definitely put markers: true to test your triggers and measurement. Also I find it helpful to test each selector to make sure it's working with something like a simple color change like gsap.set(`.chapter-${numChapter} .page-${numPage} .storyline`, {color:'red'}) 4 Link to comment Share on other sites More sharing options...
3mo Posted June 13, 2023 Author Share Posted June 13, 2023 Excuse me, I've run into some trouble with CodePen, if I can sort it out I'll share a link. In the meantime, I've noticed something with the isInViewport() function. As soon as I scroll a bit, all my pages are considered in the viewport even if they're not yet visible. My project is quite complex, consisting of several sections each 100% the size of the viewport. Here's a scheme that might clarify things for you : https://www.tldraw.com/r/v27csguvzfDD-U9eSBNrVf_ As soon as I have time, I'll try to solve this problem without using getBoundingClientRect() if possible. Link to comment Share on other sites More sharing options...
GreenSock Posted June 14, 2023 Share Posted June 14, 2023 @3mo can you please provide a minimal demo? I'd love to take a look. Did you realize that by default it only considers the VERTICAL position - I wonder if you're trying to test the horizontal position? If so, there's a "horizontal" parameter that you'd set to true for that. See the docs. Link to comment Share on other sites More sharing options...
3mo Posted June 14, 2023 Author Share Posted June 14, 2023 Hello, I've edited my 1st post with a CodePen link. Sorry for the delay, I hope it's clear enough. Link to comment Share on other sites More sharing options...
GreenSock Posted June 15, 2023 Share Posted June 15, 2023 Hm, I don't see any of that code in the CodePen you provided. No ScrollTrigger code at all. Nothing matched the sample code higher up in your post. Here are some tips that will increase your chance of getting a solid answer: A clear description of the expected result - "I am expecting the purple div to spin 360degrees" A clear description of the issue - "the purple div only spins 90deg" A list of steps for someone else to recreate the issue - "Open the demo on mobile in IOS safari and scroll down to the grey container" A minimal demo - if possible, using no frameworks, with minimal styling, only include the code that's absolutely necessary to show the issue. Please don't include your whole project. Just some colored <div> elements is great. Link to comment Share on other sites More sharing options...
3mo Posted June 15, 2023 Author Share Posted June 15, 2023 12 hours ago, GreenSock said: Hm, I don't see any of that code in the CodePen you provided. No ScrollTrigger code at all. Nothing matched the sample code higher up in your post. Here are some tips that will increase your chance of getting a solid answer: A clear description of the expected result - "I am expecting the purple div to spin 360degrees" A clear description of the issue - "the purple div only spins 90deg" A list of steps for someone else to recreate the issue - "Open the demo on mobile in IOS safari and scroll down to the grey container" A minimal demo - if possible, using no frameworks, with minimal styling, only include the code that's absolutely necessary to show the issue. Please don't include your whole project. Just some colored <div> elements is great. Sorry, I hope this new version will be easier to understand : GSAP Starter Template (codepen.io) My aim is to launch an animation on the text of each <div class="sheet"> when the latter is in the viewport. When rewriting my code in CodePen, I noticed that isInViewport(element) returned true if element was in the viewport horizontally (as if the viewport were 100vh high but 100% of the body wide instead of 100vw). So I'd like a way for isInViewport(element) to return true only if (element) is "really" visible. I hope this description is clearer. Link to comment Share on other sites More sharing options...
Solution GreenSock Posted June 15, 2023 Solution Share Posted June 15, 2023 Yes, that's because that method is focused on one direction only (in the vast majority of cases, developers only want their page to scroll in one direction, vertically or horizontally and we wanted to optimize performance accordingly). It's still quite easy to accomplish. Here are two options: 1) Call the method once to check vertically (default) and again to check horizontally document.addEventListener("scroll", updateValues, {passive: true}); function updateValues() { viewport.innerText = ScrollTrigger.isInViewport(sheet) && ScrollTrigger.isInViewport(sheet, 0, true); } 2) Or just use IntersectionObserver: let observer = new IntersectionObserver(handleIntersect); observer.observe(sheet); function handleIntersect(entries) { entries.forEach(entry => { viewport.innerText = entry.isIntersecting; }) } I hope that helps. Link to comment Share on other sites More sharing options...
3mo Posted June 16, 2023 Author Share Posted June 16, 2023 19 hours ago, GreenSock said: Yes, that's because that method is focused on one direction only (in the vast majority of cases, developers only want their page to scroll in one direction, vertically or horizontally and we wanted to optimize performance accordingly). It's still quite easy to accomplish. Here are two options: 1) Call the method once to check vertically (default) and again to check horizontally document.addEventListener("scroll", updateValues, {passive: true}); function updateValues() { viewport.innerText = ScrollTrigger.isInViewport(sheet) && ScrollTrigger.isInViewport(sheet, 0, true); } 2) Or just use IntersectionObserver: let observer = new IntersectionObserver(handleIntersect); observer.observe(sheet); function handleIntersect(entries) { entries.forEach(entry => { viewport.innerText = entry.isIntersecting; }) } I hope that helps. Thank you very much, that's exactly what I needed Link to comment Share on other sites More sharing options...
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