지난 번 슬라이드 기능을 구현하기는 했지만,
맨 마지막 이미지에서 첫 번째 이미지로 넘어가는 화면이
매끄럽게 다음 이미지로 이어지는 것이 아닌 뒤로 롤백 되듯이 돌아가게 되어서
그 부분을 이번에 고쳐보고자 한다.
와 할 일이 너무 많았네..?
괜히 건드린 건가...
슬라이드 기능 중 이제 겨우 첫번째인데, 여전히 헤매고 있다.
오른쪽 버튼을 계속 눌러도 뒤로 돌아가는 애니메이션이 아닌
계속 넘어가는 애니메이션으로 같은 이미지들을 반복해서 보여주려고 하는데
이 부분이 생각보다 꽤 어려운 부분인거 같아서 몇일을 고민했었다.
/// 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을 판단해 어떤 동작을 할것인지를 삼항연산자를 통해 구현했다.
생각했던 방법대로 잘 구현이 된 것을 확인했다..!
살짝 로직자체가 길고 복잡하지만 그래도 내 손으로 직접 만들어 보니..
굉장히 좋았다..!