React 컴포넌트의 위치나 크기, 회전 등은 고정되어있는 경우가 많지만 때로는 이런 요소들을 조작해야 하는 경우가 있다.
특히, Figma, Framer 등 개체를 그려야 하는 웹 페이지에서는 이런 기능이 필수적이다.
이런 기능을 제공하는 다양한 라이브러리들이 있지만, 그중에서도 하나의 라이브러리로 많은 요소를 컨트롤 할 수 있는
react-moveable 라이브러리를 소개하고자 한다
1. react-moveable이란?
React Moveable은 드래그, 크기 조정, 회전 등 다양한 인터랙션을 쉽게 구현할 수 있는 강력한 라이브러리로, CSS 스타일과 함께 동작해서 다양한 UI 인터랙션을 쉽게 추가할 수 있는 장점이 있다
주요 기능
- 드래그 : 요소를 자유롭게 이동 가능
- 리사이즈 : 크기 조절
- 회전 : 원하는 각도로 회전 가능
이외에도 수많은 기능들을 제공하지만, 일단은 기본적이고 가장 많이 쓰이는 기능은 이 세가지인 것 같다.
2. 설치 및 컴포넌트 생성
설치는 매우 간단한 편.
React 19 버전에 대응되며, 따로 타입 패키지를 설치하지 않아도 된다.
//npm
npm install react-moveable
//yarn
yarn add react-moveable
설치를 완료했으면, Moveable을 적용한 컴포넌트를 하나 만들어준다
import React, { useRef } from "react";
import Moveable from "react-moveable";
export default function MoveableComponent() {
const targetRef = useRef<HTMLDivElement>(null);
return (
<div>
{/* 움직일 컴포넌트 */}
<div
ref={targetRef}
className="absolute w-32 h-32 bg-blue-500"
style={{
left: 100,
top: 100,
}}
/>
{/* Moveable 컨트롤러 */}
<Moveable
target={targetRef.current}
/>
</div>
);
}
하나의 div 안에 움직임을 수행할 컴포넌트와 컨트롤러를 같이 넣어주어야 한다.
useRef를 이용해 움직일 컴포넌트의 DOM 정보를 가져오고, 컨트롤러는 이 DOM 정보를 이용해 컴포넌트를 조작하게 된다.
Moveable 컨트롤러에 다양한 속성을 추가하여 컴포넌트 컨트롤을 수정 할 수 있다
3. 기능 추가
기능들은 대부분 Moveable 컨트롤러 컴포넌트에 {기능able} 속성을 추가해 사용 할 수 있다.
A. 드래그
<Moveable
target={targetRef.current}
draggable={true}
onDragStart={) => {
//드래그 시작시 실행될 이벤트
}}
onDrag={({ beforeTranslate }) => {
//드래그 중 실행될 이벤트
}}
onDragEnd={({ target, lastEvent }) => {
//드래그가 끝나면 실행될 이벤트
}}
/>
draggable 속성을 true로 설정해주고, onDragStart, onDrag, onDragEnd 이벤트에 각각 실행될 로직을 넣어준다.
onDrag 이벤트에서 접근할 수 있는 beforeTranslate는 number[] 타입으로 리턴되는데 각 요소가 나타내는 것은 다음과 같다.
- beforeTranslate[0] : X축 이동 거리 (px)
- beforeTranslate[1] : Y축 이동 거리 (px)
- beforeTranslate[2] : Z축 이동 거리 (px) (보통 0, 3D 변환이 있을 경우 사용)
- beforeTranslate[3] : 이동 행렬(Matrix)의 기타 값 (주로 1 또는 0, 특정 변환에 따라 다름)
보통 beforeTranslate[0], beforeTranslate[1]만을 이용해 드래그 이후 위치를 저장해주는 방식을 많이 사용한다
적용 예시
드래그시 일정 기준에 맞춰 이동시키고 싶거나, 다른 요소와의 간격을 맞추고 싶다면 'snappable' 속성을 추가하면 된다
<Moveable
target={targetRef.current}
snappable={true}
draggable={true}
onDrag={({ beforeTranslate }) => {
if (targetRef.current)
targetRef.current.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`;
}}
snapDirections={{ top: true, left: true, bottom: true, right: true }}
snapThreshold={10}
verticalGuidelines={[50, 150, 250, 450, 550]}
horizontalGuidelines={[0, 100, 200, 400, 500]}
/>
- snapDirections={{ top: true, left: true, bottom: true, right: true }} : 각 방향으로 스내핑 적용
- snapThreshold={10} : 10px 이내로 접근하면 스내핑 작동
- verticalGuidelines={[50, 150, 250, 450, 550]} : 수직 스내핑 가이드라인
- horizontalGuidelines={[0, 100, 200, 400, 500]} : 수평 스내핑 가이드라인
적용 예시
B. 리사이즈
<Moveable
target={targetRef.current}
resizable={true}
onResizeStart={() => {
//리사이즈 시작시 실행될 이벤트
}}
onResize={({ width, height, target }) => {
//리사이즈 중 실행될 이벤트
}}
onResizeEnd={) => {
//리사이즈가 끝나면 실행될 이벤트
}}
/>
resizable 속성을 true로 만들고, onResizeStart, onResize, onResizeEnd이벤트 안에 리사이즈 로직을 넣어주면 된다.
onResize의 target은 선택된 컴포넌트, 그리고 width, height는 target의 리사이즈된 너비, 높이를 나타낸다.
이를 잘 이용해 리사이즈 로직을 짜주면 된다.
코드 예시
<Moveable
target={targetRef.current}
resizable={true}
onResize={({ width, height, target }) => {
target.style.width = `${width}px`;
target.style.height = `${height}px`;
}}
/>
적용 예시
C. 회전
<Moveable
target={targetRef.current}
rotatable={true}
onRotateStart={() => {
//회전 시작시 실행되는 이벤트
}}
onRotate={({ target, rotate }) => {
//회전 중 실행되는 이벤트
}}
onRotateEnd={() => {
//회전이 끝나면 실행되는 이벤트
}}
/>
rotatable 속성을 true로 설정하고, onRotateStart, onRotate, onRotateEnd 이벤트에 로직을 추가한다.
Moveable 컨트롤러를 회전시킬 컴포넌트 안에 넣으면 rotate가 동작하지 않는다.
어떻게 아냐고요? 저도 알고싶지 않았습니다
컨트롤러는 Ref를 통해 요소에 접근하므로 위치는 상관 없다고 생각했으나, 형제 노드 관계여야 적용이 되는 것 같다.
onRotate의 target 역시 회전시킬 요소, rotate는 회전 각도이다. 역시 target의 style을 잘 조작하여 회전을 적용하면 된다
코드 예시
<Moveable
target={targetRef.current}
rotatable={true}
onRotate={({ target, rotate }) => {
target.style.transform = `rotate(${rotate}deg)`;
}}
/>
적용 예시
react-moveable의 기본적인 기능들을 살펴 보았다. 이외의 기능은 이곳에서 더 확인 할 수 있다
react-moveable
A React Component that create Moveable, Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable.. Latest version: 0.56.0, last published: a year ago. Start using react-moveable in your project by running `npm i react-moveable`. There are
www.npmjs.com
정말 쉽고 간단하게 요소를 조작할 수 있어서 매우 편리한 라이브러리인 것 같다.
다만 마지막 업데이트가 2년전이고(근데 어떻게 19에서 돌아가지...?), 사이즈가 좀 큰 편인것이 단점.
react-draggable이나 react-dnd같은 다른 드래그 라이브러리의 6~10배 정도 크기인 것 같다.
드래그 기능만을 사용하려면 다른 라이브러리를 사용하는 것이 좋겠으나, 위에 소개된 다양한 기능들을 모두 사용하기엔 이만한 라이브러리는 없는 것 같기도 하다 ㅋㅋㅋ
'Frontend is 실전' 카테고리의 다른 글
[Tailwind] @Tailwind 삼형제가 동작하지 않는다면!?!?!?! (0) | 2025.03.26 |
---|---|
[Next] API Routes를 이용해 사이드 서버 구축 해보기 with Typescript (0) | 2025.01.20 |
[React] React-Query로 데이터 통신 해보기 (0) | 2025.01.10 |
[Next] Next.js의 layout 적극 활용해 보기 (1) | 2024.12.03 |
[Git] Git rebase와 cherry-pick (0) | 2024.05.28 |