Jump to content
GreenSock

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

Search the Community

Showing results for tags 'gsap3'.



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
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


Twitter


CodePen


Company Website


Location


Interests

Found 63 results

  1. With over 100,000 posts in the popular GreenSock forums, we've noticed some common mistakes that you'd be wise to avoid. We threw in a few tips as well. Here is a summary of the mistakes: Creating from() logic issues Not setting ALL transforms with GSAP Not using xPercent and yPercent Recreating animations over and over Adding tweens to completed timelines Not using loops Using the old/verbose syntax Creating from() logic issues It's usually smart to use .to() and .from() tweens instead of .fromTo() because they're more dynamic - they pull either the starting or ending values from whatever they happen to CURRENTLY be at the time that tween renders for the first time. It’s one of the tips in the article on animating efficiently. But be careful because that dynamic nature can bite you in a few scenarios. First, keep in mind that .from() tweens go from the provided value to the current value. Take a look at this example: See the Pen Illustrating .from() effects - Part 1 by GreenSock (@GreenSock) on CodePen. Try clicking it one time and letting it play. It works, fading in the element. Now try clicking it multiple times right after each other. The box stops showing up because it uses the current opacity as the end point which, if the animation has not completed, is some value less than 1. The fix for this is simple: use a .fromTo(). Alternatively you could create the animation beforehand and use a control method (we'll talk more about this approach later in this article). See the Pen Illustrating .from() effects - Part 1 by GreenSock (@GreenSock) on CodePen. Second, keep in mind that by default immediateRender is true by default for .from() and .fromTo() tweens because that's typically the most intuitive behavior (if you're animating from a certain value, it should start there right away). But if you create a .from() tween after a .to() tween affecting the same properties of the same object, try to figure out what will happen: const tl = gsap.timeline() tl.to(".box", {x: 100}); tl.from(".box", {x: 100}); You might expect the box to animate x from 0 to 100 and then back to 0. Or maybe you'd expect it to animate from 0 to 100 and then stay at 100. Let’s see what happens: See the Pen Illustrating .from() effects - Part 1 by GreenSock (@GreenSock) on CodePen. The box animates x from 100 to 100 and then back to 0. Why is that? By default .to() tweens wait to render until their playhead actually moves (it's a waste of CPU cycles to render at a time of 0 because nothing will have changed). But since from() has immediateRender: true, x jumps to 100 immediately on the current tick! Then it runs the .to() tween on the next tick (since it’s first in the timeline) and records the current starting value which is 100! So it animates 100 to 100 over 0.5 seconds. Then it runs the .from() tween which has the cached value of 0 as the end value. If you have several timelines affecting the same element, situations like this can be a little tricky to catch. So just be mindful of how things work when using .to() and .from() tweens. They’re very powerful but with power comes responsibility. A simple solution here is to set immediateRender: true on the .to() tween, or immediateRender: false on the .from() tween. The third situation is similar but involves repeatRefresh and repeats. Let’s say you have a situation where you want a looped animation that fades in some text and fades it out. You could create a timeline, use a .from() to fade in the text, then use a .to() to fade it out: const tl = gsap.timeline({repeat:-1}); tl.set(".text", { color: "random([green, gray, orange, pink])" }, 2); tl.from(chars, { opacity: 0 }); tl.to(chars, { opacity: 0 }); This will work just fine! Here’s the same thing but staggered using SplitText to make it look a little nicer: See the Pen Fade in and out text by GreenSock (@GreenSock) on CodePen. But this only randomizes the colors at the start. What if we want new random values each repeat? That’s where repeatRefresh comes in. Let’s add repeatRefresh: true to see what happens: See the Pen Random on Reset (wrong way) by GreenSock (@GreenSock) on CodePen. The animation plays correctly the first time but after that the elements don’t fade in a second time! Why is that? repeatRefresh uses the end values of the animation as the starting values of the next iteration. In this case, the opacity of our text elements are all 0 at the end. So when the animation gets to the .from() the second time around, the opacity animates from a value of 0 to a value of 0 since the tween is relative. What we want to do instead is always animate from a value of 0 to a value of 1 so here the easiest fix is to use a .fromTo(): See the Pen Random on Reset by GreenSock (@GreenSock) on CodePen. Now it does what we want. There are other solutions like using a .set() before the .from() but most often it’s easiest to just use a .fromTo() in cases like this. Not setting ALL transforms with GSAP If you are going to animate an element with GSAP, even the initial transform values should be set with GSAP because it delivers better: Accuracy - The browser always reports computed values in pixels, thus it's impossible for GSAP to discern when you use another unit like % or vw in your CSS rule. Also, computed values are in matrix() or matrix3d() which are inherently ambiguous when it comes to rotation and scale. The matrix for 0, 360, and 720 degrees are identical. A scaleX of -1 results in the same matrix as something with rotation of 180 degrees and scaleY of -1. There are infinite combinations that are identical, but when you set transform-related values with GSAP, everything is saved in a perfectly accurate way. Performance - GSAP caches transform-related values to make things super fast. Parsing all of the components from a computed value is more expensive. If you are worried about a flash of unstyled content, you can handle that by using a technique that hides the element initially and then shows it via JavaScript as this post covers. Or you can set the initial styles with CSS rules and ALSO set them in GSAP. Not using xPercent and yPercent Did you know that you can combine percentage-based translation and other units? This is super useful if, for example, you'd like to align the center of an element with a particular offset, like {xPercent: -50, yPercent: -50, x: 100, y: 300}. We often see people use percent values in the x and y properties which is technically possible but can cause confusion at times. For example, if you set x and y to "-50%" and then later you set xPercent: -50, you'd see it move as if it's at xPercent: -100 because the x and xPercent both have -50%. Whenever you're setting a percentage-based translation, it's typically best to use the xPercent and yPercent properties. // Not recommended x: "50%", y: "50%", // Recommended xPercent: 50, yPercent: 50 Recreating animations over and over Creating your tweens and timelines beforehand has several advantages: Performance - Instead of having to create them right as they’re needed, you can do it ahead of time. Additionally, you need fewer instances of animations. Most of the time you’d never notice, but it’s good practice. Simplified logic - This is especially true when related to user interaction events. Freedom - Want to pause an animation when an event happens? Do it. Want to reverse an animation when the user does something? No problem. This sort of thing is much more difficult to handle when you create animations inside of event callbacks. Most of the time when you create animations beforehand, you will want to keep them paused until they’re needed. Then you can use control methods like .play(), .pause(), .reverse(), .progress(), .seek(), .restart(), and .timeScale() to affect their play state. Here’s a simple example: See the Pen Playing and reversing an animation on hover by GreenSock (@GreenSock) on CodePen. For more information related to creating animations beforehand, you can see the animating efficiently article. One exception to this rule is when you need things to be dynamic, like if the initial values may vary. For example, if you’re animating the height of the bars in a chart between various states and the user may click different buttons quickly, it’d make sense to create the animation each time to ensure they flow from whatever the current state is (even if it's mid-tween) like the demo below. See the Pen Playing and reversing an animation on hover by GreenSock (@GreenSock) on CodePen. Adding tweens to completed timelines A common pattern of mistakes that I’ve seen goes like this: const tl = gsap.timeline() tl.to(myElem, { x: 100 }); myElem.addEventListener("click", () => tl.to(myElem, { x: 300 }) ); Did you catch the mistake? If you add new tweens to a timeline that is already completed, they won’t be called unless you re-run the timeline. Almost always in these situations you should just use control methods for a previously created animation or create a new animation instead (not using an existing timeline) following the guidelines that we covered in the previous section. Not using loops If you want to apply the same effect to multiple elements (sections, cards, buttons, etc.) when a certain event happens to each one, you should almost always use a loop. For example, don’t use a selector like "button" when you want it to affect just one button. For example, if you wanted to fire an effect when each button is clicked: // BAD: immediately animates ALL buttons at once! gsap.effects.explode("button", { direction: "up", duration: 3 }); // GOOD: animation is specific to each button, and only when clicked gsap.utils.toArray("button").forEach(btn => btn.addEventListener("click", () => gsap.effects.explode(btn, { direction: "up", duration: 3 })) }); Inside of this loop, you can use a selector that is scoped to the given element so that you're only getting things INSIDE that element. For example: gsap.utils.toArray(".container").forEach(container => { let info = container.querySelector(".information"), silhouette = container.querySelector(".silhouette .cover"), tl = gsap.timeline({ paused: true }); tl.to(info, { yPercent: 0 }) .to(silhouette, { opacity: 0 }, 0); container.addEventListener("mouseenter", () => tl.play() ); container.addEventListener("mouseleave", () => tl.reverse() ); }); See the Pen Who's That Pokémon? - forEach example demo by GreenSock (@GreenSock) on CodePen. Using the old/verbose syntax Drop the Lite/Max I regularly see people using the old syntax even though they are loading GSAP 3. Old habits die hard. Even though the old syntax still technically works, the new modern GSAP 3 syntax is sleeker and simpler. Plus the old syntax won't be supported in GSAP 4 (which is far off in the future, but it's still a good idea to write future-friendly code). For example instead of using something that has Lite/Max in it, just use gsap: // old TweenLite.to() TweenMax.from() new TimelineMax() // new gsap.to() gsap.from() gsap.timeline() Use the string form for eases The shorter string form of eases requires less typing and lets you avoid extra import statements in module environments. // old Power2.easeOut Sine.easeInOut // new "power2" // The default is .out "sine.inOut" Duration belongs in the vars parameter Putting the duration inside of the vars parameter does require a bit more typing, but it makes things more readable and intuitive. GSAP’s defaults and effects are very helpful but you can’t make use of them if you’re putting the duration as the second parameter. // old gsap.to(elem, 1, { x: 100 }); // new gsap.to(elem, { duration: 1, x: 100}); // using GSAP’s defaults: const tl = gsap.timeline({ defaults: { duration: 1 } }); tl.to(elem, { x: 100 }); // no duration necessary! tl.to(elem, { y: 100, duration: 3 }); // easily overwrite the default value For a more full listing of changes in GSAP 3, check out the GSAP 3 Migration Guide. Numerical values don’t usually need to be strings For example if you want to set the x transform to 100 pixels, you don’t need to say x: "100px", you can just say x: 100. Simple! The only time when you need to pass numerical values as strings are if you need to change the unit (like x: "10vw") or pass in a complex value (like transformOrigin: "0px 50px"). The target of a tween can be a selector string I often see people do something like this: gsap.to(document.querySelectorAll(".box"), { x: 100 }); Or even with jQuery: gsap.to($(".box"), { x: 100 }); Both of the above will work but could be simplified by passing a selector string in as the target; GSAP will automatically use .querySelectorAll() to get a list of all of the elements that match. So the above can be written simple as gsap.to(".box", { x: 100 }); You could also pass in a complex selector string like ".box, .card" and it will select all boxes and cards. Or use an Array of elements so long as they are of the same type (selector string, variable reference, generic object, etc.). Conclusion So how'd you do? Is your GSAP code clear of these common mistakes? Hopefully you learned a few things. As always, if you need any help, the GreenSock forums are a fantastic resource. We love to help people develop their animation superpowers. If you're looking for another great learning resource, read how to animate efficiently! Now go forth and tween responsibly!
  2. Hi there! I´m using the brand new Scroll Trigger plugin, it´s amazing! But i´m having a problem using it with Smooth scroll: i have a link that scroll the page to some point, but after this scroll the Scroll Trigger markers move and the animation that should be triggered doesn´t start. If not scrolled, the script works as it should. Here is the example with markers: https://byhumans.works/area/cliente/roalca/ The bottom blue section have a countdown ( gsap timeline ) that is triggered once with Scroll Trigger. Click on buttons after "Nuestros Productos" title and you will see how the blue section with numbers below lost the trigger start point. I have to do something else after i smooth scroll the page? if i use other script to scroll the page same thing happens. This happens in all browsers, in pc, ipad and smartphone. Thanks My js: // scroll on click category var prodCatBtn = util.$$('.prod-cat-link'); // scroll util.on(prodCatBtn, 'click', function(){ gsap.to(window, { duration: 0.35, delay: .35, scrollTo: { y: ".switcher-prod", offsetY: 140 }, ease: "power2.inOut" }); }); // top boxes animation var counter1 = { var: 1950 }; var counter2 = { var: 0 }; var counter3 = { var: 0 }; var count1 = util.$(".number-1"); var count2 = util.$(".number-2"); var count3 = util.$(".number-3"); count1.innerHTML = counter1.var; count2.innerHTML = counter2.var; count3.innerHTML = counter3.var; gsap.registerPlugin(ScrollTrigger); // counter animation var tl = gsap.timeline({ repeat: false, ease: "none" }); tl.to(counter1, { var: 2004, duration: 3, onUpdate: function () { count1.innerHTML = Math.ceil(counter1.var); }, }) .to(counter2, { var: 16, duration: 3, onUpdate: function () { count2.innerHTML = Math.ceil(counter2.var); }, }, "-=2") .to(counter3, { var: 160, duration: 3, onUpdate: function () { count3.innerHTML = Math.ceil(counter3.var); }, }, "-=2"); ScrollTrigger.create({ trigger: ".counter-wrap", animation: tl, toggleActions: "play pause resume pause", start: "top bottom", markers: true, });
  3. Hello Everyone, I am trying to animate the text using the new scrollTrigger Plugin, there is a glitch when the start point reaches the scroller-start, why is this happening? I am unable to figure it out. Please help me to fix this glitch issue. Thanks.
  4. I'm having a problem and i'm unsure as to whether it's either with Barba or Gsap ScrollTrigger itself I have no clue . So in my website , when I go from the homepage to the about page everything works as normal except the horizontal scroll part that I have put in (Facts Section) , thing is I do this very same action on mobile and it works perfectly sometimes and then other times it does the same as it does with the Desktop Version , so it's either my code and the way I have implemented the horizontal scroll but thing is when I go directly to the page as in not through the homepage and just initiate all the functions in about.js independently , everything including the horizontal scroll works as desired and perfectly , so I don't know which is causing the problem , could ye have a look maybe ?? So here is my homepage.js (Barba Init code) //Variable Declarations and Function Definitions let viewBox = "" heading_Pos = [0, 0] displayState = "" hamburger_display_button = Array.from($('.mobile_nav_sticky'))[0] opened_nav_buttons = document.querySelector('.options') logo = $(".Actual_Logo_Svg") // Morphing Circles and ellipses to paths to be able to morph them and checking the viewbox for device size MorphSVGPlugin.convertToPath("ellipse"); shapes = Array.from($('.Logo_In_Shapes path')) const homeInit = () => { viewBox = "", heading_Pos = [0, 0], displayState = "" hamburger_display_button = Array.from($('.mobile_nav_sticky'))[0] opened_nav_buttons = document.querySelector('.options') logo = $(".Actual_Logo_Svg"); // Morphing Circles and ellipses to paths to be able to morph them and checking the viewbox for device size MorphSVGPlugin.convertToPath("ellipse"); shapes = Array.from($('.Logo_In_Shapes path')) } const logo_tl_func = () => { let logo_tl = gsap.timeline({ onComplete: moveLogo, }) // Morphing into the Logo logo_tl.from(shapes, 1, { y: -600, autoAlpha: 0, ease: "bounce", stagger: 0.15 }) logo_tl.to(shapes, 1, { fill: '#F0C368', stagger: 0.05 }) let firstAnimation = gsap.to('.shapes', { duration: 2, morphSVG: ".Logo_Proper_Background" }); let secondAnimation = gsap.to('.textShape', { duration: 2, fill: '#1D373F', morphSVG: ".Logo_Proper_Text" }); logo_tl.add([firstAnimation, secondAnimation]) } const changeViewBox = media_query => { media_query.matches ? viewBox = "-150 -180 2495 890" : viewBox = "-150 -350 3574 880" media_query.matches ? heading_Pos = [-511, -15] : heading_Pos = [-1540, 40]; media_query.matches ? displayState = "none" : displayState = "block" } const moveLogo = () => { gsap.to(logo, { attr: { viewBox: viewBox }, duration: 3 }) fadeInHeadingAndLinks(); } const fadeInHeadingAndLinks = () => { gsap.to('.nav_links', { display: displayState, scale: 1, duration: 3 }) gsap.to('.logo_heading', { display: "block", x: heading_Pos[0], y: heading_Pos[1], // scale:1, duration: 3 }) gsap.to('.mobile_nav_sticky', { display: "block", scale: 1, duration: 5 }, "+=.7") } const pageTransition = () => { var tl = gsap.timeline(); tl.set('.loading_container img', { scale: 0.3 }) tl.to('.loading_container', { duration: 1.2, width: "100%", left: "0%", ease: "circ.out", }) .to('.loading_container img', { scale: 0.6, duration: 1 }, "-=1.2") .to('.loading_container', { duration: 1.2, width: "0%", right: "0%", ease: "circ.out", }) .to('.loading_container img', { scale: 0.3, duration: 1.2 }, "-=1.3") } // Helper Functions const delay = (ms) => { return new Promise(resolve => setTimeout(resolve, ms)); } // Initialization Methods $(document).ready(() => { window.matchMedia("(max-width: 600px)").matches ? logo.attr('viewBox', '-350 -700 1274 1680') : logo.attr('viewBox', '-680 -380 2074 1080') var viewbox = window.matchMedia("(max-width: 600px)") changeViewBox(viewbox) }) hamburger_display_button.onclick = () => { opened_nav_buttons.classList.toggle('open') } barba.init({ sync: true, transitions: [{ name: 'transition-base', preventRunning: true, timeout: 5000, async leave() { const done = this.async(); pageTransition(); await delay(1000); done(); }, async enter() { window.scrollTo(0, 0); }, }], views: [ { namespace: 'home', afterEnter() { homeInit() window.matchMedia("(max-width: 600px)").matches ? logo.attr('viewBox', '-350 -700 1274 1680') : logo.attr('viewBox', '-680 -380 2074 1080') let viewbox = window.matchMedia("(max-width: 600px)") changeViewBox(viewbox) logo_tl_func(); hamburger_display_button.onclick = () => { opened_nav_buttons.classList.toggle('open') } }, }, { namespace: 'about', afterEnter() { aboutInit() face_tl_func() scroll_p_tl_func() scroll_skills_tl_func() scroll_facts_tl_func() }, } ], }); // //Global Hooks // barba.hooks.leave(() => { // const done = this.async(); // pageTransition(); // await delay(1000); // done(); // }) // barba.hooks.enter(() => { // window.scrollTo(0, 0); // }) and here's my about.js // Variable Declarations and Function Definitions let factsContainer_sm = document.querySelector(".factsContainer_sm") const aboutInit =() => { factsContainer_sm = document.querySelector(".factsContainer_sm") let head = document.getElementsByTagName('head')[0], link = document.createElement('link') link.rel = 'stylesheet' link.href= "../../Resources/CSS/about.css" head.appendChild(link); } const face_tl_func = () => { let face_tl = gsap.timeline(), paths = document.querySelectorAll('.My_Face path'), filledYellowElements = ['.Main_Hair_Part', '.Eyeball_2', '.Eyeball_1', '.Nostril_1', '.Nostril_2', '.Tongue_Part'], filledNavyElements = ['.Pupil_2', '.Pupil_1']; face_tl.set(filledNavyElements, { fill: 'unset' }), face_tl.set(filledYellowElements, { fill: 'unset' }), face_tl.fromTo(paths, { drawSVG: "0%" }, { duration: 1, drawSVG: "100% ", stagger: 0.15 }) let firstAnimation = gsap.to(filledYellowElements, { duration: 2, ease: "slow", fill: '#F0C368' }, "-=.7"), secondAnimation = gsap.to(filledNavyElements, { duration: 2, ease: "bounce", fill: '#1D373F' }, "-=.7") face_tl.add([firstAnimation, secondAnimation]) } const scroll_p_tl_func = () => { let scroll_tl = gsap.timeline({ scrollTrigger: { trigger: '.content', start: "top center", end: "+=1000", markers: true, scrub: true // pin: true } }) scroll_tl.to('.first', { transform: "rotateX(50deg) rotateZ(331deg) translateX(42px)", duration: .5, }), scroll_tl.to('.flag', { scale: 1 }, '-=.1'), scroll_tl.addLabel("first_down") scroll_tl.to('.second', { transform: "rotateX(50deg) rotateZ(331deg) translateX(42px)", duration: 2, }, "first_down-=.1") scroll_tl.addLabel("second_down") scroll_tl.to('.third', { transform: "rotateX(50deg) rotateZ(331deg) translateX(42px)", duration: 2, }, "second_down-=.01") } const scroll_skills_tl_func = () => { let scroll_tl = gsap.timeline({ scrollTrigger: { trigger: '.skillsContainer', start: "top center", markers: true, } }), barWidth = "", bars = [...document.querySelectorAll('.bar')] bars.map(bar => { barWidth = bar.dataset.width; let barAnimation = gsap.to(bar, { width: barWidth, }), percentageAniamtion = gsap.to('.percentage', { scale: 1, }) scroll_tl.add([barAnimation, percentageAniamtion]); }) } const scroll_facts_tl_func = () => { let scroll_tl = gsap.timeline({ scrollTrigger: { trigger: '.factsContainer', start: "top center", // pin: true, scrub: true, end: "+=300", markers: true, } }), facts = [...document.querySelectorAll('.fact')] scroll_tl.to('.factsContainer h2', { scale: 1.5, duration: 1, ease: "slow" }) scroll_tl.to(facts, { xPercent: -85 * (facts.length - 1), scrollTrigger: { trigger: ".factsContainer_sm", start: "center center", pin: true, // pinSpacing:false, markers: true, scrub: 1, snap: 1 / (facts.length - 1), // base vertical scrolling on how wide the container is so it feels more natural. end: () => `+=${factsContainer_sm.offsetWidth}` } }); } // //Initialization Methods aboutInit() face_tl_func() scroll_p_tl_func() scroll_skills_tl_func() scroll_facts_tl_func() Here's the website homepage - https://adamoceallaigh.netlify.app/ Here's the about page - https://adamoceallaigh.netlify.app/about.html Appreciate all the help ye can give , if ye can , can ye check both mobile and desktop versions. 🤙 Cheers Adam
  5. Hi there, TL;DR How to prevent the gsap animations to be aborted in react because of a rerender/prop change How to use dynamic props/state inside a gsap tween without beeing interrupted I'm building a spinng wheel with dynamic start- and end-points. You guys already helped me a lot with this: Now I need to implement this into an acutal react application. The biggest problem is, that I use dynamic Properties inside my gsap tweens to calculate e.g. the stop position or when to stop animation. React rerenders my component and aborts the whole animation as soon as a property changes. Of course react should do that - but how to I keep my animation running? What my code should do: start spinning by clicking the "Start Spinning" Button Wheel is spinning infinite Stop wheel by clicking the "Stop Spinning" Button Wheel at least the minimum amount (5) and then stops at the set position What my code actually does: start spinning by clicking the "Start Spinning" Button Wheel is spinning infinite Clicking "Stop Spinning" does not work -> triggers in my local invironment a rerender and aborts the animation in codepen it flickers and then nothing happens (the stop position is never passed into the tween) ... In the codepen it actually does not rerender but the updated prop won't be passed into the tween. const loopAnim = gsap.to(circleRef.current, { rotation: "+=360", ease: "none", duration: 0.5, onComplete: () => { // The props won't update in here... if (loopIteration.current >= fullSpins && typeof stopAt === "number") { stopAnim.play(); } else { loopIteration.current++; loopAnim.play(0); }, paused: true });
  6. Ahmed Elabbasy

    tilt effect

    How can I change the transform to matrix I find it difficult to drag in the slider when creating the tilt effect as well as some delay in changing the slide and I think this will fix it just a belief I use gsap.to https://codesandbox.io/s/broken-currying-05h9k
  7. Hi everyone, I'm working on a projet where I have a menu, and a side-menu. Every thing is fine: when i click on the menu button the side menu opens, and when i click again it get back to close state. But if I click to fast the side menu closes but the text inside doesn't disapear, any idea on why please ? :) (I can't reproduce on codepen so I guess the code here and the two screen would help ^^" ) Screen 1: side menu is closed Screen 2: side menu is open Screen 3: side meni is closed but text inside is still visible My GSAP code: const handleAnim = () => { let sideMenuBackground = document.querySelector(".sideMenu__background"); let sideMenu = document.querySelector(".sideMenu"); if (menuCheckbox) { TweenMax.from(sideMenuBackground, 0, { width: "0px", ease: Power1.easeIn }) TweenMax.to(sideMenuBackground, 0.3, { width: "324px" }) TweenMax.from(sideMenu, { display: "none", opacity: "0", ease: Power0.easeNone }) TweenMax.to(sideMenu, 0.3, { display: "block", opacity: "1", delay: 0.4 }) } else { TweenMax.to(sideMenu, { display: "none", opacity: "0", ease: Power0.easeNone }) TweenMax.to(sideMenuBackground, 0.1, { width: "0", delay: 0.2 }) } } The "handleAnim" function is called in menu burger button and icons button: <nav className={`navList ${menuCheckbox && "navList__isOpen"}`}> <div className={menuCheckbox ? "menuBurger__nav menuBurger__cross" : "menuBurger__nav"}> <input type="checkbox" onClick={() => { handleCheckbox(); }} /> <span className="top"></span> <span className="middle"></span> <span className="bottom"></span> </div> <ul> <li> <button onClick={() => { handleCheckbox(); }}> <i className="fal fa-folders"></i> </button> </li> <li> <button onClick={() => { handleCheckbox(); }}> <i className="fal fa-balance-scale"></i> </button> </li> <li> <button onClick={() => { handleCheckbox(); }}> <i className="fal fa-receipt"></i> </button> </li> </ul> </nav>
  8. Hello, I am try to create some UI micro interactions for my buttons on a react app I am currently developing. I have seen Mo.js and I noticed that it had a easy way to add burst animations using a burst object. I have never really tackled any complex animation with GSAP, so I was hoping someone may offer an opinion on a way to tackle these types of animations (ideally with GSAP 3)? Thanks A
  9. Hi everyone, I'm trying to implement this effect from this website https://isolation.is/. The grid moves by itself and the animation repeat itself as the items always go back to their starting position. Actually it's not only that, once an item goes past a certain point, the element is taken and positioned at the end of the div (so just append in js I guess). First of all I need to make the grid, in the website though there is no row (as in no parent div for the items) so I have a bit of trouble understanding how it's done. I guess I would have to use gsap.set on all my elements but how to calculate the space and offset needed and then the repeat ? I will post a codepen later as I started my project directly in local. Thank you
  10. <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <style> .loading{ background: orangered; position: absolute; top: 0; bottom: 0; right: 0; height: 100%; width: 100%; z-index: -99; } button{ padding: 10px 30px; background:#323232; color: white; outline: none; border: none; position: absolute; z-index: 9; top: 45%; left: 45%; cursor: pointer; } </style> <body> <div class="loading"> </div> <div class="btn"> <button>CLick</button> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js "></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js "></script> <script> const ld_gray = gsap.timeline({paused: true}); ld_gray.from('.loading', {duration: 1, delay: 0.5, scaleX: 0, transformOrigin: 'left', ease: "expo.out",}); ld_gray.to('.loading', {duration: 1, delay: 1, scaleX: 0, transformOrigin: 'right', ease: "expo.in",} ); $('button').click(function () { ld_gray.restart(); }); </script> </body> </html>
  11. I want to animate the background, If click the button background will be animate, It works fine except that after one click, It doesn't work again. <body> <div class="loading"></div> <div class="btn"> <button>CLick</button> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js "></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.min.js "></script> <script> $('button').click(function () { ld_gray = gsap.from('.loading', 1,{delay: 0.5, scaleX: 0, transformOrigin: 'left', ease: "expo.out",}); gsap.to('.loading', 1,{ delay: 1.5, scaleX: 0, transformOrigin: 'right', ease: "expo.in",} ); }); </script> </body>
  12. I want to change color of my background and text again and again parsing my array of colors. I don´t know if I can do that using a variable or changing itemColor value, I was thinking in using an onComplete funcion by I will use this inside React, let itemColor = 0; var tl = gsap.timeline(); tl.to("#bg", { backgroundColor: colors[itemColor].dark, duration: 1, delay: 3 }).to("#h1go", { color: colors[itemColor].light, duration: 1, delay: 0 }); Also I have a Codesandbox link for React https://codesandbox.io/s/gsap-react-text-gsaptimeline-cuk58?file=/src/App.js Thanks in advance
  13. Just moved to GSAP 3.2 from TweenMax 2.latest and noticed this warning. Does not happen with TweenMax.set equivalent. For code gsap.set("#nb", {top: "200px"}); //... //... gsap.set("#nb", {clearprops: "top", bottom: "58px"}); I get a warning in 3.2.6, but things continue to work well. Invalid property clearprops set to top Missing plugin? gsap.registerPlugin() Here is the full log demo.localhost-1588964285633.log PS: #nb { position: absolute; padding-top: 8px; white-space: normal; /* needed for edge because edge doesn't understand break-spaces */ white-space: break-spaces; font-size: 16px; width: 100%; left: 0%; line-height: 1.3; }
  14. Hi guys, this is how i normally created my loops in my banners before gsap3: // ... tl.addCallback(function(){ if(loopCount < 3){ loopCount++; // fade out elements }else{ tl.pause(); } }); Now, that addCallback is not present anymore I use "call()", but the ad does not loop correctly, but only two times. Is "call" not being processed in every loop of the timeline? This would be my whole timeline. Also notice the "tl.to({}, 0.1, {});" in the end, which is needed to avoid a flickering when looping. This was not the case in gsap2 as well. var loopCount = 0; var tl = new TimelineMax({paused:true, repeat:-1}); tl.timeScale(1.2); //fr1 tl.from('#logo', 1, {scale:1.2, opacity: 0 }); tl.to({}, 2, {}); tl.from('.line, .line2', 0.2, { opacity: 0 }); tl.to('.cls-1', 1.2, { 'stroke-width': 102 }); //fr2 tl.from('#bg-blue', 3, {opacity: 0}, 'kaas') tl.from('#stuk1', 0.2, {opacity: 0}, 'kaas'); tl.from('#shop', 0.5, {y: 50, opacity: 0, ease:Back.easeOut},'kaas'); tl.from('#stuk1_shade', 0.2, {opacity: 0}, 'kaas'); tl.from('#stuk2r', 1.3, {x: -72, opacity: 0, ease:Power4.easeOut}, 'kaas'); tl.from('#stuk2l', 1.3, {x: 72, opacity: 0, ease:Power4.easeOut}, 'kaas'); tl.from('#stuk3r', 1.5, {x: -121, opacity: 0, ease:Power4.easeOut}, 'kaas'); tl.from('#stuk3l', 1.5, {x: 121, opacity: 0, ease:Power4.easeOut}, 'kaas'); tl.from('#stoerer', 0.5, {scale: 0.5, opacity: 0, ease:Back.easeOut}, 'kaas+=1.2'); tl.to({}, 1, {}); tl.to('#stoerer', 0.2, {scale: 0.95, yoyo: true, repeat: 3}); tl.to({}, 2, {}); // loop tl.call(function(){ if(loopCount <= 5){ loopCount++; tl.set('.cls-1', { 'stroke-width': 14 }); tl.set('.line, .line2, #logo', { opacity: 0 }); tl.to('#frame2', 0.5, {opacity: 0}); }else{ tl.pause(); } }); tl.to({}, 0.1, {}); What am I doing wrong? Thanks!
  15. I am trying to add a defaults values for my fromTo(), I tried putting defaults: {} inside gsap.timeline({}) as below const tl_shapes = gsap.timeline( { defaults: { opacity: 0 } }, { defaults: { opacity: 1 } } ); function step_shapes_animation () { return tl_shapes .fromTo( ".step-2 .shapes img:first-child", { x: -200 }, { x: 0, duration: duration } ) .fromTo( ".step-2 .shapes img:last-child", { y: -200 }, { y: 0, duration: duration }, "-=0.4" ); } I am not sure if this is the right way to do it but second element doesn't seem to work and it starts with initial opacity: 1 and I guess it is because fromTo() has 2 objects and I can't put 2 objects for defaults. I am wondering if there is a right way to do it.
  16. Hello When my website launches im creating a timeline and then saving it in an object so later I can control it's playback. Thing is, when I call that timeline again, I would like to pass a parameter that will change the background color of my animation dinamically. I know that the timeline is just an object, and going to _first.vars.background I could change the color, but this is cumbersome. Is there a more direct approach so when I try to play or reverse my timeline I could pass parameters directly and change the burger background color? Thanks in advance :)
  17. Hi there, I am trying to make a div(#rec) follow an svg path with I did in my below code but, I want the div to follow down, as I scroll down and follow back up as I scroll up, I will appreciate if you help work on the code below, Thanks https://codepen.io/onseyi/project/editor/DeWepm <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> body { margin:0; width: 100%; height: 3000px; background:#dfdfdf; overflow-x: hidden; } #rec { position: absolute; width: 150px; height: 100px; background-color: #8894aa; } </style> </head> <body> <div id="rec"></div> <svg fill="none" xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 1300 3000"> <path id="path" d="M143.78,431.83c103.76,235.99,223.54,324.48,318.04,360c143.34,53.87,223.51-16.03,379,51.84 c136.54,59.6,292.87,208.71,272.99,325.44c-25.74,151.18-320.87,94.36-612.23,336.96c-155.68,129.63-367.75,392.59-331.29,624.96 c43.59,277.79,443.64,520.03,985.93,492.48" stroke="black" stroke-width="8"/> </svg> <script src="gsap.min.js"></script> <script src="MotionPathPlugin.min.js""></script> <script> gsap.registerPlugin(MotionPathPlugin); gsap.set("#rec", {xPercent:-50, yPercent:-50, transformOrigin:"50% 50%"}); gsap.to("#rec",{duration:5, motionPath:{ path:"#path", autoRotate: true } }); </script> </body> </html> index.html
  18. Hello, guys 😃 I have some div, positioned as 'left: 10px; top: 10px'. And then, i'm trying move it to 'left: 50%; top: 50%' and it works, but at the beginning of animation, div jumps. How can i fix this?
  19. Hi, I meet a simple problem with a tween : when I execute a first time my tween and then resize my window, the tween is happens badly, but if I refresh my page everything works fine, I've searched on forums but I don't find expected results 😕 In a first time, I've thinked the problem was linked to my CSS properties but when GSAP tweening it uses pixels values, and that's my only clue to resolve the problem. Here, an attached minimal repository : https://github.com/pierredarrieutort/Jape/tree/minimal_repo_for_menu
  20. I'm trying to convert Craig Roblewsky's CodePen Horizontal full-screen slider w/4 controls to GSAP 3 but I'm getting a console log error that I don't understand. Can anyone take a look and see if it's a simple fix? I'd like to use this slider with GSAP3. Thanks!
  21. I've create a function which scrolls to the next anchor detecting the scroll direction (See below) const CONTAINER_STRING = '#main-container>main', CONTAINER = document.querySelector( CONTAINER_STRING ) let currentChild = 0 gsap.registerPlugin( ScrollToPlugin ) CONTAINER.addEventListener( 'wheel', ( { deltaY } ) => { if ( currentChild < CONTAINER.childElementCount - 1 && deltaY > 0 ) currentChild++ if ( currentChild > 0 && deltaY < 0 ) --currentChild gsap.to( CONTAINER, .5, { scrollTo: '#' + document.querySelector( `${CONTAINER_STRING}>:nth-child(${currentChild + 1})` ).id } ) }, { passive: true } ) My problem is i can't detect if gsap is currently tweening in my page. I've tried some tricks like extract the tween into a variable, but nothing works... 🤔 So how can i detect an interpolation in my page or detect if this specific tween is active ?
  22. The GreenSock Animation Platform (GSAP) animates anything JavaScript can touch (CSS properties, SVG, React, canvas, generic objects, whatever) and solves countless browser inconsistencies, all with blazing speed (up to 20x faster than jQuery). See why GSAP is used by roughly 10,000,000 sites and many major brands. Hang in there through the learning curve and you'll discover how fun animating with code can be. We promise it's worth your time. Quick links What is GSAP? Loading GSAP Tweening Basics CSSPlugin 2D and 3D transforms Easing Staggers Callbacks Sequencing with Timelines Timeline control Getter / Setter methods Getting Current Values of an Element's Property Club GreenSock We'll cover the most popular features here but keep the GSAP docs handy for all the details. First, let's talk about what GSAP actually does... GSAP is a property manipulator Animation ultimately boils down to changing property values many times per second, making something appear to move, fade, spin, etc. GSAP snags a starting value, an ending value and then interpolates between them 60 times per second. For example, changing the x coordinate of an object from 0 to 1000 over the course of 1 second makes it move quickly to the right. Gradually changing opacity from 1 to 0 makes an element fade out. Your job as an animator is to decide which properties to change, how quickly, and the motion's style (known as easing - we'll get to that later). To be technically accurate, we could have named GSAP the "GreenSock Property Manipulator" (GSPM) but that doesn't have the same ring. DOM, SVG, <canvas>, and beyond GSAP doesn't have a pre-defined list of properties it can handle. It's super flexible, adjusting to almost anything you throw at it. GSAP can animate all of the following: CSS: 2D and 3D transforms, colors, width, opacity, border-radius, margin, and almost every CSS value. SVG attributes: viewBox, width, height, fill, stroke, cx, r, opacity, etc. Plugins like MorphSVG and DrawSVG can be used for advanced effects. Any numeric value For example, an object that gets rendered to an <canvas>. Animate the camera position in a 3D scene or filter values. GSAP is often used with Three.js and Pixi.js. Once you learn the basic syntax you'll be able to use GSAP anywhere that JavaScript runs. This guide will focus on the most popular use case: animating CSS properties of DOM elements. (Note: if you're using React, read this too.) If you're using any of the following frameworks, these articles may help: React Vue Angular What is GSAP Exactly? GSAP is a suite of tools for scripted animation. It includes: The GSAP core - The core of the engine which animates any property of any object. It makes use of tweens and to give you more control over your animations. Extras like time-saving plugins, easing tools, utility methods, and more. Loading GSAP
  23. Juraj

    gsap3 cycle method?

    Hey guys I may be blind, but is cycle method supported in the gsap3 release? Can't seem to make it work the old way. Thank you!
  24. Hi! Help me please!)) Now I have loop animation to the right. If I click "Left(reverse)" animation go to the left, but animation stops. What I need do that animation works loop and when i click" Right(play)" and when I click "Left(reverse)"
  25. dada78

    jquery gsap Plugin

    Hi guys, I am working on this app that uses jquery for functionality, however I have never really used it, especially not in conjunction with GSAP. I did get the animation to work thanks to your doc, however I am not clear as to how I would do a GSAP fromTo method using the jQuery syntax. Basically I am trying to use GSAP to animate some jquery modal transitions. To just test that the animation is working at all I used the below .animate method which is animating fine, but what I really want to do is a fromTo animation, where the modal is scaled up from width/height:0 to 1200px x 705px. In my showModal function I have this: var showModal = function () { setTimeout(function(){ //alert("Boom!"); }, 2000); $(options.selector.outer).css('display', 'flex'); $(options.selector.inner).animate({width:"1200px", height:"705px", display:'flex'}, {duration:1000, complete:onShowComplete}); }; Thank you!
×