Jump to content
Search Community

Leaderboard

Popular Content

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

  1. Alright, I couldn't help myself - I just had to find an algorithm to try to smooth out the movement when the path goes backwards. After about 10 hours, I think I've figured it out, and also demonstrated how you can make the bee kinda twist itself to remain oriented in the direction it's moving using scaleX and scaleY: https://codepen.io/GreenSock/pen/mdgmawg?editors=0010 Notice that pathEase() helper function has been updated and you can pass in a config object with smooth: true. I hope that helps!
    2 points
  2. Almost another 6 years, we're due for a comment
    1 point
  3. Thanks @Rodrigo for pointing me in the right direction. I discovered I also need to use nextTick() with the watcher before the instances can be accessed. This is the code I landed on that is working now. Appreciate the help! watch(posts, (newData) => { if (newData.length > 0) { nextTick(() => { gsap.to('.blog-thumb', {opacity: 1, stagger: 0.2 }); }); } });
    1 point
  4. This is quite an amusing one. 😂 So innerHTML isn't technically an animatable value, it's either a string or nothing. Animatable values are things that can gradually change from one value to another, like numbers or percentages. e.g. You can rotate from. 10 to 360 easily as all the values in between 10 and 360 are valid You can't animate between backgroundImage: "none" and backgroundImage: url("myImage.gif"); because there aren't any intermediary states, you either have an image or you don't. However - GSAP does some clever stuff where it recognises complex strings and tries to animate between them for some CSS properties. I guess here you're passing GSAP a string and asking it to animate it. Obviously 1 is animating to 2 because that maps, but also the word "transparent" is something that you can animate with GSAP too, as that's used in CSS to represent a colour, and ultimately an rgba value.. 😂 This made me laugh but TLDR - it's not the right way to approach this. I assume you just want to set new text on scroll? You could do that with a set tween? If you want to actually tween the text you can use GSAP's text plugin for a more typewriter-esque effect. // instantly set the new text gsap.set("h1", { innerHTML: "Prepare for accelerated ramp-up, with transparent roadmap for staffing, knowledge transfer, team integration and performance KPIs.", }); // using text plugin? // replaces yourElement's text with "This is the new text" over the course of 2 seconds gsap.to(yourElement, { duration: 2, text: "This is the new text", ease: "none", }); Alternatively if you want to fade out one block of text for another, you'll need to layer the elements on top of each other and use opacity to fade them. Hope this helps!
    1 point
  5. You have to create ScrollTriggers in the order they appear on the page, if you have multiple forEach loops this might be throwing things off. Might be helpful to look into refreshPriority and sort? https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.sort()/
    1 point
  6. Hi, I’m not in front of my computer right now, but mainly the issue stems from when the gasp instances are created, in this case when the component is mounted so the elements are the ones present at that point. You should create a watcher and create the animations when the array is updated (you’re using a v-for directive so I’ll assume that an array is involved). https://vuejs.org/guide/essentials/watchers.html Hopefully this helps. Happy Tweening!
    1 point
  7. Hi, In the SrollTrigger config is markers (plural) not marker: // Wrong scrollTrigger: { marker: true, }, // Right scrollTrigger: { markers: true, }, Also once again you're making the same mistake. Sooner or later this will become a logical issue: const menuTimeline = gsap.timeline({ scrollTrigger: { trigger: "#pin-container-2", pin: "#pin-container-2", pinnedContainer: "#pin-container-2", start: "top top", // YOU HAVE SCRUB HERE scrub: true, markers: { indent: 140 }, id: "menu" } }); Then you have this: function selectEgg() { menuTimeline.reverse(); } function selectFish() { menuTimeline.reverse(); } Your menu timeline's playhead position is controlled by the scroll position when using scrub, then you want to reverse it using a button, which can be done, but as soon as the user scrolls ScrollTrigger will update the same timeline's playhead position based on the scroll position which will make the menu elements visible again and behave in an erratic fashion. You cannot have a scrubbed animation play/reverse using other event handlers unless you remove the ScrollTrigger instance associated with it, in which case you no longer will be able to scrub that GSAP instance. IMHO it should be like this: const menuTimeline = gsap.timeline({ scrollTrigger: { trigger: "#pin-container-2", pin: "#pin-container-2", pinnedContainer: "#pin-container-2", start: "top top", toggleActions: "play none none reverse", markers: { indent: 140 }, id: "menu" } }); Finally I think this is not a good approach as well: function selectEgg() { menuTimeline.reverse(); const eggTimeline = gsap.timeline({ scrollTrigger: { trigger: "#pin-container-2", pin: "#pin-container-2", pinnedContainer: "#pin-container-2", start: "top top", scrub: true, markers: { indent: 300 }, id: "btn" } }); eggTimeline .to("#besteck-2", { display: "block", x: "-20vw" }) .to("#egg-dish", { display: "block", x: "-60vw" }); } I wouldn't create a GSAP instance controlled by ScrollTrigger on an event handler. What happens if the user opens the menu and clicks on that button again? The same instance will be created again, but the previous one is already there and the same element is already pinned. Finally I think you are overcomplicating this quite a bit and because of that your app has several logic and architectural issues. I think the best approach right now is to decide what exactly you want to do and start by creating an HTML and CSS structure that looks the way you want. Then start adding animations one by one, go section by section and then also start adding complexity to this. It seems to me that you are a bit over your head right now, so that's why going back to basics should be a solid first step. Hopefully this helps. Happy Tweening!
    1 point
  8. Hi, One solution is to wrap the lotties section and the next one in a common parent and pin that one: https://codepen.io/GreenSock/pen/ExJmWdp The other solution is to create two ScrollTrigger instances to pin both sections at the same time for each lottie section and use pinSpacing false for the looties wrapper: https://codepen.io/GreenSock/pen/ZEZeLmL Hopefully this helps. Happy Tweening!
    1 point
  9. I didn't quite follow your logic there - are you saying that solution is better than ScrollToPlugin? Keep in mind that ScrollToPlugin works around a bunch of browser inconsistencies plus it automatically handles cancellation of the tween if/when the user interacts with the scroll (imagine how annoying it'd be if they try grabbing the scrollbar while the tween is in progress), plus it works on the window as well. I'm pretty sure the solution you offered only works in certain browsers on certain types of scenarios. And actually, you could simplify it even more by setting autoCSS:false and animating scrollTop directly on the element itself (skip the whole onUpdate). But maybe I misunderstood what you were suggesting. Oh, and it's typically best to start a new topic for things like this rather than jumping into one that's almost 6 years old Happy tweening!
    1 point
×
×
  • Create New...