Draggable 구현하기

2024. 6. 4. 18:09·Stack/Next.js
반응형

Next.js 에서 Draggable 구현하기

개인프로젝트를 만들던 중, 내가 만든 컴포넌트 Draggable 컴포넌트를 직접 구현하였다.

import React, { RefObject, useRef } from "react";
import styles from "./draggable.module.css";
import { getOffset } from "@/app/utils/utils";

interface DraggableProps {
  children: React.ReactNode;
  refObject?: RefObject<HTMLDivElement>;
}

const Draggable: React.FC<DraggableProps> = ({ children, refObject }) => {
  const draggableRef = useRef<HTMLDivElement>(null);

  let shiftX = 0;
  let shiftY = 0;

  const onMouseMove = (e: MouseEvent) => {
    moveAt(e.pageX, e.pageY);
  };

  const moveAt = (pageX: number, pageY: number) => {
    const targetRef = refObject?.current || draggableRef.current;
    if (targetRef) {
      const offset = getOffset(targetRef.parentElement);
      const newLeft = pageX - shiftX - offset.left;
      const newTop = pageY - shiftY - offset.top;
      targetRef.style.left = `${newLeft}px`;
      targetRef.style.top = `${newTop}px`;
    }
  };

  const onMouseUp = () => {
    // 이벤트 제거
    document.removeEventListener("mousemove", onMouseMove);
    document.removeEventListener("mouseup", onMouseUp);
  };

  const onMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
    // 마우스와 오브젝트간의 간격차이를 계산함
    e.preventDefault();
    if (draggableRef.current) {
      const rect = draggableRef.current.getBoundingClientRect();
      shiftX = e.clientX - rect.left;
      shiftY = e.clientY - rect.top;
    }
    document.addEventListener("mousemove", onMouseMove);
    document.addEventListener("mouseup", onMouseUp);
  };

  return (
    <div
      ref={draggableRef}
      onMouseDown={onMouseDown}
      className={styles.draggable_div}
    >
      {children}
    </div>
  );
};

export default Draggable;

 

getOffset 함수


// div에 겹겹히 쌓여있는 div태그의 정확한 위치 알수 있게 하기
export const getOffset = (
  element: HTMLElement | null
): { left: number; top: number } => {
  let offsetLeft = 0;
  let offsetTop = 0;
  while (element) {
    offsetLeft += element.offsetLeft - element.scrollLeft + element.clientLeft;
    offsetTop += element.offsetTop - element.scrollTop + element.clientTop;
    element = element.offsetParent as HTMLElement;
  }
  return { left: offsetLeft, top: offsetTop };
};

 

필수 css 요소

.container {
  display: flex;
  position: absolute;
}

 

- offset 함수는 지정한 HTMLElement 요소 left값과 top 값을 가지고 오는 함수이다.

- refObject는 Draggable 컴포넌트로 움직임을 제어하지만 전체적으로 움직여야될 것은 그 외부 HTMLElement 요소일 경우 refObejct로 넣어주면 된다.

참고한 내용

onMoseDown : 마우스 클릭시 이벤트 실행

onMoseUp : 마우스 클릭을 땔 시에 실행

onMoseMove : 마우스를 움직일때 moveAt를 실행

moveAt : 참조한 ref의 위치를 마우스의 변경정도 만큼 변경시킴

반응형

'Stack > Next.js' 카테고리의 다른 글

Three.js 화면 조정하기 Next.js 한스푼을 더해서  (1) 2024.06.26
Button으로 Resizable 구현하기  (2) 2024.06.04
Next.js metadata 다루는 방식의 변  (1) 2024.05.14
Next Image 사용하는 방법  (1) 2024.05.14
📘 Next.js 에 markdown 설치 하기  (1) 2024.05.09
'Stack/Next.js' 카테고리의 다른 글
  • Three.js 화면 조정하기 Next.js 한스푼을 더해서
  • Button으로 Resizable 구현하기
  • Next.js metadata 다루는 방식의 변
  • Next Image 사용하는 방법
WHITE_FROST
WHITE_FROST
개발공부리뷰블로그
    반응형
  • WHITE_FROST
    하얀하얀IT
    WHITE_FROST
  • 전체
    오늘
    어제
    • 분류 전체보기 (119)
      • Stack (43)
        • Next.js (7)
        • React (12)
        • React-Native (15)
        • TypeScript (0)
        • Python (2)
        • JavaScript (2)
        • Android (1)
        • DB (2)
        • JAVA (1)
      • Obsidian (1)
      • AI (3)
      • AI Tools (0)
      • Tools (0)
      • Mac (0)
      • Error (7)
      • 알고리즘 정리 (6)
      • 알고리즘 문제풀이 (46)
      • 공부일상 (4)
      • 개발 도구 & 라이브러리 (0)
      • 정보처리기사 (0)
      • 기타 (6)
      • Tip (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준
    Expo
    error
    react-native
    reactnative
    react-native-maps
    코테
    프로그래머스
    Next.js
    코테준비
    SWEA
    ios
    javascript
    java
    D2
    코딩테스트
    hooks
    mongoDB Atlas
    오블완
    알고리즘
    ReactHook
    mongodb cloud
    Python
    d1
    React Hooks
    티스토리챌린지
    리액트네이티브
    react
    React-Native cli
    boj
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
WHITE_FROST
Draggable 구현하기
상단으로

티스토리툴바