maxvia Posted December 7, 2020 Share Posted December 7, 2020 Hi, I am trying to implement the first horizontal section effect of the following website: https://rino-pelle.com/ Images are moving from right to left when you are not doing anything BUT moving faster when scrolling down. I know how to accomplish the first part using as example the following code: gsap.to(movableImageWrapper, { xPercent: -100, duration: 40, repeat: 100, ease: 'none'}, '<' ) I also know how to accomplish the 2nd part using scrolltrigger: gsap.timeline(movableImageWrapper, {xPercent: -100, scrollTrigger: { trigger: mainSection, start:"top 50%", end: "bottom 300", scrub: true, toggleActions: "play none none none", } }) However where I am confused is how to combine both because if I try doing this my scrolltrigger function will move my images depending of their original axis not the current one (not sure if I am clear). How would you guys proceed with that? is there anw to track the first transformation ? Thanks for the tips Btw I am using react but js is fine as well Thank you Link to comment Share on other sites More sharing options...
ZachSaucier Posted December 7, 2020 Share Posted December 7, 2020 Hey maxvia. I'd make use of ScrollTrigger's .getVelocity() method paired with GSAP's modifiers to do this. Modifiers will also help with the infinite wrapping (GSAP's wrap utility method can also help there). You will want to animate each element individually so that you can wrap it properly. That also means that you should probably stick to the x property instead of xPercent. 3 Link to comment Share on other sites More sharing options...
maxvia Posted December 8, 2020 Author Share Posted December 8, 2020 hey @ZachSaucier, Thank you for pointing out the different options I have however after some hours looking for the solution, I wasnt able to come to a good one that. I first took care of the scrolltrigger method this way: const imagesScrollerTrigger = ScrollTrigger.create({ trigger: mainSection, start:"top 50%", end: "bottom 50%", markers: true, ease: 'none', onUpdate: function(self) { let velocity = self.getVelocity() //first image let axis = images[0].getBoundingClientRect().x firstImagesAxisValue = axis if (velocity > 0) { gsap.to(moveImages, { ease: "none", x: calculateNewX(velocity, axis), modifiers: { x: gsap.utils.unitize(x => parseFloat(x) % -window.innerWidth ) }, }) timelineImage.pause() } } }) I am quite happy with my scrolltrigger. It is working fine and the images are moving to speed I like. Also I dont want them to move on scroll up thats why I only make change is the velocity is positive. then I set up a timeline as follow : let timelineImages = gsap.timeline() timelineImages.fromTo(imagesArray, { //x value of my first image x: images.current[0].getBoundingClientRect().x, } , { ease: "none", duration: 40, x: -window.innerWidth, repeat: -1 }) } My first intention was to do when scrollTrigger onUpdate isActive => timeImages.pause() and when onUpdate is not isActive => timeIineImages.play() or .restart() (in order to have a new accurate value of from x, since this one was modified by the scrolltrigger) Is there anyway to do such a thing or I try another way? Thank you! Link to comment Share on other sites More sharing options...
ZachSaucier Posted December 8, 2020 Share Posted December 8, 2020 1 hour ago, maxvia said: My first intention was to do when scrollTrigger onUpdate isActive => timeImages.pause() and when onUpdate is not isActive => timeIineImages.play() or .restart() (in order to have a new accurate value of from x, since this one was modified by the scrolltrigger) Is there anyway to do such a thing or I try another way? You technically could do something like this by using a setTimeout or GSAP delayedCall but I would think you would have syncing issues unless your animations are affecting different elements (like a container instead for one of them). Why not use modifiers like I suggested? I would likely set things up along the lines of this (pseudo-code): let additionalY = { val: 0 }; let additionalYAnim; items.forEach(item => { gsap.to(item, { x: -containerWidth, modifiers: { x: gsap.utils.unitize(x => { (parseFloat(x) + additionalY.val) % -containerWidth }) } }); }); const imagesScrollerTrigger = ScrollTrigger.create({ trigger: mainSection, start: "top 50%", end: "bottom 50%", markers: true, ease: 'none', onUpdate: function(self) { const velocity = self.getVelocity(); if(additionalYAnim) additionalYAnim.kill(); additionalYAnim.val = velocity/1000; if (velocity > 0) { additionalYAnim = gsap.to(additionalY, { y: 0 }); } } }) 2 Link to comment Share on other sites More sharing options...
maxvia Posted December 8, 2020 Author Share Posted December 8, 2020 thanks for the reply Zach So this wouldnt work if I add a duration value? items.forEach(item => { gsap.to(item, { x: -containerWidth, modifiers: { x: gsap.utils.unitize(x => { (parseFloat(x) + additionalY.val) % -containerWidth }) } }); }); I wanted my animated to go over all the picture within 40 second so I added to duration: 40 as a paramaters. If i remove the duration parameters it goes way to fast. It takes about one second to go all over the pics. It was working fine, meaning all the pics were moving on their own, however I tried to give a value to additionalY.val to see if it would go faster but it was changing changing anything. Animation was not going faster. Also, sorry but I am confused about this part? if (velocity > 0) { additionalYAnim = gsap.to(additionalY, { y: 0 }); } Did you mean the array of items instead of additionalY? Link to comment Share on other sites More sharing options...
ZachSaucier Posted December 8, 2020 Share Posted December 8, 2020 Adding a duration is fine. 24 minutes ago, maxvia said: Did you mean the array of items instead of additionalY? Nope. The goal of my approach is to have a single object that is storing the additional (i.e. increased speed) value. So you update one thing when ScrollTrigger updates and that one thing is used to affect the offset of all of your other tweens. Perhaps it would be helpful if you made a minimal demo of what you're trying. 1 Link to comment Share on other sites More sharing options...
maxvia Posted December 8, 2020 Author Share Posted December 8, 2020 I created the following codepen with the pseudo code you gave me. See the Pen QWKEevR by skima37 (@skima37) on CodePen As you can see, the first method is working fine however the second one (the one using scrolltrigger) is buggy at the moment. What I basically want is that whenever I am scrolling and I am within my scrolltrigger area, I want my images going left faster relative to my scrolling activity. Thank you Zach Link to comment Share on other sites More sharing options...
Solution ZachSaucier Posted December 8, 2020 Solution Share Posted December 8, 2020 You've got several logical issues. As I said, my code was very much pseudo-code. Fixing the logic issues you should get something like this: See the Pen NWRRKQg?editors=1000 by GreenSock (@GreenSock) on CodePen With that being said, I don't really understand what you're trying to do with the "hidden images". It'd probably make more sense to absolutely position the images because the calculations are harder if you don't. There are a lot of examples of how to do wrapping like this including these: See the Pen e09daad9223a4745f12934332ac11afa by ZachSaucier (@ZachSaucier) on CodePen That'd probably fix the flashing issue that the pen I included above has. 1 Link to comment Share on other sites More sharing options...
maxvia Posted December 9, 2020 Author Share Posted December 9, 2020 Thank you @ZachSaucier, this works out good at the moment except the flashing. In this particular exemple. Is it the wrapping + the updateProgress function that makes the animation infinite? Link to comment Share on other sites More sharing options...
ZachSaucier Posted December 9, 2020 Share Posted December 9, 2020 7 hours ago, maxvia said: In this particular exemple. Is it the wrapping + the updateProgress function that makes the animation infinite? Yes, those are key parts. I encourage you to spend time understanding exactly what my code is doing in both examples That will help you figure out the differences in the approaches and how you can make an approach that exactly fits your needs. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now