Jump to content
Search Community

Leaderboard

Popular Content

Showing content with the highest reputation on 04/23/2024 in all areas

  1. hi @alexr8 maybe these 2 demos help 1 with draggable and 1 without https://codepen.io/GreenSock/pen/BaQXjWw?editors=0010 https://codepen.io/GreenSock/pen/RwKwLWK
    2 points
  2. Your video is around 15 seconds long, so I've split it up in three sections of each 5 seconds. First of the best thing to do when working with ScrollTrigger is to remove it! This seems counter intuitive, but ScrollTrigger is just animating something on scroll, so just focus on the animation at first and only when you're happy with the animation add ScrollTrigger back in. This way you can focus on one part at a time and it will save a lot of headache when debugging. I've enabled GSDevTools for the animation, so we can first fully focus on the animation and create what we want to happen on scroll. I've modified your HTML and CSS, I've created a .trigger element and have everything stack right on top of each other with CSS (please disable all the JS to see what it looks like) I've taken this logic from my stacking cards post I encourage you to read through it, see below Then on the timeline I've put all the tweens, frist the video tweens to 5 seconds over a duration of 5 seconds, then the video tweens to 10 seconds over a duration of 5 seconds and at the same time the first card animates in from of screen, and them the same for the next card. This is probably not fully correct, but it shows you how you can create a timeline and have things happen at the same time. I've add some ScrollTrigger code but this is commented out, but you can enable it to see what this would do on scroll, but be sure to disable it again when you want to tweak the animation. If you're new to GSAP check out this awesome getting started guide https://gsap.com/resources/get-started/ and check out this awesome tutorial how to work with ScrollTrigger. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/bGJOQzq?editors=1010
    2 points
  3. You where almost there! I've move your timeline outside the loop and add the ScrollTrigger logic to the one timeline, then I've add all your tweens to that one timeline and let ScrollTrigger control it. Does that make sense? Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/qBwLJXX?editors=1010
    2 points
  4. Thanks, If others may need I m currently using import gsap from "gsap"; export class LifecycleManager { public ctx: gsap.Context | null; private boundAfterSwapHandler: () => void; private boundPageLoadHandlers: Map<string, () => void>; constructor() { this.ctx = null; this.boundAfterSwapHandler = this.onChangePage.bind(this); this.boundPageLoadHandlers = new Map(); document.addEventListener("astro:after-swap", this.boundAfterSwapHandler); } /** * Initialize the context */ initializeContext(): void { if (this.ctx === null) { this.ctx = gsap.context(() => {}); } } /** * Check if the component with the given ID exist in the DOM * @param id id of the element * @returns boolean */ elementExists(id: string): boolean { if (!id) throw new Error("ID cannot be null"); return document.getElementById(id) !== null; } /** * Execute the callback when the page is loaded and the component is visible * @param id id of the element * @param callback callback function */ onElementLoaded(id: string, callback: (ctx: gsap.Context | null) => void): void { if (!this.boundPageLoadHandlers.has(id)) { const handler = () => this.onPageLoad(id, callback); this.boundPageLoadHandlers.set(id, handler); document.addEventListener("astro:page-load", handler); } } /** * Callback for the page load event * @param id id of the element * @param callback */ onPageLoad(id: string, callback: (ctx: gsap.Context | null) => void): void { if (this.elementExists(id)) { this.initializeContext(); callback(this.ctx); } } /** * Revert the context */ revertContext() { if (this.ctx !== null) { this.ctx.revert(); this.ctx = null; } } /** * When changing page revert the context * and remove the event listeners */ onChangePage(): void { this.revertContext(); } /** * Cleanup all event listeners */ cleanup(): void { this.revertContext(); document.removeEventListener("astro:after-swap", this.boundAfterSwapHandler); this.boundPageLoadHandlers.forEach((handler, id) => { document.removeEventListener("astro:page-load", handler); }); this.boundPageLoadHandlers.clear(); } } export default LifecycleManager; usage <script> import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { SplitText } from "gsap/SplitText"; import { LifecycleManager } from "@/services"; gsap.registerPlugin(ScrollTrigger, SplitText); let manager = new LifecycleManager(); manager.executeWhenVisible("hero", () => { manager.ctx?.add(() => { const childSplit = new SplitText("[data-hero-text-reveal]", { type: "lines", linesClass: "split-child", }); const parentSplit = new SplitText("[data-hero-text-reveal]", { // type: "lines", linesClass: "split-parent", }); gsap.timeline() .set("[data-hero-text-reveal]", { opacity: 1 }) .from(childSplit.lines, { yPercent: 300, skewY: 7, stagger: 0.2, }) .to( "[data-hero-reveal]", { opacity: 1, stagger: 0.1, }, "<=", ); const pathsToAnimate = document.querySelectorAll( '[wb-element="path-to-animate"]', ); pathsToAnimate.forEach((path) => { const finalPath = path.getAttribute("wb-final-path"); gsap.timeline({ scrollTrigger: { trigger: path, start: "top bottom", end: "bottom top", scrub: 1, }, }).to(path, { attr: { d: finalPath || "" }, ease: "none", }); }); }); }); </script>
    1 point
  5. Example: CustomEase.create("in-out", "0.42,0,0.58,1") And then: gsap.to(".box", { ease: "in-out", ... });
    1 point
  6. Hi, In your original demo you had both toggleActions and scrub in your ScrollTrigger configuration. It has to be one or the other, but definitely not both, since they pretty much don't work together. From the ScrollTrigger docs: https://gsap.com/docs/v3/Plugins/ScrollTrigger/#config-object scrub Boolean | Number - Links the progress of the animation directly to the scrollbar so it acts like a scrubber. You can apply smoothing so that it takes a little time for the playhead to catch up with the scrollbar's position! It can be any of the following Boolean - scrub: true links the animation's progress directly to the ScrollTrigger's progress. Number - The amount of time (in seconds) that the playhead should take to "catch up", so scrub: 0.5 would cause the animation's playhead to take 0.5 seconds to catch up with the scrollbar's position. It's great for smoothing things out. toggleActions String - Determines how the linked animation is controlled at the 4 distinct toggle places - onEnter, onLeave, onEnterBack, and onLeaveBack, in that order. The default is play none none none. So toggleActions: "play pause resume reset" will play the animation when entering, pause it when leaving, resume it when entering again backwards, and reset (rewind back to the beginning) when scrolling all the way back past the beginning. You can use any of the following keywords for each action: "play", "pause", "resume", "reset", "restart", "complete", "reverse", and "none". I'd assume that Jack picked scrub over toggleActions, since your demo was scrubbing, but most definitely I can't read his mind! 😉 Hopefully this clear things up. Happy Twening!
    1 point
  7. Yeah that definitely makes it more clear to me Thanks a lot for your help and explanations!
    1 point
  8. Yes this is what I was looking for!!! I never knew about the immediateRender: false! Just one question: you removed toggleActions, but As I scroll back it it moves in reverse, why? Thanks for solving my problem!
    1 point
  9. ah i see! i would have to create instance variables for each of the parts, and then retrieve their height values onMount. Ok i'll give that a go. Many thanks!
    1 point
  10. No, that is why I said: Everything is hard coded right now, because that is the easiest way to demonstrate how the logic works. I have no idea how Svelt works, but I would get the elements as soon as they are ready and grap their heights and then add that to the array.
    1 point
  11. Hi @Sandeep Choudhary welcome to the forum! You just needed to scope the pin: ".right" element eg pin: galleryObj.querySelector(".right"), otherwise it would always gets the first .right element. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/ExJGMed?editors=0011
    1 point
  12. Hi @vexkiddy welcome to the forum! Am I missing something? I don't see any GSAP code! Again we would love to see what you can come up with that way we can better help you understand the tools, so please try to get something working then someone here will definitely point you in the right direction. If you're new to GSAP check out this awesome getting started guide https://gsap.com/resources/get-started/ Hope it helps and happy tweening!
    1 point
  13. Hi @kevin.dev welcome to the forum! By default GSAP renders all the logic it needs on page load and because you're targeting the same element multiple times they all get the same start point en thus will not flow like you want to. What you can do is in your later tweens set immediateRender: false, so that they will wait until it is needed to calculate their animations. Personally for such a simple animation I would create one timeline with one ScrollTrigger, this is much easier to debug and maintain in the future. I've also tweaked the logic a bit. There is no need for a .fromTo(), the default scale of an element is 1, so setting .from() 0.75 will automatically scale to 1, if you use a timeline it will see in the next tween it is 1 and then animate .to() 0.75. Also if you want to have scale in both direction, you can just set scale. I've add two ScrollTrigger because from your question I get you want the pin to happen later then the scale up, so one handles the scale and the other the animation. In the animation I've add a pause twen for 1 second where the animation does nothing, to me this looks good, but be sure to tweak it if you want. Check out this tutorial how to work with ScrollTrigger if you want some more tips! Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/eYobPKB?editors=0010
    1 point
  14. Thank you very much. This is exactly what I needed. Your help has solved my long-standing problem. Now I can achieve the effect I need. Now I just need to integrate it into the Vue framework. Thanks again. https://codepen.io/sw355498/pen/ExJGpQe
    1 point
  15. Hi, I think the main issue here is the fact that you're using the same element as the scroller (the document element). ScrollTrigger allows you to define a scroller which is the element where ScrollTrigger will look for the scroll position in order to update any Tween/Timeline you pass to it. 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 Here are a couple of demos that use a similar approach: https://codepen.io/GreenSock/pen/yLRQozy https://codepen.io/GreenSock/pen/OJBvBjB Hopefully this helps. Happy Tweening!
    1 point
  16. Thanks for reporting back! Great news that the Lenis team worked fast on this and that everything is working as expected!
    1 point
×
×
  • Create New...