Jump to content
GreenSock

Leaderboard

Popular Content

Showing content with the highest reputation since 07/15/2022 in all areas

  1. Oh, it does work - only it gets triggered when it isn't in view anymore, at the same time the animation on the third section gets triggered. The logic of that example was built to work like that - just in that very scenario - because it was only suggested in the first place when I thought that all the OP from that other thread wanted, was to 'pin' the very last section - once I understood that he actually wanted to be able to 'pin' every section, I suggested the other example. So once more; I do not suggest using this example. Note that these examples in general are not intended for copy/pasting in a way that you can just add some things of your own and expect them to work like you want - most of them are just showing concepts for how to approach certain things in certain scenarios with ScrollTrigger, like this one. That too is not a ready-to-go all-in-one copy-and-paste custom-code solution - if you put in the time and effort you can change it to whatever you like as long as you understand the logic that lies underneath it all. As mentioned in that other thread too... ...and the position parameter in addition to that. It can not hurt to also have a deeper look at flexbox if you want to have segments with specific widths in this scenario https://css-tricks.com/snippets/css/a-guide-to-flexbox/ Besides some general changes with regard to naming (to make it a bit more evident what is what) of the elements and to the layout in CSS, I changed the position parameter of the tweens responsible for the fake horizontal-scrolling here, so it won't have a delay between when the bars are done tweening and the movement to the next slide and with that regard also got rid of the empty tween for the last segment. Also the amount which slide needs to move here isn't dependent on the increment variable anymore but instead on each section's individual offsetWidth. Maybe this will help, but nonetheless, this isn't the most trivial thing you want to do, so I suggest diving into how all those things mentioned work. One problem now, is that when you do have sections with different widths in there, they will not move to the left at the same speed - wider sections will move much faster than narrower sections because of how the durations of the tweens are set up. If you needed, you could change that by doing some calculations for the durations of the individual tweens of the timelines, but that is getting quite out of scope for what this forum can offer and thus is nothing I can do for you. https://codepen.io/akapowl/pen/QWmObNv
    4 points
  2. Heya! So sometimes it's good to step back from the syntax and the tech and just think about the logic of what you're trying to achieve. (at least it is for me!) Adding an infinite animation to a scrollTriggered animation that has a finite distance to play in isn't going to work - that's a logical impossibility. You need a way to pause the 'wander' animation at certain toggle points. In order to do that you need to be able to access and control the tween that is controlling the wandering. To do that, the tween needs to have a name so you can tell it to do things. Right now you just have an unnamed tween inside the wander function. You can't call pause() on that function - you have to call pause on the tween itself. If you move the wander function inside the circles loop, you can create a named tween for each circle and then control it. (There's likely a way to do this while keeping that function global but I'm not quite sure how.) https://codepen.io/GreenSock/pen/vYRzVLL?editors=0010 I also noticed when you 'get rid' of the circles in the timeline at the end, the animation keeps playing, even though you can't see it. That's going to be bad for performance so I recommend killing the wander tween at that point. FYI - This is a quick 'rough' idea - I would suggest going through and logging out wanderTween at different steps and thinking through the logic. There are lots of different things happening to these dots and they could happen in different orders, e.g. What happens if the hover happens before the wander tween has been created? You'll need to work out what combinations of steps could exist and then make sure you have conditional logic in place to handle it! It helps me to get a pen and paper out and draw/write out the logic for stuff like this.
    3 points
  3. Ha, no... I thought maybe it was hard to explain. You could wrap each icon in its own group <g> this way you can animate the element twice, once as the element it self and once as the <g> element. See my code below, you just create extra <g> elements just so that you have something to target <g class="animateMe"> <path class="someIcon"/> </g> <g class="animateMe"> <path class="someOtherIcon someIcon"/> </g> This way your first timeline could target all the .someIcon's and animate them and the scroll timeline could animate all the <g> .animateMe elements, this way the targets don't overlap and your timelines will not fight for the same elements
    3 points
  4. @slyrt you're doing a great job with keeping your timelines separate within functions. The problem is with trying to animate the same elements with different timelines. When I know I need to animate the same element multiple times I'll try and structure my SVG accordingly. If you for instance wrap all your scaling icons in a <g> tag and at first scale everything within the <g> tag and on scroll animate the <g> tag itself they don't conflict with each other. The benefit of this is that the visitor doesn't have to wait before they can scroll, but it requires you to go in a restructure your SVG. It's up to you what you find best. Good luck!
    3 points
  5. Thanks Cassie! It seems like this fixes the shaky scroll: useLayoutEffect(() => { ScrollTrigger.normalizeScroll(true); const smoothScroll = ScrollSmoother.create({ smooth: 1, // how long (in seconds) it takes to "catch up" to the native scroll position // This causes buttons to scroll to top ======================================================================= // smoothTouch: 0, // much shorter smoothing time on touch devices (default is NO smoothing on touch devices) ignoreMobileResize: true, // normalizeScroll: true, onUpdate: x => { useScrollValue.setState({ scrollValue: x.scrollTop() }); }, }); if (window.location.hash) { smoothScroll.scrollTo(window.location.hash, true); } return () => { smoothScroll.kill(); }; }, []);
    3 points
  6. That's because you did call it immediately Just because the code is below your timeline declaration doesn't mean that it'll wait to execute that code until the timeline completely finishes playing. Think of all your timeline code like an initial setup which happens immediately, and then it'll start running over the course of the next many requestAnimationFrames. So all you need to do is toss it in an onComplete on the timeline: onComplete: () => gsap.utils.toArray(".animation-container").forEach(wander) https://codepen.io/GreenSock/pen/zYWJYrK?editors=0010 That's because you're looping through all 5 ".animation-container" instances and EACH time through that loop, you're doing this: gsap.utils.toArray(".animation-container").forEach(wander); Which loops again through all 5 of them, starting an independent recursive wander routine. So you're creating a ton of conflicting tweens. Instead of creating one for each, you're creating 5 for each. So the jerking is caused by the fact that the animations keep getting interrupted by each other (they're all fighting for control). I think you meant to do this: // OLD gsap.utils.toArray(".animation-container").forEach(wander); // NEW wander(animationContainer.querySelector(".circle")) But slap that into an onComplete as discussed above. Also, you could reduce your code a lot by just creating a variable at the top for the circle instead of using that querySelector() every time, and you don't have to recreate the wander function in each loop: https://codepen.io/GreenSock/pen/mdxGdWG?editors=0010 Does that help?
    3 points
  7. I looked at it, but it didn't really seem to sync to the text fully. If I wanted to do this, I just would check how many words there are and check how long the audio file is. Then set the words showing up to audio in seconds / words = show word ever x amount e.g 60 seconds of audio / 20 words = show word every 3 seconds And there is probably a async function to check if the audio is loaded and playing, so you should probably connect them to each other to only animate GSAP if the audio is playing.
    3 points
  8. I'd just hold off creating the event listeners until the first animation is completed. ☺️ let tlHdrInit = gsap.timeline({ defaults: { ease: "sine.out", duration: 0.5, delay: 0.5 }, onComplete: () => { box.addEventListener("mouseenter", function () { return tl.play(0); }); box.addEventListener("mouseleave", function () { return tl.reverse(); }); } });
    3 points
  9. Hi @zhewar welcome to the forum! You're trying to animate your trigger element, you never want to animate the element that is also your trigger, this will create some weird behavior because your trigger element is moving while scrolling. Also there is a property called xPercent and yPercent, these are for animating based on percentage, so better to use those, instead of `x` and `y`. And at your last tween you set the position parameter to '-=1' this is fine, but you could also set it to '<' then it will animate at the same time with the previous tween, no matter what time the previous tween takes. To me this animation seems to run fine now, was this what you are looking for? https://codepen.io/mvaneijgen/pen/MWVBgdw?editors=1010
    3 points
  10. Hi @pranayraj09 welcome to the forum! I'm not really sure what you are trying to do. The space between the two divs is created by the red box, so if you don't want that to happen you'll have to change your CSS so that the box is not part of the flow of the document, you could do that with `position: absolute`. As a general tip you don't want to animate the trigger element of ScrollTrigger, because if you the element you move the trigger, which makes it a cat and mouse game. So wrap the elements you want to element in a custom div and make that the trigger. Last tip focus on the animation first, remove ScrollTrigger and first make sure you animation is correct before adding ScrollTrigger. Just comment out your ScrollTrigger code and add it back in when you are happy with the animation. https://codepen.io/mvaneijgen/pen/ExERqJq?editors=0010
    3 points
  11. @Nephtys cool! I did some more digging in your pen. I would start off by positioning your elements correctly with CSS. You want all the `.info` panels on top of each other, because you want them too animate all from the same starting position (this is also what the first demo you posted does, so try and choose and pick logic from that one). Then when you're happy with the animation you could add a ScrollTrigger to the container of all the elements and pin this container, then connect the timeline to that scroll trigger and have it animate over a height of three times the window height. https://codepen.io/mvaneijgen/pen/rNdddVJ?editors=0010 Be sure to post back here if you stuck or you've got the solution!
    3 points
  12. Hello @flysi3000 Interesting to know what version of safari for MacOS, iOS or iPadOS version this is being caused on? Not sure if this will help you without seeing your code example, but it has worked for me in the past. You can tell the browser not to render a parents children in 3D space or 3D transforms by adding the CSS property transform-style: flat; to the parent of the troublesome blurry child. Not sure if Safari will honor the spec in this regard, since any parent with transform-style: flat; should not have any of their children using the 3D space or 3D transforms. Keep in mind, very important that technically you add transform-style to the same element your transforms are being applied to since they work hand in hand. But transform-style is not inherited so you will also need to apply it to all children (descendants). .parent-element-with-transform { transform-style: flat; } transform-style https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style Indicates that the children of the element are lying in the plane of the element itself. But best solution is like @GreenSock (Jack) advised to not scale above a factor of 1. Many years ago that became an issue and still is to this day for webkit based browsers. Start your initial scale lower than a factor of 1 and scale your element to its full size of scale 1. That trick works cross browser since even Chrome webkit has this blurry transformed element on <img> tags. But force3D:false should solve this, but Safari plays by its own rules and doesnt follow the spec most of the time. If all else fails just uninstall Safari (kidding) Jonathan
    3 points
  13. Hi there, welcome to the GSAP forums. This is a lovely effect! Well done. I'm afraid I don't have an easy answer here though. It's largely 'don't animate Clip Path on mobile safari'. Sorry, I know it's not a nice answer. There's no real magic-trick for mobile. You just have to be careful what you're animating/animate less. Also on IOS, Chrome is Safari. Apple don't allow any other browsers on their devices, so it's just safari wrapped up to look like chrome. Transforms and Opacity are going to be your friends for mobile animations, you can create effects like this by wrapping elements in a div with overflow hidden and then animating the internal or external elements to create masking/clipping effects. Another option that tends to be smoother on mobile is using SVG clip paths or masks. Or alternately - animating the clipped elements 'within' a clip path with transforms rather than the clip path itself. That's sometimes more performant. Happy to elaborate a bit more on one of these options if it helps. Good luck!
    3 points
  14. I'm not sure if this is what you're going after, as you didn't explain it that well what you're trying to achieve (sorry for being straightforward :P), but from what I can see you're using sync mode, so probably you want both animations happen at same time, and you see some annoying flicker, and other animation doesn't play correctly, right? In sync mode, you neeed to handle the positions absolute/fixed of barba containers yourself, as they will show at the same time in static position, the next page container will be next to the old one (which will be out of screen), until the previous page container disappears (after first transition is complete) and the new container will show in position of old one - just imagine two divs, that have width of 100% viewport next to each other, and you change display of the first one to "none" - it's similar behaviour. So long story short, you need to add class .fixed (you can name it whatever), set position to fixed and higher z-index .fixed { position: fixed; top: 0; left: 0; z-index: 10; } Then on your barba leave hook, you need to add (with jQuery, I tried to do it with vanilla js but for some reason it doesn't work for me) $(data.next.container).addClass('fixed'); And lastly, on your enter, afterEnter, or after hook (depending on your setup), you have to remove it $(data.next.container).removeClass('fixed'); Then the transitions should work. Hope it works for your case!
    3 points
  15. ha. i tried something with adjusting the position parameter but things got all weird. in my haste i just put on a jet pack down the wrong rabbit hole. lol. tweening the zIndex is neat approach. definitely wouldn't have thought of that. thanks for the help and sanity. i knew i was missing something obvious.
    3 points
  16. @GreenSock Yeah, overcomplicating stuff is one of my strengths I'm not proud of. 😆 But wow, this is exactly what I need. Just tried it and it works perfectly! Many thanks for that, really appreciate that superb help!! 😊
    3 points
  17. Perhaps just put the zIndex into the tweens so that it starts out at 100 for whichever one is animating in, then it goes to 50 in the middle, and to 0 when it's done fading out (arbitrary values I chose - the important thing is that they're ordered). Definitely no need to use 10,000 set() calls Also, I didn't quite see why there was a need for the CustomEase - couldn't you adjust the insertion point for the out animations? I may be missing something. If so, I apologize. Here's a fork with my attempt: https://codepen.io/GreenSock/pen/MWVOOwZ?editors=0010 Is that the effect you're going for?
    3 points
  18. I was going to suggest the typical "snap" feature of ScrollTrigger (which would work...but it can't work until scrolling has stopped), and then I had an idea... Dynamically apply legitimate CSS scroll snapping by adding invisible elements to the DOM that serve as snapping positions, and set them up them onRefresh! Then we set scrollSnapType on the document.scrollingElement when the ScrollTrigger toggles active/inactive. Seems to work: https://codepen.io/GreenSock/pen/JjLrgWM?editors=0010 Does that work the way you hoped?
    3 points
  19. 'Ello! Allow me to butt in. Sometimes one just finds the idea enticing enough to do the work for others. Bear in mind there are several ways to skin a cat and this is one. Also, bear in mind I did get carried away and added other bells and whistles that are not within the question here BUT, I do hope the code is written in such way that everyone can reason around it. And as per request, it's a GSAP-based solution. Enough rambling. https://codepen.io/dipscom/pen/wvmrNpe/326ea45a277aa98cd3df85553f2ede48?editors=1010
    3 points
  20. Those examples largely use an external css file. This is great for maintaining consistency across the examples as well as making "global" updates to all the demos. However, it's not so good for people who want to look at the css. If you go into the css section of the pen settings you will see where the css is coming from that external css file is pulled from here https://codepen.io/GreenSock/pen/ZEGdQLM/7ba936b34824fefdccfe2c6d9f0b740b
    3 points
  21. Hello @ricksanchez You can not pin in a fake-horizontal scenario as such because you are not actually scrolling horizontally but only just tweening the content to the left on vertical scroll. One way to achieve an effect similar to pinning in a fake-horizontal scenario as such would be to just change the way that the horizontal tweening of the sections behaves altogether - something like was shown in this thread ...and also suggested in this thread. Another way would be to tween whatever you want to 'pin' to the right for the same amount over time that your content gets tweened to the left but that will also require a bit of a different setup where it is not the actual sections being tweened to the left a surrounding container, so you can tween on the sections themselves to create that nullifying 'fake-pin' tween on the sections themselves - but this approach will probably become quite tedious as you will have to consider all following sections and re-adjust the values for the fake-horizontal scroll back and forth - so I would definitely suggest going with what was suggested above instead. Nonetheless here is an example of what I mean with this second approach. https://codepen.io/akapowl/pen/zYWEpBd Edit: If you want to go with that second approach (which again, I wouldn't really recommend as it can become quite cumbersome at some point) you might want to have a look at the containerAnimation property that was used in my demo. containerAnimation Tween | Timeline - A popular effect is to create horizontally-moving sections that are tied to vertical scrolling but since that horizontal movement isn't a native scroll, a regular ScrollTrigger can't know when, for example, an element comes into view horizontally, so you must tell ScrollTrigger to monitor the container's [horizontal] animation to know when to trigger, like containerAnimation: yourTween. See a demo here and more information here. Caveats: the container's animation must use a linear ease ( ease: "none"). Also, pinning and snapping aren't available on containerAnimation-based ScrollTriggers. You should avoid animating the trigger element horizontally or if you do, just offset the start/end values according to how far you're animating the trigger.
    3 points
  22. Hello @etheric I suggest having a look at containerAnimation, which will make it much easier to trigger things within a fake-horizontal scenario as such containerAnimation Tween | Timeline - A popular effect is to create horizontally-moving sections that are tied to vertical scrolling but since that horizontal movement isn't a native scroll, a regular ScrollTrigger can't know when, for example, an element comes into view horizontally, so you must tell ScrollTrigger to monitor the container's [horizontal] animation to know when to trigger, like containerAnimation: yourTween. See a demo here and more information here. Caveats: the container's animation must use a linear ease ( ease: "none"). Also, pinning and snapping aren't available on containerAnimation-based ScrollTriggers. You should avoid animating the trigger element horizontally or if you do, just offset the start/end values according to how far you're animating the trigger. On a different note: While you have invalidateOnRefresh in there, your setup will not react to resizing because you never re-populate/update the variables that you use in your ScrollTriggers, so they will always contain the values that you fed them with initially. You might want to consider changing that. Either update your variables on resize or just get the values neccessary directly in ScrollTrigger. I'll leave that up to you though. Here's a pen showing what I understood you want to achieve with regard to the fake-pinning. I hope it will help. https://codepen.io/akapowl/pen/xxWXPmd
    3 points
  23. I had absolutely no idea you could tween arrays 😂 - that's awesome! The object approach is industrial, so I'll probably have a play with array tweening and refactor. Succint code helps me sleep at night. I did know about the MorphSVGPlugin though. This started off as a simple experiment for animating limbs (rubberhose style) so I thought "I'm just moving a couple of coordinates right?" but I can see how the MorphSVGPlugin could be perfect. Time to play! Thanks for the info 🤘
    3 points
  24. I occasionally reach for grid when I need multiple things (usually text) centered on top of each other. A byproduct of the approach below is that the child containers are all the same size. this approach was borrowed from stephen shaw (shshaw) and encompasses everything I know about grid. https://codepen.io/snorkltv/pen/JjYJpgw Your suggestion seems similarly useful, however it would really help to see a very simple demo. Setting up a functioning css layout is probably the hardest part of using GSAP, so I imagine this could help quite a few people. Sharing helpful tips is encouraged here and a nice way to engage with the community.
    3 points
  25. Even the simple simplified even more complex version works https://codepen.io/mvaneijgen/pen/jOzLjQO?editors=0010
    3 points
  26. lol. guess I over minimalized. I will start my 15 minute "time-out" over in the moderator jail. happy to see this all sorted out. very cool to see the more complex version working too!
    3 points
  27. Out of curiosity I took a look at WeGlot, and found the API documentation - which is thin, to say the least - I'm just guessing here, but to me it sounds that the Weglot.on("languageChanged", callbackFunction) event likely is fired when the language is changed from e.g. EN to ES through whichever mechanism. The actual replacement of one language string to another logically can only happen afterwards. That would explain the described behavior. As I'm guessing that the translated string is loaded asynchronously you would have to make sure to start your text-splitting only after it has arrived. I don't know obviously how they do it, and as there seem to be no documented API way to hook into, even if you could hitch onto - say a promise it might stop working the moment they change their internal workings. So if my life depended on it, I would probably store the content of the element that is targeted by the splitText at document.ready or pageload which ever is the first one to give a useful result. Then, after the 'languageChanged' is fired I would check for changes in said element. (Either MutaionObserver or plain old setIntervall come to mind.) Once that change is detected, let loose splitText... Sounds complicated and might be, but hey it's a challenge.
    3 points
  28. Heya! Also a little tip - I'm not sure what graphics editor you use - but I hugely recommend Affinity designer as you can save out SVG's with relative coordinates *and* flatten transforms on export. So all those inline matrices are now gone. Nice clean SVG markup to start off with makes animating a breeze. https://codepen.io/GreenSock/pen/YzaxbeW
    3 points
  29. A few problems: You can't pass in selector text as the element. It expect a legitimate DOM element. This is an edge case that exposed an issue in getRelativePosition() which should be resolved in the next release. Here's a fork that loads a pre-release version with the fix in place: https://codepen.io/GreenSock/pen/BardvXQ?editors=0010 You can still use convertCoordinates() instead. I wrapped the functionality into a helper function here: https://codepen.io/GreenSock/pen/abYyXdx?editors=0010 Does that clear things up? @Carl thanks a bunch for the simplified demo! 🙌
    3 points
  30. Let's work together to clarify a few things... I don't think anyone is faulting you, @joxd, for pointing out that the user-created demo isn't fully responsive. Resizing screens appears to cause it to render oddly. Perhaps we haven't acknowledged that adequately and you didn't feel heard. We are not Three.js experts here. Most (if not all) of the issues here are related to rendering, so it's really not in our wheelhouse. We're not in a position to dig in, learn Three.js and fix some else's demo for them to make it fully responsive. But we're happy to answer any GSAP-specific questions. It may not be obvious to you from your experience in this particular thread, but this community bends over backwards to help users around here and we spend hours and hours every day trying to keep up with the constant stream of posts. It can be overwhelming, especially when so many of them end up having very little to do with GSAP. Quite a few people basically expect us to provide free general consulting services and do their development work for them or solve logic issues in their code...and they often won't even bother to provide a clear minimal demo. These forums cost thousands of dollars every month to operate, so we have to draw boundaries somewhere. We get questions that are specific to Three.js, React, Vue, Angular, Next, Nuxt, Barba, Pixi, Swiper, LocomotiveScroll, ASScroll, ScrollBar, WordPress, Elementor, and Svelte, just to name a few. We simply cannot learn all of those tools and provide full support. I'm sorry if my initial boundary-setting post came off as rude or unwelcoming. I definitely didn't mean it that way. Though you probably didn't mean it this way, your responses have come across as very disrespectful and insulting. It sounds like you felt similarly about some responses you got. So everyone got a little offended and salty here. Let's just put an end to that and give each other the benefit of the doubt. Thanks for being a customer back in 2017. We sure appreciate that. We couldn't do what we do without the support of Club GreenSock members. As a company, we place a HUGE amount of value on earning trust and treating customers with respect. One of the biggest ways we try to be there for our users is via these forums. We hear over and over again about how special this place is, how it is warm and welcoming, etc. It has taken years of very intentional effort to cultivate that. We don't have big marketing budgets or corporate sponsors - we simply focus our efforts on creating the best tools we can and supporting them well, trusting that the market will reward the efforts. Again, I'm sorry if your experience didn't reflect that. Let us know what it'd take to right the ship in your eyes. If you still think there's a GSAP problem at play here, how about if you create a minimal demo that doesn't use Three.js and only focuses on the animation-related challenge instead? I'd be glad to look at that and provide advice.
    3 points
  31. As of now the fix hasn't been deployed. It'll be in the next version of GSAP, most likely either 3.10.5 or 3.11.0 If you can, it's easiest to just wait for the update. If that's not an option, I'd say either use the beta files or Damian's solution. As a temporary measure either should be fine.
    3 points
  32. I too am quite confused by all your posts here and how you are seemingly misrepresenting the responses that you have received here in this thread on the GreenSock forums? ¯\_(ツ)_/¯ You were asking about responsive tendencies then switched your entire feedback and arguments to accessibility. The feedback and advice you have been given has been correct as has been the initiative to try and help you through asking for pertinent information on what you are hoping to accomplish along with your own relative demo. None of which you have chosen to provide. In the end both responsiveness and accessibility are up to the individual developer to implement based upon project requirements and expectations regardless of using GSAP or Three.js or any other web stack. 99.9% of the examples you find on this forum answer specific GSAP logic questions and do not encompass the full spectrum of development requirements, nor should they. You mentioned that the Three.js forum was unkind to you and sent you here? Though the only relative recent posts relating to the same topic that I can see over there are the following, in which no responses were given, nor was that user ever directed to these forums. These comments specific to your initial comment above (none of which received a response on the Three.js forum): https://discourse.threejs.org/u/peet88/activity Recent overall GSAP threads / posts: https://discourse.threejs.org/search?q=gsap%20order%3Alatest The problem with injecting into an old thread that was already answered correctly for that logic requirement, is that you have now changed the scope of the thread which it never intended to address. So it’s immensely difficult to assist when a person just points to other peoples examples, threads, discussions and simply gives the blanket claim that something does not work. When this occurs there is rarely enough relative context to move forward with this approach and provide concise answers. The GSAP forums are some of the friendliest most helpful developer / code related forums you will find on the internet. GreenSock products are innovated and supported on a level rarely matched. So it’s really disheartening that you have chosen to misrepresent the sincere responses which you were given and make claims in response that simply are not accurate or true.
    3 points
  33. Very glad to hear it. Yeah, @Carl does an excellent job of explaining complex topics in a way that's easy to understand. Smart move signing up for Creative Coding Club 🙌
    3 points
  34. I appreciate the effort to minimize the demos. You clearly put in a lot of work and time and followed what GreenSock suggested. However, for first-time viewers it's still a bit much to decipher what we see in the code and what is present in the svg for example selectors like "#shape", "people > *", "toHere" have no descriptive relationship to what we see in the svg with a few different colored circles and a square. In other words I can't look those selectors without digging through the svg to find them and then I have to figure out their hex fill colors or positions to further know what is what. Things get further complicated with multiple animations: animating around a path, scaling the center, then triggering an onComplete As I said earlier, I'm a bit rusty on getRelativePosition() but with all the work you put in I decided it was worth my time to see if I could help and get you closer to a solution. Although your project requires those multiple animations and I understand you left them in there to illustrate the complexity you needed to address, it seems to me that the heart of the problem is getting 3 circles to go to the center of another circle. If we can figure that out, then we can add the other stuff. I simplified the demo as much as I could and tried to make things match your approach as best as I could with a few subtle name changes. Here's my attempt to get 3 red circles to go to the center of the green circle https://codepen.io/snorkltv/pen/QWmMqXz?editors=1011 It doesn't work, but perhaps this will allow @GreenSock or anyone else to more easily see what is wrong. What it does show is that all the circles can move to a relative "0,0" position but for some reason it doesn't like working with the "#greenCenter" group. lastly, please don't take my comments on your demos as a strong criticism, I'm just trying to point out how to make improvements in the future. I really appreciate the effort you put in.
    3 points
  35. Yep Creative Coding Club. It is such a brilliant resource for GSAP and at a really affordable lifetime license price. So worthwhile! I've been really impressed with how supportive the community is here in the forums and generally with tutorials and support. Really happy I've stumbled across it. Thanks so much for your help!
    3 points
  36. Oh and to actually answer your question: You would set a CSS variable on the attribute you want to animate and tween the CSS variable. // In your CSS you'd set something like: /* div:before { transform: translateX(var(--move-x)); } */ // In your JS you'd then: gsap.to("div", { "--move-x": "33px" });
    3 points
  37. I haven’t used it in awhile but see if getRelativePosition() can help https://greensock.com/docs/v3/Plugins/MotionPathPlugin/static.getRelativePosition
    3 points
  38. Hey Refinery! You are just overthinking it a bit. All you need is the following: gsap.from(".list__item", { opacity: 0, duration: 0.5, x: 50, stagger: 0.5 }); What you are doing in your code is creating an individual Tween for each of the list items, not a timeline that contains all the items. As each tween is independent and only contains one item, there is nothing to stagger and they all paly at the same time.
    3 points
  39. Thanks for the minimal demo! Super clear. 🙌 It's always best to set your transform-related values through GSAP because: It works around browser bugs and inconsistencies It ensures accuracy (the browser reports existing transforms as a matrix which is inherently ambiguous when parsing rotational data, like scaleX: -1, scaleY: -1 is identical to rotation: 180 but GSAP caches things and tracks each component independently for perfect accuracy) It improves performance (again, caching so that it doesn't need to parse the values every time). The reason it sets transform-origin to 0 is to work around Firefox and Safari browser bugs - it actually embeds the origin data directly into the matrix() itself to produce consistent results across all browsers. And it uses matrix values in the transform attribute (rather than CSS) to work around other browser bugs. For example, Safari had bugs related to CSS-based transforms in some scenarios. The attribute-based ones are most consistent. And matrices are fastest to render in most cases. So GSAP is actually protecting you in all this stuff You were setting values in CSS which was contaminating things. And your order of operation on the transform string was non-standard. Here's a fork of your demo, showing that if you set things properly through GSAP it all works nicely across all browsers and it delivers consistent order-of-operation too: https://codepen.io/GreenSock/pen/GRxWbqa?editors=0010 To answer your direct question, there is no way to tell GSAP to stop using matrix on SVG transforms. It's sorta like saying "can you tell GSAP to implement transforms in ways that are proven to be buggy and error-prone?" Does that help?
    3 points
  40. You could actually accomplish that with just Observer: https://codepen.io/GreenSock/pen/BarWMQq?editors=0010 More concise, and smaller file size.
    3 points
  41. Ah, with a proxy? https://codepen.io/GreenSock/pen/yLKMjpQ
    3 points
  42. Are you looking for something like this?: https://codepen.io/GreenSock/pen/poLePrv?editors=0010 The code could be simplified. The new-ish gsap.quickTo() is useful here. One of the main issues with your demo was actually an order-of-operation thing where your ScrollTrigger's onUpdate was firing BEFORE the scrub tween had a chance to render, and you circumvented that render by invalidating the tween and restarting it, so it wouldn't actually kick in until the containerAnimation stopped moving (stopped hijacking those renders).
    3 points
  43. Removing antialias: true in the PIXI.JS renderer's constructor allowed to get to ~55FPS on Raspberry PI. So it was unrelated to GSAP in the end.
    3 points
  44. Yep, complete oversight on my end my apologies. But you definitely pointed me in the right direction. For anyone in the future struggling with this issue, if this doesn't fix the issue inside your tsconfig.json: { "compilerOptions": { ... }, "files": [ "node_modules/gsap/types/index.d.ts" ] } Try adding this to your tsconfig.json. { "compilerOptions": { "declaration": true } } If that doesn't resolve it you may be getting eslint errors and not actually TypeScript errors. To resolve undef errors from eslint add this to your .eslintrc.js file. This won't have a negative impact as TS checks for this already. official explanation overrides: [ { files: [ "*.ts", "*.vue", //or your relevant framework file extensions ], rules: { "no-undef": "off", }, }, ],
    3 points
  45. Ha, yeah I noticed that you were creating your ScrollTriggers out of order in your example - but since I figured that in this specific scenario it wasn't neccessary to mention because of that .wrapper element being pinned, I decided not to include a sidenote about that. Even better you found the solution yourself Happy tweening!
    3 points
  46. I think there might be a misunderstanding at play here... When you add a listener like this: ScrollTrigger.addEventListener("refresh", someFunc); That is not adding it to a particular ScrollTrigger instance - that is a static method that is completely unaffected by this line: // kills every individual instance ScrollTrigger.getAll().forEach(t => t.kill()); So someFunc() would still get called on refresh in this case. That's the proper behavior. You should remove your listeners if you don't want them to get called anymore, like: ScrollTrigger.removeEventListener("refresh", someFunc); But reading through your post, I think it may be wise to add a ScrollTrigger.killAll() method that does two things: Calls kill() on every ScrollTrigger instance (same as ScrollTrigger.getAll().forEach(t => t.kill())) Removes ALL event listeners. What do you think? Either way, though, I'm very curious to see a minimal demo that shows things NOT working when you kill all the instances AND you remove your event listeners properly. I suspect that maybe you just didn't realize you needed to remove your static event handlers(?)
    3 points
  47. Thank you both for the answers I ended up using the Flip plugin - it was precisely what I needed. What an amazing library and community, thank you so much! 🙏
    3 points
  48. Hi @adelkov welcome to the forum! You can use .getBBox() to get coordinates from the SVG space (read more about it on the MDN docs). And then I would find the origin point from where you want to transform the element and that that as the svgOrigin (check more about it in this forum thread) https://codepen.io/mvaneijgen/pen/eYMgWyv
    3 points
  49. I think maybe you were missing a little part of my last post- you can run conditional logic inside the batch So you can handle how the animation happens for each element. Does this help? https://codepen.io/GreenSock/pen/zYWoyyK?editors=1011
    3 points
  50. It sounds like you're trying to do what @Mamboleoo tweeted about yesterday Give that a shot
    3 points
×