React.js 드래그 구현 및 스크롤 바 숨기기

강정우·2023년 3월 7일
0

react.js

목록 보기
42/45
post-thumbnail
post-custom-banner

구현목표

1. 옆에 사이드 바 숨기기

global.css

  • 우선 creat app을 실행하면 globlas.css에 자동으로 들어가있는 css가 있다.
  • 대략 85번째 줄에 저렇게 들어가있는데 우선 넘친다고 다 가려버리면 스크롤이 안 먹기 때문에 저 코드는 삭제하고
    스크롤 바를 안 보이게 해주는 속성값을 넣어준다.
body {
    max-width: 100vw;
}
body::-webkit-scrollbar {
    display: none;
}

2. 드래그 구현

  • 드래그
  • 이때 확장성을 위해 touch event도 추가하였다.
  • 또 추가적으로 screen, page, client, offset의 차이를 알아둘 필요가 있다.
    우선 screen은 모니터 기준이다. 위 검정색 네모의 가장 왼쪽 위이다.
    다음은 page 기준이다. Dom의 전체 width와 height으로 이해하면 편하다.
    다음은 client이다. 위의 초록 네모이고 이는 현재 내가 모니터에 띄워놓은 창을 기준으로 한다. 대부분 마우의 위치를 찾을 때 많이 사용한다.
    마지막으로 offset이다. 이는 Dom위에 렌더링된 요소의 x,y좌표값이라고 생각하면 편하다.

드래그 구현

  • 최상단 요소가 움직임에 따라 dom 내부의 모든 요소들이 움직여야한다.
    이를 구하는 코드는 아래와 같은데 별로 어렵지 않다.
const [startX, setStartX] = useState<number>();
const [startY, setStartY] = useState<number>();

const onDragStart = (e:any) => {
  setStartX(e.pageX + bodyRef.current!.scrollLeft);
  setStartY(e.pageY + bodyRef.current!.scrollTop);
};
const onDragMove = (e:any) => {
  bodyRef.current!.scrollLeft = startX! - e.pageX;
  bodyRef.current!.scrollTop = startY! - e.pageY;
};

<div>
  ref={bodyRef}
  onMouseDown={onDragStart}
  onMouseMove={onDragMove}
  onMouseUp={onDragEnd}
  onMouseLeave={onDragEnd}
</div>
  1. 우선 움직일 대상은 reference를 걸어준다.
  2. 드래그를 시작할 때의 마우스 위치를 구해준다. 이때 마우스라고 client로 해버리면 전체 DOM 요소가 움직이지 않기 때문에 따로 마우스(따지고 보면 DOM상의 위치)를 구해줘야한다.
  3. 다음 위치를 구해줬으면 추가로 더해준 page만큼을 빼줘서 실제값을 남게 만들면 된다.

    즉, startX = e.pageX + bodyRef.current!.scrollLeft - e.pageX 로 현재 스크롤 위치를 설정하겠다. 라는 것이다.
    그래서 정리하면 startX = bodyRef.current!.scrollLeft 라는 깔끔한 식이 남는다.

  • 하지만 이때 궁금증이 생긴다 왜 굳이 2번 계산하지 걍 startX = bodyRef.current!.scrollLeft로 하면 편할텐데 나도 우매하게 그렇게 생각했지만 잘 생각해보니 start와 move는 다른 메서드이고 이를 각각 다르게 설정해줘야한다. 즉, start(click) 할 때 만큼의 너비(높이)를 구하고 move할 때 만큼 빼면서 계산해 주어야 비로소 우리가 원하는 모습이 나온다.

touch

  • touch는 page이지만 중간에 touches라는 속성이 하나 들어가주면 된다.
  • 추가적으로 조건도 붙이면 아래와 같은 boiler code가 완성된다.
const onTouchDragStart = (e:any) => {
  if(dragMode.isMode===false){
    return
  }
  dispatch(setIsDrag(true));
  setStartX(e.touches[0].pageX + bodyRef.current!.scrollLeft);
  setStartY(e.touches[0].pageY + bodyRef.current!.scrollTop);
};
const onTouchDragMove = (e:any) => {
  if(dragMode.isMode===false){
    return
  }
  if (dragMode.isDrag) {
    bodyRef.current!.scrollLeft = startX! - e.touches[0].pageX;
    bodyRef.current!.scrollTop = startY! - e.touches[0].pageY;
  }
};
profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글