Share Posted April 18, 2021 Hi everyone, I've been trying to solve this problem for many hours, but I can't find a solution. I hope some of you can help me. Depending on the situation, I dynamically create a timeline to run when needed. Below I leave you an example code: let itemScrollTimeLine = gsap.timeline({ paused: true, onComplete: resetTimeline }); function resetTimeline() { console.log('Completed'); itemScrollTimeLine.clear(); } if (itemList.indexOf(elem.id) >= 0) { let elemPos = (window.innerHeight - document.getElementById(elem.id).offsetHeight) / 2; itemScrollTimeLine.add(gsap.to(window, { duration: 1.2, ease: "power1.inOut", scrollTo: { y: elem, offsetY: elemPos } })); } else { itemScrollTimeLine.add(gsap.to(window, { duration: 1.2, ease: "power1.inOut", scrollTo: { y: elem, offsetY: 100 } })); } itemScrollTimeLine.add(gsap.to(elem, { ease: "power3.inOut", duration: 0.8, '--line-color-top': '#a18248' }), '>'); // And so on.... When i click a button I start the timeline with the command itemScrollTimeLine.play(); . Depending on the button clicked (in the code it is saved in the "elem" variable) a scroll is carried out on a specific position on the page. If the buttons are clicked sequentially fast, however, there is a bad effect, and I'm trying to find a solution. I thought a solution would be to check if the animation is currently active, and if the scroll is running, stop it, and immediately complete the rest of the animations a jump effect upon immediate completion of the animation). This is the code I tried to write that I inserted as a control before creating a new timeline of the pressed key: if (itemScrollTimeLine.isActive()) { if (itemScrollTimeLine.progress() < 0.6) { itemScrollTimeLine.seek(1.2); let children = itemScrollTimeLine.getChildren(false, true, true); itemScrollTimeLine.remove(children[0]); } itemScrollTimeLine.progress(1); } I entered 0.6 as the progress value because the timeline has a total duration of 2 seconds and the scroll has a duration of 1.2 seconds. Unfortunately running this code I always have a jump effect to the immediate completion of the running timeline. Can you tell me a method to solve this annoying problem? Many thanks in advance!🙂 Link to comment Share on other sites More sharing options...
Solution Solution Share Posted April 19, 2021 Hm, it sounds like there may be some logic flaws in your code, but it's difficult to troubleshoot without a minimal demo. But I'll offer a few thoughts: It looks like you're reusing the same timeline instance over and over again and doing a clear() after it's done. That's not "wrong", but it's probably simpler to just create a new timeline each time (or if you're not sequencing things or need to control multiple as a whole, just skip the timeline altogether and use tweens). Remember that by default, when you add() something to the timeline, it gets added to the END of it. So let's say the user clicks multiple times quickly, that means your code is just sequencing the new ones after the current ones that haven't finished yet. See the problem? Or do you clear() it before running each time too? Again, it's tough to know by just looking at a small excerpt. You don't need to timeline.add(gsap.to(...)) - that's just a long way of using the convenience methods: // long timeline.add( gsap.to( ... )); // short timeline.to(...); Be careful about creating conflicting tweens where they're fighting to control the same property of the same object. You can set overwrite: true to have GSAP immediately kill all other tweens of those targets, or overwrite: "auto" to only kill the individual parts (properties) of the tweens that overlap. I'd rewrite your first block of code like this: // OLD let itemScrollTimeLine = gsap.timeline({ paused: true, onComplete: resetTimeline }); function resetTimeline() { console.log('Completed'); itemScrollTimeLine.clear(); } if (itemList.indexOf(elem.id) >= 0) { let elemPos = (window.innerHeight - document.getElementById(elem.id).offsetHeight) / 2; itemScrollTimeLine.add(gsap.to(window, { duration: 1.2, ease: "power1.inOut", scrollTo: { y: elem, offsetY: elemPos } })); } else { itemScrollTimeLine.add(gsap.to(window, { duration: 1.2, ease: "power1.inOut", scrollTo: { y: elem, offsetY: 100 } })); } itemScrollTimeLine.add(gsap.to(elem, { ease: "power3.inOut", duration: 0.8, '--line-color-top': '#a18248' }), '>'); // NEW let itemScrollTimeLine = gsap.timeline(); itemScrollTimeLine.to(window, { duration: 1.2, ease: "power1.inOut", overwrite: "auto", scrollTo: { y: elem, offsetY: itemList.indexOf(elem.id) >= 0 ? (window.innerHeight - document.getElementById(elem.id).offsetHeight) / 2 : 100 } }); itemScrollTimeLine.to(elem, { ease: "power3.inOut", overwrite: "auto", duration: 0.8, '--line-color-top': '#a18248' }); You really shouldn't need to getChildren() and remove() any of them. Ditch that altogether. I think that was more of a band-aid that was attempting to cover over the fundamental problem which had more to do with your reusing the same timeline and continuing to shove new tweens one-after-the-other or maybe overwriting (or lack thereof). If you're still having trouble, it'll greatly increase your chances of getting a solid answer if you can provide a minimal demo. Thanks for being a Club GreenSock member! 🙌 Happy tweening! 1 Link to comment Share on other sites More sharing options...
Author Share Posted April 19, 2021 Thanks a lot for the answer! I was able to solve my problem, I improved my code and I learned new things.☺️ 1 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