Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Search the Community

Showing results for 'overwrite'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


Twitter


CodePen


Company Website


Location


Interests

  1. it's smooth on my imac though I don't have a retina display. Maybe in the full code you've got some kind of throttling added that I'm not seeing but if I'm interpreting it correctly your code appears to create a new tween and overwrite the previous every time the event listener sees a delatY change. Maybe you could refactor it to throttle the number of tween calls and pass the dynamically changing deltaY to the tween in a modifiers function? Not sure if that would work better but it seemed logical to me. Also you're doing a lot of console logging and writing the changing deltaY to a data item, these would also probably be slowing down execution.
  2. Hi, I've created a smooth page scroll. That is the shortened code this.el_body.addEventListener('wheel', e => this.wheel(e)) scrolling() { console.log('--- scrooolling') }, wheel(e) { e.preventDefault() let deltaY = e.deltaY // firefox if (e.deltaMode === 1) deltaY = 40 * e.deltaY this.raf('move', deltaY) }, move(delta) { TweenMax.to(this.el_body, 1, { y: -this.scrollTop, ease: Power2.easeOut, overwrite: true, force3D: true, }) } Sometimes on macOS Chrome the animation becomes choppy, I played a little bit around and figured out that if I add onUpdate: () => this.scrolling() it becomes much more smoother. The function only outputs a log. My Question ist does onUpdate something more behind the scenes? Or am I just imagining it?
  3. I see, I understand and thank you for providing the information on the overwrite field!
  4. Ah yes, that's just because I added a 1 second delay (because I thought it looked better) to that handle appearing, so if you click too fast, it's possible to have the fade-out tween start BEFORE the fade-in one starts. It's just a timing thing. But it's very easy to fix - you just add overwrite:true and that basically tells the engine to find any other tweens of that element and kill them. I adjusted the codepen accordingly. Better?
  5. In that case you could try forcing he images elements to a opacity of 0 using the config object available in the .tween methods of TimelineMax. The sweet part of it is that GSAP has a killer overwrite manager that will detect any other lingering GSAP instance that affects the images, kill them and send them to garbage collection. You could try something like this: tl.tweenFromTo(t, "b", { onStart: function() { TweenMax.to(images, 0.1, {opacity: 0}); } }); That will tween the opacity to 0 very quickly on all the images when the timeline playhead starts moving to the "b" label. Happy Tweening!!
  6. Hi and welcome to the GreenScok forums. After reviewing your file, we have some advice to you as it seems you're not very familiar with some key-core concepts about GSAP. First and most important in order to simplify and speed up the support process, we advise users that they create a reduced sample in codepen that illustrates the issue they are having. To learn how to do that please look at this post and video from @Carl Second, among many amazing tools, GSAP has the CSS Plugin, that takes cares of any non-experimental CSS property you want to animate in a DOM element. Having said that, in your file we could spot quite a few of these: var tween = TweenMax.to(sec, 1, {transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 421.8, 1010.15, 0, 1)'}); var tween2 = TweenMax.to(sec, 1, {transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1004.58, 1011.1, 0, 1)'}); var tween3 = TweenMax.to(sec, 3, {transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1008.7, 3100, 0, 1)'}); Now for what I see mostly you're applying a 2D translate in these cases. Well GSAP has you covered, all you need is to pass x and y values to it: var tween = TweenMax.to(sec, 1, {x: 421.8, y: 1010.15}); var tween2 = TweenMax.to(sec, 1, {x: 1004.58, y: 1011.1}); var tween3 = TweenMax.to(sec, 3, {x: 1008.7, y: 3100}); Quite simpler and cleaner, right? If your concern is passing the animation to the GPU, no worries, when animating any type of transform property, GSAP uses a transform matrix for you, so it gets rendered by the GPU on it's own layer. You can read more about the CSS Plugin here: https://greensock.com/docs/Plugins/CSSPlugin The final issue is applying more than one GSAP instance on the same element and the same properties at the same time. When that GSAP overwrite manager will kill any pre-existing tween and apply the new one. In your case it kind of works like this: You create tween, the instance read the start and end values, and then starts to apply the updates to the css styles. A few milliseconds later you create tween2, GSAP sees that the target is already being animated and the properties are the same, it kills the existing tween, records the start and end values and start applying the updates to the css styles. A few milliseconds later you create tween3, same as #2. If you want to concatenate a series of animations during time, my advice is to create a timeline. Here is an extract from the docs, regarding overwrite: overwrite: String (or integer) - Controls how (and if) other tweens of the same target are overwritten. There are several modes to choose from, but "auto" is the default (although you can change the default mode using theTweenLite.defaultOverwrite property): "none" (0) (or false) - no overwriting will occur. "all" (1) (or true) - immediately overwrites all existing tweens of the same target even if they haven't started yet or don't have conflicting properties. "auto" (2) - when the tween renders for the first time, it will analyze tweens of the same target that are currently active/running and only overwrite individual tweening properties that overlap/conflict. Tweens that haven't begun yet are ignored. For example, if another active tween is found that is tweening 3 properties, only 1 of which it shares in common with the new tween, the other 2 properties will be left alone. Only the conflicting property gets overwritten/killed. This is the default mode and typically the most intuitive for developers. "concurrent" (3) - when the tween renders for the first time, it kills only the active (in-progress) tweens of the same target regardless of whether or not they contain conflicting properties. Like a mix of "all" and "auto". Good for situations where you only want one tween controlling the target at a time. "allOnStart" (4) - Identical to "all" but waits to run the overwrite logic until the tween begins (after any delay). Kills tweens of the same target even if they don't contain conflicting properties or haven't started yet. "preexisting" (5) - when the tween renders for the first time, it kills only the tweens of the same target that existed BEFORE this tween was created regardless of their scheduled start times. So, for example, if you create a tween with a delay of 10 and then a tween with a delay of 1 and then a tween with a delay of 2 (all of the same target), the 2nd tween would overwrite the first but not the second even though scheduling might seem to dictate otherwise. "preexisting" only cares about the order in which the instances were actually created. This can be useful when the order in which your code runs plays a critical role. Remember, please do your best to create a reduced case sample so we can take a better look at it and that illustrates what you're trying to achieve. Happy Tweening!!
  7. soupking

    Tween Override?

    Hey guys, thanks for the response. Y'all are great as always. You know, I figured out something where I made a duplicate of the button I wanted to sustain after the first loop. That seemed to do the trick. I'm not quite sure how one would use a conditional override in Timeline other than overwrite:true, but thought I'd ask. Thanks anyway!
  8. Or if you're talking about overwriting, you can do overwrite:true to make it kill all other tweens of that object immediately. It'd sure help if you had a codepen demo we could look at for the most basic/simple scenario.
  9. GreenSock

    .

    That's one of the things I'm most proud of about the community around GreenSock (especially these forums) - there's none of that arrogant critical "oh what a stupid question...I'm so much smarter than you" kind of stuff. Read through the threads here and I'm sure you'll see what I'm talking about. And to be honest, if I were looking into which animation library I'm gonna invest in for the long term, having a friendly community with a long track record of prompt, accurate answers would be a big factor. When you're wrestling with an animation with a deadline looming, that's HUGE. Again, I'm not going to criticize anime.js specifically, but I'll mention some of the things that I'd be looking at if I were in your shoes: Reliability - does it work around the many browser bugs and inconsistencies out there? We've put a ton of effort into normalizing behavior between browsers so you don't have to smash your head against the screen trying to solve all that stuff. For example, GSAP solves the transform-origin madness in SVGs. From my initial tests, it doesn't look like anime.js does things like that but perhaps I'm doing something wrong. There are countless other examples of inconsistencies that GSAP works around. Robust feature set - can it animate canvas, SVG, generic objects, etc.? Can it handle very complex sequencing? Morphing with mis-matched numbers of points? Bezier curves? Custom easing with unlimited points/segments? Basic physics? Can timelines be nested inside timelines infinitely? Is there a plugin system? Are there dev tools to make it easier during development? Most animation libraries have no trouble covering the basics, but when you've written a bunch of code on top of a certain tool and then you discover "crap! It can't do what I need..." on a more aggressive project, it's really frustrating. We typically hear from customers that when they discover a need, they poke around GSAP and find that it's already solved whatever they were facing. Like ExpoScaleEase. Details - we've been doing this a long time and there are a lot of details that often get missed (not that anime.js missed them...I don't know). For example, does it have seamless loops that don't allow time drift? (most animation libraries just restart when a tween completes in a way that allows time drifts and those can bite you in some cases). Does it avoid layout thrashing? Does it offer overwrite management? Lag smoothing? Does it power down its ticker when there are no animations running (to conserve battery life on mobile devices)? How does it do with dropped frames? I'd certainly recommend looking at this: https://greensock.com/gsap-1-12-0 (there are some demos that may be enlightening). Ubiquity - GSAP is the only robust animation library (that I'm aware of) that's whitelisted on every major ad network, meaning that its file size doesn't count against any ads that are served through those places. DoubleClick, Adwords, Sizmek, AOL, etc. That's a BIG deal to anyone in the advertising world. GSAP has been vetted by all the big companies. Its ubiquity also helps when you're looking to find talent; GSAP has been around for a long time and hundreds of thousands of people know its API. Support - in my 11+ years of doing this, I've seen countless animation libraries come and go. They seem so exciting when they first come out, or for the first year or two, but eventually the authors moves on and stop supporting them (at least most of the time). That's a real bummer for anyone relying on them. GSAP has a funding mechanism in place that has allowed us to build a crazy long track record of ongoing support. We have no plans of going anywhere. Again, none of those things were meant as knocks on anime.js - for all I know, it may do great in many of those categories. I only meant this list as a loose set of criteria I'd be looking at if I were in your shoes. I love hearing that! It makes all the hours I've put in (as well as others in the community) worthwhile. We really aim to make animators say "gosh, this is such a pleasure to use and it solve tricky problems for me..." Well, this next release has some big updates/additions to MorphSVGPlugin which is indeed a members-only benefit. But there are plenty of other things in the public files that I hope you'll love too. Again, we're aiming to launch next week so keep your eyes peeled. Does that answer your question? Anything else we can do?
  10. Dipscom is on the right path. The issue in fact is related to both tweens trying to change opacity at the same time. The second tween starts changing the alpha before the first tween ends. GSAP does not yet merge competing tweens (referred to as additive animation), it kills one of them. If you think about it, it isn't very efficient for the engine to try to set 2 values on the same property at the same time, so the engine intelligently kills the pre-existing tween. In your case the first tween gets killed by the second tween which means it will not run or render when your timeline repeats. It's dead. You can change this behavior by setting an overwrite mode. In your case the easiest solution would be to set overwrite:"none" on your second tween (as shown below) or schedule it to run at a time that does not conflict with the first tween.
  11. As Oliver pointed out, If two tweens are trying to control the same property of the same object at the same time they will literally be fighting for control and one tween must win. The engine by default kills the pre-existing tween. Once it's killed it can not play again. You can set overwrite:"none" on the second tween to prevent the first tween from being killed. tl.to(heroimage, 3, { x:"+=400",y: "-=100",ease: Power3.easeOut }); tl.to(heroimage, 4, { x:"+=20",y: "-=20",ease: Power0.easeNone, overwrite:"none" },"-=0.5"); More info on overwrite settings from the TweenLite docs overwrite: String (or integer) - Controls how (and if) other tweens of the same target are overwritten. There are several modes to choose from, but "auto" is the default (although you can change the default mode using theTweenLite.defaultOverwrite property): "none" (0) (or false) - no overwriting will occur. "all" (1) (or true) - immediately overwrites all existing tweens of the same target even if they haven't started yet or don't have conflicting properties. "auto" (2) - when the tween renders for the first time, it will analyze tweens of the same target that are currently active/running and only overwrite individual tweening properties that overlap/conflict. Tweens that haven't begun yet are ignored. For example, if another active tween is found that is tweening 3 properties, only 1 of which it shares in common with the new tween, the other 2 properties will be left alone. Only the conflicting property gets overwritten/killed. This is the default mode and typically the most intuitive for developers. "concurrent" (3) - when the tween renders for the first time, it kills only the active (in-progress) tweens of the same target regardless of whether or not they contain conflicting properties. Like a mix of "all" and "auto". Good for situations where you only want one tween controling the target at a time. "allOnStart" (4) - Identical to "all" but waits to run the overwrite logic until the tween begins (after any delay). Kills tweens of the same target even if they don't contain conflicting properties or haven't started yet. "preexisting" (5) - when the tween renders for the first time, it kills only the tweens of the same target that existed BEFORE this tween was created regardless of their scheduled start times. So, for example, if you create a tween with a delay of 10 and then a tween with a delay of 1 and then a tween with a delay of 2 (all of the same target), the 2nd tween would overwrite the first but not the second even though scheduling might seem to dictate otherwise. "preexisting" only cares about the order in which the instances were actually created. This can be useful when the order in which your code runs plays a critical role.
  12. Hi Wishing you all a Happy 2019. I have an animation requirement where I have a TimelineMax instance and number of TweenMax instances added to it and some of these TweenMax instances (not all) need to be repeated for number of times. So my question is can I create TimelineMax instances and add repeating instances to it and add these repeating TimelineMax instances to the main TimelineMax instance will it work. Example: // somewhere globally create main var mainTimeline = new TimelineMax({repeat: false, paused: false}); //later on we loop through an array of objects If (obj.repeat){ var tlr = new TimelineMax({repat:99, yoyo:true, paused: false}); tlr.add(TweenMax.to(obj, duration, { x:x, y:y, ease:Quint.easeOut, onUpdate:updateDraw, overwrite: "none" })); }else{ //add TweenMax instances to mainTimeline mainTimeline.add(TweenMax.to(obj, duration, { x:x, y:y, ease:Quint.easeOut, onUpdate:updateDraw, overwrite: "none" })); } mainTimeline.add(tlr, self.getDelay(); //end code Thanks in advance
  13. Hi @SummerBummer, If you tween the same object, the same property, you should have in mind what was and what is going on. A little more to overwrite here and in the docs overwrite: String (or integer) - Controls how (and if) other tweens of the same target are overwritten. There are several modes to choose from, but "auto" is the default (although you can change the default mode using theTweenLite.defaultOverwrite property): "none" (0) (or false) - no overwriting will occur. "all" (1) (or true) - immediately overwrites all existing tweens of the same target even if they haven't started yet or don't have conflicting properties. "auto" (2) - when the tween renders for the first time, it will analyze tweens of the same target that are currently active/running and only overwrite individual tweening properties that overlap/conflict. Tweens that haven't begun yet are ignored. For example, if another active tween is found that is tweening 3 properties, only 1 of which it shares in common with the new tween, the other 2 properties will be left alone. Only the conflicting property gets overwritten/killed. This is the default mode and typically the most intuitive for developers. "concurrent" (3) - when the tween renders for the first time, it kills only the active (in-progress) tweens of the same target regardless of whether or not they contain conflicting properties. Like a mix of "all" and "auto". Good for situations where you only want one tween controling the target at a time. "allOnStart" (4) - Identical to "all" but waits to run the overwrite logic until the tween begins (after any delay). Kills tweens of the same target even if they don't contain conflicting properties or haven't started yet. "preexisting" (5) - when the tween renders for the first time, it kills only the tweens of the same target that existed BEFORE this tween was created regardless of their scheduled start times. So, for example, if you create a tween with a delay of 10 and then a tween with a delay of 1 and then a tween with a delay of 2 (all of the same target), the 2nd tween would overwrite the first but not the second even though scheduling might seem to dictate otherwise. "preexisting" only cares about the order in which the instances were actually created. This can be useful when the order in which your code runs plays a critical role. Kind regards Mikel
  14. Hi @SummerBummer, Welcome to the GreenSock Forum. Your click function overrides the x value of the stagger one. So give it a try: 'overwrite: 0' Happy tweening ... Mikel
  15. Hey RolandSoos, Sorry for the disappearance, deadlines, babies and general life, you know... Gotta earn that bread else, I shall starve. So, for all intents and purposes we can all agree this is some sort of float rounding error - At least this is everybody's best guess. I still have difficulties reproducing the double callback but I have spotted it once so, we'll go with it happening. My question to you is: do you really need to create one big timeline that holds all of those animations and has to account for so many variations? Can't you just create/update a timeline whenever the conditions change? In general it is pretty cheap to create and overwrite timelines. I know you said in your real application everything is more complex but still, I fail to see why this would need to be one single big timeline. Have you considered having your system create tiny timelines with onComplete callbacks that ask a central state manager for the where to go next?
  16. I read your question a few times but I don't understand what you're asking. Can you provide a reduced test case as a codepen so that we can see what's going on? Also, if you're animating transforms (maybe you're not), "rotate" should be "rotation". I wonder if you're creating overlapping tweens of the same object which would cause overwriting to kick in. You could set overwrite:false and see if that resolves things, but beware that when you create overlapping tweens that overwrite, they're literally fighting each other for control of the same property at the same time, so be careful about setting overwrite:false. Lastly, you can make your code more concise by tapping into the convenience methods of TimelineMax. Instead of timeline.add( TweenMax.to(...), someDelay) you can simply do timeline.to(..., someDelay)
  17. Thanks @GreenSock Jack. Wow, an overwrite mode and I see now even an onOverwrite event.. never knew about these. Guess I will spend some time later to go through all options there to see if there are more ones I didn't know about. But somehow had the feeling this was already build in, because it's pretty hard to think of something that isn't there. Also nice way to kill tweens of variables going through plugins. Thanks a lot for the beautiful work with obviously a lot of passion and experience put in there!
  18. Good questions. Yes, by default GSAP applies overwrite:"auto" which means that when a tween renders for the first time, it'll look for other tweens of the same target that are controlling the same properties and kill ONLY those properties (in the other/competing tweens). That's automatic. You can, of course set overwrite:true and it'll kill all of the tweens that are running of that same object (regardless of what properties are tweening). For killTweensOf(), you don't need to include the "pixi" wrapper. So you can just TweenLite.killTweensOf(this.bmp, {x:true}); I love hearing that you're enjoying the tools so much!
  19. Are you getting any errors? Do you have tree shaking enabled? If so, I bet ScrollToPlugin is getting dumped by your build process. Do you have a demo, perhaps on stackblitz or codepen? It's tough to troubleshoot blind. Oh, and autoKill:true should only be inside of the scrollTo object. I'm also curious why you have overwrite:5. From what I can tell, your ticking variable wouldn't be getting set properly either because you've got it as a local variable in the scope of that function. We'd be happy to try to assist if you can provide a reduced test case.
  20. I am trying to create slow smooth scroll on website in React and it doesn't work, this is what I tried so far. constructor(props) { super(props); this.state = { scrollTime: 0.5, // Speed scrollDistance: 100, // Scroll easing distance ticking: false, }; } componentDidMount() { window.addEventListener('mousewheel', this.mousewheelHandler, false); window.addEventListener('DOMMouseScroll', this.mousewheelHandler, false); } mousewheelHandler = (event) => { event.preventDefault(); let { scrollDistance, scrollTime, ticking } = this.state; // // SLOW SCROLL var slowScroll = () => { var delta = event.wheelDelta / 120 || -event.detail / 3; var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop; var finalScroll = scrollTop - parseInt(delta * scrollDistance); TweenLite.to(window, scrollTime, { scrollTo: { y: finalScroll, autoKill: true }, ease: Power1.easeOut, autoKill: true, overwrite: 5 }); ticking = false; }; if (!ticking) { requestAnimationFrame(slowScroll); ticking = true; } };
  21. React has updated and introduced hooks since this article was written. We recommend reading our updated guide to animating with GSAP in React. This page was also created for GSAP version 2. We have since released GSAP 3 with many improvements. While it is backward compatible with most GSAP 2 features, some parts may need to be updated to work properly. Please see the GSAP 3 release notes for details Preface This guide assumes a basic knowledge of both the GreenSock Animation Platform (GSAP) and React, as well as some common tools used to develop a React app. As GSAP becomes the de-facto standard for creating rich animations and UI's on the web, developers must learn how to integrate it with other tools like React which has become popular because it allows developers to write their apps in a modular, declarative and re-usable fashion. As a moderator in the GreenSock forums, I've noticed that there are a few common hurdles to getting the two working together seamlessly, like referencing the DOM element appropriately, doing things The React Way, etc. which is why I'm writing this article. We won't delve into how a React app should be structured since our focus is on using GSAP, but the techniques used throughout this guide follow the official guidelines and have been reviewed by maintainers of the React Transition Group tool. We'll start simple and get more complex toward the end. How GSAP Works GSAP basically updates numeric properties of an object many times per second which creates the illusion of animation. For DOM elements, GSAP updates the the inline style properties. const myElement = document.getElementById("my-element"); TweenLite.to(myElement, 1, {width: 100, backgroundColor: "red"}); As you can see this means that we need access to the actual DOM node rendered in the document in order to pass it to the TweenLite.to() method. How React Works Explaining how React works is beyond the scope of this article, but let's focus on how React gets the JSX code we write and puts that in the DOM. <div className="my-class"> Some content here </div> With React, we normally don't pass an id attribute to the element because we use a declarative way to access methods, instances, props and state. It's through the component's (or the application's) state that we can change how things are represented in the DOM. There's no direct DOM manipulation, so typically there's no need to actually access the DOM. The React team has given developers ways to access the DOM nodes when needed, and the API changed a bit over the years as React matured. At this time (September, 2018) the latest version of React (16.4.2) allows developers to use Refs to access the DOM nodes. In this guide we'll mainly use the Callback Refs to create a reference to the DOM node and then feed it into GSAP animations because it's much faster for GSAP to directly manipulate properties rather than funneling them through React's state machine. Creating Our First Animation We'll use the ref to access the DOM node and the componentDidMount() lifecycle method of the component to create our first animation, because this will guarantee that the node has been added to the DOM tree and is ready to be passed into a GSAP animation. class MyComponent extends Component { constructor(props){ super(props); // reference to the DOM node this.myElement = null; // reference to the animation this.myTween = null; } componentDidMount(){ // use the node ref to create the animation this.myTween = TweenLite.to(this.myElement, 1, {x: 100, y: 100}); } render(){ return <div ref={div => this.myElement = div} />; } } Not that difficult, right? Let's go through the code so we can understand what is happening. First when we create an instance of this class, two properties are added to it: myElement and myTween, but both are equal to null. Why? Because at this point the node has not been added to the DOM tree and if we try to pass this node to a GSAP animation, we'll get an error indicating that GSAP cannot tween a null target. After the new instance has been initialized, the render() method runs. In the render method we're using the ref attribute that is basically a function that has a single parameter – the DOM node being added to the DOM tree. At this point we update the reference to the DOM node created in the class constructor. After that, this reference is no longer null and can be used anywhere we need it in our component. Finally, the componentDidMount() method runs and updates the reference to myTween with a TweenLite tween whose target is the internal reference to the DOM node that should animate. Simple, elegant and very React-way of us! It is worth mentioning that we could have created a one-run-animation by not creating a reference to the TweenLite tween in the constructor method. We could have just created a tween in the componentDidMount method and it would run immediately, like this: componentDidMount(){ TweenLite.to(this.myElement, 1, {x: 100, y: 100}); } The main benefit of storing a TweenLite tween as a reference in the component, is that this pattern allows us to use any of the methods GSAP has to offer like: play(), pause(), reverse(), restart(), seek(), change the speed (timeScale), etc., to get full control of the animations. Also this approach allows us to create any GSAP animation (TweenLite, TweenMax, TimelineLite, etc.) in the constructor. For example, we could use a timeline in order to create a complex animation: constructor(props){ super(props); this.myElement = null; this.myTween = TimelineLite({paused: true}); } componentDidMount(){ this.myTween .to(this.myElement, 0.5, {x: 100}) .to(this.myElement, 0.5, {y: 100, rotation: 180}) .play(); } With this approach we create a paused Timeline in the constructor and add the individual tweens using the shorthand methods. Since the Timeline was paused initially, we play it after adding all the tweens to it. We could also leave it paused and control it somewhere else in our app. The following example shows this technique: Simple Tween Demo Animating a Group of Elements One of the perks of using React is that allows us to add a group of elements using the array.map() method, which reduces the amount of HTML we have to write. This also can help us when creating an animation for all those elements. Let's say that you want to animate a group of elements onto the screen in a staggered fashion. It's simple: constructor(props){ super(props); this.myTween = new TimelineLite({paused: true}); this.myElements = []; } componentDidMount(){ this.myTween.staggerTo(this.myElements, 0.5, {y: 0, autoAlpha: 1}, 0.1); } render(){ return <div> <ul> {elementsArray.map((element, index) => <li key={element.id} ref={li => this.myElements[index] = li} > {element.name} </li>)} </ul> </div>; } This looks a bit more complex but we're using the same pattern to access each DOM node. The only difference is that instead of using a single reference for each element, we add each element to an array. In the componentDidMount() method we use TimelineLite.staggerTo() and GSAP does its magic to create a staggered animation! Multiple Elements Demo Creating a Complex Sequence We won't always get all the elements in an array so sometimes we might need to create a complex animation using different elements. Just like in the first example we store a reference in the constructor for each element and create our timeline in the componentDidMount() method: Timeline Sequence Demo Note how in this example we use a combination of methods. Most of the elements are stored as an instance property using this.element = null, but also we're adding a group of elements using an array.map(). Instead of using the map() callback to create tweens in the timeline (which is completely possible), we're adding them to an array that is passed in the staggerFrom() method to create the stagger effect. Animating Via State The most commonly used pattern to update a React app is through changing the state of its components. So it's easy to control when and how elements are animated based on the app state. It's not very difficult to listen to state changes and control a GSAP animation depending on state, using the componentDidUpdate() lifecycle method. Basically we compare the value of a state property before the update and after the update, and control the animation accordingly. componentDidUpdate(prevProps, prevState) { if (prevState.play !== this.state.play) { this.myTween.play(); } } Control Through State Demo In this example we compare the value of different state properties (one for each control method implemented in the component) to control the animation as those values are updated. It's important to notice that this example is a bit convoluted for doing something that can be achieved by calling a method directly in an event handler (such as onClick). The main idea is to show the proper way of controlling things through the state. A cleaner and simpler way to control an animation is by passing a prop from a parent component or through an app state store such as Redux or MobX. This modal samples does exactly that: // parent component <ModalComponent visible={this.state.modalVisible} close={this.setModalVisible.bind(null, false)} /> // ModalComponent constructor(props){ super(props); this.modalTween = new TimelineLite({ paused: true }); } componentDidMount() { this.modalTween .to(this.modalWrap, 0.01, { autoAlpha: 1 }) .to(this.modalDialog, 0.25, { y: 50, autoAlpha: 1 }, 0) .reversed(true) .paused(false); } componentDidUpdate(){ this.modalTween.reversed(!this.props.visible); } As you can see the modal animation is controlled by updating the visible prop passed by its parent, as well as a close method passed as a prop. This code is far simpler and reduces the chance of error. State Modal Demo Using React Transition Group React Transition Group(RTG) is a great tool that allows another level of control when animating an element in a React app. This is referred to as the capacity to mount and unmount either the element being animated or an entire component. This might not seem like much when animating a single image or a div, but this could mean a significant performance enhancement in our app in some cases. SIMPLE TRANSITION DEMO In this example the <Transition> component wraps the element we want to animate. This element remains unmounted while it's show prop is false. When the value changes to true, it is mounted and then the animation starts. Then when the prop is set to false again, another animation starts and when this is completed it can also use the <Transition> component to wrap the entire component. RTG also provides the <TransitionGroup> component, which allows us to control a group of <Transition> components, in the same way a single <Transition> component allows to control the mounting and unmounting of a component. This is a good alternative for animating dynamic lists that could have elements added and/or removed, or lists based on data filtering. Transition Group Demo <Transition timeout={1000} mountOnEnter unmountOnExit in={show} addEndListener={(node, done) => { TweenLite.to(node, 0.35, { y: 0, autoAlpha: show ? 1 : 0, onComplete: done, delay: !show ? 0 : card.init ? props.index * 0.15 : 0 }); }} > In this example we use the addEndListener() callback from the <Transition> component. This gives us two parameters, the node element being added in the DOM tree and the done callback, which allows to control the inner state of the <Transition> component as the element is mounted and unmounted. The entire animation is controlled by the in prop, which triggers the addEndListener() and ultimately the animation. You may notice that we're not creating two different animations for the enter/exit state of the component. We create a single animation that uses the same DOM node and the same properties. By doing this, GSAP's overwrite manager kills any existing animation affecting the same element and properties, giving us a seamless transition between the enter and exit animations. Finally, using RTG allows us for a more fine-grained code, because we can use all the event callbacks provided by GSAP (onStart, onUpdate, onComplete, onReverse, onReverseComplete) to run all the code we want, before calling the done callback (is extremely important to notify that the animation has completed). Animating Route Changes Routing is one of the most common scenarios in a React app. Route changes in a React app means that an entirely different view is rendered depending on the path in the browser's address bar which is the most common pattern to render a completely different component in a route change. Obviously animating those changes gives a very professional look and feel to our React apps. Rendering a new component based on a route change means that the component of the previous route is unmounted and the one for the next route is mounted. We already covered animating components animations tied to mount/unmount using the <Transition> component from RTG, so this is a very good option to animate route changes. <BrowserRouter> <div> <Route path="/" exact> { ({ match }) => <Home show={match !== null} /> } </Route> <Route path="/services"> { ({ match }) => <Services show={match !== null} /> } </Route> <Route path="/contact"> { ({ match }) => <Contact show={match !== null} /> } </Route> </div> </BrowserRouter> This main component uses React Router's <BrowserRouter> and <Route> and checks the match object passed as a prop to every <Route> component, while returning the component that should be rendered for each URL. Also we pass the show property to each component, in the same way we did in the transition example. <Transition unmountOnExit in={props.show} timeout={1000} onEnter={node => TweenLite.set(node, startState)} addEndListener={ (node, done) => { TweenLite.to(node, 0.5, { autoAlpha: props.show ? 1 : 0, y: props.show ? 0 : 50, onComplete: done }); }} > As you can see, the code is basically the same used to animate a single component; the only difference is that now we have two animations happening in different components at the same time. Route Animation Demo It's worth noting that the animations used in this example are quite simple but you can use any type of animation even complex, nested animations. As you can see by now, using GSAP and React can play together nicely. With all the tools and plugins GSAP has to offer the sky is the limit for creating compelling and amazing React applications! FAQ What is this "Virtual DOM" thing, that is referred so much when it comes to React Apps? Can GSAP work with this virtual dom? The Virtual DOM is what React uses to update the DOM in a fast and efficient way. In order to learn more about it check this article and the React Docs. GSAP can't work with the virtual DOM because the elements in the Virtual DOM are not exactly DOM nodes per-se. I often read about the declarative nature of React. Does that affect how we use GSAP in a React APP? Yes. React works by updating the rendered DOM through changes in the App state, so when creating an animation using GSAP, instead of reaching out directly to the DOM, like in most other cases, we need to wait for those changes in the app state and the DOM to be rendered, in order to use the current representation of the app state and create the animation. To learn more about how declarative and imperative code work read this article. In the second sample I see this code in the ref callback ref={div => this.cards = div}. Why is the index being used instead of just pushing the element in the array? The reason for that is that every time a React component is re-rendered, the render method is executed, but the original instance remains unchanged. The array used to create the animation is created in the component's constructor. The GSAP animation (a TimelineLite) is created in the componentDidMount hook. These two elements are created just once in the App's lifecycle, while the render method is executed on every re-render. Therefore if we push the elements to the array on every re-render, even though the Timeline instance won't change, the array will get bigger and bigger every time the component is re-rendered. This could cause a memory issue, especially for large collections. In the guide one of the samples triggers animations via the state of a component or the app. Is it possible to update the state of the component/app using GSAP? Absolutely! All you have to do is use one of the many callback events GSAP has to offer. The only precaution is to be aware of infinite loops. That is if an animation is started on the render method of a component and a callback from that animation updates the state of the component then that will trigger a re-render, which will start the animation again. You can check this simple example of how that can be done. Is it possible to trigger a route change using GSAP? It is possible using React Router's API. Although is not recommended because using React Router's API directly will prevent triggering the route change animations when using the browser's back and forward buttons. However, using React Transition Group with GSAP does trigger the route change animations with the native navigation methods. Can I use other GSAP plugins and tools in a React App? This guide shows only TweenMax, Timeline and the CSS Plugin? Yes, any GSAP tool or plugin you want can be used in a React app. Just be sure to follow the same patterns and guidelines from this article and you'll be fine. I tried the code in the guide and samples, but it doesn't work. What can I do? Head to the GreenSock forums where all your questions will be answered as fast as possible. I want to contribute or post an issue to this guide. Where can I do that? Even though this guide was reviewed by GreenSock and React experts, perhaps something might have slipped away, or with time and new versions, some things should or could be done differently. For those cases please head to this GitHub Repo and inform any issues or create a Pull Request with the changes you think should be added. New to GSAP? Check out the Getting Started Guide. Got questions? Head over to the GreenSock forums where there's a fantastic community of animators. Acknowledgments I'd like to thank the three developers that took time from their work and lives to review this guide as well as the samples in it. I couldn't have done this without their help and valuable input. Please be sure to follow them: Xiaoyan Wang: A very talented React developer. While Xiaoyan doesn't have a very active online social life (Twitter, Facebook, etc), you can follow what he does on GitHub. Jason Quense: One of the maintainers of React Transition Group and part of the React Bootstrap Team. Jason also collaborates in many other React-related projects. Check Jason's GitHub profile for more info. Matija Marohnić: The most active contributor and maintainer of React Transition Group and Part of the Yeoman Team. Matija also contributes in a lot of React-related projects as well as many other open source software. Be sure to follow Matija in GitHub and Twitter. A guest post from Rodrigo Hernando, a talented animator/developer who has years of experience solving animation challenges. Rodrigo is a seasoned React developer and he was one of our first moderators, serving the GreenSock community since 2011 with his expert help and friendly charm.
  22. When you define a from tween, GSAP will set your element to that position and animate back to original position. So for example if your element is at 0 and you create a from tween with value of 100, GSAP will set your element to 100 and animate back to 0. If while creating the tween if element was at 50, then GSAP will animate from 100 to 50. If it was already at 100, then nothing will happen because start and end positions are same. I removed each because it was unnecessary. You can still use each and it will work. Also, with GSAP you don't need anything like jQuery's stop. GSAP overwrites any tweens for same property of the element by default. You can change the overwrite behavior if you ever need, check the docs. https://greensock.com/docs/TweenLite You can visit the learning page and youtube channel to get familiar with GSAP API, https://greensock.com/learning https://www.youtube.com/user/GreenSockLearning
  23. I've read some topics on the forum about this, but they had some dead links, so that's why I'm asking this again. I have this script that listens to the scroll event and then "scrolls through" the Timeline progress depending on the mouse position. It's working great, especially on my MacBook Pro that has built-in inertia/momentum to the trackpad. What I would like to do is to add some kind of smoothing or easing to the progress value, so that it's eases from the last value to the next on scroll, or whatever method that would work best. This is the script I'm using: $window.on("scroll", function () { var documentHeight = $(document).height(); var windowHeight = $window.height(); scrollTop = $(window).scrollTop(); var scrollPercent = Math.max((scrollTop) / (documentHeight - windowHeight), 0); timeline.progress(scrollPercent).pause() }); Any idea on how to implement easing to the progress change? I've tried to use this script below for smoothing out the mouse movement overall, but somethings tells me that changing the progress change instead of the scroll movement itself would be better/more performant? Especially if they both are called on the same scroll event. Maybe someone have some best practice advise for this. function smoothScroll() { var a = $(window); a.on("mousewheel DOMMouseScroll", function (b) { b.preventDefault(); b = b.originalEvent.wheelDelta / 120 || -b.originalEvent.detail / 3; b = a.scrollTop() - parseInt(400 * b); TweenMax.to(a, 1.1, { scrollTo: { y: b, autoKill: !0 }, ease: Power1.easeOut, overwrite: 5 }) }) }
  24. In the site there is a part of horizontal scrolling and when you get in the cabinet the scroll becomes vertical. The scroll does not work on huawei mobile phones. I do not know what the problem is. I put the code I used for the horizontal scroll $(function(){ var $window = $(window); var scrollTime = 1.2; var scrollDistance = 300; $window.on("mousewheel DOMMouseScroll", function(event){ event.preventDefault(); var delta = event.originalEvent.wheelDelta/120 || -event.originalEvent.detail/3; var scrollLeft = $window.scrollLeft(); var finalScroll = scrollLeft - parseInt(delta*scrollDistance); TweenMax.to($window, scrollTime, { scrollTo : { x: finalScroll, autoKill:true }, ease: Power1.easeOut, autoKill: true, overwrite: 5 }); }); });
  25. Hi Jack I have to try that code, it is work but not perfect var tl = new TimelineMax({repeat:0, yoyo:true, repeatDelay:0, overwrite: true}) tl.to(text1_img, 9, {y:167, ease: Power1.easeInOut},"+=1.8") .to(text1_img, .5, {y:"+=40", ease: Elastic.easeOut, overwrite: false}, "-=4") attached the screen record video, could you take a look please you will understand very well at 6.sec of the video, there is a gap. how can I fix it? Many Thanks test2.mp4
×