Jump to content
Search Community

jh3y

Premium
  • Posts

    77
  • Joined

  • Last visited

Everything posted by jh3y

  1. Hey Jack @GreenSock Yep, I never assumed it would be recalculating on each replay ? It would work similar to other plugins, etc. My timelines were being generated in a function as were my flips ? But, that's the part that had tripped me up. The window resizes, I kill the timeline, and regenerate it within a debounced handler. debounce(() => { // Timeline that was generated with a function MAIN.kill() // Clear all the Flip setting of initial positions gsap.set('li', { clearProps: 'all' }) // Set them all again to the new positions of the things to Flip to. setFlips() // Regenerate the timeline. MAIN = genFlips() // ScrollTrigger stuffz window.scrollTo(0, 0) TRIGGER.disable() gsap.delayedCall(1, TRIGGER.enable) }, 250) Storing the progress wouldn't be necessary as ScrollTrigger's refresh would assign the scrub to the correct position on the timeline ? But, what was missing was regenerating the loop head for ScrollTrigger to scrub the time. All I needed was to kill the loop head and regenerate it ? Fixed. https://codepen.io/jh3y/pen/XWpvyxr
  2. Hey y'all! Quick one with this pen. Using ScrollTrigger to scrub a timeline that uses FLIP to shift in and out the different sections. On window resize, how can you reset the `FLIP` positions? I've tried a couple of different things but can't seem to find the one that should work and have left it as is with broken resizing ? - The `resize` handling is at the bottom. - `MAIN` is the timeline used for the FLIP transitions. - `li` are all the list items being FLIPped. I did think this was something with the ScrollTrigger. But, I think somewhere the FLIP settings get cached perhaps and I'm looking for some way to flush them perhaps? Timing and snapping are out of scope here. But, I did have a bit of an issue getting them nailed but I don't think I'm quite sure how I wanted this one to feel on scroll. It was purely an idea I wanted to see working with FLIP ?
  3. Yeah, that was kinda what I was looking for and wanted to avoid doing the "Am I clicking the left/right half of the track" part ? I came up with this in the end. It seems to scale well when I change the number of boxes, etc. document.querySelector('.boxes').addEventListener('click', e => { const BOX = e.target.closest('.box') if (BOX) { let TARGET = BOXES.indexOf(BOX) let CURRENT = gsap.utils.wrap( 0, BOXES.length, Math.floor(BOXES.length * SCRUB.vars.position) ) let BUMP = TARGET - CURRENT if (TARGET > CURRENT && TARGET - CURRENT > BOXES.length * 0.5) { BUMP = (BOXES.length - BUMP) * -1 } if (CURRENT > TARGET && CURRENT - TARGET > BOXES.length * 0.5) { BUMP = BOXES.length + BUMP } scrollToPosition(SCRUB.vars.position + BUMP * (1 / BOXES.length)) } }) Love that Draggable way of doing it! The proxy method popped up before when I made the light bulb tug and wondered if something similar could be done here ? That works nice on mobile and desktop ? Thanks!
  4. Hey @GreenSock Ahh cool. I did wonder if something with a proxy might work. But, my Draggable experience is limited to a few demos. Thanks for that. Erm. I'm not sure that is an error/problem. That only works because the spacing and number of cards align "perfectly". But, as soon as you change the number of cards or changing the spacing(STAGGER), the snapping will no longer work. If you try either changing the count to 50 cards or changing the spacing to 0.25, the demo will break. Whereas in my version, the snapping will continue to work with either value changed. There was one thing I had a little bit of trouble working out. But, I think that's because I've been looking at it for some time at this point. Calculating the offset of a clicked card from the center. If I click a card that's 2 to the left, how do I get `-2` from that to move the timeline ? Still messing with that. I'm sure there's a Math way with wrap to normalize the center point and the indexes somehow based on the current position. I think I've written out what I need to do there ?
  5. No worries. That was kinda what I was looking to find out with opening this thread ? "Was I missing something straightforward?". I haven't really played with nested scroll and ScrollTrigger ? I don't think I knew that there were two different pin styles. I think I assumed that `position: fixed` was already being used, not that it was being kept in place by `transform` which I should've noticed really ? As you say, `position: absolute` will do the trick and means I don't need to set anything on the child element ? Thanks!
  6. Hey @GreenSock ? The use case was about being able to pin something in a container that can be moved around. For when there's nested scrolling and I want to pin something in the container with nested scroll. I'm relying on CSS here where elements fix relative to the container if it has a transform or position relative. The idea is that it wouldn't be unpinned in the container kinda like the infinite scroller. It was more a case of wondering how this might be done. For example, I anticipate the content scroller might want to be put in its own container and moved around without relying on body scroll. Didn't know if there was an appropriate approach. But, the pen I posted seems to work for my needs ?
  7. Hey ? Yeah, that's almost the same approach which confirms it to me ? `position: relative` has the same effect as applying a `transform` on the container for `fixed` children. That demo you provided works with the `padding` removed and `height: 100%` set on the `#container`. In its current form, the green box will scroll up towards the end of the container ? But, thank you, this confirmed my thinking in how to approach it ? I have a sneaky suspicion there will be some requests to contain the scrolling demo I've been working on into portable containers and wanted to make sure I had the right idea for doing this before going forwards ? Thanks again! Jhey
  8. Howdy Y'all! ? This may be the way to do it or there may be a cleaner way ? But, if you want to `pin` something inside a `scroller` element, is this the way to do it? const TRIGGER = ScrollTrigger.create({ horizontal: false, trigger: '.scroller', pin: '.panel', end: '+=2000', scroller: '.scroller', onUpdate: self => { // Doing anything here for hypotheticals ? gsap.set('.panel', { rotate: self.progress * 360, }) }, }) The "trick" I'm using is that if you use CSS `transform` on the container, that will scope `fixed` to the container. Or is there another API way of doing this?
  9. That's awesome @GreenSock ? I think we're at a point where we can say this one has been answered ? Here's where I got to. Again, you're a hero! https://codepen.io/jh3y/pen/WNRvqJP
  10. jh3y

    NFTs

    I have minted and sold an NFT ? But, I did so through Rarible which only comprised of submitting the GIF/Video. Purely for experiment. But, who knows in the future. Not sure how different file types will pan out. Many people do things like have the NFT as GIF/Video but then offer unlockables on the side. For example, I think Beeple distributes pieces of the work in perspex frames with what is sold.
  11. Hey @GreenSock ? Appreciate this a lot! ? I'll make some time to go through it and swing my article in this direction ? I had built it up around the idea of taking three timelines and tacking them onto a main timeline. But, that can get confusing and looping over the elements three times is more intuitive once that timeline concept is in place. That's how I'll swing the direction shift I think ? Again. I appreciate this a lot. Looking forward to getting this one written up and sent off. Thank you for all your help. I still have a feeling I'll be posting in this thread again though ? I did have one idea which I have only pseudo-coded in my head. Would it be possible to use a Draggable proxy and drag the time? I imagine so, right? That would be cool. I imagine it will be a case of putting a threshold on how much distance correlates with the time scrub ?
  12. Hey @GreenSock ? That's fine! Thank you for the heads up. It's more relief that you can see a solution ? I'll happily wait on that haha. I'm interested to see how I've broken the navigation buttons too. I think it's linked to this. But the way I've tried making them has perhaps made it more prominent. I have some other GSAP content to make in the mean time ?
  13. Hmm. I've tried a couple of things here @GreenSock ? But to no avail. Perhaps there's a trick to stopping the snap from going into a loop or I'm missing a piece of logic. I noticed also in this demo you posted previously, I can get it to sit in an infinite loop where it rocks the scroll position. https://codepen.io/GreenSock/pen/qBqEZKg I have this issue in my demo too. The other issue I have though is that my buttons don't work for wrapping which is strange because the logic is the same from what I can see. Unless I'm missing a line somewhere. https://codepen.io/jh3y/pen/gOLQLYW
  14. I mean, I state that I usually use a `ref` pattern. But, I always use a ref pattern. I threw a concept demo for it together maybe yesterday though to see how it might look. I think for those comfortable, it's not necessary. It's using the DOM afterall. The rule, keep a handle on your state updates. That said, although some are comfortable, it doesn't mean that everyone is comfortable. And for convenience things, a lot of people reach for tools like Framer arguably because of that. They have a component that they drop in, throw some props on, and they're done. It's easy to take a skillset for granted and assume others have that same skill. But, if conveniences were offered to users, it would perhaps act as a gateway for those who want to explore more advanced GSAP usage who then look further at using refs more extensively. An example library that does this, React and ThreeJS. We could write all our ThreeJS code ourselves in an effect. However, React Three Fiber exists with convenience hooks and components to create meshes, etc. I guess what I'm getting at is that I wouldn't dismiss providing things like that for users if it were a stepping stone to using GSAP more extensively. Of course, only my thoughts and observations. As mentioned above. `innerRef` or `ref` depending on your Styled Components version should get the job done. I'd be happy to look at a demo if you have one though ? It should work the same as a normal element. const Spinner = styled.div` height: 25vmin; width: 25vmin; border-radius: 50%; border: 2vmin solid hsl(90, 80%, 60%); border-left-color: transparent; border-right-color: transparent; ` const App = () => { const spinnerRef = useRef(null) useEffect(() => { gsap.to(spinnerRef.current, { rotation: 360, repeat: -1, ease: 'none' }) }, []) return ( <Spinner ref={spinnerRef}/> ) } https://codepen.io/jh3y/pen/oNYQVrP
  15. The only issue with using regular CSS selectors is that you can get caught out if your components share classnames/attributes. With regards to refs, according to the docs, the callback ref gives you finer control over when to set the ref for an element. However, I've yet to find an instance where I've needed this for GSAP. I usually use a ref pattern. I have been playing with proof of concept pieces for how to create convenience components for React && GSAP ? The issue faced is how/what would be the nicest way to expose GSAP in React whilst still providing all the benefits. I think timelines could likely still live in effects. But, there are some different directions it could go in. Custom hooks, <GSAP.div yoyo duration={2}/>, <To scale={2}><div/></To>.
  16. Oh wow. These libraries look great! Thanks for sharing @Shrug ¯\_(ツ)_/¯ ? I imagine something like that could work. It was when I was making this pen. https://codepen.io/jh3y/pen/gOLjyrm The original path for the 'stache would've been cool to rig to a path that I could've morphed and had the 'stache path follow if that makes sense? Instead I opted to dig in a little more with working on path manually. But I thought I'd ask if anyone had seen/done this kind of rigging ? Hadn't seen or heard of this one before. Looks like a great tool to check out ?
  17. Looks like I've got hung up on the original issue @GreenSock hahaha ? Next/Prev buttons with this method. I have snapping in place. But, I can't get past an iteration with this method for some reason. I'm sure I'm missing something straightforward. I'm determined to get a draft of this article complete this week! https://codepen.io/jh3y/pen/WNoYoMY This works fine until I try to wrap ? Then it gets caught understandably I guess in an infinite loop. Is there a way to get out of the loop? My snap is set up based on the amount of elements which seems to work until I try scrubbing with the buttons. NEXT.addEventListener('click', () => { const DESTINATION = SNAP(SCRUB.vars.totalTime + (1 / BOXES.length)) scrubTo(DESTINATION) }) PREV.addEventListener('click', () => { const DESTINATION = SNAP(SCRUB.vars.totalTime - (1 / BOXES.length)) scrubTo(DESTINATION) }) I guess that's one issue I've not sussed out yet. It has the ability to get stuck in a loop of wrapping when progress is 1. Would it make sense to change the conditionals slightly?
  18. This one's fantastic! ? https://codepen.io/osublake/pen/vKdGAy I was thinking the other day about how to approach a certain demo and wondered, would it be possible to do rigging with GSAP? As in mapping one path to another. This demo kinda reminded me of it. I can imagine something like that would be very hard to calculate but wondered if there were any good examples in the wild. For example, if this demo was one polygon rigged to the underlying path.
  19. Yep! Exactly that ? Thrilled we're on the same page. This is quite the thread ? I can totally mention that optimization though. I think that's the part I originally struggled to visualise. Where that chop gets calculated. Now, I've been practicing the technique in the wild some more, it's kinda sunk in. I figured that might be what I needed to do. It's a real cool technique and definitely feels like unlocking a superpower when you start doing these "meta" things.
  20. Hey @GreenSock ? Ahh, that's perfect. Thanks! Makes a bunch of sense. That's my bad on leaving it as `repeat: -1` on the shifts. Completely right that it wouldn't make sense there ? That was the 17th part and I'd likely got a little flustered putting it together. That z-index part and positioning makes complete sense too. Looking at it again, not sure what I'm thinking there ?? I likely needed to step back for a moment! Do you think it makes sense to approach the scroll in this way? As in stacking the three timelines? I've found this maybe a little easier to incrementally build up to for people. I will revisit the original approach again though and see if I can break that down and relate it too ? This is all really useful. Thank you again Jack for all the help with this! ? ʕ •ᴥ•ʔ
  21. No problem at all! I'm going to take another look at the original method too and see if I can break it down again. I'll also get the snapping back that way too. I was intrigued to know if this way was also possible though ? As always, big thanks in advance with this.
  22. Hey @GreenSock Bringing the thread back to life! ? I'm trying to write up the article for this at the moment. Not going to lie, this is one of the trickiest articles I've tried to write. Happy to send you a draft link for it. Would be good to get your eyes on it. Anyway. I've got to a point where I'm explaining hooking up ScrollTrigger without the looping. I'm trying to make the technique as "verbose" as possible. The technique I'm using is adding a tween three times to a timeline and replaying a window of that timeline. But, when I hook this up to scroll I get a flicker if I try scrolling back up quick from the end. https://codepen.io/jh3y/pen/jOVzExq I'm not 100% sure what's causing that. Any ideas? Or is this a drawback of trying to go about doing it this way? I'm thinking this might cause more issues when it comes to wrapping , etc. I notice that this way, I've also made a mess of the snapping ? Perhaps I need to go back to the drawing board and find a better way of explaining the original approach. I felt like doing the three timelines was a good way to explain it and then introduce the padding/overlap concept once the idea has sunk in. I'm trying to find a "nice" way of explaining building the loop and why it's done the way it is instead of cutting out a section of a repeated timeline. If you get a chance to check this out, thanks in advance!
  23. Hey @GreenSock! Yeah, that clears some things up. I think the best way for me to try and fully have a handle on this is to start writing up the article for it. I think it might be neat for me to create a non-looping version too using the same technique. That will likely make it easier to see the progression from having the scroll to adding the overlap. One thing with your new snapping version. If you scroll it to "0", it'll infinitely bounce slightly. Or, at least did for me above.
  24. Hey @GreenSock! I think we're starting 2021 off great with an attempt for longest thread ? I think I get the overlap. Perhaps my wording wasn't quite right again. I had a play around with overlaps and manually adjusting the spacing, etc. I think typing out the calculations and their values may help me understand it a bunch more. I've been messing with unpausing the timeline and slowing down Raw here https://codepen.io/jh3y/pen/WNoNoLZ And now I'm going to walkthrough as I understand it. For example, with 50 cards, an overlap of 10 and a spacing of 0.1. https://codepen.io/jh3y/pen/zYoYoaM Loop time: (50 + 10) * 0.1 + 1 = 7 Start time: 50 * 0.1 + 0.5 = 5.5 Then the LOOP tweens RAW to a time and duration of time: 7 duration: 1.5 That first part is responsible for moving the items from right to left. To a time of 7 equates to the 70 cards in this case which may be coincidence. As a loop time for 30 cards would be. (30 + 10) * 0.1 + 1 = 5 Maybe not then. That number is equal to (Cards + (2 * overlap))? But, the start time would be at the 55th position in the tween. Minus the overlaps that would mean showing the 45th card and up? Why a duration of 1.5 though? https://codepen.io/jh3y/pen/zYoYoaM I could adjust that to offset the positioning, etc.? That first part of the loop goes from the first overlap to card 20. That first part of the loop using a duration of 1.5 with a time of 7 means we go from position 45 to 20. But, I'd have assumed it would be travelling only 15 places not 25. https://codepen.io/jh3y/pen/BaQapXq Then we set `fromTo` to Raw Go from `time` time: 10 * 0.1 + 1 = 2 to time: 5.5 duration: 5.5 - 2 The time is moving to the start position from 20 positions in? Is there a reason for being 20 positions in? In this case, that's 2 lots of overlap but I'm not sure why that works. The extra + 1 on times. In this case it shows 0,1,2,3,4 then jumps to 20 which makes sense. The .5 gives us those 5 starting positions. The tween goes from card 20 to card 5. That little bit of wrap. https://codepen.io/jh3y/pen/bGBGgaK I think I get the concept of the overlap. I think it's the Math part that lets me down a little here with wrapping my head around the different calculated times/duration ? Also, the way loop works. The way it's split into this `to` and `fromTo`. The durations having + 1 on them or being split in a particular way. The `to` and `fromTo` are tweening a different end of the raw timeline. Then when pushed together they do this: https://codepen.io/jh3y/pen/poNoejo If I'm right in thinking it's because logically looking at it. The to is handling our start position + the second overlap and the the fromTo handles the first part of the loop and the first overlap. But, the missing "Eurekah" I think for me is the Math of the time linking to the duration. Although, the raw time is explicitly set above actually so that means we are going. I read the LOOP as: 5.5 > 7 > 2 > 5.5 > 5.5 > 7 > 2 > 5.5 > 5.5 > 7 etc. Which I think... makes sense? That leaves me to think about the durations. We know that Raw's stagger gives 8. 70 * 0.1 + 1. Is that that +1 in our durations for padding out the duration of the movement? LOOP has durations of (7 - 5.5) and (5.5 - 2) 1.5 and 3.5. I think I'm trying to sus what these are tied to to and then I'm pretty much there ? The scrub part I think makes sense to me. I needed to reference the docs for `totalTime` to see that it's a method for scrubbing the playhead to a certain spot ?‍♂️ Another huge response I'm sorry. I'm adament I'm going to learn this. You're right. It's advanced, but, it's cool! And it will be an awesome thing to have in my toolbelt. I think I'm getting there with the understanding. It's thinking on the meta level ?
  25. Hey @GreenSock ? I've sat down to try and get my head around things ? It might take me a couple of rounds to fully get the picture accurately in my head. My goal though, is to make this easier to understand for people. If I can make it make sense to people who've barely used GSAP, that's a huge win! With that in mind. I'm going to fire out some random notes I took from reading your response. Yep. We're "Meta GSAP" ? 3x The way the gap is covered is based on the overlap defined and the amount of items available. In our example, 10 because `Math.ceil(1/0.1)`. With a number of items as low as 5, the spacing would need to be increased or the overlap reduced? Because you need enough elements to wrap the front and back at the right time. And that's how the RAW timeline works because the modulo grabs the overlaps and tacks them onto the loop? The loop's job is to move the playhead on raw. And because raw infinitely repeats and our scrolling increases the `totalTime`, it'll keep moving the playhead? Raw.time sets that center point for us I think I need to spend more time looking at what loopTime, start, etc. are doing with regards to the fromTo on raw. But, a high level explanation is that. It's still that code snippet I posted before that I need to get my head around for the timing. ScrollTrigger part. '+=3000' could be whatever we want in reason? I think the wrapping part I understand. I like how that and the next/prev part are done. It's neat. The actual movement with ScrollTrigger. Is that because increasing/reducing `totalTime` affects the playhead position of the loop? Or is it because the scrub keeps tweening the time up and down of the loop incrementally/decrementally? Yeah, the way it's all done on one makes a lot of sense. I can feel the performance difference between the two. It's noticeable. The obsession is appreciated. I'd rather do it right than get it out the door quick and hit hurdles later. Yep, I got that `yoyo` part. Don't think I worded myself very well. Working on it! Oof. A lot to digest ? Sorry if I sound like a broken record with some of them pointers. I'm keen to make something visual to help people out with this. Heck, I understand it better than I did at first glance. Progress is being made! Thanks again for all this. I really appreciate your help.
×
×
  • Create New...