
인스타그램에서 스토리를 작성할 때처럼 텍스트 박스를 원하는 위치에 옮기는 방법에 대해서 소개하겠다.
npm install react-use-gesture
먼저 react-use-gesture라는 패키지를 설치해준다.
import {useDrag} from 'react-use-gesture';
이 패키지의 useDrag 훅을 사용할 것이므로 import 해준다.
useDrag 훅은 함수를 리턴하는데, 이 함수는 이벤트 핸들러가 있는 객체를 반환한다. 이 함수를 {...func()} 이런 식으로 호출하여 컴포넌트의 props로 넘겨주면 실제로는 onPointerDown, onPointerMove, onPointerUp 이벤트 핸들러를 컴포넌트에 등록하는 것이다.
공식문서에 나와있는 useDrag 훅에 대한 설명이다.
const [textPos, setTextPos] = useState({ x: 0, y: 0 });
const bindTextPos = useDrag((params) => {
setTextPos({ x: params.offset[0], y: params.offset[1] });
});
먼저 텍스트의 좌표를 저장할 textPos라는 state를 생성하고, useDrag의 반환함수를 bindTextPos에 저장한다. useDrag의 콜백함수 내에서는 인자로 offset 배열(초기 좌표로부터 떨어진 정도를 저장한 배열 [offsetX, offsetY])을 넘겨받게 된다. 이를 textPos에 저장한다.
<TextArea
{...bindTextPos()}
$x={textPos.x}
$y={textPos.y}
value={text}
onChange={(e) => setText(e.target.value)}
></TextArea>
{...bindTextPos()}로 드래그와 관련된 이벤트 핸들러를 등록해준다. 그리고 textPos 좌표를 styled-components props로 넘겨준다.
const TextArea = styled.textarea`
position: absolute;
top: ${(props) =>
props.$y >= 0 ? (props.$y <= 250 ? props.$y + "px" : "250px") : "0px"};
left: ${(props) =>
props.$x >= 0 ? (props.$x <= 250 ? props.$x + "px" : "250px") : "0px"};
넘겨받은 props를 top, left로 설정한다. 배경 이미지의 범위를 넘어가지 않도록 약간의 분기처리를 했다. 참고로 배경 이미지의 가로 세로 길이는 300px이다.