admin管理员组文章数量:1405324
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>
本文标签: reactjsLogo Scroll Carousel Animation HitchingStack Overflow
版权声明:本文标题:reactjs - Logo Scroll Carousel Animation Hitching - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744329497a2600892.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论