Jump to content
GreenSock

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

Search the Community

Showing results for tags 'articles'.



More search options

  • 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

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


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

Found 5 results

  1. Note: This page was 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. As the author of GSAP I'm sometimes asked if the Web Animations API (WAAPI) will be used under the hood eventually. My responses have gotten pretty long so I thought I'd share my findings with everyone here. Hopefully this sheds light on the challenges we face and perhaps it can lead to some changes to WAAPI in the future. WAAPI is a native browser technology that's similar to CSS animations, but for JavaScript. It's much more flexible than CSS animations and it taps into the same mechanisms under the hood so that the browser can maximize performance. Support is a bit spotty right now and there are multiple levels to the spec, so some browsers may support only "level 1", for example, but the hope is that eventually all major browsers will support WAAPI fully. Progress in that direction has been very, very slow. You could think of WAAPI almost like a browser-level GSAP with a bunch of features stripped out. This has led some to suggest that perhaps GSAP should be built on TOP of WAAPI to reduce file size and maximize performance. Ideally, people could tap into the rich GSAP API with all of its extra features while benefiting from the browser's native underpinnings wherever possible. Sounds great, right? Unfortunately, WAAPI has some critical weak spots that make it virtually impossible for GSAP to leverage it under the hood (at least in any practical manner). I don't mean that as a criticism of WAAPI. In fact, I really wanted to find a way to leverage it inside GSAP, but I'll list a few of the top reasons why it doesn't seem feasible below. To be clear, this is NOT a feature comparison or a bunch of reasons why GSAP is "better" - these are things that make it architecturally impossible (or very cumbersome) to build GSAP on WAAPI. Custom easing WAAPI only supports cubic-bezier() for custom easing, meaning it's limited to one segment with two control points. It can't support eases like Bounce, Elastic, Rough, SlowMo, wiggle, ExpoScaleEase, etc. GSAP must support all of those eases plus any ease imaginable (unlimited segments and control points - see https://greensock.com/customease). This alone is a deal-breaker. Expressive animation hinges on rich easing options. Independent transform components The most commonly animated values are translation (x/y position), rotation, and scale (all transform-related) but you cannot control them independently with CSS or WAAPI. For example, try moving (translate) something and then halfway through start rotating it and stagger a scale toward the end: |-------- translateX() ------------| |------ rotate() ------| |---------- translateY() -----------| |-------------- scale(x,y) --------------| Animators NEED to be able to independently control these values in their animations. Additive animations (composite:"add") probably aren't an adequate solution either. It's unrealistic to expect developers to track all the values manually or assume that stacking them on top of each other will deliver expected results - they should be able to just affect the rotation (or whatever) at any time, even if there was a translate() or scale() applied previously. GSAP could track everything for them, of course, but continuously stacking transforms on top of each other seems very inefficient and I imagine it'd hurt performance (every transform is another matrix concatenation under the hood). There is a new spec being proposed for translate, scale, and rotate CSS properties which would certainly help, but it's not a full solution because you still can't control the x/y components independently, or all of the 3D values like rotationX, rotationY, z, etc. This is an essential feature of GSAP that helped it become so popular. Example See the Pen Independent Transforms Demo by GreenSock (@GreenSock) on CodePen. Custom logic on each tick Certain types of animations require custom logic on each tick (like physics or custom rounding/snapping or morphing). Most GSAP plugins rely on this sort of thing (ModifiersPlugin, for example). I'm pretty sure that's impossible with WAAPI, especially with transforms being spun off to a different thread (any dependencies on JS-based logic would bind it to the main thread). Non-DOM targets As far as I know, WAAPI doesn't let you animate arbitrary properties of generic objects, like {myProperty:0}. This is another fundamental feature of GSAP - people can use it to animate canvas library objects or generic objects...whatever. Global timing controls I don't think WAAPI lets you set a custom frame rate. Also, GSAP's lag smoothing feature requires the ability to tweak the global time (not timeScale - I mean literally the current time so that all the animations are pushed forward or backward). As far as I know, it's impossible with WAAPI. Synchronization (transforms and non-transforms) As demonstrated in this video, one of the hidden pitfalls of spinning transforms off to another thread is that they can lose synchronization with other main-thread-based animations. As far as I know, that hasn't been solved in all browsers. We can't afford to have things getting out-of-sync. Some have proposed that GSAP could just fall back to using a regular requestAnimationFrame loop to handle things that aren't adequately supported by WAAPI but that puts things at risk of falling out of sync. For example, if transforms are running on a separate thread they might keep moving while other parts of the animation (custom properties that get applied somehow in an onUpdate) slow down or jank. Compatibility GSAP has earned a reputation for "just working" across every browser. In order to deliver on that, we'd have to put extra conditional logic throughout GSAP, providing fallbacks when WAAPI isn't available or doesn't support a feature. That would balloon the file size substantially and slow things down. That's a tough pill to swallow. WAAPI still isn't implemented in several major browsers today. And then there are the browser inconsistencies (like the infamous SVG origin quirks) that will likely pop up over time and then we'd have to unplug those parts from WAAPI and maintain the legacy raw-JS mechanisms internally. Historically, there are plenty of cross-browser bugs in natively-implemented technologies, making it feel risky to build on top of. Performance WAAPI has a performance advantage because it can leverage a separate thread whereas JavaScript always runs on the main thread, right? Well, sort of. The only time a separate thread can be used is if transforms and/or opacity are the only things animating on a particular element (or else you run into synchronization issues). Plus there's overhead involved in managing that thread which can also get bogged down. There are tradeoffs either way. Having access to a different thread is fantastic even if it only applies in certain situations. That's probably the biggest reason I wanted to leverage WAAPI originally, but the limitations and tradeoffs are pretty significant, at least as it pertains to our goals with GSAP. Surprisingly, according to my tests GSAP was often faster than WAAPI. For example, in this speed test WAAPI didn't perform as well as GSAP on most devices I tried. Maybe performance will improve over time, but for now be sure to test to ensure that WAAPI is performing well for your animations. File Size To ensure compatibility, GSAP would need all of its current (non-WAAPI) code in place for fallbacks (most browsers won't fully support WAAPI for years) and then we'd need to layer in all the WAAPI-specific code on top of that like conditional logic checking for compatible eases, sensing when the user is attempting something WAAPI can't support, tracking/stacking additive animations, etc. That means file size would actually be far worse if GSAP were built on WAAPI. Some have suggested creating a different adapter/renderer for each tech, like a WebAnimationsAdapter. That way, we could segregate the logic and folks could just load it if they needed it which is clever but it doesn't really solve the problem. For example, some plugins may affect particular CSS properties or attributes, and at some point conditional logic would have to run to say "oh, if they're using the WebAnimationsAdapter, this part won't work so handle it differently". That conditional logic generally makes the most sense to have in the plugin itself (otherwise the adapter file would fill up with extra logic for every possible plugin, bloating file size unnecessarily and separating plugin logic from the plugin itself). So then if anyone uses that plugin, they'd pay a price for that extra logic that's along for the ride. Weighing the Pros & Cons At the end of the day, the list of "pros" must outweigh the "cons" for this to work, and currently that list is quite lopsided. I'd love to find a way to leverage any of the strengths of WAAPI inside GSAP for sure, but it just doesn't seem feasible or beneficial overall. The main benefit I see in using WAAPI inside GSAP is to get the off-the-main-thread-transforms juice but even that only seems useful in relatively uncommon scenarios, and it comes at a very high price. I'm struggling to find another compelling reason to build on WAAPI; GSAP already does everything WAAPI does plus a lot more. I'm hopeful that some of the WAAPI benefits will someday be possible directly in JS so that GSAP wouldn't have to create a dependency on WAAPI to get those. For example, browsers could expose an API that'd let developers tap into that off-the-main-thread transform performance. Ideally, browsers would also fix that hacky matrix()/matrix3d() string-based API and provide a way to set the numeric matrix values directly - that'd probably deliver a nice speed boost. Please chime in if I'm missing something, though. (Contact us or post in the forums) Why use GSAP even if/when WAAPI gets full browser support? Browser bugs/inconsistencies Lots of extra features like morphing, physics, Bezier tweening, text tweening, etc. Infinite easing options (Bounce, Elastic, Rough, SlowMo, ExpoScaleEase, Wiggle, Custom) Independent transform components (position, scale, rotation, etc.) Animate literally any property of any object (not just DOM) Timeline nesting (workflow) GSDevTools Relative values and overwrite management from() tweens are much easier - you don't need to get the current values yourself Familiar API Why WAAPI might be worth a try If you don’t need broad browser support today or any of GSAP’s unique features, you could save some kb by using WAAPI Solid performance, especially for transforms and opacity Always free Again, the goal of this article is NOT to criticize WAAPI at all. I think it's a great step forward for browsers. I just wanted to explain some of the challenges that prevent us from using it under the hood in GSAP, at least as it stands today. EDIT: Brian Birtles, one of the primary authors of the WAAPI spec, reached out and offered to work through the issues and try to find solutions (some of which may involve editing the spec itself) which is great. Rachel Nabors has also worked to connect people and find solutions. Although it may take years before it's realistic to consider building on WAAPI, it's reassuring to have so much support from leaders in the industry who are working hard to move animation forward on the web.
  2. This is a guest post from one of our top moderators, Craig Roblewsky (known as PointC), whose "zero-to-hero" story became one of the most popular posts in the forums. His animation skills are also showcased in the "What is GSAP?" video on our home page which he created. He certainly has a knack for helping people understand challenging concepts in a concise way, as you'll see below. Preface ScrollMagic is not a GreenSock product nor is it officially supported here, but GSAP and ScrollMagic work well together, so many questions about it are asked on the GreenSock forums. This article will not be an extensive guide to using ScrollMagic or GSAP, but rather a quick primer to using GSAP and ScrollMagic together. Demos There are eight demos which can be forked as a starting point for your projects. They represent the most common types of scroll triggered animations. It is assumed that you understand the basics of GSAP and ScrollMagic. I won’t be going into detail about the code in each demo, but simply highlighting the most important aspect of each one. I’ve made them with just a few <divs> or <sections> so they’ll be easy to understand and/or reverse engineer. Scripts The first thing to know is which scripts are necessary. For starters, you’ll need the GSAP files. I recommend TweenMax. <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script> Using ScrollMagic requires the main script. <script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/ScrollMagic.min.js"></script> To allow ScrollMagic to take control of your tweens, you will also need the GSAP plugin. <script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/plugins/animation.gsap.min.js"></script> Finally, for debugging purposes, I highly recommend the addIndicators plugin. <script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/plugins/debug.addIndicators.min.js"></script> Please note: it is important to load TweenMax before loading the animation.gsap script. If you try to use the setTween() method and do not have the animation.gsap script loaded, you will see an error in the console. The following demo is an empty shell which loads all the above scripts and jQuery. Demo 1: GSAP, ScrollMagic and jQuery Empty Starter See the Pen GSAP, ScrollMagic and jQuery Empty Starter by PointC (@PointC) on CodePen. Duration You have two choices when using GSAP tweens with ScrollMagic. You can either use the actual tween duration which then plays the animation at normal speed when you hit the trigger or you can allow ScrollMagic to hijack the duration and the tween will be played as you scroll. To use the actual tween duration, you simply omit the duration from the scene parameters. Demo 2: GSAP and ScrollMagic w/tween duration See the Pen GSAP and ScrollMagic w/tween duration by PointC (@PointC) on CodePen. If you'd like the animation to play as the user scrolls, you can add a duration in pixels or percentage to the scene parameters. This is the same demo, but the scene duration is now set to 50%. When hijacking the duration, I’d recommend changing the default ease to Linear.easeNone. Demo 3: GSAP and ScrollMagic w/scene duration See the Pen GSAP and ScrollMagic w/scene duration by PointC (@PointC) on CodePen. Looping to create scenes A common question many users have is how to create the same animation for multiple elements without manually creating a tween and scene for each one. The easy approach in these situations is to use a jQuery each() loop. If you aren’t using jQuery, a vanilla JS loop can be used too. Demo 4: GSAP and ScrollMagic jQuery each() loop See the Pen Looping to create scenes by PointC (@PointC) on CodePen. Pinning Another common animation is pinning an element, playing a tween or timeline and then unpinning. The biggest thing to remember is create a parent container for the actual pinned section. The animation then plays inside that element while it’s pinned. Quite often users will try to pin the sections that are animating and that will not give you the desired results. Demo 5: GSAP and ScrollMagic Pinning See the Pen GSAP and ScrollMagic Pinning by PointC (@PointC) on CodePen. Horizontal Scrolling This can be achieved by animating the xPercent of a parent element containing the sections in your series of slides. Note the duration is 100% * the number of (panels -1). This example has five slides so the duration is set to 400% and each panel move is 20%. This timeline is manually created but could also be created in a loop. Also note the sections themselves are not animating here. The parent container is the only element that is moving. Demo 6: GSAP and ScrollMagic Horizontal Scrolling See the Pen GSAP and ScrollMagic Horizontal Scrolling by PointC (@PointC) on CodePen. Horizontal Pinning A similar effect to horizontal scrolling is a horizontal pinning. Here we have a main pin scene to hold the parent element in a pinned position. Again, the duration is 100% * the number of (panels -1). In this case that is 500%. The first loop creates an animation for each section to move into place with xPercent:100. Using the position parameter offsets each section by an additional second. That space allows the individual animations to play. This first timeline plays in the main scene with the setPin(). The jQuery each() loop creates a simple SplitText animation for each section. Notice the trigger element is always the #pinMaster div. The trick is adding an offset for each section. The index of the loop is used to multiply by the offset variable which in this case is set to window.innerHeight. Learn more about the SplitText plugin. Demo 7: GSAP and ScrollMagic Horizontal Pin, Tweens and jQuery Loop See the Pen GSAP and ScrollMagic Horizontal Pin and Tweens and jQuery Loop by PointC (@PointC) on CodePen. Scroll w/Parallax Finally, it is possible to achieve a neat little parallax effect as you scroll. In the following demo I’ve used a wrapper class with a child and parent div for illustration purposes. Setting the child element to the right and bottom of the parent allows for animating the div up slightly as the user scrolls. The duration in this case is set to 100% but you can certainly set that to your liking. Demo 8: GSAP and Parallax ScrollMagic See the Pen GSAP and Parallax ScrollMagic by PointC (@PointC) on CodePen. Conclusion As I mentioned at the beginning of this article, ScrollMagic is not a GreenSock product nor is it officially supported here on the GreenSock website or forum. But the GreenSock community likes to help everyone so hopefully the demos will serve as a springboard for your scroll triggered projects and a learning resource as you start using GSAP with ScrollMagic. You can also view the entire demo collection here. 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. Need additional details about ScrollMagic? Check out the ScrollMagic docs.
  3. 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. 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 a 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 social life (twitter, facebook, etc), you can follow what he does in 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.
  4. GreenSock

    GSAP 2.0 Released

    Note: This page was 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. We've been getting requests for better support of modern build tools. With version 2.0 we're pleased to announce a switch to ES modules via NPM which should make your building, bundling, and tree shaking even smoother. Don't worry, the UMD/CommonJS flavor is still available and the CDN serves the same browser-friendly files as always. If terms like "UMD", "ES Modules", and "tree shaking" leave you scratching your head, fear not - GSAP 2.0 will work like a champ for you (as usual). There are no syntax, API, or browser-support changes. None. The major version bump was primarily due to the switch to ES modules for NPM users, that's all. DOWNLOAD GSAP NOW NPM, ES Modules, Webpack, oh my! Modern bundlers like Webpack and Rollup just love to snack on ES modules these days, usually grabbing them from NPM. So GSAP 2.0 is extra delicious covered in its chocolatey ES module outer shell. (If you're not using a bundler or NPM, skip this section entirely) npm install gsap Then you can import individual classes like: import TweenMax from "gsap/TweenMax"; import Draggable from "gsap/Draggable"; TweenMax includes (and exports) many of the commonly-used classes so you can also do this: import { TweenMax, TimelineLite, Power2, Elastic, CSSPlugin } from "gsap/TweenMax"; (TweenMax includes TweenLite, TimelineLite, TimelineMax, CSSPlugin, RoundPropsPlugin, BezierPlugin, DirectionalRotationPlugin, AttrPlugin, and all eases except CustomEase, CustomWiggle, and CustomBounce) As a convenience, there's also an "all" file that imports/exports every GSAP tool (except members-only bonus plugins), so you can do this: import { TimelineMax, CSSPlugin, ScrollToPlugin, Draggable } from "gsap/all"; IMPORTANT: if your animations aren't working as expected, it's likely an issue with tree shaking which can be easily resolved by referencing any plugins you're using. Read more. UMD/CommonJS If your environment doesn't accommodate ES modules yet, don't worry - we've got you covered. There's a "umd" directory that contains...you guessed it...regular old ES5 UMD (Universal Module Definition) versions of the files which are compatible with pretty much everything (RequireJS, Browserify, etc.). So you could import them like: //get the UMD versions. Notice the "/umd/" in the path... import { TweenMax, Power2, TimelineLite } from "gsap/umd/TweenMax"; import ScrollToPlugin from "gsap/umd/ScrollToPlugin"; import Draggable from "gsap/umd/Draggable"; What about bonus plugins like MorphSVGPlugin? Obviously we can't distribute the members-only bonus plugins via NPM, so all you need to do is log into your GreenSock account and download the latest zip which has a "bonus-files-for-npm-users" folder with the bonus plugins. Then just plop that into your project, like maybe in your /src/ folder (or wherever) and import them directly. For example, to save some typing you could rename the "bonus-files-for-npm-users" to simply "gsap-bonus" and put that in the root of your project and then: import MorphSVGPlugin from "./gsap-bonus/MorphSVGPlugin"; import SplitText from "./gsap-bonus/SplitText"; You could certainly put the bonus files in /node_modules/gsap/ if you prefer, but most people don't like doing that because it makes things less portable/updatable. There's a brand new page in the docs dedicated to NPM usage. NEW: Custom rounding increments in RoundPropsPlugin Have you ever needed to round animated values to the nearest 10 or hundredth? With the new object syntax in RoundPropsPlugin, you can round properties to various custom increments, not just integers! Simply pass in [property]:[increment] pairs like so: TweenLite.to(element, 5, { x:600, y:100 roundProps:{ x:10, //round x to nearest increment of 10 y:0.1 //round y to nearest increment of 0.1 } }); Watch the video Demo See the Pen RoundPropsPlugin Update by GreenSock (@GreenSock) on CodePen. NEW: SplitText "specialChars" SplitText recognizes a new specialChars property that allows you to specify an array of special characters to protect. This is typically used for multi-character symbols like in some languages where there are pairs (or sometimes even 4 characters) combined to form a single character. See the Pen SplitText with specialChars feature by GreenSock (@GreenSock) on CodePen. No need to do this for most emoji's, though, because those are already supported natively in SplitText! Got questions? If you haven't checked out the forums, you're missing out! It's a great place to get your questions answered and participate in the community. We carefully monitor and answer questions there. Or feel free to contact us directly if you prefer. Changelog View the full changelog here (note: version 2.0.0 is just 1.20.5 with a version bump to avoid breaking changes for NPM users) Happy tweening! DOWNLOAD GSAP NOW
  5. Feature lists are nice, but they can get lengthy and they don't always tell the story in a way that's relevant to you as the developer or designer in the trenches, trying to get real work done for real clients. You hear plenty about theoretical benefits of CSS animations or some whiz-bang library that claims to solve various challenges, but then you discover things fall apart in all but the most modern browsers or the API is exceedingly cumbersome or there frustrating "gotchas". You need things to just work. .project-post p { font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif; } .project-post h2 { padding-top: 16px; margin-bottom: 10px; } .expPoint, .project-post .expList li { font-size: 1.1em; list-style: none; line-height: normal; margin: 0px 0px 0px 8px; padding: 6px 4px 4px 20px; position:relative; border: 1px solid rgba(204,204,204,0); } .expPoint, .expContent { font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif; } .expPoint:hover, .project-post .expList li:hover { background-color:white; border: 1px solid rgb(216,216,216); } .expContent { height: 0px; overflow: hidden; color: #656565; font-size: 0.9em; line-height: 150%; font-weight: normal; margin: 5px 0px 0px 0px; padding-top: 0px; } .toggle { width:6px; height:8px; position:absolute; background-image:url(/_img/toggle_arrow.gif); background-repeat: no-repeat; left: 9px; top: 12px; } .expMore { color: #71b200; text-decoration: underline; font-size:0.8em; } #featureAnimation, #featureBox { background-color:#000; border: 1px solid #333; height: 220px; overflow:hidden; line-height: normal; font-size: 80%; } #featureAnimation { position:relative; visibility:hidden; } #featureBox { position:absolute; } #featureAnimation, #featureBox, #whyGSAP, .featureTextGreen, .featureTextWhite { width: 838px; } #whyGSAP, .featureTextGreen, .featureTextWhite { text-align: center; } #whyGSAP, .featureTextGreen, .featureTextWhite { font-size:50px; position:absolute; font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif; top:0; } .featureTextGreen { color:#91e600; font-weight: bold; } .featureTextWhite { color:white; font-weight:normal; } .star { position: absolute; width: 16px; height: 16px; display: none; } #browserIcons { top:64px; left: 100px; width: 92px; height: 92px; position: absolute; text-align:left; } #browserIcons img { position:absolute; } .featureTextMinor { color:#CCCCCC; font-weight:normal; font-size:20px; position:absolute; font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif; visibility:hidden; } .dot { position:absolute; background-color: #91e600; } #ctrl_slider { position:absolute; width: 725px; height:10px; left:18px; top:196px; background: rgba(80,80,80,0.3); border:1px solid rgba(102,102,102,0.5); visibility:hidden; } Why GSAP? Performance Compatibility Other tools fall down in older browsers, but GSAP is remarkably compatible. Scale, rotate & move independently (impossible with CSS animations/transitions) XNJYHQLJYQEW CSS, canvas libraries, colors, beziers, etc. Total control pause(), play(), reverse(), or timeScale() any tween or sequence. GSAP The new standard for HTML5 animation replay
×