I had been trying to do this for weeks with Framer Motion using a different approach, but I wasn’t as satisfied. Thank you for this great tutorial. I’m learning a lot by following you. I prefer this video format focused on a replicable component that can easily adapt to various situations over the lengthy clone videos.
Glad to hear you’re finding value from the videos! And thanks for the feedback on the video lengths, I’ll continue to focus on more narrow tutorials but may experiment with a longer build in the future.
after 25 sec of duration it give a jerk and restart from the 1st image that looks wired if you decrease duration to less i.e 5. is there any fix for this thing ?
great video, just 1 quick question, what is that rerender state for? I can't see anywhere using this state apart from setting it true or false, I removed it and everything is still working fine, is it just for triggering useEffect to rerender the component? I think mustFinish state is enough to trigger, please let me know if i am wrong. also duration * (1 - xTranslation.get() / finalPosition) seems to be unnecessary, just use duration and can't tell the difference
Yep the rerender variable wasn't really necessary :) On the duration piece - you need the custom version when mustFinish is true, because the default duration lengths correspond to the time it takes to scroll the entire row. By definition if mustFinish is true, we have already progressed part way through the row of cards, so we need to scale the duration to get the correct intended speed.
I used this as example for my infinite vertical carousel, I am having issue where complete callback is never called despite animation running in loops, this in turn causes issue when onDrag Y pos is updated, I end up creating control version where Y pos is not different after animation has finished looping once :D quite funny, I'll try to sort that on my own ----update Fun fact, onRepeat callback is not implemented, it only exists as part of .d.ts file as interface value. I fixed my issue by manually detecting when I am close to finishing single iteration via onUpdate callback, and seting mustFinish(false)
nice guide... but if mouseover the picture how can set paused and after mouseout retake the animation keeps on the moving from the same point without restart the animation... I would really appreciate it if you could help me
I used a trick by setting the FAST_DURATION variable to a really big number (100,000) to make it seem like it’s paused. It still moves, but super slowly, so it looks like it’s on pause. If you come up with a better way to do this, that would be great
In CSS, you can use the ::-webkit-scrollbar:horizontal selector and set the width/height to 0 & background to transparent. If you want an example, I do this for a vertical scrollbar towards the end of my custom scrollbar video.
loved the approach i was trying to do the same but I am stuck on a problem if the content increases let's say card's data from a API the speed increases how do we decrease speed proportionally to content
Instead of using a fixed value for the duration, you can make it dynamic based on the length of the response array. E.g., something like duration = arrayLength * 10 (the 10 will control the speed which you can play around with)
I'm sticking with the Pages Router for now because Framer Motion has issues with the App Router, particularly around and page transitions. But I think this specific project *should* work fine in the App Router.
There's still a slight occasional jump in the scrolling behaviour when the reset of the scrolling items happens. Did you figure out what's causing this by any chance?
Great video, thanks! Not entirely sure about the last part. I have refactored it with an `isSlow` state value and the useEffect like this: ``` useEffect(() => { if (!width) return; const finalPosition = -width / 2 - 16; const controls = animate(xTranslation, [xTranslation.get(), finalPosition], { ease: "linear", duration: (isSlow ? 120 : 60) * (1 - xTranslation.get() / finalPosition), repeat: Infinity, repeatType: "loop", repeatDelay: 0, }); return () => { controls.stop(); }; }, [width, xTranslation, isSlow]); ``` Was there a bug that made you implement the useEffect with `mustFinish` & `rerender`?
I probably didn't need `rerender` :). But I needed `mustFinish` to know whether to set the xTranslation animation to start at 0 (reshift everything back to the starting point) or to xTranslation.get() (handle changes in speed). Looking at your code, I don't see a place to reset the value of xTranslation to 0, so not sure if this would work. But let me know if I'm missing something.
This works through the "infinite" animation and smartly selecting the endpoint for the xTranslation to line up the second copy of the cards with the original starting position.
thx 4 vid! i have the problem with undefined reading resolver in controls.stop, so i used this method to handle the problem. 👇 const stopAnimation = () => { if (controls) { controls.stop(); } }; return stopAnimation;
I had been trying to do this for weeks with Framer Motion using a different approach, but I wasn’t as satisfied. Thank you for this great tutorial. I’m learning a lot by following you. I prefer this video format focused on a replicable component that can easily adapt to various situations over the lengthy clone videos.
Glad to hear you’re finding value from the videos! And thanks for the feedback on the video lengths, I’ll continue to focus on more narrow tutorials but may experiment with a longer build in the future.
Bro I was trying to do this for so long but you were the only one who explained it properly! thanks so much for the video !
To eliminate the jump give the motion.div a width: max-content
exactly! otherwise it might have width capped by the end of the viewport
thank you
I actually don't get how he got it to work without this
best framer-motion carousel tutorial, blessing
This is class. Made it super simple to understand what everything is!
back with a banger ⚡🧪💯
You just saved my day! Thank you!
Glad I could help!
Thanks a lot for this video !
Wow! Super Top!
Didn't really need to use a 3rd party package to get the size of the div container, could've used `scrollWidth` to get that value
after 25 sec of duration it give a jerk and restart from the 1st image that looks wired if you decrease duration to less i.e 5. is there any fix for this thing ?
great video, just 1 quick question, what is that rerender state for? I can't see anywhere using this state apart from setting it true or false, I removed it and everything is still working fine, is it just for triggering useEffect to rerender the component? I think mustFinish state is enough to trigger, please let me know if i am wrong.
also duration * (1 - xTranslation.get() / finalPosition) seems to be unnecessary, just use duration and can't tell the difference
Yep the rerender variable wasn't really necessary :)
On the duration piece - you need the custom version when mustFinish is true, because the default duration lengths correspond to the time it takes to scroll the entire row. By definition if mustFinish is true, we have already progressed part way through the row of cards, so we need to scale the duration to get the correct intended speed.
Awesome! Thanks
I used this as example for my infinite vertical carousel, I am having issue where complete callback is never called despite animation running in loops, this in turn causes issue when onDrag Y pos is updated, I end up creating control version where Y pos is not different after animation has finished looping once :D quite funny, I'll try to sort that on my own
----update
Fun fact, onRepeat callback is not implemented, it only exists as part of .d.ts file as interface value.
I fixed my issue by manually detecting when I am close to finishing single iteration via onUpdate callback, and seting mustFinish(false)
I been trying to replicate the same but i get snaps back to the begining instead of it reseting in the background, what am i doing wrong?
Great 🎉 very helpful , Just one question can we change animation direction from left to right.?
nice guide... but if mouseover the picture how can set paused and after mouseout retake the animation keeps on the moving from the same point without restart the animation... I would really appreciate it if you could help me
I used a trick by setting the FAST_DURATION variable to a really big number (100,000) to make it seem like it’s paused. It still moves, but super slowly, so it looks like it’s on pause. If you come up with a better way to do this, that would be great
when it gets in the end of the second array, it its with a black spot, how can i fix it?
blank**
Can the slowdown on hover effect be done using only javascript? If so can someone please reply with a link to any video explaining how it's done?
Great video!
This causes a horizontal scrollbar to show up on my website, can anyone help me remove it?
Any help would be greatly appreciated.
In CSS, you can use the ::-webkit-scrollbar:horizontal selector and set the width/height to 0 & background to transparent. If you want an example, I do this for a vertical scrollbar towards the end of my custom scrollbar video.
Is there other way to solve that ? ::-webkit-scrollbar is non standard and not recommended in production
loved the approach i was trying to do the same but I am stuck on a problem if the content increases let's say card's data from a API the speed increases how do we decrease speed proportionally to content
Instead of using a fixed value for the duration, you can make it dynamic based on the length of the response array. E.g., something like duration = arrayLength * 10 (the 10 will control the speed which you can play around with)
Gem hidden here
Thank you so much
Awesome, ty
Great Video! Just want to ask can I reverse the direction? Can anyone help me with the code
Thanks ❤
[QUESTION]: Why the use of the pages directory? Is there a particular reason or just preference.
I'm sticking with the Pages Router for now because Framer Motion has issues with the App Router, particularly around and page transitions. But I think this specific project *should* work fine in the App Router.
I'll try this on the app router
@@Dexquest3d Did you manage to try this on routed? I am unable to get the infinite scrolling to start.
There's still a slight occasional jump in the scrolling behaviour when the reset of the scrolling items happens.
Did you figure out what's causing this by any chance?
same problem(
same issue, please tag me if you find an answer
@@meirbek241i just solved it by creating a similar animation with tailwind without frame motion
@@n59kk interesting, do you mind sharing link to repo how you solved it?
it waits for the last item to reach the end and then reset and start the loop which leaves a lot of space, I don't understand why
Did you map over two copies of the card array?
it's because the formula he used, won't work for you as it is.
Great video, thanks! Not entirely sure about the last part. I have refactored it with an `isSlow` state value and the useEffect like this:
```
useEffect(() => {
if (!width) return;
const finalPosition = -width / 2 - 16;
const controls = animate(xTranslation, [xTranslation.get(), finalPosition], {
ease: "linear",
duration: (isSlow ? 120 : 60) * (1 - xTranslation.get() / finalPosition),
repeat: Infinity,
repeatType: "loop",
repeatDelay: 0,
});
return () => {
controls.stop();
};
}, [width, xTranslation, isSlow]);
```
Was there a bug that made you implement the useEffect with `mustFinish` & `rerender`?
I probably didn't need `rerender` :). But I needed `mustFinish` to know whether to set the xTranslation animation to start at 0 (reshift everything back to the starting point) or to xTranslation.get() (handle changes in speed). Looking at your code, I don't see a place to reset the value of xTranslation to 0, so not sure if this would work. But let me know if I'm missing something.
@@builtwithcode Yes you're right, good catch. I refactored it and set the `speed` attribute.
```
const control = useRef(null!);
useEffect(() => {
if (!width) return;
const finalPosition = -width / 2 - 16;
control.current = animate(xTranslation, [0, finalPosition], {
ease: "linear",
duration: 60,
repeat: Infinity,
repeatType: "loop",
repeatDelay: 0,
});
return () => {
control.current.stop();
};
}, [width, xTranslation]);
...
onPointerDown={() => control.current.speed = 0.5}
```
I am a bit disappointed that the formula wasn't explained properly at all because the exact final position formula will not work for everyone.
Sorry to hear that, is there anything I can clarify?
remove left and right padding if their is any on scroll container
Can you provide the entire code?
GitHub repo link is in the description, the main branch has the final code
where is the logic for resetting the image container content ??
This works through the "infinite" animation and smartly selecting the endpoint for the xTranslation to line up the second copy of the cards with the original starting position.
thx 4 vid!
i have the problem with undefined reading resolver in controls.stop, so i used this method to handle the problem.
👇
const stopAnimation = () => {
if (controls) {
controls.stop();
}
};
return stopAnimation;
Where did you put this one?
@@luiscosta2385 to the same place where he writes return controls.stop
perfect! you saved my day, thanks