Visual23 Posted January 30, 2023 Posted January 30, 2023 Hi all, If you look at the link below I have the section animations playing when a section is in view. It works by scrolling or using the dot navigation. After I go to a section and it animates in as intended. I'd like to be able to leave that section, reset it so when I come back it plays again. I've tried adding toggleActions but it doesn't seem to work. Thanks in advance! Username: demo Password: demopass https://v23static.wpengine.com/story-of-water.php My GSAP code: const timelines = []; timelines[0] = gsap.timeline({ scrollTrigger: { trigger: "#section-0", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-0", onLeaveBack: () => video_00.play(), } }) timelines[1] = gsap.timeline({ scrollTrigger: { trigger: "#section-1", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-1", //onEnter: () => video_00.pause() } }) timelines[2] = gsap.timeline({ scrollTrigger: { trigger: "#section-2", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-2" } }) timelines[3] = gsap.timeline({ scrollTrigger: { trigger: "#section-3", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-3", } }) timelines[4] = gsap.timeline({ scrollTrigger: { trigger: "#section-4", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-4" } }) timelines[5] = gsap.timeline({ scrollTrigger: { trigger: "#section-5", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-5" } }) timelines[6] = gsap.timeline({ scrollTrigger: { trigger: "#section-6", start: () => { return `top top` }, end: () => { return `bottom bottom` }, //markers: true, id: "section-6" } }) timelines[1] .fromTo('.section-menu', { opacity:0 }, { opacity:1, duration:0.5, ease: "none", delay: 0, }) .fromTo('#section-1 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .fromTo('#section-1 #title', { opacity:0 }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0 }) .from("#section-1 #mask-path-1", { duration: 2, drawSVG: 0, ease: "none" }) .from("#section-1 #mask-path-2", { duration: .5, drawSVG: 0, ease: "none" },">-0.05") .fromTo('#section-1 .blob-wrapper', { opacity:0, scale: ".5" }, { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 },">-0.05") .fromTo('#section-1 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 }) timelines[2] .fromTo('#section-2 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .from("#section-2 #mask-path-1", { duration: .3, drawSVG: 0, ease: "none" }) .from("#section-2 #mask-path-2", { duration: .2, drawSVG: 0, ease: "none" },">-0.1") .fromTo('#section-2 .blob-wrapper', { opacity:0, scale: ".5" }, { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 }) .fromTo('#section-2 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 }) timelines[3] .fromTo('#section-3 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .fromTo('#section-3 #mini-tower-1', { opacity:0, }, { opacity:1, duration:0.3, ease: "linear", delay: .5 },">-0.4") .fromTo( "#section-3 #mini-tower-1 .water", { transform: "translateY(36px)" }, { transform: "translateY(0px)", duration: 1 },">-0.3") .fromTo( "#section-3 #mini-tower-1 .water-waves", { transform: "translateX(44px)" }, { transform: "translateX(1px)", duration: 1,ease: "linear", repeat: -1 },">-0.8") .fromTo('#section-3 #mini-tower-2', { opacity:0, }, { opacity:1, duration:0.3, ease: "linear", delay: 0 },">-1") .fromTo( "#section-3 #mini-tower-2 .water", { transform: "translateY(36px)" }, { transform: "translateY(0px)", duration: 1 },">-0.3") .fromTo( "#section-3 #mini-tower-2 .water-waves", { transform: "translateX(44px)" }, { transform: "translateX(1px)", duration: 1,ease: "linear", repeat: -1 },">-0.8") .fromTo('#section-3 #mini-tower-3', { opacity:0, }, { opacity:1, duration:0.3, ease: "linear", delay: 0 },">-1") .fromTo( "#section-3 #mini-tower-3 .water", { transform: "translateY(36px)" }, { transform: "translateY(0px)", duration: 1 },">-0.3") .fromTo( "#section-3 #mini-tower-3 .water-waves", { transform: "translateX(44px)" }, { transform: "translateX(1px)", duration: 1,ease: "linear", repeat: -1 },">-0.8") .fromTo('#section-3 #mini-tower-4', { opacity:0, }, { opacity:1, duration:0.3, ease: "linear", delay: 0 },">-1") .fromTo( "#section-3 #mini-tower-4 .water", { transform: "translateY(36px)" }, { transform: "translateY(0px)", duration: 1 },">-0.3") .fromTo( "#section-3 #mini-tower-4 .water-waves", { transform: "translateX(44px)" }, { transform: "translateX(1px)", duration: 1,ease: "linear", repeat: -1 },">-0.8") .fromTo('#section-3 #mini-tower-5', { opacity:0, }, { opacity:1, duration:0.3, ease: "linear", delay: 0 },">-1") .fromTo( "#section-3 #mini-tower-5 .water", { transform: "translateY(36px)" }, { transform: "translateY(0)", duration: 1 },">-0.3") .fromTo( "#section-3 #mini-tower-5 .water-waves", { transform: "translateX(44px)" }, { transform: "translateX(1px)", duration: 1,ease: "linear", repeat: -1 },">-0.8") .fromTo('#section-3 #mini-tower-6', { opacity:0, }, { opacity:1, duration:0.3, ease: "linear", delay: 0 },">-1") .fromTo( "#section-3 #mini-tower-6 .water", { transform: "translateY(36px)" }, { transform: "translateY(0)", duration: 1 },">-0.3") .fromTo( "#section-3 #mini-tower-6 .water-waves", { transform: "translateX(44px)" }, { transform: "translateX(1px)", duration: 1,ease: "linear", repeat: -1 },">-0.8") .fromTo('#section-3 .panel', { opacity:0 }, { opacity:1, duration:0.3, ease: "power1.out", y: "-=25", delay: 0 },">-0.8") .call(initSection3) timelines[4] .fromTo('#section-4 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .fromTo('#section-4 .dc-wrapper', { opacity:0, }, { opacity:1, duration:0.5, ease: "none", delay: 0 }) .fromTo('#section-4 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 }) timelines[5] .fromTo('#section-5 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .from("#section-5 #mask-path-1", { duration: .3, drawSVG: 0, ease: "none" }) .fromTo('#section-5 .blob-wrapper', { opacity:0, scale: ".5" }, { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 }) .fromTo('#section-5 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 }) timelines[6] .to('.scroll-to-continue', { opacity:0 }) .fromTo('#section-6 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .fromTo('#section-6 #title', { opacity:0 }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0 }) .from("#section-6 #mask-path-2", { duration: .3, drawSVG: 0, ease: "none" },">-0") .from("#section-6 #mask-path-1", { duration: .6, drawSVG: 0, ease: "none" },">-0") .fromTo('#section-6 .blob-wrapper', { opacity:0, scale: ".5" }, { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 }) .fromTo('#section-6 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 }) See the Pen oNMywPR by visual23 (@visual23) on CodePen.
Rodrigo Posted January 30, 2023 Posted January 30, 2023 Hi, Sorry to hear that you're having problems, but it's impossible for us to debug a live site, plus your site requires a user and password for accessing ?♂️. Please provide a minimal demo that clearly illustrates the problem you're having and include just a few elements, not a complete fork of your project. Be sure that you're using the latest version of GSAP and ScrollTrigger (don't mix them, use the same version for the core and plugins). Happy Tweening!
Visual23 Posted January 30, 2023 Author Posted January 30, 2023 Hi @Rodrigo I realized I didn't add the username and password but I edited the post. Username: demo Password: demopass I will work on the codepen demo. Thanks!
Visual23 Posted January 30, 2023 Author Posted January 30, 2023 Hello, I added the codepen demo. Just for demo purposes, I have the h2 scaling when the section is in view, I'd like that to reset and happen every time the section is in view. Thanks!
Rodrigo Posted January 30, 2023 Posted January 30, 2023 Hi, There is an issue in your setup with your start and end points on your ScrollTrigger instances config. You have this right now: gsap.timeline({ scrollTrigger: { start: "top top", end: "bottom bottom", }, }); That tells GSAP to start when the top of the element reaches the top of the viewport and to end when the bottom of the element reaches the bottom of the viewport. Since each section's height is 100vh both points are reached at the same time, so that triggers the enter/leave and enterBack/leaveBack triggers/callbacks at the same time. So you have to tinker with those a bit in order to have them working in the way you intend. In order to run just the h2 animation with the rest of the timeline and just re-run that when the section is visible again and since the rest of the animations run only once, you can use the callback events with a simple check for each section in order to animate just the titles. Something like this (this just shows the first two sections but this can run easily inside a loop): See the Pen OJwoyZL by GreenSock (@GreenSock) on CodePen. I also changed the start and end points. Hopefully this helps. Happy Tweening!
Visual23 Posted January 30, 2023 Author Posted January 30, 2023 Hello! Thanks for pointing on the issue with the start and end points. That makes sense now. I will give this a try and let you know. Thanks so much! 1
Visual23 Posted January 30, 2023 Author Posted January 30, 2023 Hi @Rodrigo I think I'm getting close. Everything is great when I'm going forward the first time and then backwards but when I get back to section 1 and go forward again, it get's whacky. I included the code for timeline 1. If I understand your example, onEnter and onEnterBack are basically the "to" items and onLeave and onLeaveBack are the "from" items. Is that correct? Thanks!!! timelines[1] = gsap.timeline({ scrollTrigger: { trigger: "#section-1", start: () => { return `top center`; }, end: () => { return `bottom center`; }, //markers: true, id: "section-1", //onEnter: () => video_00.pause() onEnter: () => { if (sectionChecks[1]) { console.log('s1 - onEnter') gsap.to('.section-menu', { opacity:1, duration:0.5, ease: "none", delay: 0, }) gsap.to('#section-1 .svg-wrapper', { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) gsap.to('#section-1 #title', { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0 }) gsap.from("#section-1 #mask-path-1", { duration: 2, drawSVG: 0, ease: "none" }) gsap.from("#section-1 #mask-path-2", { duration: .5, drawSVG: 0, ease: "none" }) gsap.to('#section-1 .blob-wrapper', { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 }) gsap.to('#section-1 .panel', { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 3 }); } else { sectionChecks[1] = true; } }, onEnterBack: () => { console.log('s1 - onEnterBack') gsap.to('.section-menu', { opacity:1, duration:0.5, ease: "none", delay: 0, }) gsap.to('#section-1 .svg-wrapper', { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) gsap.to('#section-1 #title', { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0 }) gsap.from("#section-1 #mask-path-1", { duration: 2, drawSVG: 0, ease: "none" }) gsap.from("#section-1 #mask-path-2", { duration: .5, drawSVG: 0, ease: "none" },">-0.05") gsap.to('#section-1 .blob-wrapper', { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 },">-0.05") gsap.to('#section-1 .panel', { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 3 }); }, onLeave: () => { if (sectionChecks[1]) { console.log('s1 - onLeave') gsap.to('#section-1 .svg-wrapper', { opacity:0, scale: "1.5", duration:0.1, ease: 'none' }) gsap.to('#section-1 #title', { opacity:0, duration:0.1, ease: 'none' }) gsap.from("#section-1 #mask-path-1", { duration: 0.1, drawSVG: 0, ease: "none" }) gsap.from("#section-1 #mask-path-2", { duration: 0.1, drawSVG: 0, ease: "none" }) gsap.to('#section-1 .blob-wrapper', { opacity:0, scale: ".5", duration:0.1, ease: 'none' }) gsap.to('#section-1 .panel', { opacity:0, duration:0.1, ease: 'none', y: "-=0", }); } else { sectionChecks[1] = true; } }, onLeaveBack: () => { console.log('s1 - onLeaveBack') gsap.to('#section-1 .svg-wrapper', { opacity:0, scale: "1.5", duration:0.1, ease: 'none' }) gsap.to('#section-1 #title', { opacity:0, duration:0.1, ease: 'none' }) gsap.from("#section-1 #mask-path-1", { duration: 0.1, drawSVG: 0, ease: "none" }) gsap.from("#section-1 #mask-path-2", { duration: 0.1, drawSVG: 0, ease: "none" }) gsap.to('#section-1 .blob-wrapper', { opacity:0, scale: ".5", duration:0.1, ease: 'none' }) gsap.to('#section-1 .panel', { opacity:0, duration:0.1, ease: 'none', y: "-=0", }); } } }) .fromTo('.section-menu', { opacity:0 }, { opacity:1, duration:0.5, ease: "none", delay: 0, }) .fromTo('#section-1 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .fromTo('#section-1 #title', { opacity:0 }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0 }) .from("#section-1 #mask-path-1", { duration: 2, drawSVG: 0, ease: "none" }) .from("#section-1 #mask-path-2", { duration: .5, drawSVG: 0, ease: "none" },">-0.05") .fromTo('#section-1 .blob-wrapper', { opacity:0, scale: ".5" }, { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 },">-0.05") .fromTo('#section-1 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 });
Rodrigo Posted January 30, 2023 Posted January 30, 2023 Hi, You just mentioned an h2 on each section not a bunch of elements. In the case of the DrawSVG instances it would be a good idea to create some set instances before creating the ScrollTrigger-controlled Timelines and draw the svgs to 0% and 100%. Check this example and in the array replace 10% with 0% and click the Run button in order to restart the codepen and see what happens when you get to that point. If you keep having issues, please create a minimal demo in order to have a better look. Happy Tweening!
Visual23 Posted January 30, 2023 Author Posted January 30, 2023 Hi @Rodrigo Outside of the DrawDVG instances and knowing I'm animating many elements, is your example with the callback events still the way to go? Thanks!
Rodrigo Posted January 30, 2023 Posted January 30, 2023 Yep, I would stick to that approach if possible, try to make it more flexible and dynamic actually. Sorry I forgot the example link, here it is: See the Pen bNdLyR by GreenSock (@GreenSock) on CodePen. Happy Tweening! 1
Visual23 Posted January 31, 2023 Author Posted January 31, 2023 Hello, I have been messing with this for hours and I finally see what is happening. If you scroll at normal speed through each section and then go back and forth to each section everything works fine but if you can faster and an animation hasn't finished, it will keep happening in the background and what I have in onLeave and onLeave back doesn't reset the elements. It's almost like on onLeave and onLeaveBack I need to kill the animations. You can see what I mean in the codepen above. Thanks in advance!
Visual23 Posted January 31, 2023 Author Posted January 31, 2023 Woohoo! I finally got it all working perfectly. I created my timeline for each section and then a scrollTrigger for each section. In each scrollTrigger I have the "animation" set to the section timeline and the toggleActions to play onEnter/onEnterBack and reset onLeave/onLeaveBack. Thanks for all of your help! const animate_01 = gsap.timeline({paused:true}) .fromTo('#section-1 .svg-wrapper', { opacity:0, scale: "1.5", }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0, }) .fromTo('#section-1 #title', { opacity:0 }, { opacity:1, duration:0.5, ease: "none", scale: "1", delay: 0 }) .from("#section-1 #mask-path-1", { duration: 2, drawSVG: 0, ease: "none" }) .from("#section-1 #mask-path-2", { duration: .5, drawSVG: 0, ease: "none" },">-0.05") .fromTo('#section-1 .blob-wrapper', { opacity:0, scale: ".5" }, { opacity:1, duration:0.5, ease: "back", scale: "1", delay: 0 },">-0.05") .fromTo('#section-1 .panel', { opacity:0 }, { opacity:1, duration:0.5, ease: "power1.out", y: "-=25", delay: 0 }); ScrollTrigger.create({ trigger: '#section-1', animation: animate_01, toggleActions:"play reset play reset", start: () => { return `top center`; }, end: () => { return `bottom center`; } }); 2
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