en en en en en en en en en en en en en en en en fa en en fr hbs_lat en en en es en en en ms en de en fr en en en ca en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en en nb en en en fa en en en en en en en en en nb en en en fa en en en en en en en sv en en nb en en en fa en en en en en en en en en nb en en en fa en en en en en en en en en en nb en en en en ceb en en en en en en sv en en nb en en en en ceb en en en en en en en en nb en en en en ceb en en en en en en en en nb en en en en ceb en en en en en en en en en en en en en en en en en en en ms en en en en en sv en en nb en en en en ceb en en en en en en en en nb en en en en ceb en en en en en en en en nb en en en en ceb en en en en en en en ko nb en en ko mk en en en en nl en de en en en fr en hu en en en de en en en en en en en en en en en fr cv es tr es en en en en ms en en en en en en fr en hbs_lat en en en en en en en fr cv es tr es en en en en de en en en ca en en en en en
Follow up question...how do I capture the instance of the   element itself? What I'm trying to do...since these cards showcase quite a bit of data...is to add additional animations to the card or   itself if certain conditions are met. The data-attributes method works great for spotting a certain value etc, but then triggering another animation doesn't necessarily make it clear why a burger, or a whale in my case, is flying across the screen? From my research (and errors!) you can't tween a data-attribute, nor is it possible to render a data attribute (like take the value from the attribute and pass it to a   tag or something?). I suspect that, because I had already used .map to go through and animate the entire array with staggerFromTo I may be complicating things? Perhaps a for each loop is in order? Any ideas are appreciated!
Mapping through arrays - list items the react way, with conditional logic
UnioninDesign replied to UnioninDesign's topic in GSAP
As always - thanks @Rodrigo - works great! Adding the data-attribute to my list items totally makes sense - but glad I made this post, I don't think I would have figured out the 'instance.target.getAttribute' part on my own!
UnioninDesign posted a topic in GSAP
UnioninDesign changed their profile photo February 28, 2019
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
I have a follow-up question, and I've been trolling through the forums and stack overflow in search of a solution that still escapes me at the moment! So...quick recap...I am animating markers on a map of the US, and since there's over 500 an hour, roughly 8,000 a day the stagger methods and TimelineMax have made a very nice visualization - thanks GSAP! -- How to Toggle 'visibility' of tweens throughout the timeline -- The question is that, to avoid showing all of these map markers on render, I've set the CSS for the svg circle element to " visibility: hidden", which I then toggle in the animation using autoAlpha: 1. If I drag the slider to the left to go back in time, or click the reverse or restart buttons, and also when the animation repeats...all of the map markers have now been set to autoAlpha: 1, and every single one that has rendered so far is visible. Without a better codepen (Still working on the Globe...) and, it looks likes GSAP has many built-in methods to do this, but I haven't found the right one? I've tried chaining to my buttons something like this.tl.restart().pause(0)... as well as clear(), kill() - there's also remove(), Invalidate() - so many options! I must not be using any of them correctly! I've also attempted to use many of these in the onCompleteAll callback that fires at the end of the timeline, still no success! Any ideas? Additionally - and this relates more to react/javascript/dealing with async data fetching...but when the new data set comes in I'm having trouble making a smooth transition from one set of map markers to the next. I know...tough to guess without seeing what's going on, but if you have any tips on best practices or can point me towards examples of someone else doing this that would be huge help! I did do as Rodrigo suggests above and do a deep comparison of the two data sets using the loDash _.isEqual method, inside componentDidUpdate. I was hoping the 'this.forceUpdate() wouldn't be necessary but so far seems to be the only way to tell the D3 map library (react-simple-maps) that it's time to generate new markers? I'm also working on migrating this project into true D3, should be ready for iteration v2! Here's a snippet of that function in my child or map component where it is getting the data as state passed down as props: componentDidMount() { //Animations with GSAP this.animateBookings(); } componentDidUpdate(previousProps) { //console.log("DidUpdate child was called!"); if (!_.isEqual(previousProps.data, this.props.data)) { //console.log("DidUpdate child was called no. 2!"); this.setState({ data: this.props.data }); this.theWhale(); this.tl.kill(); this.animateBookings(); this.tl.play(); } } Thanks to everyone who has helped with this project! Big shout out to @Rodrigo !!!
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
This was a tricky one for me that took a while to figure out...but Rodrigo was spot on in terms of what the problem was...when fetching data asynchronously, you need to make sure the fetch is complete before attempting to render other components. I was getting an error about 'Can’t call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.' In case anyone else is dealing with the same issue - this article here was a huge help! Although this is a React issue, and not GSAP - worth noting how to handle these kinds of things! https://www.robinwieruch.de/react-warning-cant-call-setstate-on-an-unmounted-component/
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
Thanks Rodrigo! You've got the right idea...and it was getting late...I was missing (duh) the . in front of the className "animateMapMarker" which should have been ".animateMapMarker", like you said GSAP was getting a string for the target and not the element with a className of ".animateMapMarker". And yes, having added the . it kind of works...There's a method in the map library that will move the 'center' of the map and rotate the globe, so I do need to write some more code to get it to a point where, when I call the staggerFrom method, the map markers get bigger (which works) AND that marker would then be displayed front and center! If I could get a bezier line to animate and connect the dots, this could be cool app that would track movements around the globe with an interactive timeline...but it's not quite there yet. I'll see what I can do to use this example to recreate the problem I am having at work...I tried it again this morning, but how weird! Data that was hard-coded in an external file, then imported and passed to the 3rd party components would animate just fine using this same method of targeting the className of the   element for the map marker. But then, the 'react-way' of fetching data higher up in the component tree, passing it down as props - I get markers but no animation? Puzzling and also frustrating! To whet your whistle, if you're curious I did reach out to the map library creators about a month ago concerning this issue, before I found the bandAid of adding the className as a target, which seemed like a good fix: https://github.com/zcreativelabs/react-simple-maps/issues/119 They did respond with this codesandbox: https://codesandbox.io/s/rzr73rjjq At the time my focus was a bit more on using something like React Transition group, and trying to wrap a new 3rd party component around the 3rd party Marker component was breaking its parent, the map projection itself. The codesandbox does exactly that with a different animation library, but the data is still hard-coded so I might still run into the same issue...I guess I'll find a way to hammer it into place? If you think of any other ideas let me know! I'll of course update the thread with any breakthroughs, and hopefully a better working example so you can see what's going on!
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
Hello again! I took some time to make a test case to play around with...getting stuck on a few things... Can we talk about use of createRef, callback refs etc? I noticed in the example link you sent, your target looks like this: div className="box" ref={e => this.box = e}>   MOVE & ROTATE     I tried to replicate something similar, but could be getting stuck with a 3rd party component library so I can play with maps (react-simple-maps, that is...) Here's kicker - I've had GSAP working for several weeks now with test data that was hard coded. When trying to make my app iterative, as discussed in the posts above, I'm trying to go through the best practices of fetching data in a parent component, passing state down as props to a child component - my data renders, but the animations are gone? Up until then, my animations were working successfully by adding a className to the html element (in this case, the svg circle tag inside the   3rd party component) I've tried to recreate a similar use case, at the moment I'm not getting any animations to fire up? https://stackblitz.com/edit/react-globe-timeline?embed=1&file=index.js Let me know if you have any suggestions...much appreciated!
callback.call is not a function
UnioninDesign replied to mrbdigital's topic in GSAP
Thanks! For now I just added a simple function to log that the animation is complete, and the animation restarts as expected with no errors (because of the repeat: -1 passed in as params to this.tl = new TimelineMax(....). Always a nice when it's an easy fix! A quick note for posterity...depending on how you do this, especially with react, you may need to add 'this' in front of the onCompleteAll callback. Here's the WALL of code again: onCompleteAll() { console.log("Animation complete"); } updateSlider() { this.setState({ sliderValue: Math.round(this.tl.progress() * bookingData.length) }); } componentDidMount() { bookingInterval(); //animateBookings(); //Animations with GSAP this.tl = new TimelineMax({ onUpdate: this.updateSlider, repeat: -1 }); //controls time in seconds in between booking cycles var next = 3; //controls fadeout var nextOpacity = 5; var opacity0 = 10; var fadeOutDelay = 10; //how long markers and lines remain on screen prior to fadeout var fadeOutDuration = 3; //how long it takes bookings to fadeout this.tl .staggerFrom( ".animatedTick", 7, { ease: Power3.easeInOut, y: 1000, opacity: 1 }, next ) .staggerTo( ".custMarkers", 0.3, { autoAlpha: 1, ease: Elastic.easeOut.config(0.2, 1.5), opacity: 1, scale: 5, force3D: false, yoyo: true, repeat: 1 }, next, 1 ) .staggerTo( ".clientMarkers", 0.3, { autoAlpha: 1, ease: Elastic.easeOut.config(0.2, 1.5), opacity: 1, scale: 5, force3D: false, yoyo: true, repeat: 1 }, next, 1.5 ) .staggerTo( ".lineAmation", 1.5, { visibility: "visible", ease: Power3.easeOut, autoAlpha: 1, opacity: 1, strokeWidth: 2 }, next, 2 ) //FadeOut animations are chained to the original timeline, with a new set of animations for each target .staggerTo( ".animatedTick", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0, y: -200, x: 100, scale: 0, rotationY: -360, display: "none", ease: SlowMo.easeOut }, nextOpacity, opacity0, this.onCompleteAll ) .staggerTo( ".custMarkers", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0 }, nextOpacity, opacity0, this.onCompleteAll ) .staggerTo( ".clientMarkers", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0 }, nextOpacity, opacity0, this.onCompleteAll ) .staggerTo( ".lineAmation", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0 }, nextOpacity, opacity0, this.onCompleteAll ); }
callback.call is not a function
UnioninDesign replied to mrbdigital's topic in GSAP
I'm having the same issue using create-react-app, not sure if I made the same/similar error? I tried to move some things around in my staggerTo methods but still getting the error...any ideas? Not sure if this is a react-thing, or a google chrome thing, but I do suspect a syntax error? Per the timelineMax staggerTo docs, is it necessary to add an onCompleteAll callback, or some way to let the animations know when the animation is complete? I get this error at the end of the timeline, and sometimes during if I scrub too quickly through the timeline. I am using this for a data visualization so the timeline will be up to 15 minutes long! The error: So the note about speed optimization could suggest a browser issue? But I get the same thing in Firefox too. Here is my animation code, which lives in react's componentDidMount method - any suggestions are appreciated! updateSlider() { this.setState({ sliderValue: Math.round(this.tl.progress() * bookingData.length) }); } componentDidMount() { //Animations with GSAP this.tl = new TimelineMax({ onUpdate: this.updateSlider, repeat: -1 }); //controls time in seconds in between booking cycles var next = 3; //controls fadeout var nextOpacity = 5; var opacity0 = 10; var fadeOutDelay = 10; //how long markers and lines remain on screen prior to fadeout var fadeOutDuration = 3; //how long it takes bookings to fadeout this.tl .staggerFrom( ".animatedTick", 7, { ease: Power3.easeInOut, y: 1000, opacity: 1 }, next ) .staggerTo( ".custMarkers", 0.3, { autoAlpha: 1, ease: Elastic.easeOut.config(0.2, 1.5), opacity: 1, scale: 5, force3D: false, yoyo: true, repeat: 1 }, next, 1 ) .staggerTo( ".clientMarkers", 0.3, { autoAlpha: 1, ease: Elastic.easeOut.config(0.2, 1.5), opacity: 1, scale: 5, force3D: false, yoyo: true, repeat: 1 }, next, 1.5 ) .staggerTo( ".lineAmation", 1.5, { visibility: "visible", ease: Power3.easeOut, autoAlpha: 1, opacity: 1, strokeWidth: 2 }, next, 2 ) //FadeOut animations are chained to the original timeline, with a new set of animations for each target .staggerTo( ".animatedTick", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0, y: -200, x: 100, scale: 0, rotationY: -360, display: "none", ease: SlowMo.easeOut }, nextOpacity, opacity0 //2 ) .staggerTo( ".custMarkers", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0 }, nextOpacity, opacity0, 1 ) .staggerTo( ".clientMarkers", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0 }, nextOpacity, opacity0, 1.5 ) .staggerTo( ".lineAmation", fadeOutDuration, { delay: fadeOutDelay, autoAlpha: 0 }, nextOpacity, opacity0, 2 ); } To get an idea of the larger project, Here's two other threads I've initiated...sorry for being 'that guy' that does not post a codepen, but this is a large full stack application with a lot of moving parts. Reduced case codepen is coming soon, possibly this weekend! This one tells you a bit more what I'm up to - bigUps to Mikel! And in this one Rodrigo helped out big time getting the range slider working! Thanks all for the help!
Animate a line going from point A to B
UnioninDesign replied to Abarth's topic in GSAP
Just in case anyone reads this and wants to go a little deeper, I have a related question from a few weeks ago, similar use case:
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
Ah ha - as we say in French - "le mot juste!" Rodrigo you sir are a Wizard! I got pretty close by the end of the day yesterday - I think it came down to missing a 'this' in front of my updateSlider callback! (it's a class...duh...). Now onto the next...I'm in awe of GSAP and the support from its community. There are some very exciting possibilities for making data visualizations here! My apologies again that I have not supplied any codepen or reduced case examples...since this is a worky-thing it's not very public...but I will try to replicate something with a more public dataset and will update this post...maybe this weekend? If anyone is interested in building interactive maps using D3 (in this case react-simple-maps) along with React, and a robust animation library like GSAP to create an interactive timeline, this is the place to be! Thanks again!
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
Quick update...so here's a snip of the callback function: function updateSlider(context) { console.log("State? ", context.state); let currentProg = context.state.value; //context.setState({ value: currentProg + 1 }); context.tl.progress(currentProg / bookingData.length); } And I'm calling it at the timeline declaration at so, which I believe is correct: this.tl = new TimelineMax({ onUpdate: updateSlider, onUpdateParams: "{self}" }); But...because all of the animations live inside componentDidMount(){}, if I pass this in at after the timeline, inside componentDidMount...we are not getting passed the value that has been set here inside these two slider methods: onSliderChange = value => { this.setState({ value }); console.log("Value is: ", value); }; onAfterChange = value => { console.log(value); this.tl.progress(value / bookingData.length); this.tl.resume(); }; ...It will continue to update with no value and error out after a few seconds? Alternatively, passing in the updateSlider callback right after onSliderChange and onAfterChange, just above componentDidMount, will give you an undefined error (makes sense). I think this is not a GSAP problem! but something to do with the architecture or my app! Any ideas are appreciated! Sooooo close!
Troubles with range slider updating progress() method for timelineMax in React?
UnioninDesign replied to UnioninDesign's topic in GSAP
Rodrigo - the man I was hoping to hear from! I've spent LOTS of time in this forum the past week or so, and your posts are always very helpful! Issue fixed per below! But the next one at the bottom of this post - how do we get the slider to update the position based on the current value of the animation? BTW - Good eye spotting an inconsistency in my code! Easy to do when you try things a bunch of different ways...however, when setting a range of 0 to 100, or 0 to bookingData.length (which indeed gives you a value for how long the dataset is...I'll stick with that!)....the same result was that it kills the animation, but not getting any errors in the console. You could continue to drag the slider around and it will keep logging the values, but the play, pause, resume don't function, and you need to refresh the page to get the animation to run again. After a few more minutes playing around...as I'm pretty sure I had tried what you had suggested, but with no luck...I noticed some code I had copied into to the top of the render method: render() { this.tl .kill() .clear() .pause(0); return ( The fix was to remove the .kill() and .clear() methods!!!!! Although I'm a little curious why these are here and what purpose they might serve, perhaps to pass in some kind of initial state to the playback methods at rendering...which is not best practice, correct? better to set the initial state in your constructor, or even to use a parent level component to manage the state and pass it down as props? Still have lots to learn! For posterity, scrolling on the timeline now brings you to the next value (or booking!), but it does help to pass in the .resume() method to get the timeline working automatically, if not it will be pause when onAfterChange talks to the slider: onAfterChange = value => { console.log(value); this.tl.progress(value / bookingData.length); this.tl.resume(); }; So the next challenge, which I hope to figure out soon...we need the range slider to update itself as the timeline progresses. It sounds like what we need is an onUpdate callback: onSliderChange = value => { this.setState({ value }); console.log("Value is: ", value); }; onAfterChange = value => { console.log(value); this.tl.progress(value / bookingData.length); this.tl.resume(); }; updateSlider = () => { let currentProg = this.state.value; this.tl.progress(currentProg * bookingData.length); console.log("running", currentProg); }; I keep getting an error that on updateSlider is undefined? I am trying to pass it in like so. Quick note that all of my animations are currently housed in componentDidMount, but I do need to move these to an external animation.js file... onSliderChange = value => { this.setState({ value }); console.log("Value is: ", value); }; onAfterChange = value => { console.log(value); this.tl.progress(value / bookingData.length); this.tl.resume(); }; updateSlider = () => { let currentProg = this.state.value; this.tl.progress(currentProg * bookingData.length); console.log("running", currentProg); }; componentDidMount() { bookingInterval(); //Animations with GSAP this.tl = new TimelineMax(); // parameter: { "onUpdate", updateSlider } var next = 3; this.tl .staggerFrom( ".animatedTick", 3, { rotationY: -180, ease: SlowMo.easeOut, y: 700, delay: 1, scale: 2, opacity: 0 }, 3, "nextBooking -=3" ) .staggerFrom( ".custMarkers", 1.5, { cycle: { x: [-1000, 1000], y: [-1000, 1000] }, bezier: { curviness: 1, values: [{ x: 0, y: 0 }, { x: 125, y: -80 }, { x: 250, y: 0 }] }, ease: Power1.easeOut, opacity: 0, scale: 10 }, next, 1 ) .staggerFrom( ".clientMarkers", 1.5, { cycle: { x: [-1000, 1000], y: [-1000, 1000] }, bezier: { curviness: 1, values: [{ x: 0, y: 0 }, { x: 125, y: -80 }, { x: 250, y: 0 }] }, ease: Power1.easeOut, opacity: 0, scale: 7 }, next, 1.5 ) .staggerFrom( ".lineAmation", 2.1, { ease: Sine.easeIn, opacity: 0 }, next, 2, "-=1" ); } render() { this.tl.pause(0); return (............ So up next, where do I pass in this callback? Thanks a ton!
staggering data from multiple arrays?
UnioninDesign replied to UnioninDesign's topic in GSAP
I really appreciate the help on this! I did get the sequence timed out the way I want, but had a follow up questions on callbacks in case either of you two gentleman would like to kick this can a little further down the road? Case: so we're building a map, and using this animation I'll get report every 15 minutes with 100 - 500 bookings to display! Now that I've got a nice stagger effect so you don't see all the bookings rendered simultaneously, I'm noticing that the map starts to get cluttered? I'd like to write some kind of callback (if necessary) to make the bookings fade out after 5-7 seconds ish? I think I'm close but haven't quite nailed it just yet Here's my animation code - with some parts adapted from your codepens. I also decided to add a sidebar that show text about in each booking so it's not just a bunch of dots on the screen - the target class ".animatedTick" leads off the timeline: this.tl = new TimelineMax(); // parameter: { onUpdate: updateSlider } var next = 3; var bookingDuration = 6; this.tl .staggerFrom( ".animatedTick", 3, { rotationY: -180, ease: SlowMo.easeOut, y: 700, delay: 1, scale: 2, opacity: 0, autoAlpha: 1, timeResolution: bookingDuration }, 3, "nextBooking -=3" ) .staggerFrom( ".custMarkers", 1.5, { cycle: { x: [-1000, 1000], y: [-1000, 1000] }, bezier: { curviness: 1, values: [{ x: 0, y: 0 }, { x: 125, y: -80 }, { x: 250, y: 0 }] }, ease: Power1.easeOut, opacity: 0, scale: 10, autoAlpha: 1, timeResolution: bookingDuration }, next, 1 ) .staggerFrom( ".clientMarkers", 1.5, { cycle: { x: [-1000, 1000], y: [-1000, 1000] }, bezier: { curviness: 1, values: [{ x: 0, y: 0 }, { x: 125, y: -80 }, { x: 250, y: 0 }] }, ease: Power1.easeOut, opacity: 0, scale: 7, autoAlpha: 1, timeResolution: bookingDuration }, next, 1.5 ) .staggerFrom( ".lineAmation", 2.1, { ease: Sine.easeIn, opacity: 0, autoAlpha: 1, timeResolution: bookingDuration }, next, 2, "-=1" ) I've tried chaining to the end of this with a few different methods, am I close? This one gives me an error 'delayed call is not a function' - should this be passed in as params to the timeline? I have this one chained right after the last staggerFrom... .delayedCall(bookingDuration, bookingFadeout); function bookingFadeout() { this.tl.to( [".animatedTick", ".custMarkers", ".clientMarkers", ".lineAmation"], bookingDuration, { autoAlpha: 0, opacity: 0 } ); } And i also tried to chain this to end of the sequence... .to( [".animatedTick", ".custMarkers", ".clientMarkers", ".lineAmation"], 5, { opacity: 0, ease: Power1.easeInOut, autoAlpha: 0 } Which does nothing? Another idea was to find a way to go by the number of repeats, but the onRepeat() method executes after each repeat, not say, every 6, 7 or 8 repeats? I have a few things going on here, like trying to set the timeResolution in each staggerFrom tween equal to a global variable called 'bookingDuration' - also not working... Any ideas are appreciated!
“GSAP has been absolutely the best experience for me as a newbie. The people in this community take serious time to help you with upcoming issues on real life projects like I've never experienced before.”
“I can definitely say ever since I started using GSAP, my work exponentially improved. It basically changed my life.”
“Really quite impressed with @GreenSock JS - even the small things.”
“GSAP should be the default when it comes to Javascript animations. It should literally be part of the next Javascript update.”
“It's so correct that GSAP's logo is a superhero. Every time I use GSAP it saves me heaps of time and frustration. Thank god for GSAP honestly.”
“GSAP was a revelation for me to be compared with the introduction of jQuery.”
“After searching around the web for alternatives, I found GreenSock to be the most performant.”
“@greensock is just pure awesomeness. What more can be said?”
“The GreenSock animation platform is one of the most useful sets of tools in existence when it comes to web animation.”
Sign Up For Our Newsletter
Get the latest updates on GreenSock products, exclusive offers, and more right in your inbox.
Your information will always be kept confidential.
Thanks for signing up!
Now you'll begin receiving the latest GreenSock updates, exclusive offers, and more right in your inbox. Welcome aboard.