JonQuayle Posted August 23, 2022 Share Posted August 23, 2022 (edited) Hi, I am trying to animate elements as the parent appears in the viewport. I have followed this article (https://ihatetomatoes.net/react-and-greensock-tutorial-for-beginners/#6-how-to-use-scrolltrigger-with-react) to animate the parent as it appears in the viewport using ScrollTrigger, but I have an image and text elements as children to each of these parents which I also want to animate in - but not as the individual elements appear in the viewport, when the parent appears in the viewport. I'm assuming the best thing to do would be to play a timeline for each(?), but am struggling with where that timeline would sit and how to reference the separate elements in the timeline. I'm building this in React so I don't know if I am supposed to be calling the elements in a certain way? Whatever I have tried so far hasn't worked so I've pulled it back to the point of the above link. I'm also really struggling getting this into a Codepen as its React and is pulling data in from a headless CMS - it just isn't playing ball. So the code below is animating in the parents elements correctly, but how can I set the ScrollTrigger on these parents elements, but animate their children rather than the element that is being watched by ScrollTrigger? I'm sorry if this is a long post, I'm reaching the end of my understanding with this 😂 // Referencing the Featured Projects to reveal const revealRefs = useRef([]); // for each of the projects to reveal, add them to an array. // This will allow this array to be looped over and animate its children invididually revealRefs.current = []; const el = useRef(); const q = gsap.utils.selector(el); useLayoutEffect(() => { revealRefs.current.forEach((el, index) => { gsap.fromTo(el, { opacity: 0, }, { ease: "sine.easeOut", duration: 0.8, opacity: 1, scrollTrigger: { markers: true, trigger: el, start: "top 85%", } }); }); }, []); // Adds all found refs to the revealRefs array for animation const addToRefs = (el) => { // Check if the element exists. // If it does not include it in the revealRefs array if(el && !revealRefs.current.includes(el)){ revealRefs.current.push(el); } }; The actual markup is like this: {projects.results.map((document) => ( <div className="featured-project_wrapper" key={document.id} ref={addToRefs}> <PrismicLink className="featured-project_item" document={document} > <figure className="featured-project_image"> <div className="reveal-overlay" style={{backgroundColor: document.data.main_colour}}></div> <PrismicNextImage field={document.data.featuredImage} imgixParams={{ q: 80 }} layout="fill" /> </figure> <div className="featured-project_info"> <h2 className="heading"> <PrismicText field={document.data.projectTitle} /> </h2> <div className="underlined-text-link">View project</div> </div> </PrismicLink> </div> ))} Thanks See the Pen ExEJaBK by JonQuayle (@JonQuayle) on CodePen Edited August 23, 2022 by JonQuayle Adding link to codepen Link to comment Share on other sites More sharing options...
mvaneijgen Posted August 23, 2022 Share Posted August 23, 2022 Hey @JonQuayle could you try creating a demo in CodeSandbox, bellow there are examples for each of the major frameworks, including React. Quote If you're using something like React/Next/Nuxt/Gatsby or some other framework, you may find CodeSandbox easier to use. I personally like to create timelines for each of my ScrollTriggers so that scroll logic is separate from the tweens. Even if it is only one tween (it is never one tween, because ScrollTrigger is so fun you'll always add more tweens later) let tl = gsap.timeline({ // yes, we can add it to an entire timeline! scrollTrigger: { trigger: ".container", pin: true, // pin the trigger element while active start: "top top", // when the top of the trigger hits the top of the viewport end: "+=500", // end after scrolling 500px beyond the start scrub: 1, // smooth scrubbing, takes 1 second to "catch up" to the scrollbar snap: { snapTo: "labels", // snap to the closest label in the timeline duration: {min: 0.2, max: 3}, // the snap animation should be at least 0.2 seconds, but no more than 3 seconds (determined by velocity) delay: 0.2, // wait 0.2 seconds from the last scroll event before doing the snapping ease: "power1.inOut" // the ease of the snap animation ("power3" by default) } } }); // add animations and labels to the timeline tl.addLabel("start") .from(".box p", {scale: 0.3, rotation:45, autoAlpha: 0}) .addLabel("color") .from(".box", {backgroundColor: "#28a92b"}) .addLabel("spin") .to(".box", {rotation: 360}) .addLabel("end"); See the docs for more examples 2 Link to comment Share on other sites More sharing options...
Cassie Posted August 23, 2022 Share Posted August 23, 2022 1 hour ago, JonQuayle said: I'm also really struggling getting this into a Codepen as its React and is pulling data in from a headless CMS - it just isn't playing ball. Also - just use vanilla JS and some coloured boxes to start with! Get the GSAP/animation bit right. Then when you're happy pull it in to react and worry about data wrangling. Don't make life more difficult for yourself! 1 Link to comment Share on other sites More sharing options...
JonQuayle Posted August 23, 2022 Author Share Posted August 23, 2022 Thanks all, I've taken the time to recreate this in a codepen as simply as I can. So, I've got the 'featured project' opacity animating in using scroll trigger fine, but I don't know where to start in animating children elements in when the parent container comes into view. I'm wanting the blue overlay to scale up to 0, revealing the image beneath, and fade the title and link element in from 0. I'm probably making this harder with the project being in React. Link to comment Share on other sites More sharing options...
Solution mvaneijgen Posted August 23, 2022 Solution Share Posted August 23, 2022 Thanks for the demo, this really helps! As I said, I would create a timeline and add these animations to the timeline. Then add ScrollTrigger to the timeline to have it function on scroll. The best thing to do with ScrollTrigger is to remove it! This seems counter intuitive, but ScrollTrigger is just animating something on scroll, so just focus on the animation at first and only when you're happy with the animation add ScrollTrigger back in. I've animated the overlay and the title, I'll leave it up to you do add the link animation to the timeline. Start playing around with the position parameter to tweak the timing or have elements even animated in at the same time! See the Pen bGvJVep?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen Good luck! Oh and try enabling the scrub: 1 code that is commented out and see what that does! 1 Link to comment Share on other sites More sharing options...
Cassie Posted August 23, 2022 Share Posted August 23, 2022 Yep - React definitely makes stuff harder! Here's our guide for when you need it though -> Link to comment Share on other sites More sharing options...
JonQuayle Posted August 23, 2022 Author Share Posted August 23, 2022 Thanks @mvaneijgen, that is much clearer now, now to get this to play nicely in React :). Link to comment Share on other sites More sharing options...
Cassie Posted August 24, 2022 Share Posted August 24, 2022 May the react gods smile down kindly on you 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