Jump to content
Search Community

Bonsai

Members
  • Posts

    11
  • Joined

  • Last visited

Bonsai's Achievements

  1. Good to know about why you recommend adding the "[]." I'm not sure this will be an issue in my case, as it only renders once on startup so far in my testing, but better safe than sorry. I've been avoiding logic that would lead to additional renders lower in the component tree because I'm using nextjs pre rendering, so markup that doesn't match up with the pre rendered version will load initially out of position. As for the pinning, I haven't run into issues so far with it in this case, though I agree that it sometimes can cause problems due to the markup changes it has to make.
  2. I'm fairly new to react as well, but I'm pretty sure the empty array isn't needed, as that property can be null/undefined for useEffect and useLayoutEffect. It's apparently used to pass in dependencies, which is likely used to determine execution order. As for why I'm using useLayoutEffect instead of useEffect, the former runs synchronously, so it will delay rendering until the timeline is initialized, which avoids a brief moment of out of position elements due to my use of "fromTo." Fortunately, I was also able to figure out my issue while tinkering on the demo. I was missing the "pinSpacing: true" in the scrollTrigger configuration, so it was scrolling past the area before the animation finished. tl.scrollTrigger is still undefined for some reason, but it doesn't appear to be causing any issues in my build. Don't know why it's undefined, as it did have a value while I was tinkering with a demo to show the issue. Might be some weirdness caused by rendering the page with the nextjs framework.
  3. I'm running into a similar issue to what Théophile did, as I have multiple react components with scroll triggers and pins on the same page. The refresh solution above seems pretty straightforward, but for some reason the scrollTrigger object is undefined, so tl.scrollTrigger.refresh() throws an error. Any idea why that might be? I'm running version 3.10.4 of the greensock library if something changed to impact this since last year. Below is the relevant logic I'm using currently in the react component to create the animation (images are just divs inside that top level div). const ref = useRef<HTMLDivElement>(null); const animateImage = (isStart: boolean, isEnd: boolean, tl: Timeline, image: Element) => { tl .fromTo(image, { y: 500, autoAlpha: 0 }, { y: 0, autoAlpha: 1, duration: .5, delay: isStart ? 0 : -.4 }); if (!isEnd) { tl.to(image, { duration: .3, autoAlpha: 0 }); } } useLayoutEffect(() => { const element = ref.current; if (element) { const images = element.querySelectorAll('.imageContainer > div'); const tl = gsap.timeline({ scrollTrigger: { trigger: element, pin: true, scrub: true, start: 'top top', end: '+=' + (images.length * 2 * element.clientHeight) } }); images.forEach((image, index) => { animateImage(index === 0, index === images.length - 1, tl, image) }); console.log(tl.scrollTrigger) //scrollTrigger is undefined when I check with this } }) return ( <div ref={ref}> ... </div> ) I can put together demo of the issue if needed, but I want to check if there is a quick explanation for why tl.scrollTrigger would be undefined before doing that.
  4. I had already looked at those threads unfortunately. The overflow hidden bits are the same thing fullpage.js does. Thanks for the input though. I'll post an update if I find a solution to this issue.
  5. Yeah, I'm not a fan of scroll jacking either, but it was a requirement of the project unfortunately. Would have preferred to use Scroll Trigger's snapping capabilities. I might be able to hack my way around this issue by recording the progress of each timeline with the refreshInit event and restoring it in the refresh event. I did try this earlier without success, but I might have missed something. I think the scroll trigger was overriding the progress value I set after the refresh event. See below for the basic gist of what I tried before. var progress; var tl = gsap.timeline({ scrollTrigger: { ... }}); ScrollTrigger.addEventListener('refreshInit', () => { progress = tl.progress; }); ScrollTrigger.addEventListener('refresh', () => { tl.progress(progress); }); Any suggestions on what tweaks I should make to this logic to make this work, if any? It's a hack for sure, but I'm trying to avoid the need to rework the entire animation.
  6. I'm running into a resize issue with a slideshow animation I'm working on. When the browser resizes, all the animations are reset to the beginning (see https://ugm-staging.azurewebsites.net/). I've also attached a codepen that shows some of the weirdness I run into. It scales the font size up, but on resize the font size is reset even though it's still scrolled to the same point. Not necessarily unexpected, since my use of overflow hidden is likely throwing a wrench in how scroll trigger handles resizing. Unfortunately, that's required to ensure the slideshow works as expected on mobile devices, as things break when the address bar appears/disappears on them. I've confirmed that scrollTop is unchanged after the animation resets, so it seems that greensock isn't facturing that in for some reason. My idea right now is modify the refresh logic to fix whatever is knocking things out of position, but I'm not sure how best to go about this. Any suggestions would be much appreciated.
  7. Missed your comment. I did have only onUpdate originally, but still encountered this problem (see code earlier in this thread here). OnUpdate was triggering, but its progress was set to 0 instead of 1 even though the browser was already scrolled past the end of the scroll trigger. Only things I changed to fix it was add the onStart and onEnd callbacks and moved the logic previously in onUpdate into its own function. Will need to double check whether "onEnd" is firing, since you are right the documentation just has "onComplete." Pretty sure that callback was firing when I tested this.
  8. I figured out my problem. The issue was that the onUpdate callback does not fire if the scroll animation hasn't started or has already ended. To fix this, I needed to add the onStart and onEnd events to update the styles as well. The fixed version can be seen below. ctrl._animateIconContainer = function () { var headerHeight = angular.element('.header')[0].offsetHeight; var startY = ($window.innerHeight / 2) - headerHeight; var tl = gsap.timeline({ scrollTrigger: { trigger: ctrl._shareIcons, toggleActions: "play none reverse reset", start: `${startY}px center`, end: () => '+=298.8', scrub: true, snap: false, invalidateOnRefresh: true }, }); tl .to(ctrl._shareIcons, .25, { onStart: function () { //added this to handle when the animation hasn't started yet ctrl._setRotation(0); }, onUpdate: function () { ctrl._setRotation(this.progress()); //moved the code that was here into its own function }, onEnd: function () { //added this to handle when the animation has already finished ctrl._setRotation(1); } }) .to(ctrl._shareDiv, .2, { borderBottomRightRadius: '0rem', borderTopRightRadius: '0rem' }); } //moved animation to separate function to allow it to be used in the 3 event callbacks ctrl._setRotation = function (progress) { var rotate = 90 * progress; gsap.set(ctrl._shareDiv, { rotation: -rotate, x: -166 * Math.cos((rotate - 90) * Math.PI / 180) }) gsap.set(ctrl._icons, { rotation: rotate }); }
  9. Noted on toggleActions. I'll try removing invalidateOnRefresh. If neither of these tweaks help I'll work on putting together a reduced test case. It will take me a while to post though, as I'm busy with another project at the moment. I'll post an update in a week or two.
  10. Thought about putting a demo together, but was pressed for time. As for what I meant by "end state," I just meant the end of the connected timeline. I already tried setting progress to 1 manually on the timeline, but scroll trigger immediately reset it to 0. Need to try it with a delay, but not sure that will help. I'm using version 3.5.0 of Scroll Trigger, so it's slightly out of date. Will give that a try. For reference you can see a snippet of my current code below //this is where I make changes to get scroll trigger to position correctly if (ctrl._startsSticky) { ctrl._initScroll = ctrl._win.scrollTop(); ctrl._win.scrollTop(0); } var headerHeight = angular.element('.header')[0].offsetHeight; var startY = ($window.innerHeight / 2) - headerHeight; //animation defined here var tl = gsap.timeline({ scrollTrigger: { trigger: ctrl._shareIcons, // ctrl._shareIcons is just a div reference toggleActions: "play none reverse reset", start: `${startY}px center`, end: () => '+=298.8', scrub: true, snap: false, invalidateOnRefresh: true }, }); tl .to(ctrl._shareIcons, .25, { onUpdate: function () { var progress = this.progress(); var rotate = 90 * progress; gsap.set(ctrl._shareDiv, { rotation: -rotate, x: -166 * Math.cos((rotate - 90) * Math.PI / 180) }) gsap.set(ctrl._icons, { rotation: rotate }); } }) .to(ctrl._shareDiv, .2, { borderBottomRightRadius: '0rem', borderTopRightRadius: '0rem' }); //this is where I reset the changes I made at the beginning of the code if (ctrl._startsSticky) { $timeout(function () { ctrl._win.scrollTop(ctrl._initScroll); }); } This code does fix the animation, but causes screen flicker because it scrolls back to the top, and then waits for the next cycle to scroll back down to the original position. I'll be busy with other work this week, so I likely won't post an update until the end of this week or early next week. Let me know if you have any other ideas on how to force a timeline to the end in the meantime.
  11. I've attached a video showing the issue I'm running into. It works great when scrolling from the top. The problem occurs when I refresh the page after scrolling past the end of the animation. Chrome brings me to the same scroll position, which is often helpful, but in this case throws off the scroll trigger because it's container starts out with position fixed and it isn't able to determine that it's already past the end of it's scroll endpoint. Once I scroll up to it's endpoint, it pops into position and the animation starts working. I tried setting progress to 1 on its timeline, but it reverts that back to 0. I've tried setting the scroll position to 0 and then setting it back to its initial position. This works, but it requires a requestAnimationFrame between the two, which leads to a screen flicker. Is there any way to force scroll trigger to it's endstate without it being visible to the user? Edit: Not sure the attached video uploaded correctly. It can also be seen here.
×
×
  • Create New...