Search the Community
Showing results for tags 'release'.
-
Highlights: Clamp your triggers! - Ever had ScrollTriggered animations at the very top of your page start out partially-scrubbed? Now you can clamp() them! This handy feature ensures that the start and end positions stay within the bounds of the page and ensures that all your "above the fold" elements start off in their native positions. Clamp data-speed - More clamping! This time for ScrollSmoother, you can now wrap your data-speed value in clamp() to make the associated element start out in its natural position if it's within the viewport at the top of the page. ScrollSmoother speed - Hold onto your hats (or scroll wheels?) We've added a speed option to ScrollSmoother which you can use to make the page scroll faster or slower. 🥳 Clamp Your Triggers It can be frustrating when your "above the fold" scrubbed animations start off part-way through. With clamp() you can ensure that they always start out in their native positions, no matter where your triggers are placed. ScrollTrigger.create({ trigger: elem, start: "clamp(top bottom)", // clamped value - will always fall between 0 and the max scroll end: "bottom top" // the parsed pixel value could be negative or more than the max scroll, }) So what's going on under the hood? All scroll triggered animations have trigger points that determine where the animation starts and ends. These values are nice and flexible, you can write them out as a number, as string shorthand or return one of those options from a function. start: "bottom 50%+=100px" // flexible string shorthand start: 200, // pixel value start: () => window.innerHeight / 2 // function that returns a number or string However you write it out, ScrollTrigger converts these values into a numeric scroll positions. If you set up your start marker above the fold, the start position will be negative and the animation will start off partway through. Sometimes this is desired behaviour but it can also be a bit awkward and unexpected. The new clamp feature allows us to prevent these trigger 'leaks'. We can tell ScrollTrigger to always keep the trigger value between 0 (the top of the page) and the maximum scroll position. Check out this demo and pop open the console to see the differing values. 👀 See the Pen Clamp your triggers! by GreenSock (@GreenSock) on CodePen. On load you can see that the un-clamped animation starts part-way through. If you scroll down to the bottom you'll notice that it also doesn't complete as the end marker is further down than the maximum possible scroll distance. If you want to know what's happening under the hood check out the docs on clamp. Wrapping the trigger in "clamp()" is just like telling ScrollTrigger to run the parsed trigger position through the following util - gsap.utils.clamp(0, maxScroll, triggerPosition) Clamp data-speed You can also use the new clamp feature over in ScrollSmoother-land. Now, when you apply data-speed to "above-the-fold" elements, they'll start exactly where you placed them in your design, unaffected by their speed value. No more unexpected offsets! Check it out... See the Pen ScrollSmoother Parallax Offsets with clamp by GreenSock (@GreenSock) on CodePen. Still a bit confused about when and why this is useful? We've got you - Cassie breaks it down in this new feature video New speed option for ScrollSmoother 🚀 ScrollSmoother.create({ smooth: 2, effects: true, speed: 1.5, // 1.5x the normal speed }); Now you have the power to control your scroll speed with a simple multiplier. Want things to move faster? Set it to 2 and watch your content zoom past twice as fast! Prefer a leisurely pace? Set it to 0.5 for a leisurely scroll at half the speed. See the Pen ScrollSmoother by GreenSock (@GreenSock) on CodePen. GSAP 3.12 delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums Happy tweening! ✨
- 1 comment
-
- 1
-
-
- scrollsmoother
- scrolltrigger
-
(and 1 more)
Tagged with:
-
Highlights: gsap.matchMedia() is a game-changer for responsive, accessible-friendly animations. 💚 gsap.context() that greatly simplifies setup and reverting of a bunch of animations/ScrollTriggers, especially for React developers! You can now revert() any animation to return the targets to their original state. Set lockAxis: true on an Observer to make it lock into whichever direction the user first drags 🥳 Responsive, accessibility-friendly animations with gsap.matchMedia() One of the hardest challenges for web-animators is crafting animations that work seamlessly on all screen sizes and respect users motion preferences. Well, not anymore! gsap.matchMedia() lets you easily tuck setup code into a function that only executes when a particular media query matches and then when it no longer matches, all the GSAP animations and ScrollTriggers created during that function's execution get reverted automatically! Customizing for mobile/desktop or prefers-reduced-motion is remarkably simple and incredibly flexible. Basic syntax // create let mm = gsap.matchMedia(); // add a media query. When it matches, the associated function will run mm.add("(min-width: 800px)", () => { // this setup code only runs when viewport is at least 800px wide gsap.to(...); gsap.from(...); ScrollTrigger.create({...}); return () => { // optional // custom cleanup code here (runs when it STOPS matching) }; }); // later, if we need to revert all the animations/ScrollTriggers... mm.revert(); Conditions syntax - 💪 POWERFUL 💪 What if your setup code for various media queries is mostly identical but a few key values are different? If you add() each media query individually, you may end up with a lot of redundant code. Just use the conditions syntax! Instead of a string for the first parameter, use an object with arbitrarily-named conditions and then the function will get called when any of those conditions match and you can check each condition as a boolean (matching or not). The conditions object could look like this: { isDesktop: "(min-width: 800px)", isMobile: "(max-width: 799px)", reduceMotion: "(prefers-reduced-motion: reduce)" } Name your conditions whatever you want. Below we'll set the breakpoint at 800px wide and honor the user's prefers-reduced-motion preference, leveraging the same setup code and using conditional logic where necessary: let mm = gsap.matchMedia(), breakPoint = 800; mm.add({ // set up any number of arbitrarily-named conditions. The function below will be called when ANY of them match. isDesktop: `(min-width: ${breakPoint}px)`, isMobile: `(max-width: ${breakPoint - 1}px)`, reduceMotion: "(prefers-reduced-motion: reduce)" }, (context) => { // context.conditions has a boolean property for each condition defined above indicating if it's matched or not. let { isDesktop, isMobile, reduceMotion } = context.conditions; gsap.to(".box", { rotation: isDesktop ? 360 : 180, // spin further if desktop duration: reduceMotion ? 0 : 2 // skip to the end if prefers-reduced-motion }); return () => { // optionally return a cleanup function that will be called when none of the conditions match anymore (after having matched) } }); Nice and concise! 🎉 See the Pen gsap.matchMedia() by GreenSock (@GreenSock) on CodePen. You can set a scope so that all selector text inside the function maps only to descendants of a particular element or React Ref or Angular ElementRef. This can greatly simplify your code. See the full documentation for all the details. gsap.context()
- 4 comments
-
- 6
-
-
- gsap
- responsive
-
(and 4 more)
Tagged with:
-
Highlights: ScrollSmoother plugin for delicious, buttery-smooth scrolling that leverages native scroll. 💚 Observer plugin that greatly simplifies setup for reacting to various events across devices. gsap.quickTo() for frequent redirection to new values like mouse followers ScrollTrigger.normalizeScroll() solves a bunch of scroll-related annoyances across devices and browsers. "*=" and "/=" relative prefixes - multiply or divide the current value. Introducing ScrollSmoother.🥳 A shiny new plugin, exclusively for Club GreenSock members! ScrollSmoother makes it simple to add a buttery smooth vertical scrolling effect to your ScrollTrigger pages. Under the hood, ScrollSmoother leverages native scrolling which allows it to sidestep many of the accessibility annoyances that plague smooth-scrolling sites. No fake scrollbars, and no messing with pointer or touch functionality. See the Pen ScrollSmoother by GreenSock (@GreenSock) on CodePen. ScrollSmoother.create({ content: "#smooth-content", wrapper: "#smooth-wrapper", smooth: 1, // how long (in seconds) it takes to "catch up" to the native scroll position effects: true, // looks for data-speed and data-lag attributes on elements normalizeScroll: true, // prevents address bar from showing/hiding on most devices, solves various other browser inconsistencies ignoreMobileResize: true // skips ScrollTrigger.refresh() on mobile resizes from address bar showing/hiding }); Effects... ScrollSmoother will integrate seamlessly with all your scroll-triggered animations. but we've also added some bonus ScrollSmoother effects. ✨ speed - Great for parallax effects! It adjusts the speed at which an element moves vertically while scrolling through the viewport. A speed of 1 is normal speed, 2 is double speed, etc. lag - Add some lag* to gently flow elements behind the scroll before they ease back to their natural scroll position. * no seriously, trust us. It's the good kind of lag. <div data-speed="0.5"></div> <!-- half-speed of scroll --> <div data-speed="2"></div> <!-- double-speed of scroll --> <div data-speed="1"></div> <!-- normal speed of scroll --> <div data-lag="0.5"></div> <!-- takes 0.5 seconds to "catch up" --> <div data-lag="0.8"></div> <!-- takes 0.8 seconds to "catch up" --> Read the docs for all the juicy details, or pull up a seat and watch this short explainer video. Observer The brand new 3.5kb Observer plugin offers a super-flexible, unified way to sense meaningful events across all (touch/mouse/pointer) devices without wrestling with all the implementation details. Perhaps you want to respond to "scroll-like" user behavior which could be a mouse wheel spin, finger swipe on a touch device, a scrollbar drag, or a pointer press & drag...and of course you need directional data and velocity. No problem! Tell Observer which event types to watch (wheel, touch, pointer, and/or scroll) and it will collect delta values over the course of each requestAnimationFrame tick (debounced for performance by default) and automatically determine the biggest delta and then trigger the appropriate callback(s) like onUp, onDown, onDrag, etc. Look how easy it is to trigger next()/previous() functions based on when the user swipes up/down or uses their mouse wheel: Observer.create({ target: window, // can be any element (selector text is fine) type: "wheel,touch", // comma-delimited list of what to listen for ("wheel,touch,scroll,pointer") onUp: () => previous(), onDown: () => next(), }); Demo Notice there's no actual scrolling in the demo below but you can use your mouse wheel (or swipe on touch devices) to initiate movement so it "feels" like a scroll: Since ScrollTrigger leverages Observer internally for normalizeScroll(), we exposed it via ScrollTrigger.observe() so you don't have to load an extra file if you're already using ScrollTrigger. Excited? Why don't you observe this video or check out the docs (see what we did there?). gsap.quickTo() If you find yourself calling gsap.to() many times on the same numeric property of the same target, like in a "mousemove" event, you can boost performance by creating a quickTo() function instead. Think of a quickTo() like an optimized function tied to one particular numeric property, where it directly pipes a new number to it. Example let xTo = gsap.quickTo("#id", "x", {duration: 0.4, ease: "power3"}), yTo = gsap.quickTo("#id", "y", {duration: 0.4, ease: "power3"}); document.querySelector("#container").addEventListener("mousemove", e => { xTo(e.pageX); yTo(e.pageY); }); Mouse Follower Demo See the Pen gsap.quickTo() mouse follower by GreenSock ( @GreenSock) on CodePen. ScrollTrigger.normalizeScroll() and ignoreMobileResize Have you ever run into these problems?: Address bar on mobile browsers shows/hides and resizes the viewport, causing jumps When scrolling fast, a pinned element seems to shoot past for a brief moment and then jump to the correct pinned position (multi-thread synchronization issues) iOS jitter Overscroll behavior that seems impossible to prevent on iOS Inconsistent momentum scrolling across devices The powerful new normalizeScroll() functionality intercepts native browser scroll behavior and handles it on the JavaScript thread instead which solves the problems mentioned above on most devices (iOS Phones in portrait orientation still show/hide the address bar). To enable it, simply: ScrollTrigger.normalizeScroll(true); To prevent ScrollTrigger.refresh() from running (and recalculating start/end positions) when a mobile browser shows/hides its address bar, you can now do: ScrollTrigger.config({ ignoreMobileResize: true }); So easy! Read more in the docs. New "*=" and "/=" relative prefixes You've always been able to add or subtract from the current value, like: gsap.to(".box", { x: "+=100", // 100 more than the current value y: "-=100", // 100 less than the current value }); ...and now you can multiply or divide accordingly: gsap.to(".box", { x: "*=2", // double the current value y: "/=2", // halve the current value }); And more... GSAP 3.10 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums Happy tweening!
- 21 comments
-
- 10
-
-
-
-
- release
- scrolltrigger
-
(and 5 more)
Tagged with:
-
See the Pen box by GreenSock (@GreenSock) on CodePen. Highlights: Flip Plugin is no longer for members-only! - consider it an early Christmas present from us to you. 💚 CustomEase is now in the public downloads as well (and on the CDN)! 'Tis the season to be jolly. 🎁 Brand new Keyframe options that can drastically reduce the amount of code you must write. If you're used to CSS keyframes, you'll love this. Flip Plugin got a major overhaul and new features including batch() for complex scenarios. FLIP animations for everyone! 🥳 Flip plugin can give you some serious animation superpowers once you learn to think in terms of "FLIP" ("First", "Last", "Invert", "Play"). Here's a demo that explains the technique: See the Pen How GSAP's Flip Plugin Works by GreenSock ( @GreenSock) on CodePen. Sometimes you'll need to deal with state changes that you can't control, or reparenting of elements. Maybe a thumbnail image needs to transition to fill the viewport with position: fixed, or a grid of elements must get smoothly re-ordered within a flexbox container. This is where Flip Plugin shines! And now it's included in the public downloads and CDN! That's right, Flip Plugin isn't just for Club GreenSock members anymore (but seriously, if you haven't joined yet, what are you waiting for?). And for those who are members, don't worry - we've got something fun coming just for you in the future. Here's an example where a video that's in the flow of text seamlessly transitions into position: fixed in the corner when you scroll far enough: See the Pen Flip Video by GreenSock (@GreenSock) on CodePen. Even when the original position of elements could change - like in this spinning container, FLIP will handle the transition with ease. See the Pen Spinny flipz by GreenSock (@GreenSock) on CodePen. And here's a fan-favorite showing a grid of tiles you can filter by color and Flip smooths everything out: See the Pen Tiles by GreenSock (@GreenSock) on CodePen. Wanna learn about all the nitty-gritty details? Watch this video: New additions to the keyframe syntaxNew additions to the keyframe syntax Keyframes are a great way to animate a target through multiple steps while keeping your code nice and concise. You can think of them as a sub-timeline nested inside a tween Here's a reminder of the existing syntax. gsap.to(".elem", { keyframes: [ {x: 100, duration: 1}, {y: 200, duration: 1, delay: 0.5}, //create a 0.5 second gap {rotation: 360, duration: 2, delay: -0.25} //overlap by 0.25 seconds ] }); New options Percent-based keyframes This familiar syntax will make porting animations over from CSS a breeze! Instead of using delays and duration in the keyframes themselves, you specify the styles you want at certain waypoints during the animation, and just like CSS, if you omit a property from one of the keyframes the value will interpolate across that gap. gsap.to(".elem", { keyframes: { "0%": { x: 100, y: 100}, "75%": { x: 0 }, "100%": { x: 50, y: 50 } }, duration: 2, }) Array-of-values Just define an Array of values and they'll get equally distributed. So simple! And you don't need to make sure the Arrays are equal in length. Plenty of flexibility. gsap.to(".elem", { keyframes: { x: [100, 0, 50], y: [100, 0, 50] }, duration: 2 }) Demos With Object keyframes and Percentage keyframes you can drill down and add different eases into individual keyframes. See the Pen Bounce Party with GSAP keyframes, by GreenSock (@GreenSock) on CodePen. You can even combine multiple easing properties, keyframes and normal tween values. 🤯 gsap.to(".box", { keyframes: { y: [0, 80, -10, 30, 0], ease: "none", // <- ease across the entire set of keyframes (defaults to the one defined in the tween, or "none" if one isn't defined there) easeEach: "power2.inOut" // <- ease between each keyframe (defaults to "power1.inOut") }, rotate: 180, ease: "elastic", // <- the "normal" part of the tween. In this case, it affects "rotate" because it's outside the keyframes duration: 5, stagger: 0.2 }); See the Pen keyframe easing by GreenSock (@GreenSock) on CodePen. And more... GSAP 3.9 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums FLIP Plugin docs More information about keyframes Happy tweening!
-
GSAP 3.8 is here, and it's packed to the brim with ScrollTrigger improvements! Highlights: containerAnimation - vertical scrolling can animate a container horizontally; now you can set up ScrollTriggers on that horizontal movement. It's like having nested ScrollTriggers! preventOverlaps & fastScrollEnd - when you jump to a section, do you have lingering animations that overlap? These features can save the day. isInViewport() - a simple way to check if an element is in the viewport positionInViewport() - find out exactly where an element is in relation to the viewport Directional snapping - by default, snapping will now always go in the direction that the user last scrolled. Much more intuitive! There's even a .snapDirectional() utility method. containerAnimationcontainerAnimation We try to keep an eye on common challenges that the GSAP community faces. A popular effect is to create horizontally-moving sections that are tied to vertical scrolling. That's simple enough with the animated horizontal "scroll" technique where a pinned container is animated along the x-axis to emulate horizontal scrolling. However, since the effect is an animation as opposed to native scroll, it's very tricky to trigger animations within this horizontally "scrolling" container. Enter containerAnimation. 🥳 With containerAnimation, you can actually create ScrollTriggers on that fake-scrolling container to detect when an element is 'scrolled' into view horizontally and then trigger an animation. Think of it like a ScrollTrigger inside a ScrollTrigger. 🤯 First, we create a linear tween to handle the horizontal 'scroll' Then we can pass that animation (as the containerAnimation) to the ScrollTriggers of tweens or timelines // keep a reference of the horizontal 'fake scrolling' animation so we can pass it around let scrollTween = gsap.to(".container", { xPercent: -100 * (sections.length - 1), ease: "none", // <-- IMPORTANT! scrollTrigger: { trigger: ".container", start: "top top", end: "+=3000", pin: true, scrub: 0.5 } }); // now let's create an animation that triggers based on the horizontal fake-scroll: gsap.to(".box", { y: -100, scrollTrigger: { trigger: ".box", start: "left center", containerAnimation: scrollTween, // <-- NEW!! } }); Check out this demo to see it in action! See the Pen Horizontal "containerAnimation" - ScrollTrigger by GreenSock (@GreenSock) on CodePen. preventOverlaps and fastScrollEndpreventOverlapsAndFastScrollEnd Special thanks to Creative Coding Club for providing this video. We highly recommend their courses at CreativeCodingClub.com. Take your animation skills to the next level. Scroll-triggered animations pose unique challenges. Unlike animations that play on load, you're putting control in the users' hands. They decide how fast to scroll, which direction to scroll – and by association – when the animations get triggered. With this in mind, we added two new features to ScrollTrigger to help avoid overlaps between successive non-scrubbed animations: preventOverlaps kicks in as a ScrollTrigger is about to trigger an animation; it finds preceding scrollTrigger-based animations and forces those previous animations to their end state – avoiding unsightly overlaps. fastScrollEnd will force the current ScrollTrigger's animation to completion if you leave its trigger area above a certain velocity (default 2500px/s). This property can help to avoid overlapping animations when the user scrolls quickly. We're especially excited about the UX benefits this brings. When users are in a hurry to access information, slow animation can be a frustrating hindrance to their goal. With fastScrollEnd, we can avoid wearing down the patience of task-focused users by quickly forcing animations to their end state when scrolling quickly. scrollTrigger: { trigger: ".container", fastScrollEnd: true // (default 2500px/s) // or fastScrollEnd: 3000 // (custom 3000px/s velocity) preventOverlaps: true // prevent overlaps in preceding scrollTrigger animations // or preventOverlaps: "group1" // prevent overlaps in specific group of scrollTrigger animations } You can take a look at how these new properties work, independently and in unison, by scrolling down in this demo at different speeds and toggling the options: See the Pen preventOverlaps and fastScrollEnd | ScrollTrigger | GSAP by GreenSock (@GreenSock) on CodePen. In addition to these new features we've added some handy methods to help you detect when an element is in view, and where. isInViewport()isInViewport ScrollTrigger.isInViewport() lets you find out if a particular element is in the viewport. if (ScrollTrigger.isInViewport("#selector")) { // in the viewport vertically } You can also find out if a certain proportion is in view. The following will return true if at least 20% of the element is in the viewport: if (ScrollTrigger.isInViewport(element, 0.2)) { // at least 20% of the element is in the viewport vertically } To check horizontally instead of vertically, just use the 3rd parameter (boolean): if (ScrollTrigger.isInViewport(element, 0.2, true)) { // at least 20% of the element is in the viewport horizontally } positionInViewport()positionInViewport The ScrollTrigger.positionInViewPort() method lets you get a normalized value representing an element's position in relation to the viewport where 0 is at the top of the viewport, 0.5 is in the center, and 1 is at the bottom. So, for example, if the center of the element is 80% down from the top of the viewport, the following code would return 0.8: ScrollTrigger.positionInViewport(element, "center"); For the reference point (2nd parameter), you can use keywords like "center" (the default), "top", or "bottom". Or you can use a number of pixels from the element's top, so 20 would make the reference point 20 pixels down from the top of the element. Demo See the Pen isInViewport() and positionInViewport() by GreenSock (@GreenSock) on CodePen. Directional snapping By default, snapping will now always go in the direction that the user last scrolled. Much more intuitive! Previously, it would snap to the closest value regardless of direction which could lead to annoying snap-back behavior. There's even a ScrollTrigger.snapDirectional() utility method that lets you do your own directional snapping for any numeric values. It returns a snapping function that you can feed a value to snap, and a direction where 1 is forward (greater than) and -1 is backward (less than). For example: // returns a function that snaps to the closest increment of 5 let snap = ScrollTrigger.snapDirectional(5); snap(11); // 10 (closest, not directional) snap(11, 1); // 15 (closest greater than) snap(11, -1); // 10 (closest less than) You can even use an Array of values! let values = [0, 5, 20, 100]; // returns a function that'll snap to the closest value in the Array let snap = ScrollTrigger.snapDirectional(values); snap(8); // 5 (closest, non-directional) snap(8, 1); // 20 (closest greater than) snap(99, -1); // 20 (closest less than) And more... Make sure to check out the ScrollTrigger docs for more information. GSAP 3.8 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums ScrollTrigger docs Happy tweening!
- 1 comment
-
- release notes
- fastscrollend
- (and 6 more)
-
GSAP 3.7 is here! Here are some of our favorite bits... Percentage based position parameter options for timelines Better support for SVG elements with Flip plugin. Easily scope animations to your components! New scoped selector - gsap.utils.selector() Optional scope parameter added to gsap.utils.toArray() Percentage based position parameter. The position parameter is small but mighty. It's the key to building sequenced animations with precise control over timings, and now it's even more powerful! This update gives us the ability to position animations using percentage values - either relative to the previous tween or animation, or relative to the duration of the animation being inserted. The percent is based on the totalDuration(), so repeats, yoyos and staggers will be factored in. This is such an exciting one because it allows us to tweak durations without affecting positioning! Say we wanted to overlap a tween by half of it's own duration. Until now we would do a little mental math, divide the duration in half and add it to the position parameter as a relative position. tl.to(..., {duration: 2}, "-=1"); But if we were to change the duration, we would also have to update the position parameter Now, with the addition of percentages, we can do this instead: // overlap by half of the inserted tweens duration, -1s: tl.to(..., {duration: 2}, "-=50%"); Alternately, we can position a tween or timeline in relation to the most recently-added animation. tl.to(".other", {x: 100, duration: 2}); // insert 25% of the way through the most recently added animation. // In this case - 0.5s into the 2s duration. tl.to(".class", {x: 100}, "<25%"); Or at a percentage from the end of the most recently-added animation, like ">-25%". >-25% is equivalent to <75% tl.to(".other", {x: 100, duration: 2}); // insert 25% of the way from the end of the most recently added animation. // In this case - 0.5s from the end of the 2s duration. tl.to(".class", {x: 100}, ">-25%"); As '+=' and '-=' are always based on the inserting animations total duration, we can even use a pointer to reference the starting point of the previous tween, whilst using the inserting tweens duration as the percentage offset. tl.to(".other", {x: 100, duration: 2}); // insert 50% of the inserting tweens duration from the beginning of the most recently added animation. // In this case - 0.5s from the start of the previous tween. tl.to(".class", {x: 100, duration: 1},"<+=50%"); Powerful stuff! If you want to dig in a bit more, here's a video explainer and some demos to play around with. You'll be a positioning pro in no time! Check it out in action in these demos. Interactive Position Parameter Demo Better support for SVG elements with Flip plugin. Flip plugin has been extended with better support for SVG elements. SVG already has a great coordinate system to work within - but we think this could assist transitions in live data-vis or when animating between states in generative SVG. We'd love to see what you do with this so don't forget to share your demos with us! In the meantime, here's a simple example Easily scope your animations Modern front end dev is all about encapsulated components, but scoping animations to each individual component can be tricky. React devs, for example, often find themselves in "ref Hell" creating a ref for each and every element they want to animate. Wouldn't it be nice to just use classes and selector text that's limited to your component instance? gsap.utils.selector() With gsap.utils.selector() you can grab descendant elements from the selected element. It's similar to jQuery.find() This is great for components because you can create a scoped selector for that component's main container element and then use that to select descendants. It's similar to calling .querySelectorAll() on that element – rather than on the document – except with a few added benefits: It returns an Array rather than a NodeList, so you get access to convenient array methods like .filter() and .map(). You can pass a React ref or Angular ElementRef to gsap.utils.selector(). Then when you use the resulting function, it will automatically check for the .current/.nativeElement in case it was re-rendered since creation. // Vanilla let q = gsap.utils.selector(myElement); // or use selector text like ".class" let boxes = q(".box"); // finds only elements with the class "box" that are INSIDE myElement // or plug directly into animations gsap.to(q(".circle"), {x: 100}); // React let el = useRef(); let q = gsap.utils.selector(el); useEffect(() => { // uses el.current.querySelectorAll() internally gsap.to(q(".box"), {x: 100}); }, []); // Angular @Component({ ... }) class MyComponent implements OnInit { constructor(public el: ElementRef) { this.q = gsap.utils.selector(el); } ngOnInit() { // uses this.el.nativeElement.querySelectorAll() internally gsap.to(this.q(".box"), { x: 100 }); } } A common pattern in React is to declare a ref for every element you want to animate, but that can make your code very verbose and hard to read. By using a scoped selector, we only need to use a single ref. Then we can simply select the descendants. gsap.utils.toArray() We've also added an optional, second scope parameter to gsap.utils.toArray() This will find all the descendant elements of myElement with the class of "box": gsap.utils.toArray(".box", myElement) And more... GSAP 3.7 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Position parameter article Full documentation Getting started with GSAP Learning resources Community forums Happy tweening!
-
Introducing Flip Plugin Flip Plugin lets you seamlessly transition between two states even if there are sweeping changes to the structure of the DOM like re-parenting of elements which would normally cause them to jump to a new position/size. UI transitions that would normally be a nightmare just got remarkably simple to code. Watch the visual walk through video and you'll see why this is not your typical FLIP library. It's called "Flip" because it uses the FLIP (First, Last, Invert, Play) animation technique (coined by Paul Lewis). Resources Full documentation Showcase How-to demos DrawSVG Values Beyond 0-100% DrawSVG now allows you to animate to values beyond the 0-100% range. That means that creating looping/wrapping effects with DrawSVG is even easier! Check out this collection of demos by Craig, a GreenSock moderator and the creator of MotionTricks.com. See the Pen Infinity Symbol Looping by Craig Roblewsky (@PointC) on CodePen. See the Pen Multicolor/target Looping (New DrawSVG) by Craig Roblewsky (@PointC) on CodePen. DrawSVG is one of many Club GreenSock plugins (not in the public downloads or repos). ScrollTrigger snap: "labelsDirectional" When you've got a timeline hooked up to a ScrollTrigger, you've always been able to set snap: "labels" to have it dynamically snap to the closest label, but the new snap: "labelsDirectional" option will take into consideration the direction of scrolling and force it to go to the next label in that direction. So, for example, users aren't forced to drag past the halfway point of sections to have it snap to the next one. It may sound like a small thing, but it can make things feel so much more delightfully intuitive. In the demo below, try changing snap: "labels" for a comparison - notice it'll only snap once you go past halfway? But "labelsDirectional" snaps based on the direction of playhead movement. See the Pen "labelsDirectional" Demo by GreenSock (@GreenSock) on CodePen. Other Improvements and Bug Fixes GSAP 3.6 also has a slew of other improvements and bug fixes so make sure to grab the latest files today!
- 1 comment
-
- 4
-
-
- release notes
- release
-
(and 5 more)
Tagged with:
-
Hi , I am trying to achieve similar effect as the below post in Gatsby, I am new to Gsap much appreciate any support. https://codesandbox.io/s/gatsby-tests-xyij4?fontsize=14&hidenavigation=1&theme=dark
-
GSAP 3.4 has arrived with some significant improvements to ScrollTrigger like: Accommodating different setups for various screen sizes, like a mobile version and desktop version - ScrollTrigger.matchMedia() Batching and staggering elements that enter the viewport, similar to what's often done with IntersectionObserver - ScrollTrigger.batch() Integrating with smooth scrolling libraries - ScrollTrigger.scrollerProxy() ScrollTrigger.matchMedia() You can use standard media queries to seamlessly transition between different ScrollTriggers. It's surprisingly simple to set up and let ScrollTrigger automatically handle all of the creating, undoing, and destroying for you. Basic setup ScrollTrigger.matchMedia({ // desktop "(min-width: 800px)": function() { // setup animations and ScrollTriggers for screens 800px wide or greater (desktop) here... // These ScrollTriggers will be reverted/killed when the media query doesn't match anymore. }, // mobile "(max-width: 799px)": function() { // The ScrollTriggers created inside these functions are segregated and get // reverted/killed when the media query doesn't match anymore. }, // all "all": function() { // ScrollTriggers created here aren't associated with a particular media query, // so they persist. } }); See the Pen ScrollTrigger.matchMedia() Demo by GreenSock (@GreenSock) on CodePen. There's a new ScrollTrigger.saveStyles() method that can be useful with matchMedia(). It saves the current inline styles for any element(s) so that they're reverted properly if animations added other inline styles. It's explained in the video above. See the ScrollTrigger.matchMedia() docs for details. ScrollTrigger.batch() Normally, each ScrollTrigger fires its callbacks (onEnter, onLeave, etc.) immediately when they occur but what if you want to coordinate an animation (like with staggers) of ALL the elements that fired a similar callback around the same time? ScrollTrigger.batch() creates a coordinated group of ScrollTriggers (one for each target element) that batch their callbacks within a certain interval, delivering a neat Array so that you can easily do something like create a staggered animation of all the elements that enter the viewport around the same time. It's a great alternative to IntersectionObserver because it's more widely compatible and easier to work with. Plus you're not restricted to only entering or exiting the viewport - batch() can use ANY start and end values! Demo See the Pen ScrollTrigger.batch() Demo by GreenSock (@GreenSock) on CodePen. See the ScrollTrigger.batch() docs for details. ScrollTrigger.scrollerProxy() ScrollTrigger purposefully avoids "scrolljacking" (disabling the browser's native scrolling behavior in favor of a custom, non-standard scrolling solution). However, smooth scrolling was by far the most requested feature to pair with ScrollTrigger. There are plenty of smooth-scrolling libraries out there, so we created the .scrollerProxy() method to make it simple to integrate any of them with ScrollTrigger (or create your own effects). Here's a basic example using Locomotive Scroll but check out the .scrollerProxy() docs for examples with other libraries. See the Pen ScrollTrigger with LocomotiveScroll by GreenSock (@GreenSock) on CodePen. And more... GSAP 3.4 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums ScrollTrigger Express video course from Snorkl.tv Happy tweening!
-
GSAP 3.2 has some groundbreaking features for converting coordinates and aligning elements. Check out the video explanation below. Warning: it's a bit advanced, but hopefully you'll see how crazy-useful these capabilities can be. New: "alignOrigin" for motion paths MotionPathPlugin recognizes a new alignOrigin property that pins a certain spot on the target to the path. For example, alignOrigin: [0.5, 0.5] pins the center of the target on the path and sets the transformOrigin accordingly so that rotations are around that point as well. To get a similar effect before 3.2, you'd need to set the transformOrigin separately as well as a -50 xPercent/yPercent. Use the Array syntax to define progress values along the x and y axis, so [1, 0.5] would be the right side, centered vertically. Or use a point object like {x: 20, y: 50} to specify a coordinate (measured from the top left corner in pixels at its native size). Sample code // Move the element along a path, rotating it along with the line gsap.to("#spaceship", { duration: 5, motionPath: { path: "#path", autoRotate: true, align: "#path", alignOrigin: [0.5, 0.5] // aligns the center of the target on the path } }); See the Pen MotionPath aligning with path demo by GreenSock (@GreenSock) on CodePen. See the MotionPathPlugin docs for details. New: getRelativeDistance() that transcends coordinate spaces Have you ever wanted to move one element to another element even if they're in different containers... which may have various transforms, warping the coordinate systems and making it super difficult to calculate? If so, you will love this magical function which is explained in the video at the top of this page. See the Pen GSAP 3 convertCoordinates() by GreenSock (@GreenSock) on CodePen. See the getRelativePosition() docs for details. New: convert coordinates between elements/contexts GSAP can now take a local coordinate from inside one element and calculate exactly where that coordinate lines up inside of ANOTHER element's local coordinate space! So you could take a "click" pointer event from the window and map that to an element's local coordinate system even if it's deeply nested inside various containers that have transforms applied! Or, as you can see in the demo below, convert between coordinate spaces to make the blue arm stay connected with the rotating red arm: See the Pen GSAP 3 convertCoordinates() by GreenSock (@GreenSock) on CodePen. See the convertCoordinates() docs for details. And more... GSAP 3.2 also delivers various bug fixes, so install the latest version today (3.2.6). There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, etc.) Resources Full release notes on each release is on Github Full documentation In case you missed it: GSAP 3.1 highlights (previous release) Getting started with GSAP Learning resources Community forums Happy tweening!
- 1 comment
-
- 3.2
- getrelativeposition
-
(and 5 more)
Tagged with:
-
GSAP 3 is the most significant upgrade we have ever had. With 50+ new features, there's a lot to be excited about. Here are a few of the highlights: Check out the full demo collection for more. A special shout-out to @dsenneff who created the animation at the top of this page! Jump right in - here's a starter codepen: See the Pen Try GSAP 3 on CodePen by GreenSock (@GreenSock) on CodePen. More ways to play: GSAP 3 Starter Pen - Fork the CodePen and away you go. Download the files to use locally. Using a build tool? npm install gsap will get you the files. If you're a Club GreenSock user, there's a gsap-bonus.tgz tarball file in download that you can simply drop into your project's folder and then npm install ./gsap-bonus.tgz and BOOM, it'll be installed just like any other package! See the installation docs for more information. The GSAP 3 docs Tell us what you think! Feel free to post in the our forums about what you like and any questions that you have. Or you can contact us directly if a public forum isn't your style. Are you interested in having a GreenSock representative teach your team about the new version or speak at your next conference? Contact us and we'll do our best to make it happen! Happy tweening!
-
GSAP 3.1 has landed with some exciting new features and various bug fixes. We highly recommend updating at your earliest convenience. Here are a few highlights: Random staggers GSAP’s staggers get even more powerful. Use the new from: “random” option to randomize how the staggers get applied. See the Pen GSAP from: "random" stagger by GreenSock (@GreenSock) on CodePen. Learn more about the advanced staggering options available in GSAP 3 below. See the Pen GSAP 3.0 Stagger demo by GreenSock (@GreenSock) on CodePen. shuffle() any Array The new shuffle() utility method randomly shuffles the contents of any Array (in place). var array = [1, 2, 3, 4, 5]; gsap.utils.shuffle(array); // returns the same array, but shuffled like [2, 5, 3, 1, 4] Timelines can now repeatRefresh Now timelines support repeatRefresh which makes all child tweens invalidate() and get refreshed when the timeline repeats, meaning their start and end values get re-calculated. It’s most useful for relative, random, or function-based values. For example, if a tween has a value like x: “random(-100, 100)”, each time the timeline repeats x would go to a new random value. See the Pen GSAP repeatRefresh on Timelines by GreenSock (@GreenSock) on CodePen. repeatRefresh skips yoyo’s It seemed a little odd to refresh the values when going in reverse, so now repeatRefresh won’t get triggered for the yoyo phase of the animation. See the Pen GSAP repeatRefresh with yoyo demo by GreenSock (@GreenSock) on CodePen. Smooth handling of complex borderRadius, borderWidth, margin, and padding values GSAP 3.1 accommodates not only simple values like borderRadius: “50%” but also more complex ones like borderRadius: “20px 50% 40px 15px” or borderRadius: “50% 20%” and it animates between them smoothly. The same goes for borderWidth, margin, and padding which can have complex values (top, right, bottom, and left). It will also return complex values correctly via gsap.getProperty(). Plus GSAP works around a Firefox bug that mis-reports certain values like borderRadius. Download today! There are many ways to get GSAP 3.1 - see the Installation page for all the options (download, NPM, zip, etc.) Resources GSAP 3.1.0 full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums Happy tweening!
-
- release
- getrelativeposition
-
(and 7 more)
Tagged with:
-
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. There are plenty of large and small updates in GSAP 2.1; here are a few highlights... Advanced staggers Advanced staggering makes it surprisingly simple to get rich, organic timing effects with very little code. Each tween's start time can be distributed according to any ease and/or based on how close each element is to a position in the list. For example, you can have things emanate outward from the "center" or a certain index. It'll even accommodate grids, complete with auto-calculated columns and rows (great for responsive layouts)! The interactive demo below explains it all visually (notice there's an embedded video explanation too): See the Pen Advanced Staggers in GSAP by GreenSock (@GreenSock) on CodePen. So setting up an advanced stagger is as simple as: TweenMax.staggerTo(".yourClass", 2, { scale:0.1, y:40, stagger:{ amount: 2, //total seconds to divide up among staggers from: "center", //or an index value. Determines where staggers originate grid:"auto", //or [columns, rows] ease: Power1.easeIn //determines spacing } }); Parts of the advanced staggering features were prompted by suggestions from GSAP users inspired by Julian Garnier's API in anime, so we tip our hat to his efforts. He's a great contributor to the animation community. MorphSVG type:"rotational" There's an entirely new type of morph that leverages rotational and length data to move anchors and control points which can deliver cleaner, more intuitive morphs. Plus it completely eliminates kinks that can occasionally creep in with linear interpolation. The video below explains. Watch the video To tap into this new style of morphing, just set the type:"rotational" TweenMax.to("#shape1", 2, { morphSVG:{ shape:"#shape2", type:"rotational" } }); Or set it as the default to affect all morphs: MorphSVGPlugin.defaultType = "rotational"; //default is "linear" Demo 1: preventing kinks See the Pen MorphSVG type:'rotational' for preventing kinks by GreenSock (@GreenSock) on CodePen. Demo 2: more natural morphs See the Pen MorphSVG type:'rotational' for more natural morphs by GreenSock (@GreenSock) on CodePen. Fixing odd results by declaring a custom origin The default origin is 50% 50% which usually works great, but sometimes the rotations around that point look odd, as shown below. In cases like this, it's best to experiment and set your own custom origin to improve things even more. We created a findMorphOrigin() utility function which is in the codepen below (and you can copy it into your own) which allows you to simply feed in a start and end shape and then it'll superimpose an origin that you can drag around and see exactly how it affects the morph! In the demo below, go into the JS panel and un-comment the findMorphIndex() line and you'll see exactly how this works. Drag the origin around and watch how it affects things. See the Pen MorphSVG: fixing origin weirdness by GreenSock (@GreenSock) on CodePen. Note: you must load Draggable for this to work. So to set a custom origin, it would look like: TweenMax.to("#shape1", 2, { morphSVG:{ shape:"#shape2", type:"rotational", origin:"20% 60%" //or to define a different origin for the start and end shapes, "20% 60%,45% 30%" } }); Is the new type:"rotational" a silver bullet for making every morph perfectly intuitive? No, but it's a great option that delivers more natural morphs in many cases. MorphSVG canvas rendering SVG is fantastic, but sometimes developers have a canvas-based project (often for rendering performance reasons). They haven't been able to leverage the intuitive morphing that MorphSVG provides in a highly-performant way...until now. The new MorphSVG plugin allows you to define a render function that'll be called every time the path updates, and it will receive two parameters: rawPath [array]: A RawPath is essentially an array containing an array for each contiguous segment with alternating x, y, x, y cubic bezier data. It's like an SVG <path> where there's one segment (array) for each "M" command; that segment (array) contains all of the cubic bezier coordinates in alternating x/y format (just like SVG path data) in raw numeric form which is nice because that way you don't have to parse a long string and convert things. For example, this SVG <path> has two separate segments because there are two "M" commands: <path d="M0,0 C10,20,15,30,5,18 M0,100 C50,120,80,110,100,100" /> So the resulting RawPath would be: [ [0, 0, 10, 20, 15, 30, 5, 18], [0, 100, 50, 120, 80, 110, 100, 100] ] For simplicity, the example above only has one cubic bezier in each segment, but there could be an unlimited quantity inside each segment. No matter what path commands are in the original <path> data string (cubic, quadratic, arc, lines, whatever), the resulting RawPath will ALWAYS be cubic beziers. target [object]: the target of the tween (usually a <path>) This means you can even render morphs to super high-performance engines like PixiJS or anything that'll allow you to draw cubic beziers! Demo: MorphSVG canvas rendering See the Pen MorphSVG canvas rendering by GreenSock (@GreenSock) on CodePen. Here's an example of a tween and a render function that'd draw the morphing shape to canvas: var canvas = document.querySelector("canvas"), ctx = canvas.getContext("2d"), vw = canvas.width = window.innerWidth, vh = canvas.height = window.innerHeight; ctx.fillStyle = "#ccc"; TweenMax.to("#hippo", 2, { morphSVG:{ shape:"#circle", render:draw } }); function draw(rawPath, target) { var l, segment, j, i; ctx.clearRect(0, 0, vw, vh); ctx.beginPath(); for (j = 0; j To set a default render method for all tweens: MorphSVGPlugin.defaultRender = yourFunction; 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. Changelog View the full changelog here (there's a lot). Happy tweening! DOWNLOAD GSAP NOW
-
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
-
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. Here are some of the highlights of the GSAP 1.20.0 release... yoyoEase Now you can specify an ease for the yoyo (backwards) portion of a repeating TweenMax animation. Set it to a specific ease like yoyoEase:Power2.easeOut or to flip the existing ease, use the shortcut yoyoEase:true. TweenMax is smart enough to automatically set yoyo:true if you define a yoyoEase, so there's less code for you to write. Score! Animate CSS Variables (custom properties) See the Pen CSS Variables Demo by GreenSock (@GreenSock) on CodePen. Emoji support in TextPlugin 'Nuf said. ...and more There are quite a few little improvements and bug fixes as well, which are listed in the changelog at the github repository. Download GSAP today. Happy tweening!
-
- yoyoease
- css variables
-
(and 6 more)
Tagged with:
-
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. GSAP version 1.19.0 introduces some exciting new features for advanced users as well as conveniences for everyone (even the "greenest" novices). The most noteworthy improvements are summarized below: Function-based values Instead of a number (x:100) or string (width:"300px") or relative value (y:"+=50"), you can now define most values as a function that'll get called once for each target the first time the tween renders, and whatever is returned by that function will be used as the value. This can be very useful for randomizing things or applying conditional logic. See it in action in the demos below. See the Pen BzmGba by GreenSock (@GreenSock) on CodePen. ...and more GSAP 1.19.0 is more ES6-friendly (for example, you can npm install gsap and then import {TweenLite, Elastic, TimelineMax} from "gsap" in your project). Plenty of bug fixes too. See the whole list in the github changelog. DOWNLOAD GSAP TODAY Happy tweening!