[React] 가로 스크롤 캐로셀(Carousel) 구현

김지민·2022년 7월 14일
1

React

목록 보기
10/13
post-thumbnail

1. 구현하고자 한 것

스크롤바 기능은 하지만 보이지는 않게 하기

🤔 단순히 CSS 에서display:flex로 하면 안되나?

실패

모든 영화를 포함하고 있는 div에 styles를 적용해주어야 한다.

.moviesContainer {
  display: flex;
  overflow: auto;
  white-space: nowrap;
}

여기서 white-space는 CSS white-space 속성은 요소가 공백 문자를 처리하는 법을 지정한다.
이미지들의 나열이기 때문에 불필요하다고 판단해서 제거해 주었다.

👇 공식 문서 참고
https://developer.mozilla.org/ko/docs/Web/CSS/white-space

또 다른 문제점이 발생했다. 스크롤 바를 제거했더니 이미지가 넘어가지 않았다.

내가 원하는 것은 버튼을 누르면 옆에 넘어간 영화 이미지를 보여주는 것이었다.

✅ 구글링을 통해 이것을 캐로셀(Carousel) 이라고 부르는 것이 있다는 것을 알았다. 번역하면 회전목마 라고 한다!

이를 구현하기 위해서는 많은 라이버리가 있다고 하는데 나는 JS 실력 향상을 위해 javascript로 이를 구현해보고자 했다.

🎠 캐로셀 구현하기

🤔 어떻게 구현하면 좋을까?

일단 보여주고 싶은 이미지가 무엇인지 인덱스로 표현할 수 있겠다고 생각했다.

그러면 버튼을 눌를 때 마다 보여주고 싶은 인덱스만큼의 이미지만 보여주면 된다.

총 4개씩의 이미지를 보여주기로 했고, 이는 const에 담으면 될 것 같다.

todo list 만들기에서 버튼을 눌를 때마다 컴포넌트를 렌더링 해줄 때 useState를 사용했던 경험이 떠올라서
스크롤 버턴을 누르면 useState의 data를 이미지 인덱스 번호로 설정해서 렌더링이 이루어지면 좋겠다고 생각했다!

그럼 데이터를 저장했다가 버튼을 누르면 맨 왼쪽의 이미지는 사라지게 하고, 오른쪽의 이미지를 하나 생성하면서 보여지는 모든 이미지를 하나씩 왼쪽으로 이동하면 좋을 것 같았다.

🤔 이미지를 사라지게 만드는 방법?

🤔 이미지를 생성하는 방법?

이를 한번에 해결할 수 있는 화면 이동 속성 transform: translateX() 가 있었다.

👇 transform: translateX() 공식 문서

https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX

❗️ 이때 인덱스가 0보다 커져서 계속 왼쪽으로 이동하는 현상 발생!
-> if 문을 활용해서 return으로 더 이상 translate가 동작하지 못하도록 만들었다.

import React, { useEffect, useState } from "react";
import Movie from "../component/Movie";
import styles from "./Home.module.css";
function Home() {
 const [loading, setLoading] = useState(true);
 const [movieData, setMovieData] = useState([]);
 const [moveIndex, setMoveIndex] = useState(0);
 const leftMove = () => {
   if (moveIndex === 0) {
     return;
   }
   setMoveIndex((prev) => prev + 10);
 };

 const rightMove = () => {
   setMoveIndex((prev) => prev - 10);
 };
 const getMovies = async () => {
   const json = await (
     await fetch(
       `https://yts.mx/api/v2/list_movies.json?minimun_rating=9&sort_by=year`
     )
   ).json();
   setMovieData(json.data.movies);
   setLoading(false);
 };

 useEffect(() => {
   getMovies();
 }, []);
 console.log(moveIndex);
 return (
   <div>
     {loading ? (
       <h1>loading</h1>
     ) : (
       <div>
         <button onClick={leftMove}>left</button>
         <button onClick={rightMove}>right</button>

         <div
           className={styles.moviesContainer}
           style={{ transform: `translateX(${moveIndex}%)` }}
         >
           {movieData.map((movie) => (
             <div className={styles.transform}>
               <Movie
                 key={movie.id}
                 id={movie.id}
                 coverImg={movie.medium_cover_image}
                 title={movie.title}
                 summary={movie.summary}
                 genres={movie.genres}
               />
             </div>
           ))}
         </div>
       </div>
     )}
   </div>
 );
}

export default Home;

🎉 완성!

아직 css 작업과 index 를 화면 크기에 맞춰서 조정해주어야 하지만 전체적 로직은 모두 구현하였다!!! 기쁘다!!!

profile
💡Habit is a second nature. [Git] https://github.com/Kimjimin97

0개의 댓글