Search the Community
Showing results for tags 'release notes'.
-
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:
-
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. New DirectionalRotationPlugin Have you ever tweened rotation to a particular value but wished that you could control which direction it traveled (clockwise or counter-clockwise)? For example, if the current rotation is 170 and you tween to -170, normally that would travel counter-clockwise -340 degrees but what if you prefer rotating 20 degrees clockwise instead? Or maybe you just want it to go in the shortest direction to that new position (20 degrees in this case). This is all possible now with the DirectionalRotationPlugin. Previously, shortRotation was available in CSSPlugin, but there were three shortcomings (pardon the pun): It always went in the shortest direction - it wasn't possible to define a particular direction (clockwise or counter-clockwise). It required using a different property name ("shortRotation" or "shortRotationX" or "shortRotationY") instead of the regular property name ("rotation" or "rotationX" or "rotationY"). It only worked on DOM elements. What if you have a generic object or an EaselJS Shape (or whatever)? The new DirectionalRotationPlugin solves all of these issues. First of all, its functionality is baked into CSSPlugin, so you don't even need to load the DirectionalRotationPlugin if you're only animating DOM elements. The plugin is also included in TweenMax, so there's no need to load a separate plugin there either. Use the new syntax to get the desired behavior - add one of the following suffixes to the value: "_cw" for clockwise, "_ccw" for counter-clockwise, and "_short" to go whichever direction is shortest. Here are some examples: //tweens to the 270 position in a counter-clockwise direction (notice the value is in quotes) TweenMax.to(element, 1, {rotation:"270_ccw"}); //tweens to the -45 position in a clockwise direction TweenMax.to(element, 1, {rotation:"-45_cw"}); //tweens 1.5 radians more than the current rotationX value, and travels in the shortest direction TweenMax.to(element, 1, {rotationX:"+=1.5rad_short"}); If you're tweening a more generic object (anything that's not a DOM element), you can use the DirectionalRotationPlugin. If you pass in a simple value, it will assume you're attempting to tween the target's "rotation" property but you can tween ANY rotational properties of any name by passing in an object with the appropriate properties. Here are some examples: //start with a generic object with various rotation values var obj = {rotation:45, rotationX:0, rotationY:110}; //tweens rotation to 270 in a clockwise direction TweenLite.to(obj, 1, {directionalRotation:"270_cw"}); //tweens rotationX to -45 in a counter-clockwise direction and rotationY to 200 in a clockwise direction: TweenLite.to(obj, 1, {directionalRotation:{rotationX:"-45_ccw", rotationY:"200_cw"}}); As of 1.9.0, shortRotation is deprecated in favor of this new (more flexible and concise) syntax. New AttrPlugin This plugin allows you to tween any numeric attribute of a DOM element. For example, let's say your DOM element looks like this: <rect id="rect" fill="none" x="0" y="0" width="500" height="400"></rect> You could tween the "x", "y", "width", or "height" attributes using AttrPlugin like this: //tuck any attributes you want to tween into an attr:{} object TweenMax.to("#rect", 1, {attr:{x:100, y:50, width:100, height:100}, ease:Linear.easeNone}); You can tween an unlimited number of attributes simultaneously. Just use the associated property name inside the attr:{} object. The AttrPlugin is included inside the TweenMax JS file, so you don't need to load the plugin separately if you're using TweenMax. New TextPlugin This plugin allows you to tween the text content of a DOM element, replacing it one character at a time (or one word at a time if you set the delimiter to " " (a space) or you can even use a custom delimiter). So when the tween is finished, the DOM element's text has been completely replaced. This also means that if you rewind/restart the tween, the text will be reverted to what it was originally. Here is a simple example of replacing the text in yourElement: //replaces yourElement's text with "This is the new text" over the course of 2 seconds TweenMax.to(yourElement, 2, {text:"This is the new text", ease:Linear.easeNone}); If you'd like to use a different delimiter so that instead of replacing character-by-character, it gets replaced word-by-word, just pass an object with configuration properties like this: //replaces word-by-word because the delimiter is " " (a space) TweenMax.to(yourElement, 2, {text:{value:"This is the new text", delimiter:" "}, ease:Linear.easeNone}); Sometimes it's useful to have the new text differentiated visually from the old text, so TextPlugin allows you to assign a css class to the new and/or old content, like this: //wraps the old text in <span class="class1"></span> and the new text in a <span class="class2"></span> TweenLite.to(yourElement, 2, {text:{value:"This is the new text", newClass:"class2", oldClass:"class1"}, ease:Power2.easeIn}); As indicated, defining a newClass and/or oldClass will result in wrapping a <span> tag around the associated text. The TextPlugin is NOT included inside TweenMax, so you'll need to load it separately. Other updates and enhancements in 1.9.0: Added support for hsl() and hsla() colors in CSSPlugin and ColorPropsPlugin Implemented a new (more concise and clear) way to register plugins. Old plugins will still work fine, but most of the new ones in 1.9.0 use the new style of registering which won't work with old versions of TweenLite/TweenMax. Please just make sure all your files are updated. Fixed issue that caused className to be ignored by the autoCSS feature that creates the css:{} wrapper internally. Fixed issue that could cause em not to be translated to px accurately, causing a jump when the start and end units for the tween don't match (like px to em or visa-versa) Fixed backfaceVisibility so that it is properly prefixed when necessary Now setting "float" on a DOM element will work across browsers including Firefox and IE. Worked around issue that caused x/y/z transforms not to work properly if they exceeded 21,474 (or -21,474). Fixed issue that caused values not to be interpreted correctly if a negative number had a relative prefix, like "+=-50px" or "-=-50px" Fixed issue in EaselPlugin that prevented ColorMatrixFilter tweens from working correctly when the starting matrix wasn't an identity matrix Now fromTo() and staggerFromTo() methods have immediateRender set to true by default, just like from() and staggerFrom() always did. This seems like the preferred behavior for most developers, but you can certainly set immediateRender:false on any tween if you prefer that behavior. Now fromTo() and staggerFromTo() tweens that have immediateRender:false will record their pre-tween values (before even implementing the "from" part of the tween) so that if their parent timeline rewinds past the beginning of the tween, it restores values to their originals. Get it now Download the latest version of GSAP using the fancy new download screen, and notice that everything is also available as CDN links as well. The docs have been updated to reflect all these changes. Questions? Swing by the forums to get your questions answered.
- 8 comments
-
- textplugin
- release notes
- (and 10 more)