Jump to content
Search Community

stefanobartoletti

Members
  • Posts

    19
  • Joined

  • Last visited

Everything posted by stefanobartoletti

  1. Thanks. I will check these functions, probably matchMedia is what I need. A possible alternative (specific to Vue) that I'm also considering is useBreakpoints from the VueUse package (I'm reporting this here as a possible reference for other people too), but probably the two options that you gave me are covering my need. Thanks for your reply!
  2. I've tried to read the Draggable docs, but I haven't found an explicit reference to this. I've integrated a Draggable instance in one of my projects (It is based on Nuxt, but this does not seem to be relevant here), and the specific implementation should have the affected elements be draggable only on desktop viewports. Is it possible to natively enable Draggable only on certain breakpoints, or should I use a custom function before firing Draggable itself? Thanks
  3. This is not strictly a help request (my integration is working correctly), but more like a desire to understand how things work. And, it is probably also more generic and not related only to Draggable, but more generally even to other GSAP plugins. I've integrated Draggable into one Vue component, this is a schematic overview of my implementation: <template> <section> <!-- my component template --> </section> </template> <script setup> const items = ref([]) // Target items, full code omitted for brevity const { Draggable } = useGsap() // Import gsap from a dedicated composable onMounted(() => { Draggable.create(items.value, { // Draggable options }) }) onUnmounted(() => { Draggable.kill() }) </script> Everything is working correctly on the front-end, and also Draggable.kill() should be hooked correctly on the component lifecycle. I've also tried another implementation, similar to the one often suggested when using gsap.context, just like this: <script setup> const ctx = ref() const items = ref([]) // Target items, full code omitted for brevity const { Draggable } = useGsap() // Import gsap from a dedicated composable onMounted(() => { ctx.value = Draggable.create(items.value, { // Draggable options }) }) onUnmounted(() => { ctx.value.revert() }) </script> And it seems to work correctly, just like in the previous example. Since these two solutions are effectively working in the same way on the frontend, are there some reasons to prefer one over another? Under the hood, what are the differences between them? Thanks :-)
  4. Thanks for your reply! I really overlooked that part in the ScrollTrigger docs, I will check it. For ScrollSmoother I will try to see if I can find another way to implement a similar solution, but my priority was ScrollTrigger. Thanks again!
  5. I have a rather unusual layout, where the main content of the page is inside a "frame" that is exactly the size of the viewport. The body of the page itself basically never scrolls (it never gets higher than 100vh), and the scroll only happens inside .frame-content element (the blue-bordered one), that contains the main content of the page (as you can see, it contains many sections). I wish to integrate both ScrollTrigger and ScrollSmoother into this layout, by having them take effect (and do their calculations) only into the .frame-content element. But some intial trial-and-error (mostly error I would say, eheh) has given me: - ScrollTrigger does not work at all: I wish to animate elements inside the various sections when they appear on screen, but it looks like it listens to the scroll of the body, which never scrolls. So these elements do not animate at all. - ScrollSmoother, if set like this ScrollSmoother.create({ content: '.smooth-content' }), always break my layout and places this element out of the "frame" (I have not included both of them in the codepen, because I wanted to show the clean look of the original layout before applying anything to it). Is it possible to do these things, or am I only trying to force these tools to do something that they are not supposed to do? Thanks for any answer or insight about this!
  6. Thanks for your replies. From what I get, it should be called only once before all ScrollTriggers are set, am I wrong? And once set, all my subsequent scrolltriggers will automatically use it?
  7. Given my following animation import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); const icons = document.querySelectorAll('.icon'); icons.forEach(icon => { gsap.to(icon, { rotate: 180, ease: 'linear', duration: 10, scrollTrigger: { trigger: icon.parentNode, start: 'top 100%', end: 'bottom 0%', scrub: 5, } }); }); I need to implement the normalizeScroll function on ScrollTrigger, but it is not very clear to me how to do it when using Scrolltrigger inside Gsap like in my example. Can somebody help me?
  8. Does it matter for Gsap where my ref="main" is located on the template?
  9. No, I don't have any image, I'm animating a plain text, and it doesn't have any particular css that could prevent its size being correctly displayed. It does not work even without applying any style at all.
  10. Thanks for the suggestion, I managed to get an inspiration by your solution by using the xPercent property instead of trying to access the element width directly. Now this code works: onMounted(() => { ctx.value = gsap.context((self) => { const scrollingText = self.selector('[gsap="scrolling-text"]') tl.value = gsap .timeline({ repeat: -1 }) .to(scrollingText, { xPercent: -100, duration: 20 * ((1 / 1920) * window.innerWidth), // Need to better define duration/speed ease: 'none', }) }, main.value) // <- Scope! }) I still need to tweak the duration to provide a consistent experience between various screensizes, but this is another matter. And of course I have not solved the main problem itself, directly accessing needed properties, but at least I have fixed this animation. Thanks for your help.
  11. Thanks for the insights. I do not really need or want to use a timeout, it is not a clean solution, I just tried to use it to better understand what was going on. Anyway, I tried putting console.logs along all the lifecycle of the component, and all of them fire in the expected order. I also tried assigning some extra properties (color and background color) from gsap, something like this: tl.value = gsap .timeline({ repeat: -1 }) .to(scrollingText, { x: -textWidth, duration: 20 * (textWidth / windowWidth), ease: 'none', color: '#976239', backgroundColor: '#456234', }) And they are applied also in changing routes, so I can also exclude gsap not correctly targeting the given element. The real problem lies in reading some of the targeted element properties, specifically the dimensions, since apparently some others are read without any issue (like innerHTML) I'd like to provide another minimal demo, but it seems that there is something going on related to the full configuration of my project (the same specific gsap instance is applied to the stackblitz that I provided and it works there). Are there some other information that I can gather to tr to get a better picture if this issue?
  12. Thanks for your answer, it is really appreciated Unfortunately nextTick isn't working either ? I don't exactly know what is causing the difference between my real project and the demo example on stackblitz. In my real project I have dynamic routes and data received from a CMS API, but this seems to be unrelated. Even by putting in fake static data (i.e. like I did on the example), the problem is still there, so I think that is is not caused by a micro delay in waiting the API (it wuld break the animation even on the first load I think). The only difference is the dynamic route, but even here, it does not really seem so related. At the moment, my only clue is that with the timeout set at a high value (1000ms) it works, if I lower it it stops working. So there should be some kind of issue o the lifecycle of the component. Do you think that in my code, the context is correctly destroyed at onUnmounted? could the problem be related to a previous instance of the animation not completely unloaded and causing problems with the new one?
  13. Also, I've tried to use a timeout, something like this onMounted(() => { ctx.value = gsap.context((self) => { const scrollingText = self.selector('[gsap="scrolling-text"]') setTimeout(() => { const textWidth = scrollingText[0].offsetWidth const textHTML = scrollingText[0].innerHTML const windowWidth = window.innerWidth console.log(scrollingText[0]) console.log(textWidth, textHTML) tl.value = gsap .timeline({ repeat: -1 }) .to(scrollingText, { x: -textWidth, duration: 20 * (textWidth / windowWidth), ease: 'none', }) }, '1000') }, main.value) // <- Scope! }) onUnmounted(() => { ctx.value.revert() // <- Easy Cleanup! }) And now it seems to work, but of course it is not a proper solution, the animation should not be delayed that much
  14. This is a basic fork of StackBlitz, to show what I'm trying to achieve. https://stackblitz.com/edit/nuxt-starter-hxrstv?file=pages%2Findex.vue It seems that on stackblitz is is working normally even on route changes, but in my actual setup I have dynamic routes accessed from pages/[...slug].vue instead of static routes. I still don't exactly know how to diagnose further this. Thanks for your help.
  15. Hi, I'm trying to solve a problem that I'm having when trying to integrate Gsap with Nuxt 3. I started from the official example here https://stackblitz.com/edit/nuxt-starter-khrgsj My component is this one <template> <section class="overflow-hidden py-24"> <div ref="main" class="flex"> <span v-for="i in 3" :key="i" class="block whitespace-pre font-headings text-7xl font-light leading-tight text-base-300 md:text-9xl lg:text-[15rem]" gsap="scrolling-text" >{{ text + ' - ' }}</span> </div> </section> </template> <script setup> import gsap from 'gsap' const text = 'Lorem ipsum dolor' const main = ref() const tl = ref() const ctx = ref() onMounted(() => { ctx.value = gsap.context((self) => { const scrollingText = self.selector('[gsap="scrolling-text"]') const textWidth = scrollingText[0].offsetWidth const textHTML = scrollingText[0].innerHTML const windowWidth = window.innerWidth console.log(scrollingText[0]) console.log(textWidth, textHTML) tl.value = gsap .timeline({ repeat: -1 }) .to(scrollingText, { x: -textWidth, duration: 20 * (textWidth / windowWidth), ease: 'none', }) }, main.value) // <- Scope! }) onUnmounted(() => { ctx.value.revert() // <- Easy Cleanup! }) </script> The gsap animation is meant to animate a given element based on its dimensions amongst other things. At first page load everything works well, the element is correctly animated, and the console.log give this output: 2131 Lorem ipsum dolor - but when navigating to other pages/routes, the animation is not working, and console.log gives this: 0 Lorem ipsum dolor - Please note that the first value is offsetWidth and the second innerHTML I don't really have many clues about what's going on there, except that maybe these values are get in a wrong moment of the lifecycle when the elements are present (so the correct access of innerHTML) but not yet properly rendered/displayed (so, no correct value of offsetWidth) Or it can be some issues with the unmount phase, since on the first page load everything works fine. Can someone try to help me debug this and maybe propose a solution?
  16. Thanks,the batch seems to be solving my issue, I'm still tweaking it but looks like the right tool for me.
  17. Thank you guys, I've put up a minimal setup on Codepen, here it is https://codepen.io/stefanobartoletti/pen/vYjqpgZ Sorry for not having provided one before Basically I want each element of every to not start their animation together. Also @mvaneijgen thanks for your suggestions, I'll try to implement something like that and see if it works in my case.
  18. Hi, I'm trying to add a stagger to a timeline that includes ScrollTrigger. It already works fine, adding a smooth animation when each of the affected elements enter the viewport. I need to add a little delay to each element, so that when in example I have a grid with three elements aigned horizontally, they don't animate in at the same time, but each is slightly delayed from the previous. I tried to add a stagger property, but it does not seem to affect anything. // --- Imports --- import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); // --- Animation --- const gsapParallaxY = () => { const elements = document.querySelectorAll('[gsap-animation="parallax-y"]'); elements.forEach(function (element) { const tl = gsap.timeline(); tl.from(element, { y: '10vh', autoAlpha: 0, ease: 'power2.out', duration: 10, stagger: 0.5, // <-- everything works except this scrollTrigger: { trigger: element, start: 'top 100%', end: 'top 60%', scrub: 2.5 } }); return tl; }); }; // --- Exports --- export { gsapParallaxY }; Can someone help me with this?
×
×
  • Create New...