Jump to content
Search Community

Leaderboard

Popular Content

Showing content with the highest reputation on 03/15/2024 in all areas

  1. Then logically you'll need to make sure that your video is appearing on the page further up than it is now. You could e.g. calculate the distance it takes to scroll from when the 4s start fading out in your one ScrollTriggger until the point where your video enters the viewport now and then you'd know by how much you'd have to offset your video to the top for it to enter the viewport when the 4s start fading out. And this you'd have to of course do before you set up your ScrollTriggers for the video. Or - since your airpods Scrolltrigger is dependent on the window height anyway - just set a vh value that fits for you via CSS, e.g. via a negative margin-top on your video container. That is what I did in the codepen below. A bit of a warning though; keep in mind that since you have a numerical scrub on your airpods scrollTrigger, the scroll of the video and the fading out of the 4s will never be truly 'synced' - which will become more apparent when you scroll fast. You are adding the tweens for the fading of the video to your first timeline - which has a scrub set. I'm not sure if that is what you want to begin with, since you added the tweens at the very bottom of your JS after you created all the ScrollTriggers. And if you add it to the pinning Scrolltrigger like you do, of course it will only start fading in the opacity once the video has reached the top, and then the 'over-scrolling' you were trying to achieve wouldn't make any sense at all anymore. So you'll probably want to add the tweens to that other, non-pinning, ScrollTrigger instead and also set it to scrub. That out of the way, here's something from the article on the most common ScrollTrigger mistakes: https://gsap.com/resources/st-mistakes/#how-to-make-scrub-animations-take-longer ------ BTW - @GreenSock @Rodrigo @Cassie - there's a wrong link in that blue information box in that section of the article. It is an old URL which previously pointed to this content: https://gsap.com/docs/v3/Plugins/ScrollTrigger/#how-does-duration-work-with-scrub-true But although the general concept of how durations work with scrubbed: true is explained there, there isn't any mention of empty tweens as suggested in that blue information box - sort of confusing altogether. Edit: I also found a typo in the docs for the position parameter with regard to percentages, that I'm mentioning further down the post. Reporting it here, where it might be better to catch. ----- That second link explains how durations work with scrub: true, @newguy123 - you should have a thorough read on it to understand the concept. I added some comments in the codepen below that might help better understand it in combination with what the docs say. In that codepen I also make use of the aforementioned empty tween to create a 'gap' where nothing happens between the fading in and fading out. So I also got rid of your approach with the position parameter - of course you can do it with the position parameter, too, but you'd have to use the proper value - and for understanding how durations work with scrub: true to begin with it might be easier to work with empty tweens at first. Also, I'm pretty sure the value you use for the position parameter (i.e. "99%") again is invalid. Here's what the docs say with regard to percentage values in the position parameter. You see, a percentage value without any prefix is not listed in there. In your example you could in fact change it to "0%" and it would still behave exactly the same as it does now. https://gsap.com/resources/position-parameter/ That all said, here's the codepen. https://codepen.io/akapowl/pen/ExJNxJO
    3 points
  2. There's acctually a couple of things problematic with your example. You've got transforms apllied to the video element (which you use as the trigger and want to pin) and also to its parent element; they are likely going to mess with ScrollTrigger in some way - so unless you know exactly what you're doing I'd first go without them. Your video and its parent have a lower z-index set than the subsequent containers. So even if things would work right for you with regard to ScrollTrigger, the video would still sit on top of the subsequent containers which thus you would not get to see then until the video got unpinned. You are using an invalid value for your end. With ScrollTrigger a window's height is represented in % and not in vh. vh units are not valid with ScrollTrigger if I'm not totally mistaken. your start: "top bottom"doesn't make much sense for a pinning ScrollTrigger. If pinning something when its top hits the bottom of the viewport you will never see it getting pinned, as it is not in viewport that whole time then. If you want to trigger the video to start playing earlier, while pinning it at some different point, you'll probably have to use two different ScrollTriggers. As video elements can be a bit tricky to handle to some degree, I would suggest not pinning the video element itself but its wrapping container instead. Just set pinSpacing to false and you'll get the same effect you're after. All those things changed, you should already see something working a lot better. https://codepen.io/akapowl/pen/QWPKoPM
    3 points
  3. That is because you have a huge margin-left set on the .pinWrap via CSS which is not included in any way within the values you are currently using and you never add it to your calculations in any form. If you'd do so, it'd work just fine. I multiplied it by 2 here so basically it will end up with the same spacing on the right now when the tween is finished. https://codepen.io/akapowl/pen/zYXKbyJ
    3 points
  4. Hello @GreenSock @Rodrigo, and thanks for looking into this ! First approach makes sense, I although did try locally to have the length as a parameter but that didn't help it (using useEffect, so maybe by using useGSAP it will work nicely ) Sounds good for next release, thanks a lot for the quick fix and taking a deeper look into this little edge case ! I'll probably do a combination of all approaches, swap out useEffect for useGSAP solution everywhere and use the scrollTrigger beta version Thanks again, will give it a go and mark as resolved once I get it running perfectly !
    2 points
  5. https://gsap.com/docs/v3/Plugins/ScrollTrigger/ It's because one of those is a tween on a ScrollTrigger with scrub: 1 - so it will take 1 second to catch up to the scroll position - and the other one is natively scrolling. So there will always be a discrepancy between the two - which will only become more apparent the faster you scroll. If you want both to behave the 'exact same', set scrub: true instead of scrub: 1 to your airpods ScrollTrigger. You'll lose the smoothness of the scrub then, of course. Or instead tween the 'over-scrolling' of the video via a ScrollTrigger that also has a numeric scrub of 1 set. But then, one way or another, you'll get a discrepancy again between that video container and the subsequent containers which would scroll natively. At this point you might end up in a 'tween everything' approach like Mitchel (@mvaneijgen) suggested in his earlier answer with the thread he linked to. An alternative to that approach could be to use overall smooth-scrolling instead, e.g. via ScrollSmoother alongside scrub: true on the airpods ScrollTrigger. Technically it's also a 'tween everything' approach - just on another level. And you'll lose some native browser features like e.g. jump-to search via F3. Is it worth the extra mile? Depends on how much you're a sucker for detail and how much the - most of the time visually small - asynchrony bothers you. Is any one better than the other? Depends on you again. Each of them has its downsides, if you ask me. Personally I'd go with the overall smooth-srolling - but that is merely a suggestion, not a recommendation by any means. It will definitely add another level of complexity with some regards. The latter - here it was just to keep track of what marker is related to which ScrollTrigger. But it can also be a helpful tool if at any point in time you might need to target any specific ScrollTrigger on your page for whatever reason logic-releated.
    1 point
  6. This sounds like the issue discussed here: https://github.com/darkroomengineering/lenis/issues/311#issuecomment-1986531084 It's not a GSAP/Observer problem - it's a very weird Firefox behavior that Lenis doesn't handle properly but I think they're working on a fix.
    1 point
  7. Hi, On top of @akapowl's great advice and demo, maybe this thread can help as well: Happy Tweening!
    1 point
  8. @mvaneijgen Thanks again for your reply. I like the way you explain things, and that got me thinking. Finally, I found the solution. Thank you so much. Can I get one last help? In the previous post, you told me, 'The best thing to do when working with ScrollTrigger is to remove it!' This seems counterintuitive, but ScrollTrigger is just animating something on scroll. I would like to know more about this, like for example: the way I'm doing is kind of doing both at the same time (animation and scroll). How are you approaching this, and what are the best practices? Because I'm really looking forward to learning animations and GSAP. It would be great if I could get knowledge from experienced people. Thank you once again for your time and reply.
    1 point
  9. Take a look at your start and end triggers. Instead of video.play() and .pause(), console.log('onEnter has fired') and check the console if what you think should happen is happening. For the stacking of element and then animating check my post of creating a stacking card effect, but in stead of cards you have a video and two pieces (or three) of text. Hope it helps and happy tweening!
    1 point
  10. The best thing to do when working with ScrollTrigger is to remove it! This seems counter intuitive, but ScrollTrigger is just animating something on scroll, so just focus on the animation at first and only when you're happy with the animation add ScrollTrigger back in. This way you can focus on one part at a time and it will save a lot of headache when debugging. In your case you want to move the elements to the left on the x axis, the x (translateX in CSS) starts at 0 and positive numbers move to the right and negative numbers move to the left, so adding a minus sign (-) for your number makes it move to the left. Using AI is all fine, but you do have to test the values it gives you (for that matter, you also have to test your own logic) to make sure it is what you think it is! So when copying code from the internet you have to console.log() the values you're getting and test them if they make sense to you. In this case what I would do, is pick a fixed screen size and just manually type in a number until the animation looks like you want and then try to get these values dynamically. Getting the scrollWidth of the element gets you around 2000px, but moving that amount is a bit to much, so you subtract the window width from it, but that is to much, on my screen you should move around 1500px, so you need to get a random 500px from some where, where could this be? That I'll leave for to find. I've also moved to a timeline to which I've given ScrollTrigger control, this in my option makes the code much easier to read. Also you almost never need a .fromTo() tween a .to() or a .from() is all you need. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/WNWGYjG?editors=0011
    1 point
  11. Hi @Antibreez and welcome to the GSAP Forums! In this particular case is better to not tie the animation to ScrollTrigger and have it running on an endless loop, then use ScrollTrigger to play with the animation's timeScale property, like this: https://codepen.io/GreenSock/pen/NWmRMpy Finally I'd suggest this approach by @PointC, is far simpler and easier to maintain IMHO: Hopefully this helps. Happy Tweening!
    1 point
  12. Is this what you're trying to do?: https://codepen.io/GreenSock/pen/wvZGvjp I'd strongly recommend reading this article: https://gsap.com/react You weren't doing proper cleanup in React, and the useGSAP() hook solves that for you.
    1 point
  13. Here's a helper function I whipped together for handling lazy loading stuff: function handleLazyLoad(config={}) { let lazyImages = gsap.utils.toArray("img[loading='lazy']"), timeout = gsap.delayedCall(config.timeout || 1, ScrollTrigger.refresh).pause(), lazyMode = config.lazy !== false, imgLoaded = lazyImages.length, onImgLoad = () => lazyMode ? timeout.restart(true) : --imgLoaded || ScrollTrigger.refresh(); lazyImages.forEach((img, i) => { lazyMode || (img.loading = "eager"); img.naturalWidth ? onImgLoad() : img.addEventListener("load", onImgLoad); }); } // usage: you can optionally set lazy to false to change all images to load="eager". timeout is how many seconds it throttles the loading events that call ScrollTrigger.refresh() handleLazyLoad({ lazy: false, timeout: 1 }); Basically you just call the method and it'll manage calling ScrollTrigger.refresh() for you at the appropriate time. You can optionally pass in a config object to set everything to NOT be lazy (lazy: false) and you can also control how long it waits after each image loads to call ScrollTrigger.refresh(). For example, if 5 images load in quick succession, you shouldn't need to call ScrollTrigger.refresh() 5 times. By default, it waits 1 second to see if another one loads. If another one does, it starts the timer over again...so when 1 second elapses when no more images have loaded, it'll fire ScrollTrigger.refresh(). That improves performance. But again, I recommend not doing lazy loading. I definitely would not use that function you wrote - it's extremely inefficient. Literally on every single scroll event (those fire a LOT during scroll), it is doing CPU-intensive calculations to map all the position of every image. The function I provided above is many, many times more efficient.
    1 point
  14. Just to throw my two cents out there - some CodePen accounts to bookmark and/or follow. Talented coders that feature a ton of GSAP: Cassie Evans: https://codepen.io/cassie-codes Blake Bowen: https://codepen.io/osublake Carl Schooff: https://codepen.io/snorkltv Pete Barr: https://codepen.io/petebarr Steve Gardner: https://codepen.io/ste-vg Ryan Mulligan: https://codepen.io/hexagoncircle Tom Miller: https://codepen.io/creativeocean Chris Gannon: https://codepen.io/chrisgannon Darin Senneff: https://codepen.io/dsenneff Craig Roblewsky: https://codepen.io/PointC/ (this guy is awesome ?) It may not be exactly what you need, but there should some good inspiration in those accounts. Happy tweening.
    1 point
×
×
  • Create New...