Jump to content
Search Community

henryb

Members
  • Posts

    22
  • Joined

  • Last visited

Posts posted by henryb

  1. Oh, I just had one more related question, if you have time; in this scenario should I have created a contextSafe function to handle the onClick?

     

    I get a little confused about whether this needs to be made contextSafe since it is animating after the timeline has been created, from an onClick.

  2. Thanks so much, Rodrigo. That is exactly what I am looking for. P.S. Nice touch with the stagger on the cards ;)

    I think this is starting to click for me, in regards to setting up a timeline and then calling methods like restart() on the timeline, and to avoid the mistake of just recreating the timeline.

  3. Hello,

    I'm building a page (in NextJS App router) that features a toggle group that allows the user to toggle the grid layout from 4 columns to 6 columns on click. I would like to run an animation when state updates. The animation will run in the following sequence:
    1. Fade out the grid items
    2. Update the number of columns in the grid layout
    3. Fade back in the grid items

    Stackblitz

    However I am facing the following issues:
    1. If the timeline is not paused then the state toggles when the page loads (grid is 4 columns momentarily then switches to 6 columns). This would indicate to me that the timeline runs. However, if the timeline is paused when the component mounts, then I am subsequently unable to run the timeline animation by toggling the state.
    2. I can console.log that the state is being updated in the component, but despite the state being in dependency of useGSAP, the timeline does not appear to run. I am unclear why.
    NB: My reason for wanting to use state to run the animation, is that the state would also be used to toggle the sizes values passed to the Image component when the grid changes. And also because I don't think the animation would work with a simple reverse(). (The grid items must be visible when component mounts and then the animation must go, -> to autoAlpha: 0, -> change layout, -> to autoAlpha: 1 and that doesn't really work in reverse unless I am completely missing something).

    I have a feeling this is quite basic, but despite reading over the docs and reviewing other examples, I haven't been able to get this working. Very grateful for any input anyone may have. Many thanks.
    Henry

    P.S. An external website example, in case my description wasn't clear.

  4. Hi again @Rodrigo

    I'm working with the above approach, and it works well starting from the top of the viewport, before the scrollTrigger is triggered.

    However, I'm facing the issue that if I were to arrive on this page via a back navigation, positioning the viewport below the scrollTrigger, i.e. down the page, then there is a brief flash where the '.logo-large' appears. I have tried to set the style={{ visibility: "hidden" }} on the '.logo-large' element, as well as immediateRender: false in the .to() in the timeline, but still the flash appears. 

    I'm wondering if there is a way to counter this FOUC? I'm not really understanding why it is happening, and whether it is specific to the scrollTrigger.

  5. Hello,
    This question builds off of a previous question about multiple scrollTriggers, with some added elements concerning page refresh and triggering the scrollTrigger from the reverse direction.

    Outline:

    • Page has a small header logo, that only appears when the user begins to scroll.
    • Page has a large logo that appears on page load, that disappears when the user begins to scroll.

    Problem:

    • The scrollTriggers work well on first load, but when the page is refreshed the #headerlogo appears immediately regardless of the scrolled position.
    • Toggle action to play in reverse when scrolling back to top not working for me currently.

    Aim:

    • Both logos should not be visible at the same time.
    • #headerlogo fades in when scrolling past scroll trigger at top of viewport.
    • #largelogo fades out when scrolling past scroll trigger at top of viewport.
    • Animations play in reverse when returning to top of viewport.

    This site has the exact behaviour I am trying to achieve: https://www.magdabutrym.com/de-en

    Here is my current progress in this Stackblitz demo: Stackblitz link

    Many thanks for reading!
    :)

  6. Hi Rodrigo,

    Thank you for your reply; that was very useful for me to realise those selectors of course had no elements to refer to in the DOM.

    It seems that Radix's forceMount prop would force the modal portal to be present in the DOM on mount, and then it would be a matter of animating the visibility of the modal. I will test whether this works well for a modal (I would need to manage pointer events so that with visibility hidden the portal is not blocking other interactions). If all works well I will post the results here for others who might be interested in the future.

  7. Hello,

    I'm attempting to animate a dialog component from RadixUI's component library in a NextJS 14 App router project.

     

    I have converted the Radix component to a controlled component following their docs (and this useful video by Sam Selikoff), by not using the internal wiring from Radix that opens the dialog with the <Dialog.Trigger /> component and instead conditionally rendering the dialog with state isOpen and the use of forceMount prop on <Dialog.Portal />. I would expect to simply give the useGSAP() hook a dependency [isOpen] and trigger the timeline to play() or reverse() based on that state too. The forceMount prop is used to delegate the mounting and unmounting of children based on the animation state. But currently I have no GSAP animation playing. I realise there is some specificity to Radix with this question, but if anyone is willing to check my GSAP code I would be very grateful. In fact the logic described above may not be necessary; I noted another question in the forum animating a Radix component and from the code that was provided in that question it did not appear that the OP was using forceMount, indeed the conditional rendering appeared to follow a conventional approach.

     

    My Stackblitz demo is here: Stackblitz


    In the above demo there are two routes; one dialog animating with GSAP without a RadixUI dialog component, and another route with the RadixUI dialog component, but not currently animated with GSAP. The GSAP code is scaffolded out on that page, but is not animating the dialog into view. The animation I am aiming for would resemble the animation from the route currently without Radix.

    Many thanks in advance :) 

  8. Hello @mvaneijgen thanks for the response! That's great to understand the use for immediateRender: false

     

    That has fixed the scrollTrigger animation. However there is still a peculiar issue with the element flashing when the page first loads. Actually it wasn't visible in Stackblitz in the small preview browser window, but when you click to view the browser view at full viewport size, and then give the page a hard refresh, you can see the svg appear, then disappear, and then animate in.

    Any ideas about how I can avoid this? At first I wondered if it was anything to do with React Strict Mode, but no luck. Could there be an issue with forwarding the ref the way I am doing? I also tried to add a gsap.set('.logo', { autoAlpha: 0 }) before my fromTo() but again with no luck. Notably, a regular refresh does not present the issue, but the very first page load does.

  9. Hello,
     

    I am trying to animate an element in when the page loads, and also whenever the user starts to scroll I want to animate that same element out. 

    So far I am able to achieve this, but not optimally, because the out animation is not exhibiting the specified duration. The out animation is triggered with scrollTrigger, and it simply should animate the autoAlpha to 0, to make the element disappear over a duration of 2 seconds. Currently, it abruptly disappears, rather than animating out for the course of the specified duration.

    Here is my minimal reproduction to demonstrate my issue: Stackblitz

    To summarise what I am trying to achieve:
    1. Logo fades in on page load
    2. When user begins to scroll down, the logo fades out as a result of a scrollTrigger

    Currently happening:
    1. Logo fades in on page load
    2. Logo disappears abruptly without fading out when scrollTrigger is triggered

    Notes:
    1. If the useGSAP() code for the scrollTrigger is moved to the parent, to the page level, the scroll trigger animation fades out as intented — but only when I change the gsap.to() to a gsap.fromTo(). I don't understand why.
    2. Moving this code to the page level solves the scrollTrigger (somewhat) but there is a new issue with the logo flashing when the page loads.

    Many thanks in advance for any suggestions on where I am going wrong:) 

  10. Thank you very much for kindly sharing your observations, Rodrigo, that was very helpful. My apologies it has taken me a few days to reply.

    That was well-spotted with the two sets of images that are interacted with separately. It seems like the page tracks the position of the images in view in one set while the other set is being scrolled, so that when they are Flipped, the set transitioning-in are in the optimal position for a pleasing animation. I agree there seems to be some careful timing being orchestrated.

    Thanks for the link to the Flip demo too!

    Best

    Henry

  11. Hello,

     

    I have a Flip transition that animates between a single column and a grid layout. This works, however there is further control + logic required to get the transition to feel smooth and to handle which images transition into view, as well as the position of the viewport during this transition.

    Here is my current implementation: Stackblitz and here is a good example of what I am trying to achieve with a smooth transition on another website (click the `index` button in the top right corner of the page to see the transition I am aiming for).


    This may not be strictly a GSAP question, and if not please disregard, though I am curious if anyone may have any pointers on what could help to get my transition closer to the linked example website.

    From what I can observe, the linked example improves the Flip by achieving the following:

    • From grid view > column view, the grid view keeps track of which row is at the top of the viewport and always transitions so that the top row are the images that move into view in the single column view
    • From column view > grid view, the image in view transitions into the top row of the grid
    • The change in the height of the page is managed so that the viewport position does not end up away from the items on which the transition started, i.e. the items in view at the start of the transition stay in view throughout and until the end of the transition
  12. Missed that id, between different versions of the demo, apologies and thanks for catching that.


    Many thanks for your answer regarding scrolling during the Flip animation, Rodrigo. I appreciate you have been very generous with me.

    • Like 1
  13. Quote

    If you run that before the Flip instance is completed it will have no effect because that particular tween hasn't been created yet. That tween is created in the onComplete callback of the Flip instance, so GSAP won't find any tween related to that selector, that's why either killing the Flip instance or using a boolean in the onComplete is the best alternative. You can use a ref to store the Flip instance in order to simplify that.

    I see. Well noted!

    Regarding onComplete, a related question from the demo has come up — when the Flip completes, I would like to scroll to the clicked target image. I have swapped the native browser scrollIntoView method for gsap's scrollToPlugin in the onComplete, and this works. If I move the scrollTo function into the onStart — to position the viewport over the target image during the Flip animation, this doesn't work most of the time. I think this would probably be expected behaviour though right? Because during the Flip the image target doesn't have a place in the DOM, so even if the scrollTo function gets given the target image id, the scrollTo probably gets interrupted by the animation of the layout (my guess).

    My question is just: would there be another way to streamline / harmonise the Flip transition and a scrollTo animation? Or is the best way simply as I have it — 1) complete the Flip animation and then 2) scroll to the target?

    As seen here in the deployed staging site (work in progress).

    For some reason I can't get the scrollTo working in the Stackblitz demo.

  14. Hi Rodridgo,
    Thank you so much for such a generous response.
    These are some very useful learnings for me. In particular killing the Flip instance to prevent the callback from being called:

    gsap.killTweensOf('.caption');

    That also makes a lot of sense to use a ref to control whether the captions tween is created at all.
    Also well noted  your points regarding the scope within the useGSAP hook. 

    The forked demo works as intended now. 
    Thank you again!

  15. Hello,
    I am having trouble with keeping the state that controls various parts of a layout in sync with the use of Flip toggle on that page. A little context:

    I am working on a image gallery page that uses GSAP's Flip plugin to toggle between two layout states: a grid four-column view and a full single-column view. The state (`isGridView`) is used to control the srcSet that is provided to the images — so that the appropriate size images are rendered depending on the layout. Additionally other parts of the layout depend on the state but must be sequenced in the correct order of the Flip animation, i.e. when we transition to the grid view, we need to fade in captions for the images after the animation completes, but when we transition to the full view we need to  fade out those captions before the animation.

    My problem: when the page transitions a couple of times, the state stops being matched to the correct Flipped layout. This results in captions showing in the full view (incorrect) or images appearing blurry (incorrect srcSet).

    I have tried to set up my Flip to depend on the state of the layout. However my main difficulty is not knowing when / how best to update the React state before / during / after the Flip transition. I am currently using onComplete, but that only updates after the captions have completed their staggered fade-in, and it is very plausible that the user clicks to transition again before the stagger animation has completed, and as a result the state never gets updated for that cycle. I have tried to test with onStart and onUpdate, but onStart means that the srcSet changes too early, resulting in flashes during the transition, and onUpdate seems unreliable for keeping the state in sync in my testing too.

    I have a feeling I am not setting this up in the best React way. I would be so grateful if anyone has time to take a glance at my StackBlitz reproduction linked in this post to see where I am going wrong. I currently have a function `performLayoutFlip` that is called to do the Flip transition; it could be nice to have a timeline that gets reversed, but I need to account for controlling the captions (fade in after a delay vs fade out immediately) so I don't know how I would manage a timeline that isn't exactly symmetrical. (PS If you click on the images to transition a few times you should see the captions and images come out of sync). Let me know if I can help clarify anything, many thanks in advance! :) 
    Stackblitz minimal reproduction
     

  16. Hello,


    I'm trying to animate a nav opening and items animating as part of a timeline animation, in a Next.JS app. I'm using the useGSAP hook and a gsap timeline to stagger the animation in of menu items in the nav, and then I want to toggle the animation in reverse when the nav is closed.

    My issue is that the menu items are currently fetched from a CMS using a useEffect when the component mounts, and those items are set in state. But when I animate the nav, the items in state do not animate. 

    Here is a linked Stackblitz repoduction of my issue: Stackblitz reproduction

     

    My impression is that I'm misunderstanding how React lifecycles work here with useGSAP, but I would be grateful for any pointers that anyone is able to offer. Many thanks in advance!

    P.S. In my app I'm using Next.JS 14 with the Pages router, rather than the App router as in this Stackblitz, but the only aspect that changes is how I would fetch data in the component, so it should not pertain to the issue I am facing specifically.

  17. I figured out the solution was setting the repeat prop to '-1'. My next block is that I have draggable: true, which works, but I would need the marquee to resume after a dragging event completes, I can't see yet whether the horizontalLoop helper accounts for that...

  18. Hello,
    I have been reading through this thread, which has been so helpful and informative — so thank you for all of these contributions.
    I'm working on an infinite marquee, in a React app, and so I have turned to the horizontalLoop helper function for my purposes.
    I am using the useGSAP() hook, and using the horizontalLoop function with some config options passed in.

    This works but my marquee only completes two cycles and then stops. I haven't figured out why yet.

    I am also trying to better understand how to call the horizontalLoop function within the useGSAP() hook, as someone very new to GSAP (using it for the first time in fact!). Could anyone tell me if I am using the hook correctly here?

     

    import { useGSAP } from '@gsap/react'
    import { useRef } from 'react'
    
    import { gsap } from '@/lib/gsap'
    import { horizontalLoop } from '@/lib/gsap/horizontalLoop'
    
    import Card from './Card'
    
    export default function Marquee({ items }) {
      const containerRef = useRef()
      // TODO Delay start by setting paused to false after an interval
      useGSAP(
        () => {
    	// The class '.card' targeted is inside of the <Card /> component
          const cards = gsap.utils.toArray('.card')
          const horizontalLoopConfig = {
            draggable: true,
            paused: false,
            repeat: true,
            paddingRight: '32px',
          }
          horizontalLoop(cards, horizontalLoopConfig)
        },
        { scope: containerRef },
      )
    
      return (
        <div
          ref={containerRef}
          className="h-[100svh] w-screen flex flex-col pt-16 overflow-x-auto px-6"
        >
          <div className="h-full flex gap-8">
            {items.map((item, index) => (
              <Card key={index} item={item} />
            ))}
          </div>
        </div>
      )
    }

    Grateful for any pointers :) 

×
×
  • Create New...