I am trying to make a logo scroll carousel component that scrolls infinitely. The list of logos is duplicated (so it’s 200% wide) and then using a CSS animation to move it from translateX(0)
to translateX(-50%)
. When it reaches the end, it should seamlessly repeat. Unfortunately, there is a hitch when the animation resets.
How can this be fixed?
LogoCarousel.tsx
import React from 'react';
import styles from './LogoCarousel.module.css';
interface LogoCarouselProps {
logos: string[];
}
export const LogoCarousel: React.FC<LogoCarouselProps> = ({ logos }) => {
return (
<div className={styles.logoCarousel}>
<div className={styles.logoTrack}>
{/* First set */}
{logos.map((logo, index) => (
<div className={styles.logoItem} key={`logo-1-${index}`}>
<img src={logo} alt={`Sponsor logo ${index + 1}`} />
</div>
))}
{/* Second set */}
{logos.map((logo, index) => (
<div className={styles.logoItem} key={`logo-2-${index}`}>
<img src={logo} alt={`Sponsor logo ${index + 1} (copy)`} />
</div>
))}
</div>
</div>
);
};
LogoCarousel.module.css
.logoCarousel {
position: relative;
overflow: hidden;
width: 100%;
margin: 2rem auto;
}
.logoTrack {
display: flex;
width: 200%;
animation: scroll 10s linear infinite;
will-change: transform;
}
.logoItem {
flex: 0 0 auto;
width: 200px;
margin-right: 2rem;
}
.logoItem img {
width: 100%;
height: auto;
display: block;
}
@keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
I am trying to make a logo scroll carousel component that scrolls infinitely. The list of logos is duplicated (so it’s 200% wide) and then using a CSS animation to move it from translateX(0)
to translateX(-50%)
. When it reaches the end, it should seamlessly repeat. Unfortunately, there is a hitch when the animation resets.
How can this be fixed?
LogoCarousel.tsx
import React from 'react';
import styles from './LogoCarousel.module.css';
interface LogoCarouselProps {
logos: string[];
}
export const LogoCarousel: React.FC<LogoCarouselProps> = ({ logos }) => {
return (
<div className={styles.logoCarousel}>
<div className={styles.logoTrack}>
{/* First set */}
{logos.map((logo, index) => (
<div className={styles.logoItem} key={`logo-1-${index}`}>
<img src={logo} alt={`Sponsor logo ${index + 1}`} />
</div>
))}
{/* Second set */}
{logos.map((logo, index) => (
<div className={styles.logoItem} key={`logo-2-${index}`}>
<img src={logo} alt={`Sponsor logo ${index + 1} (copy)`} />
</div>
))}
</div>
</div>
);
};
LogoCarousel.module.css
.logoCarousel {
position: relative;
overflow: hidden;
width: 100%;
margin: 2rem auto;
}
.logoTrack {
display: flex;
width: 200%;
animation: scroll 10s linear infinite;
will-change: transform;
}
.logoItem {
flex: 0 0 auto;
width: 200px;
margin-right: 2rem;
}
.logoItem img {
width: 100%;
height: auto;
display: block;
}
@keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
Share
Improve this question
edited Mar 21 at 23:36
Anthony
asked Mar 21 at 23:35
AnthonyAnthony
113 bronze badges
1 Answer
Reset to default 1I think this is inherent to your method of doing it, you would rather use requestAnimationFrame() with performance.now() to get a better result !
Here is a small example in plain HTML/CSS with JS
document.addEventListener("DOMContentLoaded", () => {
const container = document.querySelector('.content');
/** Duplicating the content for seamless animation */
const originalChildren = [...container.children];
originalChildren.forEach(child => {
const clone = child.cloneNode(true);
container.appendChild(clone);
});
let startTime = performance.now();
let posX = 0;
const speed = 100;
const targetFPS = 120;
const frameTime = 1000 / targetFPS;
const resetThreshold = container.offsetWidth / 2;
function animate(time) {
let deltaTime = time - startTime;
if (deltaTime >= frameTime) {
posX -= speed * deltaTime / 1000;
if (posX <= -resetThreshold) {
posX += resetThreshold;
}
container.style.transform = `translateX(${posX}px)`;
startTime = performance.now();
}
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
});
body {
margin: 0;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.container {
position: relative;
width:500px;
height: 100px;
background: lightgray;
overflow: hidden;
}
.content{
position:absolute;
left:0;
top:0;
display:flex;
height:100%;
}
.logo.red{background:red;}
.logo {
height: 80px;
width: 80px;
background: blue;
margin:0 5px;
}
<div class="container">
<div class="content">
<div class="logo red"></div>
<div class="logo"></div>
<div class="logo"></div>
<div class="logo"></div>
<div class="logo"></div>
</div>
</div>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744329497a4568817.html
评论列表(0条)