[React] 자동 슬라이드 구현하기

Gyuhan Park·2023년 3월 3일
0

react

목록 보기
11/11


쇼핑몰 기능들을 react로 구현해보면서 공부하고 있다. 그 중에서 slider는 어디에도 많이 쓰이는 것 같다. 근데도 맨날 헷갈리는 자동 슬라이드를 천천히 알아보자.

슬라이드란?

일단 어떻게 사진이 움직이는 걸까요?

우리는 보고싶은 것만 보는 상태다. 1번 div 크기만큼 보고 싶기 때문에 1번 div는 2번 div를 감싸고 있다. 정해놓은 사이즈만큼만 화면에 보이고 나머지는 자르고 싶다면 overflow:hidden 속성을 1번 div에 적용시킨다.

1번 div는 움직이지 않는다.

1번은 고정된 상태에서 길게 세로로 나열된 이미지인 2번 div를 위로 올리면서 화면이 아래로 이동하는 효과를 줄 것이다.
2번 div에 스타일을 적용해야 정상적으로 작동한다. 강조하는 이유는 내가 너무 삽질했기 때문 ㅎㅎ
transition과 transform 개념을 제대로 몰라서 많이 헤맸다.

style={{
	height: `550px*${images.length}`,
	transition: "all 1s ease-in-out",
	transform: `translateY(${
	-1 * ((100 / images.length) * (slideIndex - 1))
	}%)`,
}}

height : div크기 * 이미지 개수
transition : 1초에 걸쳐 ease-in-out 방식으로 변화
transform : 페이지 상단방향으로 이미지 이동시키기

transition : CSS 속성을 변경할 때 변하는 속도를 조절할 수 있음.

<property : 어떤 속성에 효과를  것인지>
<duration :  초에 걸쳐 효과를 변화시킬 것인지> 
<timing-function : 속도 조절 방식 ex)ease-in, ease-out> 
<delay : 속성이 바뀌고   후에 변화할 >

transform : 요소에 회전, 크기 조절, 기울이기, 이동 효과 부여

transform: rotateX(10deg);
transform: translateY(3in);
transform: scaleZ(2);
transform: skewX(30deg);

좀 더 자연스럽게 하려면?

지금 상태는 마지막 광고를 보여준 후 첫 번째 광고로 돌아가면서 다시 올라간다.
만약 이미지가 많다면 사용자가 불편하게 느낄 수 있다.

마지막 광고에서 다시 첫 번째 광고로 갈 때도 아래로 내려가는 효과를 줄 수 없을까?

맨 앞에 마지막 광고를 붙이고, 맨 뒤에 첫 번째 광고를 붙인 가상의 배열을 만든다.

const setSlide = () => {
    const beforeSlide = images[images.length - 1];
    const afterSlide = images[0];
    // 무한 슬라이드를 구현하기 위해 새롭게 배열을 만듦.
    return [beforeSlide, ...images, afterSlide];
  };

가상의 배열 : (복제된 2), 0, 1, 2, (복제된 0)
오리지널 배열 : 0, 1, 2

2번 상황일 때 1번 상황처럼 보이게 하는 것이다.

인덱스값이 3->4 로 넘어갈 때 첫 번째 광고(복제된 0)를 보여주고 복제된 0을 가리키고 있던 인덱스값을 오리지널 0을 가리키도록 바꾼다.

인덱스값을 바꿀 때 올라가요

위에서 복제된 0을 가리키고 있던 인덱스값을 오리지널 0을 가리키라고 했다.
그래서 인덱스값이 4일 때 오리지널 배열의 0을 가리키는 1로 인덱스값을 바꿀 것이다.

안 내려가고 올라가는데요?

지금은 당연히 올라가는데 그 이유는 인덱스값에 따라 애니메이션이 발생하기 때문이다. 그럼 이제 오리지널 0을 "몰래" 바꾸려면 그 순간에 애니메이션을 없애줘야 한다. 이때 이미지를 담은 div에 접근하기 위해 useRef를 사용한다.

const slideRef = useRef(null);
if (slideIndex === 5) {
	if (slideRef.current) {
        slideRef.current.style.transition = "";
    }
    setSlideIndex(1);
    if (slideRef.current) {
      slideRef.current.style.transition = "all 1s ease-in-out";
    }
}
...
ref={slideRef}

올라가는데요?

애니메이션이 안 없어져요

분명 애니메이션 없앴는데 왜 안 없어지지?
사이에 콘솔로 찍어보면 실제로 스타일이 변경된 걸 알 수 있다. 근데 왜 안돼?

setState가 비동기로 동작하기 때문이다. 인덱스가 바뀌기 전에 스타일이 다시 적용되면서 인덱스가 바뀔 때는 애니메이션이 동작한다. 그럼 인덱스가 바뀐 뒤에 애니메이션이 동작하려면 어떻게 해야 할까? -> setTimeout()

setTimeout()을 쓰는 이유

setTimeout을 사용하여 스타일 변경을 비동기로 동작시킨다. 그럼 인덱스가 바뀐 뒤에 애니메이션이 적용되어 원하던대로 아래로만 슬라이드가 넘어가게 동작한다.

setTimeout(() => {
	if (slideRef.current) {
		slideRef.current.style.transition = "all 1s ease-in-out";
	}
}, 10);

복제된 0에서 오리지널 0으로 바꿀 땐 transition-duration을 바꿔줘야 한다. 안그러면 1초 간격으로 바뀌던 광고가 이때는 2초를 보여줄 것이다.
-> 미해결

버튼리스트에 마우스오버했을 때 delay값이 초기화되지 않아 동작이 아쉽다.
-> 미해결(마우스 오버시 delay값 초기화 안됨)

리액트 캐러셀 만들기
리액트 무한 자동 슬라이드 만들기

profile
단단한 프론트엔드 개발자가 되고 싶은

0개의 댓글