Jump to content
Search Community

m__shum

Premium
  • Posts

    10
  • Joined

  • Last visited

Everything posted by m__shum

  1. That's so much better – I completely forgot about ScrollTrigger! You've been insanely helpful!
  2. Thanks for clarifying, I'll definitely be using this syntax in the future! If this isn't too far out of the scope of my initial issue, I managed to reproduce something I'm running into with these tweens. I have two instances of the same component (it's all in the demo) – one on the page and one inside a modal. For their timelines to run independently I need to declare them as Vue refs. Which is fine, except for some reason when the timeline is reset on reside, the timeline for the other instance of the component gets messed up. For example in this demo, scroll down to activate the on-page animation, resize it, scroll again to re-activate it, then toggle the modal. The modal splitText animation doesn't run correctly, probably because the split isn't properly recalculated. I suspect it's a vue-specific issue but if there's any way to negate it I'm all ears! Here's the demo: https://stackblitz.com/edit/nuxt-starter-zdudyt?file=app.vue,components%2FTextComponent.vue
  3. Thank you SO much Rodrigo, this is so much cleaner than my mess, and works beautifully! I do have a (possibly stupid) question about your demo – in the debounce function you call timer && clearTimeout(timer) and in CreateTween you also call completed && tween.progress(1). Just curious what this does – are you returning a boolean value by doing this? I haven't seen this syntax before. Again a huge thank you, I've been banging my head against the proverbial wall for two days with this.
  4. That's my fault, I tried to narrow down my issue as much as possible to simplify it and obviously the context was important! The real issue I'm having is actually related to splittext and resizing in Nuxt, and I'm unable to include splittext in a demo since it's a club plugin and I can't for the life of me figure out how to set up a nuxt environment in codepen. What I would like to do is this: 1. On resize, immediately reset the split to its original state so that the text resizes 'naturally'. 2. Debounce re-creating the timeline 3. Set the timeline's progress to 1 so the whole thing looks like it never happened. Then, when the user goes on their merry way interacting with this element, it animates as it's supposed to, having resized and done all its business. function createTimeline() { split = new SplitText('.text', { type: 'lines' }) timeline = gsap.timeline({ paused: true, defaults: { delay: 0.15 } }) .fromTo(split.lines, { y: '100%', x: 10, autoAlpha: 0, scale: 0.99 }, { duration: 1, y: 0, x: 0, autoAlpha: 1, scale: 1, stagger: 0.07, ease: 'power2.inOut' }) } function recreateTimeline() { createTimeline() timeline.progress(1) } const debounceHandler = debounce(recreateTimeline, 300) function handleResize() { if(timeline){ timeline.revert() split.revert() } debounceHandler() } onMounted(() => { window.addEventListener('resize', handleResize) }) What ACTUALLY happens is probably an issue with Nuxt more than anything (or maybe I'm missing something!), but it's the reason I thought I had to wait for .revert(). When I run handleResize(), the timeline and split are reverted and the debounceHandler is called just fine. The problem is that when recreateTimeline() calls createTimeline(), the split is not properly reverted and SplitText() runs on text that's already been split. Even though it should've been reset to its original state when handleResize() was first called. It's like the reverts never happened, or if they did they got stuck halfway. The timeline doesn't recreate properly and none of the animations run after resize. This does not happen if I debounce the entire handleResize function but I don't want to do that because when the user resizes the window down, they will see the incorrectly positioned text for 300ms or however long I set the debounce to. What I ended up having to do is this horrorshow: Basically I'm having to call the reset behavior multiple times to make sure it's cleaned up even though the reset DOES happen immediately, but for reasons I don't yet understand, not correctly or fully. let timeline let split function createTimeline() { split = new SplitText('.text', { type: 'lines' }) timeline = gsap.timeline({ paused: true, defaults: { delay: 0.15 } }) .fromTo(split.lines, { y: '100%', x: 10, autoAlpha: 0, scale: 0.99 }, { duration: 1, y: 0, x: 0, autoAlpha: 1, scale: 1, stagger: 0.07, ease: 'power2.inOut' }) } function destroyTimeline() { timeline?.revert() split?.revert() split = null timeline = null } function recreateTimeline() { destroyTimeline() nextTick(() => { createTimeline() timeline.progress(1) }) } const debounceTimeline = debounce(recreateTimeline, 300) function handleResize() { timeline?.revert() split?.revert() debounceTimeline() } onMounted(() => { window.addEventListener('resize', handleResize) }) If you're still reading by this point, I salute your immense patience. Basically I thought that MAYBE the issue was that reverts() weren't immediate, and I had to await them before running anything that relied on them being complete.
  5. Hi all, I'm working with SplitText and I need to be able to revert everything, reset timelines, and then recreate and re-run everything on resize. The main issue I'm having is chaining everything nicely. timeline.reverse() returns itself 'for easy chaining' according to the docs. Except you can't chain timeline.reverse().then() (this throws an error) and wrapping it in a promise doesn't work either. What is the best way to make sure everything has been fully reverted when wrapping reverts in external functions? Because if I dump everything into one function, things do get cleaned up correctly, but we obviously don't want to do that.
  6. Why do you have to change the token in dev mode? Surely reading it from the .env file should be adequate? Having to change this every time you want to make a commit is a massive headache. I've tried time and time again to use the gsap token from the env file and keep getting the same 'bad auth' error. I've tried setting it as a plain env variable, I've tried exporting it in the env file, I've tried prefixing it with NPM_CONFIG, nothing works. Nevermind, I didn't realise that you had to store the env variable in bash for it to be replaced in npmrc locally. Today I learned.
  7. Yeah I'm not a huge fan of the way refs work in Vue 3 but what can you do. For the time being I simply declared the timeline as a non-reactive variable because I don't need to watch its changes. It definitely caught me out because I'm still thinking in Nuxt 2 mode, where if you wanted to access any variable, you had to declare it in data().
  8. Hi all, I've got a Nuxt 3 project with a fromTo tween. I need to be able to control its progress using gsap.to. Easy peasy, right? Well, not quite. While this is a simple operation in vanilla JS (see codepen), in Nuxt 3 it appears to only work in one direction – it tweens the progress to 1, but not back to 0. Here's a url for the minimal Nuxt 3 stackblitz reproduction: https://stackblitz.com/edit/github-vfgcdf?file=app.vue Oddly enough I can't get this tween to run in it at all. Using gsap.set() works both ways, but that's obviously not going to work since I want to be control the ease and duration. I have also tried skipping the existing tween entirely and controlling the opacity "from scratch" using gsap.to(${target}, {opacity: 1, duration: whatever}) but that doesn't work either. Again, gsap.set() works to set both the tween's progress and the opacity itself. For context: I'm using fromTo because as well as tweening opacity over a certain duration, I want to be able to tween it on scroll so it fades as you scroll out, and fades as you scroll back in at the same speed as you scroll. I did consider ScrollTrigger, however ScrollTrigger seems like overkill for this AND I want to be able to tween opacity on more than just scroll. I have a header that fades in and out on scroll but only on certain pages, and I want to fade it back to full opacity on route change. EDIT: I have played around some more and assigned the timeline to a non-reactive variable (instead of using Vue's refs) and... it works! (See reproduction here: https://stackblitz.com/edit/github-vfgcdf-kx2x5z?file=app.vue) But why?
  9. Thank you so much both, I didn't realise that registering a plugin required a valid window instance. Moving this logic to the onMounted hook worked perfectly.
  10. I keep getting a warning about registering custom ease despite having already registered it. Am I missing something here? Below is the gsap code I'm running in<script setup> import { gsap } from 'gsap' import { CustomEase } from 'gsap/CustomEase' gsap.registerPlugin(CustomEase) const customEase = CustomEase.create('custom', 'M0,0 C0.29,0 0.311,0.268 0.35,0.502 0.423,0.951 0.756,0.979 1,1 ') function createTimeline() { timeline.value = gsap.timeline({ paused: true, defaults: { ease: customEase } }) .to(modal.value, { height: '100%', duration: 0.85, }, 0) .to(modal.value, { opacity: 1, duration: 0.75, }, 0) }
×
×
  • Create New...