Carousel은 슬라이드 쇼와 같은 형식을 가지며, 스크롤을 내리지 않고도 유저에게 다양한 정보를 제공할 때 사용한다.
씬프로드를 개발하면서, 이미지 여러 장을 캐러셀로 보여주기 위해 구현해봤다.
overflow: hidden
속성을 가지고 있어서, 옆으로 넘어간 이미지의 경우 보이지 않도록 한다.transform
속성을 이용해 이동하는 모션을 준다.컴포넌트의 기본적인 구조를 그린 코드는 다음과 같다.
// 화면에 보이는 부분
<div className="carousel" ref={container}>
// 이미지 가로로 나열
<div
className="carousel__slider"
style={{
width: `${images.length}00%`,
transform: `translate3d(${index * -containerWidth}px, 0, 0)`,
}}
>
{ /* 받아온 images를 통해 이미지를 넣는다. (map을 이용) */ }
</div>
// 이전 이동 버튼
<button onClick={() => handleClick("prev")} />
// 다음 이동 버튼
<button onClick={() => handleClick("next")} />
</div>
외부에 하나의 블록이 있고, 안에 좌우 버튼과 이미지를 가로로 나열한 블록이 있다.
캐러셀 스타일에,
<div
className="carousel__slider"
style={{
width: `${images.length}00%`,
transform: `translate3d(${index * -containerWidth}px, 0, 0)`,
}}
>
width, transform 속성을 부여하는데, 이미지 만큼 너비를 가지도록 하고, 보고 싶은 이미지가 바뀔 때 (인덱스의 변경) 해당 슬라이더를 이동시키는 코드를 작성한 것이다.
const [index, setIndex] = useState<number>(0);
const [containerWidth, setContainerWidth] = useState<number>(0);
const container = useRef<HTMLDivElement>(null);
function handleClick(direction: "prev" | "next") {
if (direction === "next") {
return setIndex((x) => (x < images.length - 1 ? x + 1 : 0));
}
return setIndex((x) => (x > 0 ? x - 1 : images.length - 1));
}
const handleResize = () => {
const { current } = container;
if (!current) {
return;
}
setContainerWidth(current.offsetWidth);
};
index
는 현재 보여주는 이미지의 순서를 가진다.
containerWidth
는 캐러셀을 담는 container의 너비를 저장한다. index
가 변화함에 따라 이미지 순서를 넘기기 위해 사용한다.
handleClick
은 이전, 다음 버튼을 클릭했을 때, index
값을 변경한다.
container
에 useRef
를 사용해, HTML DOM에 바로 접근할 수 있도록 한다.
화면의 크기가 변경될 때, 캐러셀을 담는 container 블록의 크기가 달라지기 때문에,
해당 DOM에 접근해 너비를 체크해야 한다. 해당 DOM의 너비를 체크해 containerWidth를 갱신한다.
먼저, 캐러셀을 담는 블록은 넘치는 이미지를 가리기 위해 overflow: hidden
을 사용한다.
.carousel {
overflow: hidden;
}
슬라이더의 경우, flex
속성을 사용하고, flex-shrink: 0
속성을 부여한다. flex-shrink
는 가로로 나열된 블록들을 다른 비율로 보이게 한다. MDN_flex-shirink
transition
속성을 부여해 transform
으로 이미지가 변경될 때, 모션도 넣어준다.
.carousel__slider {
display: flex;
flex-shrink: 0;
transition: transform 0.5s;
}
캐러셀을 구현할 땐,
정도가 필요한 것 같다.
세부적으로 flex-shrink
라는 속성, overflow:hidden
속성을 이용한다.
이미지를 가져올 때, 원래 이미지 크기를 가져오고, 페이지에서 화면 비에 따라 변경된다. 이 때, container의 너비가 갱신되지 않는다. 그런 문제로 원래 넘어갈 크기만큼 넘어가지 않는 문제가 발생한다.