반응형
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 한스푼을 더해서 (0) | 2024.06.26 |
---|---|
Button으로 Resizable 구현하기 (0) | 2024.06.04 |
Next.js metadata 다루는 방식의 변 (0) | 2024.05.14 |
Next Image 사용하는 방법 (0) | 2024.05.14 |
📘 Next.js 에 markdown 설치 하기 (0) | 2024.05.09 |