✏️

[FE] React - 마우스 드래그해서 스크롤 이동하기 본문

PROJECT/성격 찾기 프로젝트 | PR Me

[FE] React - 마우스 드래그해서 스크롤 이동하기

콩세 2023. 5. 31. 13:42

위 사진은 내가 피그마로 계획했던 Home.jsx이다.

PR Me의 메인 페이지이며 주요 기능이 들어가서 가장 중요한 페이지라고 볼 수 있다.

 

가장 아래에 있는 "7명이 참여해줬어요!" 문구가 있는 부분을 만들면서

좌우 가로 스크롤을 넣었는데 하나의 기능을 더 더하고 싶어서

마우스로 드래그해서 스크롤을 넘기는 기능을 추가했다.


우선 완성된 모습은⬇️

깔끔하게 잘 만들어진거같다😚


const nicknamesRef = useRef(null);
// nicknamesRef는 nicknames div요소에 대한 참조를 생성하는데 사용된다.
// useRef(null)은 초기값으로 null을 할당하여 초기 참조를 설정한다.

const [startX, setStartX] = useState(0);
// startX는 마우스 드래그 시작 시 초기 X좌표를 저장하는 상태 변수이다.
// useState(0)은 초기값으로 0을 할당하고,
// setStartX는 startX값을 업데이트 하는 함수이다.

const [scrollLeft, setScrollLeft] = useState(0);
// scrollLeft는 nicknames div의 가로 스크롤 위치를 저장하는 상태 변수이다.
// useState(0)은 초기값으로 0을 할당하고,
// setScrollLeft는 scrollLeft값을 업데이트 하는 함수이다.

const [isDragging, setIsDragging] = useState(false);
// isDragging은 마우스 드래그가 진행 중인지를 나타내는 상태 변수이다.
// useState(flase)는 초기값으로 false를 할당하고,
// setIsDragging은 isDragging값을 업데이트 하는 함수이다.

useRef를 사용하여 nicknamesRref를 생성하면 해당 변수는 nicknames div요소를 가리키게 된다.

이렇게 생성된 참조를 통해 DOM요소에 접근할 수 있다.

(nicknames div요소는 가장 아래 코드블럭에서 확인)

 

useState를 사용하여 startX, scrollLeft, isDragging 상태 변수를 생성하면 해당 변수들은 초기값과 업데이트 함수를 가지게 된다.

이렇게 생성된 상태 변수들은 컴포넌트의 렌더링 중에 값이 변경되면 React가 해당 컴포넌트를 다시 렌더링하고 변경된 값으로 업데이트한다.


const handleMouseDown = (event) => {
setIsDragging(true);
setStartX(event.clientX - nicknamesRef.current.offsetLeft);
// 마우스가 눌릴 시점에서의 X좌표(event.clientX)에서
// nicknames div 왼쪽에서의 오프셋 (nicknamesRef.current.offsetLeft)을 뺀 값을
// startX 상태 변수에 저장하는 것.
};

const handleMouseMove = (event) => {
if (!isDragging) return;
event.preventDefault();
const x = event.clientX - nicknamesRef.current.offsetLeft;
const scroll = x - startX;
nicknamesRef.current.scrollLeft = scrollLeft - scroll;
};

const handleMouseUp = () => {
setIsDragging(false);
setScrollLeft(nicknamesRef.current.scrollLeft);
};

const handleMouseLeave = () => {
setIsDragging(false);
};

handleMouseDown 함수

마우스 버튼이 nicknames div 위에서 눌릴 때 호출되는 이벤트 핸들러이다.

함수 내에서는 setIsDragging(true)를 호출하여 isDragging 상태를 true로 설정하고,

event.clientX - nicknamesRef.current.offsetLeft를 통해 마우스의 초기 X좌표 (startX)를 계산하여 저장한다.

 

- event.clientX : 이벤트가 발생한 시점에서 마우스의 X좌표를 나타낸다.

- nicknamesRef.current : nicknamesRef 참조의 현재값. 실제 DOM을 가리킨다.

- offsetLeft : 해당 DOM 요소의 왼쪽에서의 위치를 픽셀 단위로 나타낸다.

 

handleMouseMove 함수

마우스가 nicknames div 위에서 움직일 때 호출되는 이벤트 핸들러이다.

함수 내에서는 현재 isDragging 상태를 확인하고, 드래그 중이 아닌 경우에는 함수 실행을 종료한다.

드래그 중인 경우, 이벤트의 기본 동작을 방지하고

현재 마우스의 X좌표를 nicknames div를 기준으로 계산하여 x에 저장한다.

x - startX를 통해 스크롤 이동 거리(scroll)를 계산하고,

이를 이용하여 nicknamesRef.current.scrollLeft를 업데이트하여 실제로 스크롤을 이동시킨다.

 

handleMouseUp 함수

마우스 버튼이 nicknames div 위에서 놓였을 때 호출되는 이벤트 핸들러이다. (버튼을 눌렀다 뗄 때)

함수 내에서는 setIsDragging(false)를 호출하여 isDragging 상태를 false로 업데이트한다.

마우스 드래그 동작이 끝났음을 나타낸다.

 

handleMouseLeave 함수

마우스가 이벤트 대상 요소를 벗어났을 때 호출되는 이벤트 핸들러이다.

setisDragging(false)를 호출하여 isDragging 상태를 false로 업데이트한다.

마우스 드래그 동작이 끝났음을 나타낸다.


<div className='participants'>
<p>12명이 참여해줬어요!</p>
<div 
  className='nicknames'
  ref={nicknamesRef}
  onMouseDown={handleMouseDown}
  onMouseMove={handleMouseMove}
  onMouseUp={handleMouseUp}
  onMouseLeave={handleMouseLeave}
>
  <button className='nick1'>hongsebin</button>
	...
</div>
</div>

onMouseDown, onMouseMove, onMouseUp, onMouseLeave 이벤트 핸들러는

각각 nicknames div에서 발생하는 마우스 이벤트를 처리하는데 사용된다.

 

onMouseDown

마우스 버튼이 nicknames div 위에서 눌러질 때 발생한다.

handleMouseDown 함수가 호출되며, 이 함수는 isDragging 상태를 true로 설정하고,

마우스의 초기 위치(startX)를 nicknames div를 기준으로 계산한다.

 

onMouseMove

마우스가 nicknames div 위에서 눌린 채로 움직일 때 발생한다.

handleMouseMove 함수가 호출되며, 이 함수는 isDragging이 true일 경우에만 실행된다.

(=마우스 버튼이 눌러졌을 때만 실행된다.)

함수는 마우스의 현재 위치 (X)를 nicknames div를 기준으로 계산하고,

이전 위치(startX)와의 차이를 이용해 스크롤을 조정한다.

 

onMouseUp

마우스 버튼이 nicknames div 위에서 눌린 채로 놓였을 때 발생한다.

handleMouseUp 함수가 호출되며, 이 함수는 isDragging 상태를 false로 설정하고,

nicknames div의 스크롤 위치 (scrollLeft)를 업데이트한다.

 

onMouseLeave

마우스가 nicknames div를 떠났을 때 발생한다.

handleMouseLeave 함수가 호출되며, 이 함수는 isDragging 상태를 false로 설정한다.