프로젝트/학수고대 프로젝트

리액트 모바일 터치 슬라이드 구현

tteokbokki-master 2024. 2. 9. 00:58

https://studysmart.tistory.com/126

 

리액트 사진 슬라이드 구현하기

이번 프로젝트의 서비스 소개 페이지가 슬라이드 형식으로 구성되어 있기에, 연습 겸 슬라이드를 구현해 볼 겁니다. 시작에 앞서 인터넷에서 맘에 드는 사진 3개를 다운받아서 기본 세팅을 했습

studysmart.tistory.com

지난번에 만든 슬라이드에 모바일 터치 슬라이드를 추가해 볼 겁니다. 

 

 

 

 

 

 

지난번 코드에서 useRef를 통해 사진을 감싸는 div를 참조해줍니다. 그리고 터치가 시작된 위치와 끝난 위치를 저장하기 위한 touch State도 생성합니다.

 

 

 

 

 

모바일 화면의 터치를 구현해야 하기에, onTouchStart, onTouchMove, onTouchEnd 이벤트를 이용합니다. 참조하고 있는 div태그 내에 onTouchStart를 생성해 줍니다. e.touches[0].pageX를 각각 설명하겠습니다.

 

e.touches는 화면에 발생한 터치에 대한 모든 정보를 포함합니다. 따라서 e.touches[0]은 첫 번째 터치를 의미합니다. 그리고 pageX는 터치가 발생한 페이지의 좌측 기준 X값을 나타냅니다. 정리하면 e.touches[0].pageX는 첫 번째 터치의 X값을 의미하는 것입니다.

 

onTouchStart가 실행되면 해당 값을 setTouch의 인자로 전달해서 start 값을 초기화합니다.

 

 

 

 

 

사진을 클릭하면 클릭된 위치의 X값이 잘 출력되는 것을 확인할 수 있습니다.

 

 

 

 

 

다음은 onTouchMove입니다. 드래그를 했을 드래그를  위치만큼 사진이 이동했다가다음 사진으로 넘어가야 자연스러운 슬라이드가  것입니다.

 

사진 정보가 없음에도 드래그 시 화면이 움직이면 안되기에, ref.current를 통해 참조하고 있는 값이 존재할 때만 실행되게 제어합니다. current 변수를 생성해서 현재의 인덱스(currentIndex)와 ref.current.clienWidth를 곱해줍니다.

 

여기서 ref.current.clienWidth는 참조하고 있는 값(사진)의 가로길이를 나타냅니다. 저 사진들의 각각의 가로길이는 414px기에, ref.current.clienWidth는 414px가 됩니다.

 

 

 

 

 

current에 현재의 인덱스와 참조 값의 clienWidth를 곱하는 이유는 사진의 위치를 판단하기 위해서입니다. 사진을 이어 붙인 채로 이동하는 구조다 보니, 모든 로직에서 사진의 위치를 판단할 값이 필요합니다.

 

다음으로 e.targetTouches[0].pageX와 첫 터치의 x값인 touch.start를 빼줍니다. 그리고 해당 값을 current의 값에서 빼고 result변수에 저장합니다. 마지막으로 setStyle의 translateX 인자로 전달해 저장해 주면 끝입니다.

 

(*onTouchMove에서의 e.targetTouches[0].pageX는 터치한 상태로 움직일 때마다 달라집니다.)

 

 

 

 

 

그림이 개판이네 증말

예를 들어 414px 크기의 인덱스가 0인 사진에서 드래그를 한다고 합시다. current는 0이 되며, x값이 250 지점에서 10인 지점까지 드래그를 끌어왔다고 가정하면, result는 - 0 + (10 - 250)으로 -240이 됩니다. 

 

result 값을 transform: `translateX(${result}px`,에 전달하면 최종적으로 -240px만큼 드래그 한 위치에서 멈추게 됩니다.

 

이제 터치를 끝냈을 때, 화면이 슬라이드 되는 로직만 구성하면 끝입니다. 

 

 

 

 

 

onTouchEnd은 간단합니다. 드래그가 끝난 지점의 x값을 변수 end에 저장하고, 시작지점이 끝 지점보다 크다면 오른쪽으로 넘기고, 반대라면 왼쪽으로 넘기면 됩니다.  다만 첫 사진과  마지막 사진에서는 함수가 실행되지 않게 합니다. 왜냐? gif를 보시죠

 

 

 

 

 

첫 번째와 마지막 사진에서 함수 실행을 제한하지 않았을 때는, onTouchMove 이후 함수를 실행해도 넘길 사진이 없기에 gif와 같은 상황이 발생합니다. 

 

 

 

 

 

하지만 첫 번째와 마지막 사진에서 함수가 실행되지 않게 하고, else문을 통해 onTouchMove 이후 원래의 위치로 돌아오게 설정하면 gif처럼 쫀쫀(?)한 슬라이드가 완성됩니다. transition을 설정하면 쫀쫀에서 말랑하게 바꿀 수도 있습니다.

 

 

 

 

 

이렇게 모바일 터치 슬라이드까지 구현 완료했습니다. 감사합니다.