[TIL] 이미지 슬라이드 (캐러셀) 구현하기_2 (노 라이브러리)

김명성·2022년 4월 27일
0

TIL

목록 보기
10/11

🧑🏻‍🏫 Intro

지난 번 슬라이드 기능을 구현하기는 했지만,
맨 마지막 이미지에서 첫 번째 이미지로 넘어가는 화면이
매끄럽게 다음 이미지로 이어지는 것이 아닌 뒤로 롤백 되듯이 돌아가게 되어서
그 부분을 이번에 고쳐보고자 한다.

🧑🏻‍💻 과정

와 할 일이 너무 많았네..?
괜히 건드린 건가...

슬라이드 기능 중 이제 겨우 첫번째인데, 여전히 헤매고 있다.
오른쪽 버튼을 계속 눌러도 뒤로 돌아가는 애니메이션이 아닌
계속 넘어가는 애니메이션으로 같은 이미지들을 반복해서 보여주려고 하는데
이 부분이 생각보다 꽤 어려운 부분인거 같아서 몇일을 고민했었다.

💥 code

/// JS

  const [currentIndex, setCurrentIndex] = useState(0);
  const [newImgArr, setNewImgArr] = useState([]);
  const slideImageBox = useRef();
  
  const nextIndex = currentIndex === list.length - 1 ? 0 : currentIndex + 1;
  const prevIndex = currentIndex === 0 ? list.length - 2 : currentIndex - 2;
  
  useEffect(() => {
    const settingArr = [...list];
    settingArr.push(list[0]);
    settingArr.unshift(list[list.length - 1]);
    setNewImgArr(settingArr);
  }, []);

내가 짠 코드 구조는 이러하다.
먼저 state로 관리하는 부분에는 현재 인덱스를 나타내는 숫자와
새로운 이미지 배열을 관리하는 state를 구현한다.
이미지 슬라이드 기능을 위한 useRef도 사용을 한다.
다음 현재 인덱스와 이전 인덱스를 나타내는 값도 하나 만들어 줬다.

그리고 최초 배열 값으로 들어온 이미지 배열의
첫번째 인덱스와 마지막 인덱스 값을 각각 양 끝에 다시 배치해뒀다.

예를들어 [1,2,3,4,5] 라는 배열의 이미지 값이 들어온다면,
setting을 통해 나오는 건 [5,1,2,3,4,5,1] 의 값이 담긴 배열이다.

   const moveRightSide = () => {
    let changeArr = [...newImgArr];
    changeArr.shift();
    changeArr.push(list[nextIndex]);
    setNewImgArr(changeArr);
    currentIndex === list.length - 1
      ? setCurrentIndex(0)
      : setCurrentIndex(currentIndex + 1);
    slideImageBox.current.style.transform = `translateX(0%)`;
    slideImageBox.current.style.transition = `none`;

    setTimeout(() => {
      slideImageBox.current.style.transform = `translateX(-100%)`;
      slideImageBox.current.style.transition = `0.5s all ease-in-out`;
    }, 10);
  };

moveRightSide는 오른쪽 버튼을 눌렀을 때 동작하는 함수다.
해당 로직이 동작하는 원리는 다음과 같다.

버튼을 누르게 되면 기존에 있던 이미지 배열을 불러와
가장 뒤에 있는 이미지를 날리고, 맨 앞에 현재 첫번째 인덱스에 있는 값의 전에 있는 값을 넣어준다.
예를들어 [5,1,2,3,4,5,1]이 기존에 있던 값이었는데,
오른쪽 버튼을 눌러주면 [4,5,1,2,3,4,5]의 배열로 재배치 되는 로직이다.

그렇게 한 뒤, 현재 인덱스의 값을 변경하고,
useRef를 이용해 DOM에 직접 접근하고 css 속성을 순간적으로 변화시켜
마치 계속 이동하는 것 처럼 눈 속임을 해주는 작업을 한다.

transform에서 translateX를 주는 이유는,
최초에 보여져야 하는 값이 두번째 인덱스에 있는 값이기 때문에 -100%를 주었다.

  const handleImgSlide = (e) => {
    const { name } = e.target;
    name === 'right' ? moveRightSide() : moveLeftSide();
  };

오른쪽 버튼을 눌렀을 때와 반대로 왼쪽 버튼을 눌렀을 때는
저 로직의 반대로 로직을 구현하면 되겠다.

그 후, 화살표 버튼에 name을 부여해서
해당 이벤트의 name을 판단해 어떤 동작을 할것인지를 삼항연산자를 통해 구현했다.

📌 결과

생각했던 방법대로 잘 구현이 된 것을 확인했다..!
살짝 로직자체가 길고 복잡하지만 그래도 내 손으로 직접 만들어 보니..
굉장히 좋았다..!

profile
잠재력은 핵폭탄급 Frontend Developer

0개의 댓글