[웹 개발][React] 커스텀 이미지 슬라이더/캐러셀 컴포넌트 만들기

박시진·2022년 9월 9일
0

웹 개발(리액트)

목록 보기
6/6

이미지 슬라이더란?

이미지 슬라이더란 말 그대로 여러 이미지들이 슬라이드되는 컴포넌트를 말한다.
예시

이미지 매핑

먼저 컴포넌트 props로 이미지 URL이 담긴 배열을 받고 그 이미지들을 매핑했다.

const Slider = ({ imgs }) => {
  const total = imgs.length;

  return (
    <div 
   	  className={classes.slider} 
      style={{ width: `${total * 100}%` }}
    >
      {imgs.map((img, i) => {
        return (
          <img 
            key={i} 
            src={img} 
            style={{ width: `${100 / total}%` }} 
          />
        );
      })}
    </div>
  );
};

.slider {
  display: flex;
}
.slider img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

나중에 슬라이드 기능을 구현하기 위해서 슬라이더 안에 이미지들을 나누어 넣었다.

이미지 슬라이드 기능 구현

나는 이미지 슬라이드 기능을 transform: translateX로 구현했다. 또한 시간 차를 두고 자동으로 이미지가 슬라이드되는 기능은 useRef를 활용해 구현했다.

const [index, setIndex] = useState(1);
const timeoutRef = useRef(null);
const total = imgs.length;

const resetTimeout = () => {
  if (timeoutRef.current) {
    clearTimeout(timeoutRef.current);
  }
};

useEffect(() => {
  resetTimeout();
  timeoutRef.current = setTimeout(() => {
    setIndex((prevIndex) => (prevIndex === total ? 1 : prevIndex + 1));
  }, 2500);
  
  return () => {
    resetTimeout();
  };
}, [index, total]);

<div
  className={classes.slider}
  style={{
  	width: `${total * 100}%`,
    transform: `translateX(-${(100 / total) * (index - 1)}%`,
  }}
>
  {/* 이미지들 */}
</div>

.slider {
  transition: transform 0.5s ease-in-out;
}

먼저 useState로 index 변수를 선언해 현재 이미지의 인덱스를 저장하게 했다. 이후 useRef로 timeoutRef을 선언해 ref 안에 이미지 인덱스를 바꿔주는 timeout 함수를 저장하게 했다. 또한 index가 바뀔 때마다 useEffect 함수가 실행되게 만들어 자연스럽게 이미지 슬라이드가 되도록 했다.

네비게이션 추가

원하는 이미지를 찾아갈 수 있도록 네비게이션을 추가했다.

const total = imgs.length;

<div className={classes.container}>
  {/* 슬라이더 */}
  <nav>
    {Array(total)
      .fill()
      .map((_, i) => (
        <button
          key={i}
          onClick={() => setIndex(i + 1)}
          className={index === i + 1 ? classes.current : ""}
        />
	  ))}
  </nav>
</div>

.container {
  position: relative;
  overflow: hidden;
}
.container nav {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 1rem;
  display: flex;
  gap: 5px;
}
.container nav button {
  padding: 0;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
}
.current {
  background-color: rgba(255, 255, 255, 0.9);
}

먼저 슬라이더와 네비게이션을 감싸는 컨테이너를 만들었다. 네비게이션은 imgs 배열을 매핑했다.

(완성)

profile
안녕하세요

0개의 댓글