Jump to content
GreenSock

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

Leaderboard

  1. GreenSock

    GreenSock

    Administrators


    • Points

      120

    • Content Count

      14,817


  2. ZachSaucier

    ZachSaucier

    Administrators


    • Points

      79

    • Content Count

      3,845


  3. OSUblake

    OSUblake

    Moderators


    • Points

      75

    • Content Count

      5,699


  4. PointC

    PointC

    Moderators


    • Points

      35

    • Content Count

      3,812



Popular Content

Showing content with the highest reputation since 07/03/2020 in all areas

  1. 10 points
    Hey fellow GreenSockers A little over five years ago, I took a chance and posted a question on the GreenSock forum. Nobody called me dumb and that was a HUGE relief! So much so that I wrote an entire GS post about it four years ago. It was a turning point for me and my JavaScript journey. Today, I’m taking another big leap in my life and launching a web animation tutorial site. My reasons for doing so are both personal and professional. This thread is a sequel to my One Year post listed above. Call it My Five Year Journey. Personal reasons My life has been full of twists, turns and milestone events over the past few years. I turned the big 50 and ask myself every day how that’s even possible. The memories of getting my first computer (TRS-80) and learning BASIC in the early 80s are so vivid that they feel like it was only a few years ago. Wasn’t it just yesterday I was programming the PET, VIC-20 and Commodore 64 in high school? Time does fly and I’m not getting any younger. I also celebrated my 30th wedding anniversary. That event itself isn’t a reason to start a new website, but the longer I’m married, the more I realize how lucky I am to have a partner and cheerleader with me when I try new things. She has been a tremendous support in this new endeavor. I wonder how I ever talked her into marrying me all those years ago and how she has put up with me for 30+ years. The other recent personal event that has shaped my decision is the one that is affecting us all right now. Seeing the effect of COVID-19 on the world and how it has robbed too many people of their lives and livelihoods has reminded me that time is precious, and you never know what’s around the corner. As they say, seize the day. Professional reasons After taking the leap and posting that first question on the forum, I was hooked on the GreenSock community. I’ve tried to help as many people as I could in my free time. I love seeing someone have that ‘ah-ha’ moment. This new site is an extension of that desire to help and teach. This will be a difficult challenge. It would be far easier to not do this. As a lifelong introvert, I’m far more comfortable in my dark office typing away on the keyboard so this definitely pushes me out of my comfort zone. It will also be a time management challenge to keep posting new content while taking care of clients and still helping on the forum. I’ll do my best. My final professional reason is that this just seems like the universe is pushing me in this direction. I loved computers and programming in my youth, but my career turned to my other loves of video production and photography. Throughout the last decade there have been many forks in the road, and it seems like every decision has led me here. My life has now come full circle. Fear and self-doubt Despite all the personal and professional reasons listed above, there has still been the nagging self-doubt. Will it be any good? Will anyone read it? Hasn’t this already been written? Maybe others don’t have that little voice in the back of their head, but mine starts yelling at me loudly when I try something big. It’s one thing to post an answer in the forum, but quite another to really put yourself out there with a whole new site. After some sleepless nights, I finally found calm from one realization. If I can help even one person with a problem, teach them something new or spark an idea, it will all be worth it. The rest of the fears don’t matter. Life is just too short to be scared or worried. The website’s focus If you know me from the GS forum, you know I love SVGs and making them move with GSAP. The website will, of course, feature a lot of SVGs and GreenSock will power everything. However, my primary focus will be real world projects. I find that I learn best when I’m building an actual project, so I’ll try to keep that as the focus. I’ll have lots of little tips and quick things too, but projects will be the main thing. Frequent visitors to the forum also know I don’t take it all too seriously and joke around a lot. You’ll be happy to know that several of the tutorials feature terrible jokes and puns at no extra charge. Thanks to the GS gang I’ve said it many times before and I’ll say it again. Thank you to Jack( @GreenSock) for creating the tools, but more importantly, thanks for fostering a terrific online community. Had I not discovered GSAP and started hanging around here, I would not know much about JavaScript and the new site would not exist. Special shout-out to @Carl too. He’s already in the trenches with training and tutorials and has encouraged me the whole way as I was getting this thing launched. All my fellow mods — thanks for the help and comradery over the years. You are all awesome! motiontricks.com Finally, without further ado, I introduce you to motiontricks.com My best to all of you. Thanks for reading. Now, let’s get those pixels movin’! 🚀 -Craig (PointC)
  2. 7 points
    By encourage I think he meant "incessantly bugged me for 2 years" Now, that Craig got his blog up, I'll move on to @OSUblake The world needs a GSAP + Pixi hero. Great job, Craig. I'm truly impressed. I can't wait to finish reading all of it. I'm sure motiontricks.com will be a tremendous resource for anyone learning and mastering GSAP. I'll whole-heartedly recommend it. When's the next post going live?
  3. 6 points
    Congrats on your new journey, can't wait to take part in it! Your "first year of gsap" post moved me so much... and your work inspires me on a regular basis. I don't even know how to express my gratitude for you sharing all this with us. What a fitting way for you now to spread your passion on to the future.👏
  4. 5 points
    Check this out - just released today: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.scrollerProxy()
  5. 5 points
    @Carl let's give Blake 12 months and if he doesn't get it done, we'll collaborate on a new site and take all the fortune and glory for ourselves. I should probably register the domain before someone else grabs it. snorklmotionpixicodingcreativetricksclubbecauseblakedidntwanttodoit.com
  6. 5 points
    Well yeah. I just didn't want to be rude. I have to write more????? 👀 I'm unofficially planning for 'New Tutorial Tuesdays'. Should fit nicely with taco Tuesday. 🌮
  7. 5 points
    You can use keyframes if you're using the same target. https://codepen.io/osublake/pen/5a8c8feb233e5bcd66b87b40be8095ac
  8. 5 points
    Congrats buddy, looks amazing. True to your tradition here is a gif to celebrate the launch:
  9. 5 points
    It's the drop area where the scrolling works. Not the container with the images. If you've already created a scroller, and it's all done with svg, then it sounds like most of the stuff in those demos probably won't apply to your use case. Those demos were to show how to drag something out of scrolling container because you literally can't drag something out of it. But if you're using SVG, you can certainly drag stuff anywhere as long as overflow is visible. If you need to clip stuff, you can use a clipPath or mask. Draggable can definitely help simplify a lot of code, and it's been battle tested to handle a bunch of different edge cases. My first thought would be to create a clone of what you dragging, and then manipulate the viewBox to move the items in the direction you want it scroll. If not the viewBox, then make sure everything is inside a <g> element, and translate it. You can read the deltaX and deltaY properties in your onDrag callback, and use those values to scroll your container if need. https://greensock.com/docs/v3/Plugins/Draggable/deltaX
  10. 5 points
    Yep, @mikel is using the approach I typically do for something like this. There are actually a bunch of ways to accomplish this. The gist is: function animate() { gsap.to(".class", { ... duration: gsap.utils.random(0.5, 3), // random number between 0.5 and 3 onComplete: animate // this is what does the infinite loop }); } animate(); // kick it off In the upcoming release of 3.4.0, you'll be able to do this instead: gsap.to(".class", { ... duration: gsap.utils.random(0.5, 3), repeat: -1, onRepeat: function() { this.duration( gsap.utils.random(0.5, 3) ); } }); (not that it's any better - just an alternative) By the way, @b1Mind, I hope you don't mind me pointing out a few things with your code... You almost never need to wrap your CSS-related values in a css:{} object. GSAP is smart enough to figure that stuff out these days and it tends to make your code less readable. Timelines can't have a duration set via the vars. They just conform to however long their children are. Think of timelines like wrappers around tweens. So if you shove a 10-second tween into a fresh timeline, that timeline will have a duration of 10 seconds. Add another 5-second tween to the end, and it's now 15 seconds. If you set the duration via the setter method like timeline.duration(5), that merely alters the timeScale accordingly. You don't need to do something like Math.floor(Math.random() * 100) - you can tap into GSAP's utility method like gsap.utils.random(0, 100, 1) To get a random color, you could tap into GSAP's inline random capability (it'll search inside strings for "random(...)" and swap in values), like: color: "rgb(random(0,255,1), random(0,255,1), random(0,255,1))". Happy tweening!
  11. 5 points
    I'm not sure about your math. Like why are you calculating angles? To see if a point is inside a circle... // assumes x and y coords are the center const dx = Math.abs(cursor.x - bubble.x); const dy = Math.abs(cursor.y - bubble.y); if (dx > attractRadius || dy > attractRadius) { // not inside } Here's how I'd do it. The bubbles aren't animating, but it makes no difference. It will work the same. https://codepen.io/osublake/pen/ae04f1f23935e7d7a13c823d6141dec2 I didn't account for the delta, but here's how to do that.
  12. 5 points
    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&#39;s That Pok&eacute;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!
  13. 4 points
    You don't need to @ people. You shouldn't use new for timelines. It's not a constructor. // BAD var tween1 = new gsap.timeline(); // GOOD var tween1 = gsap.timeline(); You also don't need timelines for a single animation. Why don't you just create a list of the properties to animate? var animationData = [ { x: 10 }, { x: -10 }, { x: 20 }, { z: 15 }, { x: 15 } ]; tweenArr.forEach((node, i) => { var settings = Object.assign({ duration: 10, ease: "none" }, animationData[i]); gsap.to(node.position, settings); });
  14. 4 points
    Hi @Tonycre8, I have put together this simple guide on how to use GreenSock together with React Hooks. Hope you will find it useful. Cheers
  15. 4 points
  16. 4 points
    Yeah, with GSAP 3 you have many more options for staggering. Check out this video on the stagger object which lets you stagger from "end" and "center" animation.from(split.chars, {opacity:0, y:50, ease:"back(4)", stagger:{ from:"end", each:0.05 }}) Demo here: https://codepen.io/snorkltv/pen/BajxopX
  17. 4 points
    What mikel said, but I'd recommend this toggleActions: "play none none reverse".
  18. 4 points
    Hi @dlsmoker, I think what you're missing the the pause play functionality. So something like: const tl = gsap.timeline({ paused: true }); // inside button click function tl.play(); // inside close overlay function tl.pause(0); As for ScrollTrigger, that functionality is built into it. So animations are automatically played/paused there. I'd highly recommend looking over the docs, and learning center: https://greensock.com/docs/ https://greensock.com/learning/
  19. 4 points
    We've always allowed other methods. Attach a zip, link to a repo, it doesn't matter. It's just faster to test, experiment, and iterate using an online editor that can be forked. And again, if codepen isn't working, then try codesandbox or stackblitz. I actually prefer them over codepen. What we don't want to see is live sites and projects with thousands of lines of code. Just the bare minimum needed to reproduce the problem.
  20. 4 points
    You only need to do that because there is a delay when the 2nd and 3rd animations start. They are essentially paused, so it's not going to jump to the first animation frame before it starts.
  21. 4 points
    The default duration is 0.5s. Change it to something higher. And set your objects to the start position so they don't jump. gsap.set(cabezas, { x: -r, }); gsap.to(cabezas, { motionPath: { path: `M ${-r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${r * 2},0z` }, ease: "none", duration: 1, stagger: { repeat: -1, each: 0.2 } });
  22. 4 points
    Because it's so beautiful and fun ... https://codepen.io/mikeK/pen/xvygbQ
  23. 4 points
    Hey @wuergeengel, Welcome to the GreenSock Forum. Here an example for a random loop https://codepen.io/mikeK/pen/gVBLME Happy looping ... Mikel
  24. 4 points
    TweenLite, TweenMax, TimelineLite, and TimelineMax are deprecated. You should use the new syntax.
  25. 4 points
    <div class="moveMe"> <h1> Hi world </h1> </div> // then gsap.from('.moveMe',{ opacity:0,y:200,duration:5 }); @Lichay Your issue is in specificity. GSAP does not break your css, it is applying a inline transform to your element (cause that's what it does). So you need to split up your transform, maybe have gsap animate a parent element. Then have your hover on the h1.
  26. 4 points
    Create a test and find out. var div = document.querySelector("div") var style = getComputedStyle(div) console.log(style.visibility) gsap.to(div, { visibility: "hidden", onUpdate() { console.log(style.visibility) } })
  27. 4 points
    You're gonna love what's coming in version 3.4. There's a new matchMedia() method that does EXACTLY what you're talking about here. This is an example: https://codepen.io/GreenSock/pen/GRoyWBd We hope to release 3.4 within the next week. You're welcome to use the beta in the mean time if you'd like. https://assets.codepen.io/16327/ScrollTrigger.min.js Does that help?
  28. 4 points
    Oh, you mean like this?: https://codepen.io/GreenSock/pen/rNxpbyX?editors=0
  29. 4 points
    Sure, you can get the function like: const ease = gsap.parseEase("power3.in"); // then feed in a number between 0 and 1 that's the progress, and it'll spit back the eased value (typically between 0 and 1, but not always, like Elastic or Back) let num = ease(0.5); Is that what you're looking for?
  30. 3 points
    Are you trying to do random animations? Create a function where you pass in a target and have it create an animation, in the onComplete, have it call a function to do another random animation. Rinse and repeat.
  31. 3 points
    This is officially in 3.4.0 which is out now.
  32. 3 points
    Congrats PointC, it looks really nice and will be a wonderful resource. Nice job! Good luck on CSSTricks buying you out when CSS still won’t be able to do all that GSAP can do by the year 3052. But in the meantime you may wish to decrease the timeScale() on that finger spinning laptop, its set so high it almost appears stationary. 😜
  33. 3 points
    Can you also tell us what you are trying to do? Right now we can only see how you are doing it, but not what it needs to do, because if we know what it must do then maybe we have a way easier solution. Also putting your code in a codepen.io with a reduced test case, so we see what the code is suppose to do exactly. When I see your code I think of a few things what maybe of use Have you checked out stagger: {}? Have you checked out the GSAP.utils? Wrap() seems of use You can animate arrays with a timeline `tl.to(["ITEM1", "ITEM2", ...., "ITEM99", {x: 5 })`
  34. 3 points
    That's what the demos in the documentation page that Jacked linked to are doing. Can you please try to explain what's not like what you're wanting?
  35. 3 points
    Insider tip: If you want to go from the end, you can actually just use a NEGATIVE stagger value
  36. 3 points
    Hey @df257666, Special ease for entire timeline - tween the timeline ... Here an example https://codepen.io/mikeK/pen/RwNKBrB Happy easing ... Mikel
  37. 3 points
    Hey @emilychews, 'Play' with all variables - for example https://codepen.io/mikeK/pen/QWymeMa Happy scrolling ... Mikel
  38. 3 points
    Congratulations, @PointC! Very well done. You're a huge asset to this community. I'm so glad that years ago you worked up the courage to post for the first time...and that it was so rewarding. You've come a long way!
  39. 3 points
    @Mamboleoo has been publishing some super handy SVG tips recently. Check them out!
  40. 3 points
    In general it's best to avoid directly using callbacks like .onresize because they might get overwritten by other scripts. You should try to stick to .addEventListener() instead whenever possible. It's really hard for us to debug on a live site. It'd be really handy if you recreated the issue using the minimal amount of code necessary using CodePen. I don't even know what section of the site you're talking about.
  41. 3 points
    It will likely be released some time this week or soon after. I don't see jitter on my Macbook Pro. However, you could improve the performance still. Check out this article for performance tips related to SVG. Since you're not animating any elements inside of the SVG I'd use a regular img element. Avoiding the use of clip-path might help as well.
  42. 3 points
    Hi @Marina its an issue because stagger needs an array. When your looping through each element and adding the timeline to them individually its still animating but has no siblings to stagger with. gsap.registerPlugin(MotionPathPlugin); let cabezas = document.querySelectorAll('.cabeza'); const r = 6; let tl = gsap.timeline(); tl.to(cabezas, { motionPath: { path: `M ${-r}, 0 a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 -${r * 2},0z`, }, duration: 5, repeat: -1, ease: 'none', stagger: 0.5, }); Strip it out of the loop and it behaves ... well it staggers
  43. 3 points
    Hi there! Sorry for my delayed response, just delivered some projects I replicated the HTML and CSS structure from the iPhone's website. With GSAP I used scrub and a simple from + scrollTrigger. Here's an example in case this is eventually useful to someone. https://codepen.io/jimmyadaro/pen/JjGLRoq
  44. 3 points
    @wuergeengel welcome ! I too love Greensock 💚🧦 If you ever have issues I would try to put together a codepen and ask your question with it attached at the bottom. This helps the others help you better. So I was curiously about this my self just had not had a chance to tinker with it. After almost nuking my browser twice in crazy loops I think I maybe narrowed it down a little bit but have to stop here for now. I am hoping one the pro's jumps in with a better solution, cause I don't think this is the way. https://codepen.io/b1m1nd/pen/BajrzJo?editors=0010
  45. 3 points
    The main problem is that the default ease is "power1.out" but your effect would require a linear ease. Just set ease: "none" and that should resolve it. Also, you can simplify this: // OLD transform: 'translateY(' + triggerHeight.offsetHeight + 'px' + ')', // NEW y: triggerHeight.offsetHeight, Is this what you want? https://codepen.io/GreenSock/pen/4921a7e4e9fbe42353a2d47064275128?editors=0010 Just beware that the reason ScrollTrigger does pinning with position: fixed is because most browsers handle the scrolling of the main page on a different thread, so if you try to accomplish it the way you're doing it (with just transforms), you can experience some "jitter" because the updates aren't synchronized. Might not be noticeable in every situation, though. I just figured I'd mention it. I didn't notice any jitter in your demo (at least in Chrome on my Mac).
  46. 3 points
    There were a few problems: You weren't loading the beta version of ScrollTrigger - scrollerProxy() is a new feature in 3.4.0 (soon to be released) You didn't actually set up the proxy stuff until AFTER you created your ScrollTriggers/animations. So at the time those get created, they look for any proxies and none exist, so they hook into the "real" element. I assume this is what you intended, right?: https://codepen.io/GreenSock/pen/84da4acf4cc292788d1099783ebbc685?editors=0010
  47. 3 points
    Hey @redfawx, Just small suggestions ... https://codepen.io/mikeK/pen/oNXoOBq https://codepen.io/mikeK/pen/a268f68810ba894fdc72bf966d7be862?editors=1010 Happy scrolling ... Mikel
  48. 3 points
    Hey @ooxablon, Welcome to the GreenSock Forum. Take a look at the new GSAP scrollTrigger. https://codepen.io/GreenSock/pen/eYpOZvX Happy scrolling ... Mikel
  49. 3 points
    Yep, the problem is that you've got competing scrubs (as you know). Also, you're breaking each "section" into individual tweens so if you scroll really fast from section 2 to 3 but due to the delayed scrubbing, the one from section 2 is barely into its progress, but you're also asking #3 to start scrubbing its (separate) tween simultaneously which goes from completely different progress values. I'd suggest just using ONE overall linear tween, and then animate the progress of that tween in an onUpdate of the ScrollTriggers like this: https://codepen.io/GreenSock/pen/pogpYVa?editors=0010 let sections = gsap.utils.toArray(".step"), // do the entire ball tween (across all), linearly ballTween = gsap.fromTo(".ball", {scale: 0}, {scale: sections.length * 2, ease: "none", paused: true}), // we'll tween the playhead of ballTween with this separate tween. This creates the delayed scrub (2 seconds to catch up, or whatever duration you define) tween = gsap.to(ballTween, {duration: 2, ease: "power3", paused: true}), // progress incremenet inc = 1 / sections.length; sections.forEach((step, i) => { ScrollTrigger.create({ trigger: step, start: "bottom bottom", end: "+=1000", pin: true, onUpdate: self => { tween.vars.progress = (i * inc) + self.progress * inc; tween.invalidate().restart(); } }); }); I'm reusing the same "tween" instance over and over and simply altering its vars.progress and then invalidating it solely to improve performance. A simpler (but less performant) option would be to gsap.to(ballTween, { progress: (i * inc) + self.progress * inc, duration: 2, ease: "power3", overwrite: true}) in the onUpdate but that creates a new tween instance each time (somewhat wasteful memory-wise). Now you get a perfectly smooth delayed scrub across everything. 👍 Is that the effect you're after?
  50. 3 points
    Welcome to the forums, @hateusall. Hm, the CodePen doesn't seem to have any of that functionality in it - did I miss something? How can I reproduce the issue? There are definitely some logic problems in your code, though. And some other things: You're creating a timeline once and then you keep adding more and more and more tweens to it each time the user clicks. You're adding tweens to a completed timeline. Instead, you should just create a new one each time and then when it's done it'll automatically be garbage collected rather than building up in a timeline uselessly. Or (even better) you can just create the animation once and then play()/reverse() it. You're using the old syntax. In GSAP 3, there's no need for TimelineMax, TimelineLite, TweenLite, or TweenMax. It's all hung off the "gsap" object. Much simpler. You've got a ton of redundant code in there, like for each of the nav elements you're basically doing the same thing. You could greatly simplify your code by either using a loop or a helper function. I'd strongly recommend reading this article that was released today because covers a lot of these issues: If you still need some help, we'd be happy to lend a hand but we'll need a little guidance about how to reproduce the issue you're talking about. Happy tweening!
×