Jump to content
GreenSock

Leaderboard

Popular Content

Showing content with the highest reputation since 12/28/2022 in all areas

  1. What a year! Such an honour to be able to serve this inspirational community. Thanks to all the moderators and helpers in these forums for their unwavering efforts and assistance in 2022. Here's to another wonderful year of creativity and adventures!
    11 points
  2. Hey, many suggest focusing on the animation first and adding scrollTrigger later, as it adds more complexity and only causes confusion when it doesn't work as expected. In general, I would try to avoid nesting scrollTrigger. Furthermore, timelines are meant to be used for sequencing animations. So instead try to create a timeline outside the loop to which you then assign your animations. codepen Hope this points you in the right direction. Good luck.
    5 points
  3. I don't think I can explain any better than the docs already do. What's not clear there?
    5 points
  4. tl.fromTo( ".main-wrapper", { blur: 20, }, { blur: 0, duration: 5, ease: "bounce.in" } ) .fromTo( ".main-wrapper", { opacity: 0 }, { opacity: 1, duration: 5, ease: "linear" }, "<" ); One way is to create a different tween for that.
    5 points
  5. Hi, The issue is due to the type of animation being applied to the main container of the page. Routing/Transition libraries normally demand that there has to be only one element to be animated. Hence we wrapped everything in a single DOM node. The animation we're using actually applies transforms to that element which causes issue with pinning in ScrollTrigger. https://stackoverflow.com/questions/15194313/transform3d-not-working-with-position-fixed-children" There are two possible solutions for this. Use pinReparent on all your ScrollTrigger instances that reside inside a transformed parent or set a default for all ScrollTrigger instances: ScrollTrigger.defaults({ pinReparent: true, }); If using that approach is not an option what you could do is on the transitions configuration remove all the styles applied by GSAP on the element being animated: const onEnter = (el, done) => { gsap.set(el, { autoAlpha: 0, scale: 0.8, xPercent: -100 }); gsap .timeline({ paused: true, onComplete() { toggleTransitionComplete(true); // Removes all styles (including transforms) // once the page/route transition is completed gsap.set(el, { clearProps: "all" }); done(); }, }) .to(el, { autoAlpha: 1, xPercent: 0, duration: 0.25 }) .to(el, { scale: 1, duration: 0.25 }) .play(); }; Both options are equally valid and should work without any issues. Hopefully this solves the issues you've been experiencing. If you have any other question/issue let us know. Happy Tweening!
    4 points
  6. Here's a demo of the best (but more fiddly) way. Ideally you'd have an aria label on the text element itself rather than assigning aria attributes to a non semantic element like a div. So something like this. I would go for this route with headings, but I'd likely duplicate text for long sections of text like paragraphs. https://codepen.io/GreenSock/pen/NWMYMQr?editors=1010 Kapture 2023-01-22 at 09.43.42.mp4 Another route I've gone in the past is adding aria-hidden on split text elements, then calling revert on them once they've animated in and removing the aria-hidden. Like so... https://codepen.io/GreenSock/pen/poZaJQa?editors=1010 Obviously all these routes are worth testing with folks that actually use screenreaders if you have the capacity to do so.
    4 points
  7. Ah, okay. Another fun challenge for me! πŸ₯³ Here's a helper function that lets you feed in a target element (like your headline) and a motion path and it'll spit back the progress value (between 0 and 1) corresponding to where it'll hit the center of that target element on the given axis ("y" axis by default): // helper function that returns the progress value for a motion path where it hits the center of the provided target on the given axis ("y" by default). function findProgress(target, path, {axis="y", precision=1, ease="none"}={}) { target = gsap.utils.toArray(target)[0]; path = gsap.utils.toArray(path)[0]; ease = gsap.parseEase(ease) || (p => p); let tBounds = target.getBoundingClientRect(), pBounds = path.getBoundingClientRect(), useX = axis === "x", tCenter = (tBounds[useX ? "left" : "top"] + tBounds[useX ? "right" : "bottom"]) / 2, rawPath = MotionPathPlugin.cacheRawPathMeasurements(MotionPathPlugin.getRawPath(path), Math.round(precision * 12)), start = rawPath[0][useX ? 0 : 1], end = rawPath[rawPath.length - 1][rawPath[rawPath.length-1].length - (useX ? 2 : 1)], pinpoint = gsap.utils.mapRange(pBounds[useX ? "left" : "top"], pBounds[useX ? "right" : "bottom"], start, end, tCenter), l = Math.round(precision * 200), inc = 1 / l, i = 1, prevV = start, p, v; if (pinpoint < Math.min(start, end)) { p = start < end ? 0 : 1; } else if (pinpoint > Math.max(start, end)) { p = start < end ? 1 : 0; } else { for (; i < l; i++) { p = i / l; v = MotionPathPlugin.getPositionOnPath(rawPath, ease(p))[axis]; if ((v >= pinpoint && prevV < pinpoint) || (v <= pinpoint && prevV > pinpoint)) { return p - (1 - gsap.utils.normalize(prevV, v, pinpoint)) * inc; } prevV = v; } } return p; } Here's a demo where I just placed a horizontal blue bar 1300px from the top (change the CSS to whatever you want) and it'll set the progress of the motionPath so that the tractor is right at that spot: https://codepen.io/GreenSock/pen/BaPdrKM?editors=0110 If it's not clear, please provide a minimal demo (like a CodePen) with your setup simplified as much as possible, and I don't mind wiring it up for you. I hope this helps you (or someone else)
    4 points
  8. Hi @anjali.pandith welcome to the forum! There is no maximum duration. GSDevTools is trying to help by providing some information if you don't give it anything, but if you properly define what animation you want GSDevTools to display everything will work as expected. https://codepen.io/mvaneijgen/pen/WNKELjR?editors=0011
    4 points
  9. This thread might prove useful also. πŸ˜‰
    4 points
  10. Hello @RaddyB - welcome to the GSAP forum. You should just target each item you create individually, instead of targetting the whole ul container element. // targets your container element, so the whole container element will be animated gsap.from(".toDoContainer", {duration: 1.5, x: -400, ease: 'power2.inOut', opacity: 0}); // targets the item you create, so only that element will be animated gsap.from(item, {duration: 1.5, x: -400, ease: 'power2.inOut', opacity: 0}); Is that what you wanted to go for? https://codepen.io/akapowl/pen/poZewzP
    4 points
  11. Tailwind's 'hidden' class sets the 'display: none' property. GSAP 'autoAlpha' sets 'visibility' and 'opacity' property. Basically you are dealing with two diff properties so how will they override.
    4 points
  12. Thanks for the demo. I don't use React at all so I can't help much with your actual project. However, I am working on a Swiper lesson for my GreenSock courses so I can share the following as a basic "work in progress" to show how to get the 2 to work together. https://codepen.io/snorkltv/pen/XWBNJjK?editors=1010 Despite not being able to help you with React I have a few thoughts on what you're doing: My strong personal opinion is: try to break free of the mindset of "adding css classes to things to trigger animations". Swiper offers events that you can use to trigger your GSAP animations. In my example everything is triggered via the "slideChange". Next, I'm a bit lost on how you plan to implement scrolling but right now your page doesn't scroll at all. I see what appears to be 3 tweens with ScrollTriggers assigned but I don't understand how the triggers are supposed to enter and leave the viewport to trigger the animations. If your carousel is going to be "locked in place" and your page doesn't scroll, I think you could use Observer to help you out. It shouldn't be too hard to wire it up to tell Swiper to go to the next or previous slides. Hopefully this helps you understand an alternate approach and you can better decide what will work best for your project.
    4 points
  13. Hi Sukro, Wondering if what you're seeing is FOUC, since the page will load with the HTML and CSS before it applies Javascript styles. This article might be helpful:
    3 points
  14. @Warren_A I've put the opening divs in my header.php and the closing divs in footer.php, assuming you're building your own theme as I am. <!-- opening tags in header.php --> <div id="smooth-wrapper"> <div id="smooth-content"> <!-- closing tags in footer.php --> </div><!-- #smooth-content --> </div><!-- #smooth-wrapper --> <!-- Opening tags go at the bottom of the header.php TIP: any "position: fixed;" elements you should put outside these tags (before opening them). Closing tags go right before <?php wp_footer(); ?> and </body> closing tag. And your overall HTML structure should be correct i.e. no unclosed divs or too many closed divs by mistake. -->
    3 points
  15. Hi there. That's very pretty simple animation to get going with. The rocket would just be a tweening up and to the right https://codepen.io/GreenSock/pen/JjBvpBL The boxes on the outside that are gently moving could be animated nicely with a stagger https://greensock.com/docs/v3/Staggers Hope that helps!
    3 points
  16. I'd say most of the time, if you want to set funky start positions for rectangles it's probably best / easiest just to use a path as @alig01 suggested. However, using the width and height you can calculate the top center and bottom center coordinates. https://codepen.io/snorkltv/pen/wvxjJwP?editors=1010 If you add rx attributes to both it will require some tweaking of the numbers, which again would bring us back to a <path>
    3 points
  17. Hey, your guess is correct, the error is in .list li. In your forEach loop, you iterate over your lists. So the element is your current list, which means you can target its children. I tried this in a pen, however I was unfortunately unfamiliar with the old syntax, so I rewrote it a bit (probably missed something). You could find the guide here. codepen Hope this helps.
    3 points
  18. Hi @AlejandroAlonzo welcome to the forum! You had it set up that the previous trigger created the next trigger, so only when the previous trigger was completed the would the next animation be crated, if you thus want to jump to animation 03, it doesn't work, because it hasn't been created yet. I would how ever also suggest looking in to https://greensock.com/docs/v3/Plugins/ScrollToPlugin you have it already loaded, and as the name implies it will scroll to the specific part on the page, instead of the browser just jumping to that part of the page. It is always great to first create working code before optimising, I personally would have like that you tried your hand your self at a looping version and posted both versions, that way we could see what your thought process was and how we could better help you. I would encourage you to read through my version and see if you understand what is going on, I've just copied one version of your setup and placed it in a .forEach loop and just filled in the blanks and scoped everything to that particular trigger in the loop. I don't see what you mean? You are using the GSAP 2 syntax in your code I would recommend using the v3 syntax, much more readable. And you are using some really fast animations 0.01 translates to 10ms which is really fast! If you don't want animations and just have it change instantly just use a .set() instead of a .to() tween. I Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/eYjMqBq?editors=1011
    3 points
  19. As you can see from the logs I added in the onUp and onDown callbacks, Observer's onUp works just fine - what fails is your custom logic. You are getting an error in console that points you to what is wrong funcs[index] is not a function If you log out the different indexes you are working with, you will notice that you are pointing towards an item of an array with a negative value for the index in multiple occasions, and arrays inherently do not have / work with negative indexes. So you will need to rework your logic with that regard, to make it work. BTW, you have a typo in your Observer: targer --> target https://codepen.io/akapowl/pen/poZLjpZ Edit: One suggestion I have is taking a look at GSAP's utility methods. Here is an example of how you could e.g. use .wrap() to wrap around your variable value to the last one in your array, if it becomes negative. Click anywhere on the body in this example to decrease the variable I'm working with by 1. https://codepen.io/akapowl/pen/QWBmjJB ... the wrapping also works in the positive direction, btw. https://codepen.io/akapowl/pen/QWBmyLJ
    3 points
  20. The only thing I can tell you for sure, is that you should call a ScrollTrigger.refresh() after you have created your ScrollTriggers when useing ST with locomotive-scroll, as is also noted in the demo on the .scrollerProxy() docs-page - right now you are only doing it after you created the smooth-scrolling instance and the scrollerProxy(). [...] // after everything is set up, refresh() ScrollTrigger and update LocomotiveScroll because padding may have been added for pinning, etc. ScrollTrigger.refresh(); Apart from that, there can be dozens of reasons for your issue - might be that you need to make sure your images are loaded before you create your ScrollTriggers (or call a .refresh() after they are fully loaded) but it might as well be something very different; possibly not even related to ScrollTrigger. After applying the suggested fixes to your current demo, I can not see the behaviour you mentioned at all. Since we can not really offer advice from looking at screenshots, because there are just too many possible problem-sources in a complex scenario like this, please add a minimal demo showcasing your issue, if you need further assistance on this.
    3 points
  21. Nah there's tons of ways round this! One route is doubling up content. You visually hide one so sighted people don't see it, but screenreaders read it out still, then whack aria-hidden on the one that's being split. https://www.a11yproject.com/posts/how-to-hide-content/#:~:text=visually-hidden class is applied,focus indicator had gone to. <h2 class="visually-hidden">This is a sentence</h2> <h2 class="split" aria-hidden="true">This is a sentence</h2> .visually-hidden { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } Another option is using aria hidden on the header and an aria label and role on a containing div <div role="heading" aria-level="2" aria-label="word"> <h2 class="title" aria-hidden="true"> <div>w</div> <div>o</div> <div>r</div> <div>d</div> </h2> </div> Another one would be to loop round the children that splittext creates and whack aria-hidden on them and an aria label on the text element. I raised this casually with Jack the other day about seeing if we can bake an option in so it's a little easier for people. Either way though, plenty of ways around this!
    3 points
  22. Hi @BruceST! On your gsap.to that control your .one-one height, add this parameter: onComplete: () => { ScrollTrigger.refresh(); } https://codepen.io/sam-tremblay/pen/OJwzwmz Happy Tweening!
    3 points
  23. @elegantseagulls I was able to figure out the big issues by breaking out the timeline creation from the foreach and now I have more control over everything. I think the code I found was flawed so that was messing me up. It all makes sense now. Thanks you for the info about the chained to or from! I really appreciate your help. GSAP Rocks!
    3 points
  24. Here is a pen of similar looking effect using splittext. https://codepen.io/tripti1410/pen/abjVKZP?editors=0110
    3 points
  25. Hi @swansondesigns welcome to the forum! I would not sweat it, if it works it works. There is so much 'optimization' you can do, that in the end you can't even recognize the code you've written, personally I'm of the mind to solve problems as they arise, so lets say you you're going to be animating 10000th of the blocks, then you'll need some optimizations or do you? GSAP is already so performant and optimized that you're not going to notice optimizations on such a small scale. Personally I like to stick to .to() and .from() animations, because 90% of the time the element is already at there start or end position. I've personally never used gsap.registerEffect() and as far as I know it is used to create animations that can be easily configured to have some other values, but I don't know if in your cause your are overcomplicating your setup by using it. I would use gsap.registerEffect() when I have a specific animation, but I want to configure certain values to be different on different elements. I don't see that in your demo, so I don't know if it is the perfect fit here. I've forked your demo and add some CSS/JS to fix FOUC, see post bellow. Below the demo without the gsap.registerEffect() and .from() animations, hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/bGjoevP?editors=0010
    3 points
  26. Hi, On top of Sam's great advice and solution, I normally use this solution for dynamic endless loops: https://codepen.io/GreenSock/pen/RwBZvpp The only difference is that for endless loops the timeline has a repeat: -1 and after the loop I add the fade in for the first element of the collection, something like this: const keywords = gsap.utils.toArray(".keywords li"); const tl = gsap.timeline({ repeat: -1 }); keywords.forEach((word, i) => { const nextWord = keywords[i + 1]; tl.to(word, { autoAlpha: 0, duration: 2 }, "+=2"); if (nextWord) { tl.to(nextWord, { autoAlpha: 1, duration: 2 }, "<"); } }); // First keyword tl.to(keywords[0], { autoAlpha: 1, duration: 2 }, "<"); @Sam Tremblay killing each instance would be a good practice, although, as far as I know, as soon as the GSAP instance is completed and since it won't be played again GSAP will make it available for garbage colletion (same happens when you manually kill/revert and instance). Happy Tweening!
    3 points
  27. Hi @Mexys welcome to the forum! I would make the third section part of the element you are pinning, so that they both pin with the scroll trigger set up you have. Personally I like GSAP to handle all my logic, so I've removed your transform .section2Left {transform: translateY(-300%);} and changed your .from to a .to, so that I can handle all my logic in GSAP. You have three elements, but only two of them need to move, so this is 100% times 2, so as you can see in the below demo the first a last image stop at the same point. Your elements are not centered by default, so I would fix that with CSS first before going to GSAP, you could wrap all you images in container and make that container the height and width of the element and center your smaller green squares in there, this way you don't have to create arbitrary margins to have them faked being in the center. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/abjwLYB?editors=0010
    3 points
  28. You forgot to scope your pinned elements https://codepen.io/mvaneijgen/pen/GRBmwxR?editors=0010
    3 points
  29. Hi, @Carl has you covered with this great video and a codepen example as well (be sure to watch the entire video in order to truly and clearly understand the process): Also you should definitely check Carl's GSAP courses, he's a great teacher and you'll find hundreds of great lessons as good as the video above: https://www.creativecodingclub.com/bundles/creative-coding-club?ref=44f484 Hopefully this helps. Let us know if you have more questions. Happy Tweening!
    3 points
  30. Thanks for reporting that, @call007! It should be resolved in the next release which I dropped into this fork: https://codepen.io/GreenSock/pen/rNrjqWy?editors=1010 In the meantime, though, you can just add this one line of code to fix 3.11.4: smoother.scrollTrigger.getTween().resetTo("totalProgress", 0); (Obviously that entails saving your ScrollSmoother as a variable named "smoother") Better? Sorry about any confusion there!
    3 points
  31. Hi, Because structurally it is inside the first panel. Keep it outside of panels. https://codepen.io/tripti1410/pen/rNrjrRb
    3 points
  32. Hi @Vicky27! You have a pretty good start here. A couple of things, though - like @geedix says, you're mixing GSAP 2.X and GSAP3 syntax here, so be careful with that. You no longer need TimelineMax, as it's included with GSAP - just use gsap.timeline(). Also, get used to using the < and > notation at the end of your tweens to insert your animations either at the end of or the beginning of the previous animation. I find it much cleaner than using the delay property. For example, if I have animation A and animation B, I can write something like: // pseudocode - just to give you an example gsap.to(animation A, {...}) gsap.to(animation B, {...}, '>') One other thing - autoAlpha and opacity aren't the same. I find it easiest to pick one and use it consistently. Opacity turns a thing invisible; autoAlpha turns it invisible and sets it to visibility: hidden, which removes it from the document flow, meaning you can't click on it and stuff like that. As far as your images, once again, @geedix is correct, in that you can either use <img> tags, or <div> with background images set in css. If you choose the latter, go ahead and use your @2x resolution image (ie. twice the dimensions, as you said), but using css, just set its background size to cover. I tweaked your code a little bit here, with some comments to explain what I was doing! https://codepen.io/flysi3000/pen/OJwWwWb?editors=0010 One last thing, if you are interested in learning from someone that I learned a ton from, starting way back in the Flash + ActionScript days, check out @Carl's site, https://snorkl.tv.
    3 points
  33. Hey there. As long as you've got objects with numeric values (like you do, using blotter.js) you should be able to tween on them directly via GSAP. This bit here is from the getting started article: What else can I animate? [...] Any numeric value, color, or complex string containing numbers GSAP doesn't need DOM elements in order to animate properties. You can target literally any property of any object, even arbitrary ones you create like this: let obj = { myNum: 10, myColor: "red" }; gsap.to(obj, { myNum: 200, myColor: "blue", onUpdate: () => console.log(obj.myNum, obj.myColor) }); Just hook it up to a ScrollTrigger and you should be good to go (I know you've used ST before, so I'm going o leave that up to you ) https://codepen.io/akapowl/pen/oNMBWRO
    3 points
  34. Hi, I see a few things. You're loading gsap 3, TweenMax and TimelineMax, but all you need is gsap 3, which includes a timeline. You don't need both image tags and background images for the same image. Since you're using background images, set the css for those to background-size:cover and then scale the div. The point of using a timeline is that you don't need to use delays, you can just use the position parameter - https://greensock.com/docs/v3/GSAP/Timeline Let me know if you're still stuck and I can make some edits for you.
    3 points
  35. Thank you guys! I did learned a lot from this. I hope it can also help somebody else in the future - as many other topics here helped me. I'll try to show up from time to time if I feel I can contribute with somebody else's question, as I get more experienced.
    3 points
  36. that was my first guess too @Rodrigo however, it seems that on further inspection it is using a triangular clip-path that animates to a full rectangle. Here is a screen shot @iuras I had a similar demo from my GreenSock courses so I made a few tweaks to the polygon coordinates. Maybe this will help https://codepen.io/snorkltv/pen/BaPLVmL
    3 points
  37. Hi @violacase, Here it is with GSAP 3 syntax. https://codepen.io/sgorneau/pen/abjmzvW Happy New Year!
    3 points
  38. The answer very likely is: That's a bad idea, since all the heavy work ScrollTrigger does will be done on refresh, which is why it's mostly only called 'automatically' by ScrollTrigger on load and on/after resizes. This is thread has a more profound answer, that I got when I tried to do something similar to that with smooth-scrollbar.js... ... that was before ScrollTrigger.scrollerProxy() was added to ScrollTrigger (you can see mention of it further down in that thread) - which is what you are likely looking for if you want to hook up ScrollTrigger to your own smooth-scrolling script.
    3 points
  39. Hi, You could use a mask or a clip-path in order to show the fill from the bottom using GSAP: https://codepen.io/GreenSock/pen/poZEoam Hopefully this helps. Happy Tweening!
    3 points
  40. Welcome to the forums, @AlexanderGS The problem is that React 18 calls your useEffect() TWICE in strict mode! Very annoying. It has caused a lot of headaches for a lot of people outside the GSAP community too. .from() tweens use the CURRENT value as the destination and it renders immediately the value you set in the tween, so when it's called the first time it'd work great but if you call it twice, it ends up animating from the from value (no animation). It's not a GSAP bug - it's a logic thing. For example, let's say el.x is 0 and you do this: useEffect(() => { // what happens if this gets called twice? gsap.from(el, {x: 100}) }, []); The first time makes el.x jump immediately to 100 and start animating backwards toward the current value which is 0 (so 100 --> 0). But the second time, it would jump to 100 (same) and animate back to the current value which is now 100 (100 --> 100)! See the issue? In GSAP 3.11, we introduced a new gsap.context() feature that solves all of this for you. It makes cleanup super easy. All you need to do is wrap your code in a context call, and then return a cleanup function that reverts things: // typically it's best to useLayoutEffect() instead of useEffect() to have React render the initial state properly from the very start. useLayoutEffect(() => { let ctx = gsap.context(() => { // all your GSAP animation code here }); return () => ctx.revert(); // <- cleanup! }, []); I'd strongly recommend reading the React article at So in your demo... // OLD useLayoutEffect(() => { titleH1Refs.current.forEach((element) => { gsap.from(element, { opacity: 0, y: 20, ease: Expo.easeInOut }) }) }, [titleH1Refs.current]); // NEW useLayoutEffect(() => { let ctx = gsap.context(() => { gsap.from(titleH1Refs.current, { opacity: 0, y: 20, ease: "expo.inOut" }); }); return () => ctx.revert(); // <-- cleanup! }, [titleH1Refs.current]); You don't need to loop through each element and create a separate tween for each one. You can feed them all into one. It's totally fine if you prefer that loop - it's just not necessary. You might also want to look into the selector scoping in gsap.context() because it can save you from the hassle of creating/managing a bunch of Refs. Enjoy!
    3 points
  41. Hi, We just created a couple of collections with starter templates for using GSAP, ScrollTrigger and ScrollSmoother in Svelte and SvelteKit. Svelte https://stackblitz.com/@GreenSockLearning/collections/gsap-svelte-starters SvelteKit https://stackblitz.com/@GreenSockLearning/collections/gsap-sveltekit-starters Adding page transitions animations is on our todo list, so as soon as we have something in that area we'll make an announcement in this thread. Happy Tweening!
    3 points
  42. @Rodrigo Big thanks, I'm new to GSAP and learning alot since I've started working with it, I've copied and pasted this sandbox that I've found on the internet because I'was too lazy to implement one-to-one copy of my production code, I'm using the latest version with context and everything. I've tried to tweak the params with hardcoded values but somehow couldnt get it working. Now it all makes sense, thanks again this solved my issue!
    2 points
  43. I think the reason for why it doesn't work properly after a page-transition, boils down to the fact, that for a certain period of time within barba's lifecycle, both, the old and the new container will live together in the DOM. Now while you are initiating your new locomotive-scroll instance everytime with reference to the new barba-container, your scrollerProxy is only being created with reference to '.smooth-scroll', which will be available in both, the old and new container at that time - and since the old container sits above the new in the DOM tree at that time, you will be referencing the old container's .smooth-scroll with that. You can check the difference between the two elements you are targetting by logging out console.log(smoothScroll.parentElement.getAttribute('data-barba-namespace')) vs. console.log(document.querySelector('.smooth-scroll').parentElement.getAttribute('data-barba-namespace')) in your initSmoothScroll function. So you can either simply just change the element you are targetting in your scrollerProxy to be the same you are targetting when creating your locomotive-scroll instance, or alternatively just remove the old barba-container at the proper time since you don't need it for your type of page-transition anyway. Both options resolved things for me. Hope they do for you, too. Thanks for the heads-up btw @Cassie - was scratching my head for a minute or two there, before I saw that.
    2 points
  44. I'm very happy! right now it is very frustrating when you see your code more than 100 times and you don't find the fault, I have to say that in your answer it was only missing a loop without end, I just added it and it was like this, I hope this will also help someone else who needs it. https://codepen.io/juan-alvarz/pen/zYLEYEZ simply added gsap.timeline({ repeat:-1, repeatDelay:1, yoyo: true }) with this the animation continue without end Thanks Rodrigo, you're my hero πŸ™‚
    2 points
  45. Hi, As Jack points out, is better to create your GSAP instances inside the layout effect and inside GSAP Context. Another option is to create the a ref that will hold the GSAP timeline and then create the timeline inside GSAP Context. Something like this: const tl = useRef(); // tl.current is undefined at this point useLayoutEffect(() => { const ctx = gsap.context(() => { tl.current = gsap.timeline(); }, scope); return () => ctx.revert(); }, []); const playTween = () => { tl.current.play(); }; const reverseTween = () => { tl.current.reverse(); }; Of course this is missing the feature to add new instances to the timeline, so in that scenario is better to follow the pattern Jack posted in the example he created, but is worth mentioning how to approach a scenario when you need a reusable GSAP instance (Tween/Timeline) in your app/component. As for adding tl to your dependencies array, that's a tricky one actually. Normally I don't add them because I either use a ref or create them inside the layout effect hook. If for some reason you still create them outside the hook eslint will ask for it, but the real question is if the code inside the effect hook needs to run again once that is updated and normally the answer to that is no. But as mentioned before, just avoid creating the GSAP instances in a constant or variable at the root scope of your component and create them in the layout effect hook or a ref if you need to access them somewhere else in your component. Happy Tweening!
    2 points
  46. Hello @aok! Try this: https://codepen.io/sam-tremblay/pen/wvxqEgW EDIT: Hey @GreenSock, does kill the tween on each complete is a good mind to adopt or not?
    2 points
  47. You didn't load GSAP in your demo, took me a while to figure out why it wasn't working. Maybe next time share a working demo, so if someone wants to jump it they don't need to first debug your pen. I've set your stroke offset to be a multiple of 60, because your stroke-dasharray is 50 + 10 = 60. 120 seemed like a nice speed. Then I've set the animation to repeat: -1 eg infinite and the ease: "none", so that the animation is linear and perfectly repeats it self. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/PoBmXRK
    2 points
  48. Just add the GSAP bonus plugins to your .gitignore file before you add the repo to github. Here some docs on gitignore setup: https://git-scm.com/docs/gitignore
    2 points
  49. It looks to me like the problem has nothing to do with registering the plugin - you just set the scroller incorrectly: // wrong scroller: '.panel-container' The page/body is what's actually scrolling. Your code was telling ScrollTrigger to watch ".panel-container" for scrolling events and that the scroll positions should all be relative to that scroller...but that element isn't the scroller Delete that line and you'll see (because it'll use the page/body as the default). Right?
    2 points
  50. Hey there! Your SVG export has some transforms inline which were throwing off the positioning. Here you go! A little tidier. https://codepen.io/GreenSock/pen/PoBZdvW SVG export tips - styles to presentation attributes - flatten transforms - run through https://jakearchibald.github.io/svgomg/ to tidy Hope this helps!
    2 points
Γ—