Jump to content

Search In
  • More options...
Find results that contain...
Find results in...


  • Posts

  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

jh3y's Achievements

  1. 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! οΌΌΚ• β€’α΄₯‒ʔ/
  2. Yes!! `progress` was what I was looking for! Thank you for reminding me of that one @OSUblake πŸ™ οΌΌΚ• β€’α΄₯‒ʔ/
  3. 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 πŸ€“
  4. 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.
  5. 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
  6. 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 😁
  7. 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!
  8. 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 πŸ˜…
  9. 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!
  10. 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 πŸ‘
  11. 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
  12. 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?
  13. 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
  14. jh3y


    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.
  15. 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 πŸ€”