Jump to content
Search Community

akapowl last won the day on April 1

akapowl had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


akapowl last won the day on April 1

akapowl had the most liked content!

About akapowl

Profile Information

  • Location
    NRW - DE

Recent Profile Visitors

13,536 profile views

akapowl's Achievements

  1. Just did 👍 Edit - For anyone wanting updates on this: Since that is not considered a regression of the fix for the original issue, it got opened as a new issue. https://issues.chromium.org/issues/332328859
  2. Thanks! ...let's just hope they don't take it as an April Fools' Day prank.😅
  3. @jdhadwin Hello there. While your demo is not exactly minimal, which makes it kind of hard to see through everything, on a quick glimpse I noticed, that you are trying to animate svg elements that are in <g> groups from a scale of 0, which I think is at least part of your problem - and I don't think this specifically is GSAP related. I stumbled upon this a few days ago, too - happening for me in all Chromium based browsers on Windows 11. It appears to be a bug in the chromium browser base that was already reported in September 2022 by @Cassie and later marked as solved from what I can tell reading that old bug report - but now it seems to have resurfaced. @Cassie if you find the time, could your maybe re-new that report or something like that? ... I have absolutely no clue how those work, tbh. https://issues.chromium.org/issues/40240236 These following pens don't use GSAP at all - and as you should be able to see, when elements in groups are being 'manipulated' so they start out with a scale of 0 and then changed later on, their values will get changed properly inline on the element - but the element just won't get rendered then (unless you resize the window along the process, e.g., or scroll the SVG fully out of viewport and then back into view again). https://codepen.io/akapowl/pen/vYMWZrL This will not happen with elements that are not in <g> groups, though. https://codepen.io/akapowl/pen/QWPOgzm What helped for me as a workaround was to tween from a very small scale like 0.001 instead of absolute 0. Maybe that can help you out somehow, until that issue gets resolved again. I will add, that this is just something I was able to quickly notice. If it doesn't help in your case, and you suspect that there still might be some issues with GSAP, please create a demo that is boiled down to the bare minimum but still reproduces the issue you're having, so it is easier to identify for others, what could be causing it. https://codepen.io/akapowl/pen/dyLZzyM
  4. 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.
  5. 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
  6. 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
  7. 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
  8. You are loading tailwind.css via the settings in the HTML section. Without tailwind, the !important statements don't matter at all, it seems. So it looks to me like it is actually more of a tailwind question; and you'll have to find out what tailwind does to your button. To be honest, asking a plumber why the lamp in your living room is flickering, might not be the best approach for seeking help. If you can not find the issue yourself, I'd suggest asking in one of tailwind's support channels, e.g. their discussion forum on GitHub. https://v1.tailwindcss.com/community https://github.com/tailwindlabs/tailwindcss/discussions
  9. Hello there. The documentation has the answers to your questions. 1. You'll want to look for the scroller property. https://gsap.com/docs/v3/Plugins/ScrollTrigger/ 2. No, unfortunatelly it is not possible for ScrollSmoother to have it smoothen the scroll of a different element than the body. https://gsap.com/docs/v3/Plugins/ScrollSmoother/#faqs
  10. The place it tweens to is actually not random at all in your case, but exactly what you tell it to. In your current case with feeding in an object of x:0 and y:0 to the convertCoordinates method what you will get in the end is the distance of the dragged element to your point element on both axis anytime you release - but then to your tween you're feeding those as absolute values, so it will always tween to that absolute point from the draggables origin - try getting very close to your point and you'll see that you'll end up very close to where the dragging originated. Or alternatively just log the values and compare them with the values of the transformMatrix on the element after the tween is done - logging values is a always a huge help with identifying your problems, btw. So I see two ways you could go about this: Keep the object at {x: 0, y: 0} but instead of using absolute values for your tween, use relative values like x: "+=" + point.x https://codepen.io/akapowl/pen/XWQXaLa Keep your tween at the absolute values, but instead feed an object of the current coordinates of the draggable object to the convertCoordinates method - something like {x: this.x, y: this.y} https://codepen.io/akapowl/pen/yLrezgX I will say, that since I never had the need for that method before myself, I can't give you much of a guarantee for any of the two ways to be the right way to go - and if something is inherently wrong with what I suggested, I'm sure someone with some more experience on that will pop in to help out. While version 2 to me feels like it's more in line with what the documentation says about the object you feed into the convertCoordinates method; ... after a bit of tinkering, it also feels like version 1 seems to work more reliable with quick drags and releases. In general though, both versions should work in your current case; but one might be better or worse suited for you when extending your usecase. I hope this will at least help in some way.
  11. TLDR: At the bottom of the post you'll find an example for how you could approach it. Nonetheless, I think reading through all this can help get a better understanding. I think that would definitely be the best way to go, if you want a solid answer - because what you are asking is heavily about how three.js works to begin with. My attempt at a short answer would be: you can not easily do that in a way that it would logically work the same as e.g. changing the object.rotation.y does. And here is why (please keep in mind that I am no full-fledged expert with three.js though): While object.rotation.y (or x or z) is a 'property' of your 3D model that three.js gives you access to, you can easily set it - e.g. by tweening on it via GSAP. object.geometry.rotateY() on the other hand is a method - it is a function you can execute on that object, where internally three.js will do all the work with the value provided by you. So for starters it is not a simple value you can easily manipulate via GSAP. https://codepen.io/akapowl/pen/ZEPgYLP As you can see in the codepen above, technically of course you can tween a value you set up on an object of your own via GSAP and onUpdate of that tween call that method provided by three.js - but: a) it will not work in the same way as tweening on the object.rotation.y in the same way would - because you are only providing a value to another pipeline (i.e. the rotateY method of three) which then again does different things with it. With some trickery around the tweening on the value you sure could settle on similar behaviour - but that would really be logic for you to figure out. Just for illustration purposes, here is that same tween (albeit with different numbers) on the object.rotation.y value to show how it behaves different. https://codepen.io/akapowl/pen/vYPoNyq Now in the first pen you could e.g. get a similar effect of yoyo-ing back and forth between the two values by simply using a linear ease or an ease that goes in and out - so you see it is not impossible to achieve similar behaviour. I'm just saying that because of that extra pipeline you'll have an extra layer of abstraction and complexity added to how you'll have to approach things, which would be all yours to figure out in the process. Still I wouldn't really recommend doing that though, because... ...probably even more importantly b) You probably should not really consider doing that all that much to begin with. What three.js does under the hood of that method is to calculate the position of every single vertex of your model; as this answer on a stackoverflow post mentions: https://stackoverflow.com/questions/71506350/three-js-set-absolute-rotation-of-sphere-rather-than-cumulative-rotation#answer-71506597 That can already be taxing with simple 3D shapes, but depending on the level of detail of your model(s) this can become rather hefty rather quickly. You can certainly access and manipulate the values neccessary to do that in different ways in JS already - like e.g. by using three's BufferGeometry instead three's provided 'pre-made' geometries, but even then the calculations would be quite a bit more complex than just setting one single value somewhere. And since you say you are loading a .glb model, that will very likely not be a way to go for you anyway. Another way you could think about doing it would be to use a shader that you provide with a value you tween on via GSAP. That would probably be a whole lot better with regard to computation cost because you could outsource all the calculations based on that value to the GPU, but it would also be a whole new world you'd open up outside of JS - and the complexity of the calculations would still stand on top of that. So yeah, depending on the level of control you want to have over what you're doing, personally - with my limited knowledge about three.js - I don't think what you are aiming to do is as easy as you might think. But maybe I'm totally off track somewehere here, and the folks over in the three.js forum can provide you with some better input and an easy solution. If so, it would be great, if you'd post back here with what you found out. Good luck! ---- Edit: Alright, I played around with it a bit now, and have now stumbled upon an oversight logic-wise, that has a huge effect on how things behave. In the first example above, I am just providing the value I am tweening on to three's .rotateY method, which does cause the appearance of 'no control' because every tick I am basically telling three.js: 'add that value the tween is currently at to the rotation'. So along the tweens duration, the rotation would add up more and more and get vastly out of what I wanted it to be. An easy way to fix that is to keep track of the rotation value in an extra variable that I called oldValue in the pen below. Now in the onUpdate callback, I subtract that oldValue from the value the tween is currently at when passing it to three's .rotateY method. And after that, I set this oldValue to the value the tween is currently at. This way I can make sure that every tick only the difference between the previous tick and the current tick will get added to the rotation. And now it behaves just like the example with tweening on the object.rotation.y does. Note, that I am now also using three's built in MathUtils.degToRad, so instead of just some arbitrary values, I can work with to me far more familiar degrees instead of radians. But for the aforementioned reasons with regard to it having huge potential for killing performance, I probably still wouldn't really recommend doing that. Maybe thiss will help you out, though. https://codepen.io/akapowl/pen/qBvebOB
  12. Why would I be lying about what I said or intentionally give you advice that I don't think will help!? 😂 Might just be me, but I think a button either works or it doesn't; not sure what you mean by 'it almost works'. The reason it sometimes works for you with opacity - and other times doesn't - is probably related to elements with an opacity of 1 having a different stacking-context than elements with any other opacity but 1, e.g. 0 or somthing in between like 0.857694857; that also pretty much correlates with what I explained in the post above; about being on scroll-positions in between. That is a browser thing - nothing related to GSAP in any other way. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context So when you're right on spot and an element's opacity is at 1 exactly - it will appear above all the other elements that do not have that opacity of 1 and thus it will be perfectly clickable. But if all the elements do not have an opacity of 1, they will all share the same stacking-context, and since the last element sits on top of all other elements z-wise within that stacking context, this element and no other will be clickable in those cases. Does that make sense to you?
  13. Hello @newguy123 The most profound way to debug your code is to use the dev-tools of your browser; e.g. right-click on elements you want to inspect and see what gets selected in certain scenarios when selecting 'inspect element' from the context menu. In your case, when the scrollTo-tween is fully done, so the scrollTriggered animation is where you want it to be, your buttons will work as expeted; but when the scrollTo-tween isn't fully finished, or you are generally in a state / at a position in between, this is what will always get selected on click: I don't have the time to look through all your code in too much detail, but that likely is the case because you seem to solely rely on opacity. Opacity will only change the element visibly; that doesnt mean that items that sit above it on the z-index won't be clickable though. So you'll need to change that - a CSS property that can help you there is visibility; you'll need to also handle that for your elements. Luckily for you, GSAP has a property that combines both CSS properties (opacity and visibility) into one in a way it spares you the head-ache to figure out proper logic for that. https://gsap.com/docs/v3/GSAP/CorePlugins/CSS/#autoalpha So just exchanging opacity with autoAlpha in the tweens of the tl in your forEach loop should already help a lot with that. I hope that will help. Cheers.
  14. Looks like Mitchel was right 👍- for that you really wouldn't need an onReverse callback. Here's just two ways you could handle something like that - and there's probably a couple others beyond those. I hope these will be helpful already, though: Depending on the index of the dot (to make sure neither the first nor the last will get toggled at the end in any direction), you could .add() functions before and after each of your tweens to toggle the class . https://gsap.com/docs/v3/GSAP/Timeline/add()/ https://codepen.io/akapowl/pen/yLwxXgX Or (even better) with similar logic with regard to the index, have things handle via GSAP altogether with .set() calls; unless you really need that active class, like maybe for something else outside of the pure styling. https://gsap.com/docs/v3/GSAP/Timeline/set() https://codepen.io/akapowl/pen/yLwxXMX Some hints with regard to syntax: // Instead of this: tl.to(dot, { rotate: "180deg" }) // You could just do this: tl.to(dot, { rotation: 180 }) https://gsap.com/docs/v3/GSAP/CorePlugins/CSS Also there is no such ease as 'linear' - if you want linear interpolation, ease: 'none' is what your looking for. If I am not mistaken, any invalid ease like that would fall back to the default ease of 'power1.out'. Edit: It looks like 'linear' seems to be accepted though, and will result in no easing 🤔 And apparently that is the case since like forever in GSAP3 ...didn't even know that 😅 https://gsap.com/docs/v3/Eases/
  15. While I definitely agree that a lot of times that might be true - probably even most of the time - I certainly wouldn't agree with 100%. There definitely are usecases where an onReverse can be handy in cases outside of events. That's why there also is a work-flow example in the helper-functions section of the docs that explains how to create your own custom onReverse() callback functionality, @MarcoCuel. https://gsap.com/docs/v3/HelperFunctions/ https://gsap.com/docs/v3/HelperFunctions/helpers/trackDirection/ It comes with caveats though - e.g. logically it will take one tick to update the direction as is explained in the orange 'caution' box over there - thus you might have to accomodate your own logic to that fact if you want to trigger things onReverse appropriately then. Some of the reasons that it is not included in GSAP's core are, that having it external like that keeps the core lightweight and doesn't require extra processing on the vast majority of animations that don't need this functionality. That last part comes directly from Jack (@GreenSock). If you have more questions, I'm sure he'll be able to answer them.
  • Create New...