앞선 포스트의 디자인이 잘리고, 최종적으로 컨펌된 디자인은 화면안에서 배너가 컨베이어벨트처럼 움직여야 하는 디자인이 되었다.
계속 DOM을 조작해야되다 보니 성능 저하가 우려되었지만..
우선 내가 아는 방법을 총 동원해 만들어보았다.
역시 carousel처럼 wrapper로 영역을 감싼 뒤, setInterval에 맞추어 translateX가 작동되도록 했다.
배너 하나가 화면에서 사라지면 배너의 맨 끝 부분에 사라진 배너가 붙도록 하였다.
Mark Up
<div className={styles.bannerBG}>
<div className={styles.bannerWrapper}>
<div className={styles.imgWrapper}>
{imgSource.map((img, idx) => (
<img key={idx} className={styles.wrapperImg} id=
{`${idx}`} src={img} alt='bannerImg' />
))}
</div>
</div>
</div>
imgSource에 이미지 주소를 배열로 저장해놓고 그것을 map을 돌려 뽑아내는 형태로 구현했다.
css
.bannerBG {
background-color: #fbfcfe;
height: 200px;
overflow: hidden;
}
.bannerWrapper {
position: relative;
}
.imgWrapper {
position: absolute;
display: flex;
transition: all 0.5s ease-out;
}
.wrapperImg {
/* width: 100px; */
height: 150px;
margin: 30px 50px;
background-color: #fbfcfe;
mix-blend-mode: darken;
opacity: 30%;
}
배너 이미지 사이즈를 고정해서 모두 균일한 사이즈를 가지도록 했다.
그렇게 해야 나중에 자바스크립트로 계산할 때 편하다.
(가로 사이즈가 균일해야 몇 픽셀을 넘어갔을 때 추가해야할 지 알기도 편하기 때문에)
jsx(javascript)
const IMG_SOURCE = [ // 이미지 주소 모아놓은 곳
'image01.jpg',
'image02.jpg',
'image03.jpg',
'image04.jpg',
'image05.jpg',
'image06.jpg',
'image07.jpg',
'image08.jpg',
'image09.jpg',
'image10.jpg',
'image11.jpg',
'image12.jpg',
'image13.jpg',
'image14.jpg',
'image15.jpg',
'image16.jpg',
'image17.jpg'
]
const [imgSource, setImgSource] = useState(IMG_SOURCE)
const [pixel, setPixel] = useState(0)
const interval: { current: NodeJS.Timeout | null } = useRef(null)
useEffect(() => {
interval.current = setInterval(() => {
setPixel((prev) => prev + 1)
}, 50)
return () => clearInterval(interval.current as NodeJS.Timeout)
}, [])
useEffect(() => {
if (pixel % 100 === 0) {
// 하나 지나갈때마다 하나 추가
const idx = (pixel / 100) % 17 // 총 이미지가 17개여서, 17로 나누어 인덱스 구함
const newImgArr = [...imgSource]
const img = newImgArr[idx]
newImgArr.push(img)
setImgSource(newImgArr)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pixel])
setInterval을 통해서 움직여야할 픽셀 값을 찾아내고,
픽셀값을 활용해서 일정 사이즈(여기선 100)를 지나칠 때마다 이미지 배열 맨 끝에다가 새로운 이미지를 추가해주도록 구성했다.
final Markup
<div className={styles.bannerBG}>
<div className={styles.bannerWrapper}>
<div className={styles.imgWrapper} style={{ transform: `translateX
(-${pixel}px)` }}>
{imgSource.map((img, idx) => (
<img key={idx} className={styles.wrapperImg} id={`${idx}`} src=
{img} alt='bannerImg' />
))}
</div>
</div>
</div>
최종적으로 inline으로 translateX를 건드려서 이미지 배열이 움직이도록 한다
직접 보고싶다면 https://mediaswitch.kr/main 에서 확인할 수 있다
translateX를 사용해도 계속 DOM을 건드리는 형태인데 보다 성능에 최적화된 방법이 없을지 고민이다.
혹시 무한 순환되는 것도 구현해보셨나요?ㅠㅠ