-
Notifications
You must be signed in to change notification settings - Fork 0
Horizonal Scroll problem
LikeFireAndSky edited this page Dec 15, 2023
·
3 revisions
desktop에서 세로축 스크롤은 간편한데 가로축 스크롤은 불편하다.
가로축 스크롤에서 휠이 작동하면 편할 것 같다.
import { useRef, useEffect } from 'react';
export const useHorizontalScroll = () => {
const scrollRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line
useEffect(() => {
const el = scrollRef.current;
if (el) {
const onWheel = (e: WheelEvent) => {
if (e.deltaY === 0) return;
e.preventDefault();
el.scrollTo({
left: el.scrollLeft + e.deltaY,
behavior: 'smooth',
});
};
el!.addEventListener('wheel', onWheel);
return () => el!.removeEventListener('wheel', onWheel);
}
}, []);
return scrollRef;
};
deltaY는 휠의 세로축의 스크롤 값을 말한다.
만약에 요소 자체에 스크롤 요소가 없다면 deltaY값이 0된다. 따라서 return으로 아무것도 내보내지 않는다.
e.preventDefault를 한 이유는 웹 페이지의 전체적인 스크롤이랑 같이 동작하면 안되기 때문이다. 만약에 같이 동작하면 가로 스크롤이랑 웹페이지 스크롤이랑 혼동되어 어지러워질 것이다.
이후 element를 scroll해야하는데
scrollLeft는 스크롤할 요소의 가장 왼쪽 모서리 값이다. 해당 값에서 움직이는 값인 deltaY값을 더해주는 것이다.
ref에 대해서 동작함으로 해당 훅은 ref를 반환하고 이 ref가 선언된 요소의 가장 왼쪽 모서리 값에 이동하는 값을 더하면서 움직일 것이다.
import { useRef, useEffect } from 'react';
export const useHorizontalScroll = () => {
const scrollRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line consistent-return
useEffect(() => {
const el = scrollRef.current;
if (el) {
let requestId: number;
const onWheel = (e: WheelEvent) => {
if (e.deltaY === 0) return;
e.preventDefault();
// 요청이 이미 예약되어 있다면 취소
cancelAnimationFrame(requestId);
// requestAnimationFrame 내에서 스크롤 동작 예약
requestId = requestAnimationFrame(() => {
el.scrollTo({
left: el.scrollLeft + e.deltaY,
behavior: 'smooth',
});
});
};
el.addEventListener('wheel', onWheel);
return () => {
el.removeEventListener('wheel', onWheel);
// 컴포넌트가 언마운트될 때 requestAnimationFrame 예약 취소
cancelAnimationFrame(requestId);
};
}
}, []);
return scrollRef;
};requestAnimationFrame을 활용해서 스크롤 이펙트가 멈추었다가 실행되는 과정을 조금 더 유연하게 변경하였다.