Enrypase Posted August 2, 2022 Share Posted August 2, 2022 Hi everybody, I have the following problem: it seems like I can't kill the animations. I have this animation: gsap.to(thisEl, {left: maxLeft, duration: props.duration, ease: Linear.easeNone, repeat: -1, delay: props.delay}) Googling I found out that I can't update the variables once the animation is started. So i thouht that a good idea was to delete/kill the animation and starting a new one with the updated value. The code is the following: // Maxiumum left attribute that the cloud must reach & animation let maxLeft, animation // This funcion is executed on window resize (evt != null) and for the first time the program is executed (evt === undefined) function updateWindow(evt){ // If it is the first execution update the left parameter and set currentHeight & currentWidth if(!evt){ thisEl = $(`#${props.propId}`) thisEl.css("left", -2 * thisEl.width()) } // Updating the variable maxLeft = 2 * thisEl.width() + $(window).width() // If the resize event occurs, delete the animation and start a new one if(evt){ animation.kill() animation = gsap.to(thisEl, {left: maxLeft, duration: props.duration, ease: Linear.easeNone, repeat: -1, delay: props.delay}) } // If this is the first execution start the first animation else{ animation = gsap.to(thisEl, {left: maxLeft, duration: props.duration, ease: Linear.easeNone, repeat: -1, delay: props.delay}) } } function stopAnimation(){ animation.kill() } /* Other code... */ <button onClick={stopAnimation}>CLICK</button> So, it seems like the animation.kill() inside updateWindow() does not work. And the animation.kill() that is executed when the button is clicked does not work either. (The animation still being executed) Thanks in advance :D Link to comment Share on other sites More sharing options...
iDad5 Posted August 2, 2022 Share Posted August 2, 2022 It seem to me, that you have a scoping issue. I cannot see where you create your first animation, so please provide us with a codePen or at least more of the code that's in play. 2 Link to comment Share on other sites More sharing options...
Cassie Posted August 2, 2022 Share Posted August 2, 2022 Hey there, welcome to the forums! I don't see a reason why you couldn't kill a tween - as long as you can access that variable from whichever scope you happen to be in. Let's step back to this comment first though - What was your original goal with this? Maybe we can suggest a better route to get there. Quote Googling I found out that I can't update the variables once the animation is started. 2 Link to comment Share on other sites More sharing options...
Enrypase Posted August 2, 2022 Author Share Posted August 2, 2022 54 minutes ago, iDad5 said: It seem to me, that you have a scoping issue. I cannot see where you create your first animation, so please provide us with a codePen or at least more of the code that's in play. I create my first animation in of updateWindow() else{ animation = gsap.to(thisEl, {left: maxLeft, duration: props.duration, ease: Linear.easeNone, repeat: -1, delay: props.delay}) } This is just a piece of all the code. I'll try right now to provide a codePen [EDIT:] In the meanwhile I'll share all the component code down here, maybe it helps... import React, {useEffect, useContext} from "react" import {gsap, Linear} from "gsap" import $ from "jquery" import "../style/backgroundCloud.css" function BackgroundCloud(props){ // Current element let thisEl // Refreshes the component let isLoaded = useContext(props.pageLoaded) // Maxiumum left attribute that the cloud must reach & animation let maxLeft, animation function updateWindow(evt){ // If it is the first execution update the left parameter and set currentHeight & currentWidth if(!evt){ thisEl = $(`#${props.propId}`) thisEl.css("left", -2 * thisEl.width()) } // --> This code must be executed in both vertical and horizontal resize <-- maxLeft = 2 * thisEl.width() + $(window).width() // Adapting cloud to new top const parent = thisEl.parent().parent().parent() const fromTop = parent.offset().top const parentDistance = fromTop + parent.height() / 2 let top = props.top if(top.includes("vh")){ top = top.replace("vh", "") top = top * 0.01 top = $(window).height() * top }else if(top.includes("px")){ top = top.replace("px", "") } thisEl.css("--top", String(parentDistance + top).concat("px")) if(evt){ animation.kill() animation = gsap.to(thisEl, {left: maxLeft, duration: props.duration, ease: Linear.easeNone, repeat: -1, delay: props.delay}) }else{ animation = gsap.to(thisEl, {left: maxLeft, duration: props.duration, ease: Linear.easeNone, repeat: -1, delay: props.delay}) } } // Exec when the site is loaded/the component refreshed useEffect(() => { if(isLoaded){ updateWindow() $(window).off().on("resize", updateWindow) } }, []) function killComponent(){ if(animation){ animation.kill() } } // Return default cloud return( <div className="backgroundCloudContainer"> <img src={props.background} className="backgroundCloud" id={props.propId} draggable="false" alt={props.propId} style={{ "--z-index": props.zIndex, "--top": props.top, "--scale": props.scale }}/> <button onClick={killComponent}>CLICK</button> </div> ) } export default BackgroundCloud I'm trying to replicate the same situation in JS but everything works fine. So, maybe, the problem is with React Link to comment Share on other sites More sharing options...
Enrypase Posted August 2, 2022 Author Share Posted August 2, 2022 8 minutes ago, Cassie said: Hey there, welcome to the forums! I don't see a reason why you couldn't kill a tween - as long as you can access that variable from whichever scope you happen to be in. Let's step back to this comment first though - What was your original goal with this? Maybe we can suggest a better route to get there. My goal is to update an animation on a window resize event So I thought the easiest way was to delete the animation with .kill() and to create a new one with the updated variable Link to comment Share on other sites More sharing options...
iDad5 Posted August 2, 2022 Share Posted August 2, 2022 So, I'm not a react guy, and that might be a problem, but just to confirm my guess or to prove it wrong, why don't you just console.log(animation) before you try to kill() it? 2 Link to comment Share on other sites More sharing options...
Cassie Posted August 2, 2022 Share Posted August 2, 2022 Agree with logging out 'animation' - but also, Just going on some of the code in the screengrab it'll be helpful to give our React guide a little run through. React doesn't play too nicely with DOM scripting, so it's recommended to use refs instead of grabbing elements directly. Using jQuery and React together is quite a bold choice too. They're both quite opinionated and have conflicting methodologies Link to comment Share on other sites More sharing options...
iDad5 Posted August 2, 2022 Share Posted August 2, 2022 10 minutes ago, Cassie said: React doesn't play too nicely with DOM scripting, so it's recommended to use refs instead of grabbing elements directly. Using jQuery and React together is quite a bold choice too. They're both quite opinionated and have conflicting methodologies Sounds very much like that old couple across the street 2 Link to comment Share on other sites More sharing options...
Enrypase Posted August 2, 2022 Author Share Posted August 2, 2022 Before trying those things together, I noticed that React calls multiple times my function, so, is enabling overwriting a good way for "skipping" some problems? And is gsap.defaults({overwrite: "auto"}); a good way for enabling it? (From: ) 1 Link to comment Share on other sites More sharing options...
GSAP Helper Posted August 2, 2022 Share Posted August 2, 2022 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 React template. Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. Setting overwrite to "auto" or true can be good, but it's important that you understand what's going on and what that's solving so that you can ensure it's not just a band-aid that covers over something like creating a bunch of conflicting animations unnecessarily. 1 Link to comment Share on other sites More sharing options...
Enrypase Posted August 2, 2022 Author Share Posted August 2, 2022 3 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 React template. Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. Setting overwrite to "auto" or true can be good, but it's important that you understand what's going on and what that's solving so that you can ensure it's not just a band-aid that covers over something like creating a bunch of conflicting animations unnecessarily. I did not include a demo because it worked perfectly in that... Anyways, I figured out the problem, and was *not* about gsap. Would be helpful to describe it and write the solution even if was because external to gsap? 2 Link to comment Share on other sites More sharing options...
GreenSock Posted August 2, 2022 Share Posted August 2, 2022 Sure, you're welcome to share your solution here. It may help others who stumble across something similar. Glad to hear it was unrelated to GSAP. 2 Link to comment Share on other sites More sharing options...
Enrypase Posted August 3, 2022 Author Share Posted August 3, 2022 I'm posting the final code down here: function BackgroundCloud(props){ // Current element let thisEl // Refreshes the component let isLoaded = useContext(props.pageLoaded) // Maxiumum left attribute that the cloud must reach & animation const maxLeft = useRef(0) const animation = useRef([]) function updateWindow(evt){ // If it is the first execution update the left parameter and set currentHeight & currentWidth if(!evt){ resetComponent() } // --> This code must be executed in both vertical and horizontal resize <-- maxLeft.current = 2 * thisEl.width() + $(window).width() // Adapting cloud to new top const parent = thisEl.parent().parent().parent() const fromTop = parent.offset().top const parentDistance = fromTop + parent.height() / 2 let top = props.top if(top.includes("vh")){ top = top.replace("vh", "") top = top * 0.01 top = $(window).height() * top }else if(top.includes("px")){ top = top.replace("px", "") } thisEl.css("--top", String(parentDistance + top).concat("px")) // Delete every ongoing animation killAnimation() // Create a new animation animation.current.push(gsap.to(thisEl, {left: maxLeft.current, duration: props.duration, ease: Linear.easeNone, onComplete: resetComponent})) } // Delete every ongoin animation function killAnimation(){ for(let i = 0; i < animation.current.length; i++){ animation.current[i].kill() } animation.current = [] } // Exec when the site is loaded/the component refreshed useEffect(() => { if(isLoaded){ updateWindow() $(window).on("resize", updateWindow) } }, []) // Reset a cloud (called when the component reaches the end) function resetComponent(){ thisEl = $(`#${props.propId}`) thisEl.css("left", -2 * thisEl.width()) killAnimation() animation.current.push(gsap.to(thisEl, {left: maxLeft.current, duration: props.duration, ease: Linear.easeNone, delay: props.delay, onComplete: resetComponent})) } // Return default cloud return( <div className="backgroundCloudContainer"> <img src={props.background} className="backgroundCloud" id={props.propId} draggable="false" alt={props.propId} style={{ "--z-index": props.zIndex, "--top": props.top, "--scale": props.scale }}/> </div> ) } To fix the problem I did the following things: 1) Using an array to store every animation I create (so I can .kill() everything) 2) Using useRef() instead of saving data in plain variables 3) Fixed the event listeners because I inserted the jquery .off() method that removes every listener from the element that, of course, made my solution not working Now I'm planning to remove the array and setting overwrite to "auto" or true so I'll save a piece of performance. Anyway, thanks for helping me. Hope that the problem I had will help someone else : D 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