Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by jh3y

  1. Howdy y'all! πŸ‘‹ Had a comment on CSS Tricks today about the article for this technique: https://css-tricks.com/going-meta-gsap-the-quest-for-perfect-infinite-scrolling/ Has something changed dramatically between versions to introduce these breaks? Or is there a property I need to update or add potentially? The other solution I could see is pinning the GSAP version in all the demos for that article to ~3.7.0 I think πŸ€”
  2. Yeah, I _think_ we mean the same thing πŸ˜… My terminology may be slightly off but I'm pretty sure we are on the same frequency there ✨ Thanks Jack! ✨ Κ• β€’α΄₯‒ʔ/
  3. Hey Jack πŸ‘‹ Sorry – I've taken a couple of days off before starting a new role this coming week. That solution is super clear and I love it! It's a great spin on the article too for showing learning process and how we've got to this solution. Kinda like the "Meta GSAP" article (Which could totally be redone with Observer now, right? Awesome!) I really like this solution because of it's simplicity. If I were to put another element such as a custom drag handle, and use Draggable for that bound to the input like I had originally, it would update the value and the Inertia would be triggered too, right? I think that's correct. I may have not worded it right but I'm pretty sure that works too, haha. Can't wait to finish off the article! οΌΌΚ• β€’α΄₯‒ʔ/ Thanks again for everything!
  4. This makes perfect sense. I'll get that other demo fixed up to use the new API too ✨ Thanks! οΌΌΚ• β€’α΄₯‒ʔ/
  5. That was a seamless switch πŸ™Œ
  6. And that won't be removed? Also, "that" demo could be converted to use this API? Rad! I'll share today.
  7. This is great! And perfect timing πŸ˜… And will be great for the article too! I could totally make this into an "Observe" demo. I'm assuming this is the tool that has been "renamed" from something else that I may have made a demo for? Thanks Jack! πŸ™ οΌΌΚ• β€’α΄₯‒ʔ/
  8. Oh wow. That is much smaller. And I like that wrapYoyo! TIL. The only issues I see here are: - I want to plug into the "collision" so I can play a noise and bump the input itself from left to right based on the velocity too. Can you detect when a wrap happens inside "onUpdate"? - If I click the track, it applies the velocity which I wouldn't necessarily want as I want that to only happen after a "drag". With this original demo, it has the "correct" behavior. But, it has the drawback of me trying to keep that element in sync with the slider thumb. I was thinking with the "Draggable" way, I'd be able to easily keep a "faux" thumb in place by updating it's position based on the input value. But, that isn't an important part here. Just something I was thinking of doing. Thanks for teaching me something new! Again! πŸ™ The best part being that I've kinda written an article using Draggable. But, it's kinda cool that I can steer it in a different direction. I love mentioning the forum powers! Jhey Κ• β€’α΄₯β€’Κ”
  9. UPDATE:: I've recreated the demo with the way I'm trying to create it without React so it's less hassle working out what's going on πŸ˜… But yeah, if you swing it hard one way it will only bounce once like the velocity can't update quick enough. Hoping it's an "easy" solution πŸ™ https://codepen.io/jh3y/pen/GRyEeYp/07ca6efd5c422ec124855582d1f82e80
  10. Hey y'all! πŸ‘‹ I've been playing with this demo some more and attempting to create it without a "proxy" element in the DOM. It works for the "most" part but the velocity seems a little off with the Inertia compared to the one above. But, that's not the main issue I'm encountering. The issue is calculating the bounce back based on the value of the input. If I animate the value of the input or drag it so that it should bounce, it gets stuck on the end as if other tweens are hanging on if that makes sense? It's like it can't keep up with itself or the tracker velocity is hanging. For example, if you bounce it off one end where you expect it to bounce off the other, it hangs. Any ideas @OSUblake && @GreenSock https://codepen.io/jh3y/pen/abEWPOo Look forward to seeing what you think on this one. Could it be the way I'm using the `inertia`? Previously, this was set on `x` because I was moving an element. Would I instead need to map this to the input values perhaps? Jhey Κ• β€’α΄₯β€’Κ”
  11. Hey y'all! πŸ‘‹ Looks like `startDrag` was the piece of magic I was looking for πŸ™Œ Thanks for sharing that one. I think this solves the issue of trying to align the slider proxy handle with the slider thumb because wherever you click, it will align, which is perfect ✨ Happy to be here! Thank you for both of your inputs. Love learning new parts of the API to solve these little challenges πŸ’š TIL "startDrag" πŸ’ͺ Now I can start writing this one up πŸ˜… Thanks again! οΌΌΚ• β€’α΄₯‒ʔ/
  12. Hey y'all! I've been thinking to write something up about this demo. But, I feel like there's a more robust way for me to handle dragging on the input regardless of where the slider thumb is πŸ€” I've tried putting in place a "Proxy" element (.slider__proxy) and I'm updating based on that. However, if you were to click the track somewhere away from the thumb, would it be possible to somehow trigger "drag" mode and move the slider thumb and proxy into place? I feel like I'm overcomplicating it somewhat seeing as a range input already has a drag handle kinda built in. But yeah, I was keen to know if there was a better approach to what I've done with it. Jhey Κ• β€’α΄₯β€’Κ”
  13. Hey! Actually, this solution makes a lot more sense. Thank you. I wanted to cover it for the demo/article and updating in the `inputs` callback would fit better I think πŸ™ Thanks! οΌΌΚ• β€’α΄₯‒ʔ/
  14. Hey y'all! ✨ Thank you @Cassie πŸ™ One more query on this demo 😁 I've got it pretty much there where I want it. There's one thing I can't seem to make work nicely. It's setting `aria-hidden` on the numbers as they slide in and out πŸ€” I've been trying this but it is a little inconsistent for me. Sometimes it works, sometimes it leaves some with the wrong values. Would it make sense to maybe do this outside of the timeline and work out which digits need the attribute applied when doing the scrub instead? (Maybe I've answered my own question there πŸ˜…) const DIGI_TIMELINE = gsap .timeline() .set(DIGIT, { yPercent: 0, attr: { 'aria-hidden': 'true', }, }) .to(DIGIT, { yPercent: 100, delay: i * COEFF, duration: 1, onStart: () => { gsap.set(DIGIT, { attr: { 'aria-hidden': 'false', }, }) }, }) .to(DIGIT, { delay: COEFF - 1, yPercent: 200, duration: 1, clearProps: 'all', onStart: () => { gsap.set(DIGIT, { attr: { 'aria-hidden': 'true', }, }) }, }) Anyways, hope you've all had an awesome weekend. Here's the demo! It's part of a series I'm doing where it's about debunking Instagram Reels/TikTok where someone shows how easy it is to make a design in Figma but it doesn't show the reality on the dev side of making said thing πŸ˜… https://codepen.io/jh3y/pen/XWzmGad Κ•Β΄β€’α΄₯β€’`Κ”
  15. Not at all! I love some humble pie ☺️ It's the best way to learn. I'll always take suggestions and discussions. 1. Totally! πŸ’― Sorry, the code is a little rough and I'd left them in as I was playing with variations trying to get it working with things like `delay: 2` etc. Sorry for that! 2. Ahh yes, that would make sense too. I guess in my head I see each timeline like its own little block/animation component πŸ˜… 3. Yes! Love this. Now the position param threw me to start with because I was in a bit of a rush. Without a label it broke and of course I needed `0` πŸ˜…. The simplified version is much nicer and again this was kind of my bad, sorry. I'd left it rough as I was playing with different eases for the effect I want. Ahh, I see that `clearProps` usage now and this is much nicer too! 4. This is a rad tip. Kinda shows the magnitude of what GSAP covers because although I've used `progress` in the past, I'd completely forgotten about it haha. Trying to spend more time documenting things I make this year for this reason πŸ˜… Appreciate the kind words massively! I'll keep creating for sure. Love sharing and challenging ha. If I don't hear from you, have a great weekend! οΌΌΚ• β€’α΄₯‒ʔ/
  16. Yes!! `progress` was what I was looking for! Thank you for reminding me of that one @OSUblake πŸ™ οΌΌΚ• β€’α΄₯‒ʔ/
  17. Think I've worked out a way. Needed another timeline to scrub the playhead of `MANIPULATOR`. Then I'm using a `delayedCall` to get the ball rolling ✨ const SCRUB = gsap.to(MANIPULATOR, { totalTime: 0, duration: 0, paused: true, ease: 'none' }) SCRUB.vars.totalTime = 4 SCRUB.invalidate().restart() gsap.delayedCall(2, () => MANIPULATOR.play()) There is likely a cleaner way to do this. The idea being that I'm going to be scrubbing a timeline composed of a few timelines and need to show the current state. I'll keep tinkering πŸ€“
  18. Hey y'all πŸ‘‹ Looping through a set of numbers infinitely by tweening `totalTime` on a timeline. But, how do I show the current state while it's `paused`? I'm setting `TL.totalTime(1)` here but nothing shows. Do I need to do something with `immediateRender`? I'm going to be scrubbing this timeline with another control so it will remain paused. I've tried the `invalidate().restart()` manoeuvre but I'm not having much luck... import gsap from 'https://cdn.skypack.dev/gsap' const TL = gsap.timeline({ paused: true, }) const DIGITS = gsap.utils.toArray('.digit') const PADDED_DIGITS = [...DIGITS, DIGITS[0]] for (let i = 0; i < PADDED_DIGITS.length; i++) { const DIGIT = PADDED_DIGITS[i] const DIGI_TIMELINE = gsap.timeline({ paused: false, onComplete: () => gsap.set(DIGIT, { clearProps: true }) }) DIGI_TIMELINE .set(DIGIT, { yPercent: 0, }) .to(DIGIT, { yPercent: 100, delay: i, duration: 1 }) .to(DIGIT, { yPercent: 200, duration: 1 }) TL.add(DIGI_TIMELINE, '- 0.5') } const MANIPULATOR = gsap.timeline({ delay: 2, paused: true, }) .fromTo(TL, { totalTime: 1, }, { totalTime: 11, duration: 4, ease: 'none', repeat: -1, }) TL.totalTime(1) Thanks in advance! Sure I'm missing something obvious. Κ• α΅’ α΄₯ α΅’Κ” Setting `MANIPULATOR` to `paused: false` plays the timeline as expected. But, I'd like to see the playhead state when it's paused.
  19. 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
  20. 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 😁
  21. 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!
  22. 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 πŸ˜…
  23. 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!
  24. 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 πŸ‘
  25. 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