Jump to content
Search Community

All Activity

This stream auto-updates

  1. Past hour
  2. Hi, This setup seems to work OK in my local machine, no errors or warnings: https://stackblitz.com/edit/remix-run-remix-bdnlqt?file=app%2Froutes%2F_index.tsx Hopefully this helps. Happy Tweening!
  3. Hi Rodrigo, I actually just dropped a link to this codepen: https://codepen.io/neontrenton/pen/PovjWLq Does that help?
  4. Hi, Sorry to hear about the issues, but without a minimal demo that clearly illustrates the problem there is not a lot we can do. I can see some space below the footer in Chrome but not on Firefox, which stems from the fact that you're giving a specific style to every <section> tag: section { background-repeat: no-repeat; background-position: center; background-size: cover; position: relative; padding: 7em 0; background: #fff; } Because of that a specific section added by a Chrome extension actually creates a problem, so the advice not just for this project but in general is to give your section tags a specific class and avoid global styles for things like <div>, <section> and other tags that could be used by extensions since you could have unexpected results. Hopefully this helps. Happy Tweening!
  5. Thanks for the above @Rodrigo. I'm using remix+vite. I tried doing this in my project, a pretty basic version. useGSAP(() => { ScrollTrigger.create({ trigger: ".hero__description", start: "top top", end: "top -=1000px", animation: gsap.to("body", { y: 1000 }), scrub: true, }); }); it works if I put the above logic in a useEffect. For some reason I get the error (screenshot shared earlier) if I put the scroll trigger logic within the useGsap hook. I'll try to create a demo when I find some time. Thanks.
  6. Hi the reason for this is not related to ScrollTrigger or scrolling speed, is about the way you have setup your animation. tl.from(".video__section", { height: "75dvh", objectFit: "cover" }); tl.to(".text__section", { yPercent: -100 }); First your video section height changes and then you translate the text element. They both have the same duration, so if you take into account the information in the video Mitchel linked, you'll see that both instances are spread along the entire scroll amount, that makes the height of the video section as long as the translation of the text element. Is also important that both instances are using the default duration which is 0.5 seconds. What you could try is give the height change of the video section a smaller duration while keeping the default duration in the text section, something like this: tl.from(".video__section", { height: "75dvh", objectFit: "cover", duration: 0.125, // 0.5 / 4, that is 25% of the duration of the text translation }); tl.to(".text__section", { yPercent: -100 }); Hopefully this helps. Happy Tweening!
  7. Hello. I'm currently working on this site: https://victory2024.wpenginepowered.com/about/ Codepen: https://codepen.io/neontrenton/pen/PovjWLq And when I near the footer (or just scrolling through), the background image in the footer seems to disappear/flash white as you scroll. It also is repeating rather than showing parallax properly. Any ideas what might be causing these issues? I tried adding this and it helps, but it also breaks my #imgWrapper section #page { will-change: transform; } Here's my code so far: window.addEventListener("load", function() { const lenis = new Lenis() lenis.on('scroll', (e) => { console.log(e) }) lenis.on('scroll', ScrollTrigger.update) gsap.ticker.add((time)=>{ lenis.raf(time * 1000) }) gsap.ticker.lagSmoothing(0) // Text Reveal Animation let splitWords = function(selector) { document.querySelectorAll(selector).forEach(el => { el.dataset.splitText = el.textContent; el.innerHTML = el.textContent.split(/\s/).map(word => word.split("-").map(subWord => `<span class="word">${subWord}</span>`).join('<span class="hyphen">-</span>') ).join('<span class="whitespace"> </span>'); }); }; let splitLines = function(selector) { splitWords(selector); document.querySelectorAll(selector).forEach(el => { let lines = getLines(el); el.innerHTML = lines.map(wordsArr => `<span class="line"><span class="words">${wordsArr.map(word => word.outerHTML).join('')}</span></span>` ).join(''); }); }; let getLines = function(el) { let lines = [], line, words = el.querySelectorAll("span"), lastTop; words.forEach(word => { if (word.offsetTop != lastTop && !word.classList.contains("whitespace")) { lastTop = word.offsetTop; line = []; lines.push(line); } line.push(word); }); return lines; }; splitLines(".reveal-text"); gsap.registerPlugin(ScrollTrigger); document.querySelectorAll(".reveal-text").forEach(element => { const lines = element.querySelectorAll(".words"); gsap.timeline({ scrollTrigger: { trigger: element, once: true, toggleActions: "restart none none reset" } }).set(element, { autoAlpha: 1 }) .from(lines, 1, { yPercent: 100, ease: Power3.out, stagger: 0.25, delay: 0.1 }); }); // Landing Page ScrollTrigger let LandingPageScrollTrigger = gsap.timeline({ scrollTrigger: { trigger: "#ImgWrapper", start: "0% 0%", end: "70% 0%", pin: "#ImgWrapper", scrub: 2.2, } }); LandingPageScrollTrigger .to('#ImgWrapper #img7', { transform: 'translateZ(4500px)', }, 0) .to('#ImgWrapper #img6', { transform: 'translateZ(3700px)', }, 0) .to('#ImgWrapper #img5', { transform: 'translateZ(3100px)', }, 0) .to('#ImgWrapper #img4', { transform: 'translateZ(2800px)', }, 0) .to('#ImgWrapper #img3', { transform: 'translateZ(2600px)', }, 0) .to('#ImgWrapper #img2', { transform: 'translateZ(2400px)', }, 0) .to('#ImgWrapper #img1', { transform: 'translateZ(2200px)', }, 0); // Parallax BG let getRatio = el => window.innerHeight / (window.innerHeight + el.offsetHeight); gsap.utils.toArray("section").forEach((section, i) => { section.bg = section.querySelector(".bg"); gsap.fromTo(section.bg, { backgroundPosition: () => i ? `50% ${-window.innerHeight * getRatio(section)}px` : "50% 0px" }, { backgroundPosition: () => `50% ${window.innerHeight * (1 - getRatio(section))}px`, ease: "none", scrollTrigger: { trigger: section, start: () => i ? "top bottom" : "top top", end: "bottom top", scrub: true, invalidateOnRefresh: true } }); }); });
  8. Hi, I just created a simple demo using the approach I mentioned in a previous post, creating a different client component that registers the plugins and creates the ScrollSmoother instance using a useLayoutEffect. Something like this: "use client"; import { useLayoutEffect } from "react"; import gsap from "gsap-trial"; import { ScrollTrigger } from "gsap-trial/dist/ScrollTrigger"; import { ScrollSmoother } from "gsap-trial/dist/ScrollSmoother"; import { useGSAP } from "@gsap/react"; const RegisterGSAP = () => { useLayoutEffect(() => { gsap.registerPlugin( useGSAP, ScrollTrigger, ScrollSmoother, ); ScrollSmoother.create({ smooth: 1, effects: true, }); }, []); return null; }; export default RegisterGSAP; Used like this on the layout.js/jsx/tsx file: import { Inter } from "next/font/google"; import "./globals.css"; import RegisterGSAP from "../components/RegisterGSAP"; const inter = Inter({ subsets: ["latin"] }); export const metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout ({ children }) { return ( <html lang="en"> <body className={inter.className}> <RegisterGSAP /> <div id="smooth-wrapper"> <div id="smooth-content"> {children} </div> </div> </body> </html> ); } I made a small demo in Stackblitz showing the general structure of the project: https://stackblitz.com/edit/stackblitz-starters-xt1ucd?file=app%2Flayout.tsx,components%2FRegisterGSAP.tsx Hopefully this helps. Happy Tweening!
  9. Today
  10. In each reply it is best to post the link to the pen you're talking about even if the link hasn't changed (of course it is best to fork you work, so you can fall back at earlier versions), so that we are all at the same page and we don't have to hunt for the pen you're talking about. ScrollTrigger works based on the start and end trigger. As you can see in your pen (having markers: true) the end trigger is really far down, so this means the animation will get stretched over that distance, to me it is perfectly smooth, but yes it is slow, due to what you told ScrollTrigger to do. I highly recommend checking out this tutorial how to work with ScrollTrigger, It goes over all the key points you'll need to create an animation hooked to scroll. Again please check the video and see if you can figure out your own logic, otherwise check here the fork of your pen. But the best way to learn it to do it yourself! Hope it helps and happy tweening!
  11. https://codepen.io/elysee15/pen/XWwNEmy I just made some changes following your suggestion, but the scrolling isn't smooth, it's slow. I don't know why.
  12. I'm using remix + vite setup. Registering ScrollTrigger in useEffect gives weird errors. I don't really understand what this error is. This error is gone and scrolltrigger works if I register the ScrollTrigger first thing in my useGsap hook BUT, if I do this, the numeric scrub values stop having any effect, they behave as if that value was scrub=true. And then if I do outside my react component if (typeof document !== "undefined") { gsap.registerPlugin(MotionPathPlugin, useGSAP, ScrollTrigger); } Everything works, but that annoying empty style tag warning pops up. 🤦🏻 Came here from this thread:
  13. Hehe! @Rodrigo thank you so kindly for your help!!!!! That's exactly what I was hoping to achieve. Definitely had a feeling the answer was in toggleActions, I have watched the "detailed summary" of scrolltrigger video (https://gsap.com/docs/v3/Plugins/ScrollTrigger/?page=1) and rewatched that part, took notes this time! I hope this may help someone else at some point in their tweening journey. Kind regards, toggleActions can be the following, Play Pause Resume Reverse Restart Reset Complete None Default value: "play none none none" And the four positions in order is, "When it enters the screen" (default: play) "Forward past the endpoint" (default: none) "When it comes back in" (default: none) "Scroll all the way past the start" (default: none)
  14. Welcome to the forums, @gchaldu! The core library is publicly available and free to use in the vast majority of cases. The same goes for several of the plugins like ScrollTrigger. See https://gsap.com/licensing and https://gsap.com/pricing Some of the plugins, like ScrollSmoother, are a membership benefit of Club GSAP. So you must join the Club to get access to those. See https://gsap.com/pricing for pricing and details about which plugins are free and which are in the various membership levels. Enjoy the tools! Let us know if you have any GSAP-related questions. 💚
  15. I really love the library and I'm just learning it. I see a lot of information and it is not clear to me what I can use in my projects and which plugins I cannot. ScrollSmoother I saw examples: is it free?
  16. Hi @bansay and welcome to the GSAP Forums! Is mostly about how toggleActions work in ScrollTrigger. When you create a ScrollTrigger instance by default ScrollTrigger will play the animation only once when it enters (the start point passes the start trigger). Maybe you're looking for this: stick_timeline.to($sticky_footer, { background: "white", scrollTrigger: { trigger: "footer.main", endTrigger: "main", pin: false, markers: true, start: "top+=80 bottom", // top of footer.main, bottom of viewport? end: "+=80px", // -80px of main, bottom of viewport?, toggleActions: "play none none reverse" } }); That will play the animation when it enters and reverse it when it leaves back (when the scroll position moves backward past the "start", typically when the trigger is scrolled all the way backward past the start). I made a fork of your demo: https://codepen.io/GreenSock/pen/ExzXymb Hopefully this helps. Happy Tweening!
  17. Hm, that doesn't sound right to me at all. ScrollTrigger doesn't cause anything to reload. Unless maybe if you had <style> tags inside a pinned element, only because ScrollTrigger has to create a wrapper <div> around it for pinning purposes (a pin-spacer), but even that is easy to work around by defining the pinSpacer yourself (so that ScrollTrigger doesn't need to create a new element for that). See the docs for pinSpacer details. I'm glad you discovered a solution, though. 👍
  18. I'm trying to transition a repeating tween to scroll controlled one. I was able to achieve what I want here but I have a few concerns: 1. The code I've written only works coz it's a circular path and I'm faking the transition by rotating the circle svg. This effect won't work perfectly if I change the shape to a square. 2. I don't like how I have to pause/play the initialAnimation, create/kill the scrolltriggers on onEnter and onLeaveback callbacks. Questions: 1. Is there a better and legit way to do this, such that the effect can be achieved on any kind of path? 2. If not, is the way I do pause/play of the initialAnimation, and how I create/kill the additional scrolltriggers a good way to do it? 3. Given the code I've written, how would one handle the window resize to align the blocks to the path again? is it by killing and triggering everything again? Thanks in advance!
  19. Hi, Maybe there is a better explanation, but as far as I can see the helper function takes the element you tell it should be protected and prevents that from being splitted by SplitText and adds it as it is to the parent element and the split, that's why the entire <sup> tag is considered as one character and not two. Finally, yeah if is not broken don't fix it! Happy Tweening!
  20. Hello, I'm hoping this is a relatively quick answer. I have a black "sticky footer" that I want to change white as soon as it is above the main footer, which is also black. I have it correctly switching to white, as soon as the top of the main footer hits the bottom of the viewport using the start property, however, I'm not figuring out the right way to "reset" the sticky footer back to black, it is above the main element, just above the main footer. Ultimately, as soon as the sticky footer is above the main element, I want it to turn back to black. Any suggestions are thoroughly appreciated! https://codepen.io/bansay/pen/rNgweVX
  21. Hi, This could be because your're using an older version of ScrollTrigger, always make sure to use the latest one. Other possibility is that some images are loading and being rendered after the ScrollTrigger instances are created, that makes all the calculations made by ScrollTrigger to be off and not work properly. In those cases is a good idea to run the refresh method after all the images are loaded. Be sure that your ScrollTrigger instances are created in the order they appear in the screen. The fact that you need a hardcoded end value tells me that for some reason some elements don't have their natural height when ScrollTrigger instances are created on a reload, but it still a bit odd since it works on the initial load. Once again, without a demo that clearly illustrates the issue we're just taking blind guesses here 🤷‍♂️ Happy Tweening!
  22. As I said I am not able to recreate this bug in demo. But its fine now, I gave hardcore scroll value to start and end so that they dont jump at random place. But I still don't understand what caused this problem. Acc to your experience what could have gone wrong, have you seen such bug before somewhere else. Or is it something I did wrong because of my insufficient working knowledge of gsap
  23. Hello @Rodrigo, @mvaneijgen. I know this isn't a common case, so that's okay. Thank you for your time anyway. I handled it by creating a new timeline to capture the position when a specific element enters into view. // Trigger a function when the position element enters the viewport ScrollTrigger.create({ trigger: positionEl, start: "top bottom", onEnter: function () { // Execute the createTimeline function when positionEl enters the viewport createTimeline(); } }); I know it’s not the most elegant solution, but it works for my case. The Codepen has been updated as well, in case someone needs such a weird solution. Cheers
  24. @GSAP Helper, I've identified the problem! It turns out that the ScrollTrigger plugin was reloading my CSS files on every resize. Since I dynamically load CSS in each component and it wasn't located in the head HTML tag, this caused the issue. I've since transferred all of the CSS stylesheet links to the head tag, and now everything works perfectly fine. Thank you once again for all your assistance, @GSAP Helper and @Rodrigo!
  25. @GreenSock Thank you for drawing my attention to this simple solution.
  1. Load more activity
×
×
  • Create New...