Rodrigo
Content Type
Profiles
Forums
Store
Blog
Product
Showcase
FAQ
Downloads
Posts posted by Rodrigo
-
-
Hi,
Just to add to @mvaneijgen's great advice, you can create a new NextJS project in Stackblitz. Click on the large New Project button at the top left and select NextJS in the FullStack tab:
The one thing we ask to our users is to keep the demo as small and simple as possible, just the easiest way to re-create the probem you're facing.
Also in ScrollTrigger you can set a scroller property if you don't want to use the window object as the default scroller. From the ScrollTrigger docs:
scroller
String | Element - By default, the scroller is the viewport itself, but if you'd like to add a ScrollTrigger to a scrollable <div>, for example, just define that as the scroller. You can use selector text like "#elementID" or the element itself.https://gsap.com/docs/v3/Plugins/ScrollTrigger/#config-object
Hopefully this helps.
Happy Tweening!
- 1
-
Hi @fejmek and welcome to the GSAP Forums!
Sure thing, you can definitely use MorphSVG for something like that. @mvaneijgen on of the forums superheroes created this thread where He shares a lot of knowledge on the subject:
Finally in your demo keep in mind that you're not using the correct syntax for a circular clip path:
// Wrong timeline.from(circle, { clipPath: "circle(0%)", stagger: 1, }); // Right timeline.from(circle, { clipPath: "circle(0% at 50% 50%)", stagger: 1 });
Hopefully this helps.
Happy Tweening!
- 1
-
Hi,
Basically your ScrollTrigger import is wrong:
// Wrong import scrolltrigger from "https://esm.sh/scrolltrigger"; // Right import ScrollTrigger from "https://esm.sh/gsap/ScrollTrigger";
ScrollTrigger is part of the GSAP package, not an individual separate package and is PascalCased, you had it in lower case.
Hopefully this helps.
Happy Tweening!
-
Hi,
You could borrow some logic from this demo:
See the Pen gOvvJee by GreenSock (@GreenSock) on CodePen
Hopefully this helps.
Happy Tweening!
-
The useGSAP hook has a dependency for at least React 16, but it doesn't use/install React 16:
"dependencies": { "gsap": "^3.12.5", "react": ">=16" },
If you already have React 18 installing the @gsap/react package won't change a thing and won't install another version of React.
I just tested this on a demo here on my local machine using the latest version of Next without any issues. We only encountered some issues while importing the @gsap/react package from esm.sh, which solves by doing this:
import React from "https://esm.sh/react@18.3.1"; import ReactDOM from "https://esm.sh/react-dom@18.3.1"; import gsap from "https://esm.sh/gsap"; import { useGSAP } from "https://esm.sh/@gsap/react?deps=react@18.3.1";
We'll update the dependencies on the hook to be at least version 17 of React.
Finally it would be super helpful if you could create a minimal demo that reproduces this error.
Happy Tweening!
- 1
-
Mhh... Why are you using intersection observer for something that can be done with ScrollTrigger?
I think you are overcomplicating this quite a bit. If I was you I'd create an extra prop for ScrollTrigger and if that prop has a ScrollTrigger configuration, you just need to check if is not falsy, instead of using just SplitText use ScrollTrigger to handle when the animation plays, something like this:
See the Pen abxMRgp by GreenSock (@GreenSock) on CodePen
I updated the demo I posted before so it uses ScrollTrigger
https://stackblitz.com/edit/nuxt-starter-vzsxyp?file=app.vue
The only detail is that this check is not needed with ScrollTrigger:
completed && tween.progress(1);
Hopefully this helps.
Happy Tweening!
- 1
-
Hi @Anas Ali Khan,
Lenis is free but is a product of Studio Freight:
https://lenis.darkroom.engineering/
Just be aware that we can't offer support for Lenis here, since we need to keep our focus on GSAP related questions.
Finally we do have a smooth scrolling solution called ScrollSmoother, that is fully integrated with ScrollTrigger:
https://gsap.com/docs/v3/Plugins/ScrollSmoother/
Happy Tweening!
-
Hi @explorerzip,
In Blake's demo all you have to do is add a repeatDelay value:
https://gsap.com/docs/v3/GSAP/Timeline/repeatDelay()
Something like this:
var tl = gsap.timeline({ paused: true, repeat: -1, repeatDelay: 2, // Two seconds between animations onRepeat: updateImages, onUpdate: updatePath }) .to(arc, { duration: 3, end: 360, ease: "none" })
Hopefully this helps.
Happy Tweening!
- 1
-
Hi,
You also posted in this other thread:
Where Jack suggested using ScrollTrigger's sort() method for solving this:
https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.sort()/
This works as expected:
sectionB.forEach((section) => { const textElement = section.querySelector("span"); // Load some data, then initialize animation later(3000).then(() => { console.log("Loaded!!"); const tl = gsap.timeline({ scrollTrigger: { trigger: section, start: "top top", end: `+=2000`, markers: true, scrub: true, pin: true } }); tl.to(textElement, { scale: 1.2, ease: "power1.inOut" }); // Sort the ScrollTrigger instances ScrollTrigger.sort(); }); });
This happens because the ScrollTrigger are not created in the order they appear on the screen, if that is not possible we recommend using the refreshPriority configuration in combination with the sort() method, from the ScrollTrigger docs:
refreshPriority
number - it's VERY unlikely that you'd need to define a refreshPriority as long as you create your ScrollTriggers in the order they'd happen on the page (top-to-bottom or left-to-right)...which we strongly recommend doing. Otherwise, use refreshPriority to influence the order in which ScrollTriggers get refreshed to ensure that the pinning distance gets added to the start/end values of subsequent ScrollTriggers further down the page (that's why order matters). See the sort() method for details. A ScrollTrigger with refreshPriority: 1 will get refreshed earlier than one with refreshPriority: 0 (the default). You're welcome to use negative numbers too, and you can assign the same number to multiple ScrollTriggers.Hopefully this helps.
Happy Tweening!
-
Hi,
I can't see anything wrong in the code you posted, plus the latest version of the hook is importing useRef as you can see here:
https://github.com/greensock/react/blob/main/src/index.js
Can you provide a minimal demo on Stackblitz that illustrates this?
Happy Tweening!
-
1 hour ago, knozz said:
I tried to reproduce what you did but I don't have access to the entire css
That demo is using Tailwind CSS
-
23 minutes ago, xtinepak said:
One thing I'm noticing is that I've to scroll multiple times to change the slides between the sections. For example when the swiper section starts I've to scroll 3 or 4 times to go to the next section. Could you please let me know what needs to be done here?
It takes only one wheel/touch event, but the previous animation has to be completed first and we want to wait for some specific situations:
let allowScroll = true; // sometimes we want to ignore scroll-related stuff, like when an Observer-based section is transitioning. let scrollTimeout = gsap.delayedCall(1, () => allowScroll = true).pause(); // controls how long we should wait after an Observer-based animation is initiated before we allow another scroll-related action
3 minutes ago, xtinepak said:if we could add fade in/out effect for the swiper section instead of scroll that would be excellent?
Sure thing, just tinker with the logic in the gotoPanel method, that's where everything happens in terms of animations:
function gotoPanel(index, isScrollingDown) { // return to normal scroll if we're at the end or back up to the start if ((index === swipePanels.length && isScrollingDown) || (index === -1 && !isScrollingDown)) { intentObserver.disable(); // resume native scroll return; } allowScroll = false; scrollTimeout.restart(true); let target = isScrollingDown ? swipePanels[currentIndex] : swipePanels[index]; gsap.to(target, { yPercent: isScrollingDown ? -100 : 0, duration: 0.75 }); currentIndex = index; }
You can switch yPercent for opacity/autoAlpha without any issues.
Hopefully this clear things up.
Happy Tweening!
-
No problemo! Also in these forums there are no stupid questions 👍
That's just the Logical AND operator:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND
Basically it checks if timer is truthy, if it is it'll clear the timeout. By default the timer variable is undefined which will return falsy and the clearTimeout won't be executed, same with the completed boolean. I want to set the progress of the tween to 1 only if the tween has run completely.
Hopefully this clear things up.
Happy Tweening!
- 1
-
Hi,
I'm not 100% sure of what you're trying to achieve here, but maybe something like this:
See the Pen poBYZyJ by GreenSock (@GreenSock) on CodePen
Hopefully this helps.
Happy Tweening!
-
Maybe something like this a mix of ScrollTrigger and Observer:
See the Pen ExEOeJQ by GreenSock (@GreenSock) on CodePen
Happy Tweening!
-
Hi,
The issue is in this funky useEffect hook you have here:
useEffect(() => { setInterval(() => { setState(Math.random()); }, 1500); });
That basically runs everytime the component is re-rendered since it has no dependencies array, but at the same time each time the interval is completed the state is updated, creating a new interval and running your custom hook again, so after the first interval is completed a new one is created and each new interval will create a new one, so this grows exponentially.
Here is a fork of your demo without that and it has only two onLeave callbacks, which makes sense since the effect hooks are called twice on StrictMode:
https://stackblitz.com/edit/react-pps835?file=src%2FApp.jsx
Hopefully this clear things up.
Happy Tweening!
-
Hi,
Actually in the demo the columns have a different height, the thing is that they are being animated in opposite directions.
Here is a fork of the same demo with both columns animating in the same direction:
See the Pen mdgoKVm by GreenSock (@GreenSock) on CodePen
Finally this is most about the calculations needed to move each column on a given direction.
Hopefully this clear things up.
Happy Tweening!
-
Hi,
You can use Stackblitz to create a Nuxt demo and the GSAP Trial package in order to use the bonus plugins on Stackblitz:
https://www.npmjs.com/package/gsap-trial
Here is a simple Nuxt demo:
https://stackblitz.com/edit/nuxt-starter-vzsxyp?file=app.vue
Hopefully this helps.
Happy Tweening!
- 1
-
Hi @fraserYT and welcome to the GSAP Forums!
You are using an extremely generic selector. I'd strongly recommend you to use a unique class in your elements even if it doesn't have any styles, just for selecting purposes. This seems to work the way you expect:
<div class="header-icons"> <div class="menu-item"></div> <div class="menu-item"></div> <div class="menu-item"></div> <div class="menu-item"></div> <div class="menu-item"></div> <div class="menu-item"></div> </div>
gsap.to(".header-icons .menu-item", { opacity: 0, y: -80, stagger: 0.1, scrollTrigger: { trigger: ".full-row", start: 0, end: 230, scrub: 0.5, markers: true } });
Here is a fork of your demo:
See the Pen oNOVqKm by GreenSock (@GreenSock) on CodePen
Hopefully this helps.
Happy Tweening!
- 1
-
Hi,
The video in your demo is over 130MB and it's dimensions are huge. As Cassie mentions rendering the video alone doesn't create any problems but together with other stuff, it can definitely become an issue.If you want to create some type of particles moving background and you want excellent performance I'd recommend PIXI's particle container:
https://pixijs.com/8.x/examples/basic/particle-container
You can check this demos by @OSUblake
See the Pen BjNZYP by osublake (@osublake) on CodePen
See the Pen PjrbWq by osublake (@osublake) on CodePen
Happy Tweening!
- 1
-
Great to hear about it! Yeah sometimes we have to hack our way into something working the way we need 🤷♂️
Happy Tweening!
-
Ahh yeah I see the problem now. Roughly this is your HTML
<div class="scroll-through-hero st-hero-animate sth-fadein-off" style="background-color: inherit;"></div> <div class="immersive-scroll-video" style="background-color: inherit;"></div> <div class="immersive-scroll-video" style="background-color: inherit;"></div> <div class="scroll-through-hero st-hero-animate sth-fadein-off" style="background-color: inherit;"></div>
In your JS you're creating the ScrollTrigger instances for the elements inside the
immersive-scroll-video
elements and then for thescroll-through-hero
elements. When using ScrollTrigger ideally create the instances in the order they appear on the screen as the user scrolls down, especially if you are pinning one or more ScrollTrigger instances.If you can't create your instances in the order they appear in the screen, then you can use the
refreshPriority
config option. From the ScrollTrigger docs:refreshPriority
number - it's VERY unlikely that you'd need to define a refreshPriority as long as you create your ScrollTriggers in the order they'd happen on the page (top-to-bottom or left-to-right)...which we strongly recommend doing. Otherwise, use refreshPriority to influence the order in which ScrollTriggers get refreshed to ensure that the pinning distance gets added to the start/end values of subsequent ScrollTriggers further down the page (that's why order matters). See the sort() method for details. A ScrollTrigger with refreshPriority: 1 will get refreshed earlier than one with refreshPriority: 0 (the default). You're welcome to use negative numbers too, and you can assign the same number to multiple ScrollTriggers.Here is the docs for the sort method:
https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.sort()Hopefully this helps.
Happy Tweening!
-
Hi,
I'm not 100% sure of what issue you're experiencing, but waiting for 1 tick of GSAP's ticker should be enough. As far as I can tell, after you revert your GSAP instances and create the new ones, it should take 1 tick to render the new ones, so that should be enough. Based on your demo this is how I would proceed:
const tweenable = document.getElementById('tweenable') let tween, timer; const createTween = () => { tween = gsap.timeline().fromTo(tweenable, {opacity: 1}, {opacity: 0, duration: 1}); }; const revertTween = () => { tween && tween.revert(); createTween(); }; window.addEventListener("resize", () => { timer && clearTimeout(timer); timer = setTimeout(() => { revertTween(); }, 200); }); createTween();
Here is a fork of your demo:
See the Pen oNOVzdg by GreenSock (@GreenSock) on CodePen
Hopefully this helps.
Happy Tweening!
-
Hi @knozz and welcome to the GSAP Forums!
Maybe something like this demo:
See the Pen vYjqXLm by GreenSock (@GreenSock) on CodePen
Hopefully this helps.
Happy Tweening!
Horizontal Scroll randomly translating to the y direction when using typescript react
in GSAP
Posted
Hi @ajk and welcome to the GSAP Forums!
First proper cleanup is very important with frameworks, but especially with React. React 18 runs in strict mode locally by default which causes your
useEffect()
anduseLayoutEffect()
to get called TWICE.Since GSAP 3.12, we have the useGSAP() hook (the NPM package is here) that simplifies creating and cleaning up animations in React (including Next, Remix, etc). It's a drop-in replacement for
useEffect()
/useLayoutEffect()
. All the GSAP-related objects (animations, ScrollTriggers, etc.) created while the function executes get collected and then reverted when the hook gets torn down.Here is how it works:
Or if you prefer, you can use the same method signature as
useEffect()
:This pattern follows React's best practices.
We strongly recommend reading the React guide we've put together at https://gsap.com/resources/React/
Finally in the case of your TSX demo, the different is that you're using snapping in your ScrollTrigger config, while in your JS demo you're not:
If you remove that line, most likely this will work the way you intend.
Hopefully this helps.
Happy Tweening!