next 14.0.1 버전을 기준으로 작성되었습니다.
Codepen에서 간단한 원리로 무한반복 슬라이드를 만든 것을 보았는데, 퍼블리싱이나 프론트 작업할때 유용하게 쓸 수 있을 것 같아서 조금 변형해서 사용해봤습니다! 👽
// infiniteLoop.tsx
import {CSSProperties} from 'react';
const InfiniteLoopSlider : React.FC<InfiniteLoopPropType> = ({children, style, onHoverStop}) => {
// 슬라이더에 마우스를 올렸을 때 이벤트
const onMouseOverSlider = (e : React.MouseEvent) => {
const slider = e.currentTarget;
if (e.target === slider) return; // 슬라이더 자체가 아닌 슬라이더 안의 요소들에 마우스를 올렸을 때 멈추고 싶어 해당 코드를 넣었습니다.
if (!(slider instanceof HTMLDivElement)) return;
slider.style.animationPlayState = 'paused';
}
// 마우스가 슬라이더에서 벗어났을 때 이벤트
const onMouseOutSlider = (e : React.MouseEvent) => {
const slider = e.currentTarget;
if (!(slider instanceof HTMLDivElement)) return;
slider.style.animationPlayState = 'running';
}
return (
<div className='InfiniteLoop__slider' >
<div
className={`InfiniteLoop__inner`}
style={style}
onMouseOver={onHoverStop ? onMouseOverSlider : undefined}
onMouseOut={onHoverStop ? onMouseOutSlider : undefined}
>
{children}
{children}
</div>
</div>
);
};
// TYPE
export interface InfiniteLoopPropType{
children: React.ReactNode;
onHoverStop?: boolean;
style?: CSSProperties; // 기본으로 설정한 스타일 덮어씌우고 싶을 경우
}
export default InfiniteLoopSlider;
.InfiniteLoop {
// 애니메이션
@keyframes loop {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
&__slider {
overflow-x: hidden;
}
&__inner {
display: flex;
width: fit-content;
animation: loop;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 30s;
& > * {
flex-shrink: 0;
}
}
}
<InfiniteLoopSlider onHoverStop={true}>
{
bestItemData.map((el, idx)=>
<div className='Main__best-item' key={`title${idx}`}>
<div className='Main__best-item-img'>
<BlurImage src={el.imgUrl} alt='' fill priority/>
</div>
<h3 className='Main__best-item-title'>{el.title}</h3>
<p className='Main__best-item-desc'>{el.desc}</p>
</div>
)
}
</InfiniteLoopSlider>
const partnerCSS : CSSProperties = {
// 방향을 반대로, 애니메이션 재생 시간을 더 길게 설정
animationDirection: 'reverse',
animationDuration: '55s'
}
...(중략)...
<InfiniteLoopSlider style={partnerCSS}>
<>
<div className='Main__partner-item'> </div>
<div className='Main__partner-item'> </div>
<div className='Main__partner-item'> </div>
<div className='Main__partner-item'> </div>
<div className='Main__partner-item'> </div>
<div className='Main__partner-item'> </div>
</>
</InfiniteLoopSlider >
감사합니다!